??ANSWER TO EXERCISE 55

Firstly, a printing rule to print the state of coins. Coin-objects will have a property called way_up which is always either 1 or 2:

[ Face x; if (x.way_up==1) print "Heads"; else print "Tails"; ];
There are two kinds of coin but we'll implement them with three classes: Coin and two sub-categories, GoldCoin and SilverCoin. Since the coins only join up into trigrams when present in groups of three, we need a routine to detect this:
[ CoinsTogether cla i x y;
  objectloop (i ofclass cla)
  {   x=parent(i);
      if (y==0) y=x; else { if (x~=y) return 0; }
  }
  return y;
];
Thus CoinsTogether(cla) decides whether all objects of class cla are in the same place. (cla will always be either GoldCoin or SilverCoin.) We must now write the class definitions:
Class  Coin
  with name "coin" "coins//p",
       way_up 1, article "the",
       after
       [; Drop, PutOn:
             self.way_up = random(2); print (Face) self;
             if (CoinsTogether(self.which_class))
             {   print ". The ";
                 if (self.which_class == GoldCoin)
                     print "gold"; else print "silver";
                 " trigram is now ", (Trigram) self.which_class;
             }
             ".";
       ];
[ CoinLT k i c;
  if (inventory_stage==1)
  {   if (self.which_class == GoldCoin)
          print "the gold"; else print "the silver";
      print " coins ";
      k=CoinsTogether(self.which_class);
      if (k==location  k has supporter)
      {   objectloop (i ofclass self.which_class)
          {   print (name) i;
              switch(++c)
              {  1: print ", "; 2: print " and ";
                 3: print " (showing the trigram ",
                    (Trigram) self.which_class, ")";
              }
          }
          rtrue;
      }
      if (~~(c_style & ENGLISH_BIT))   c_style = c_style + ENGLISH_BIT;
      if (~~(c_style & NOARTICLE_BIT)) c_style = c_style + NOARTICLE_BIT;
      if (c_style & NEWLINE_BIT)       c_style = c_style - NEWLINE_BIT;
      if (c_style & INDENT_BIT)        c_style = c_style - INDENT_BIT;
  }
  rfalse;
];
Class  GoldCoin class Coin
  with name "gold", which_class GoldCoin,
       list_together [; return CoinLT(); ];
Class  SilverCoin class Coin
  with name "silver", which_class SilverCoin,
       list_together [; return CoinLT(); ];
(There are two unusual points here. Firstly, the CoinsLT routine is not simply given as the common list_together value in the coin class since, if it were, all six coins would be grouped together: we want two groups of three, so the gold and silver coins have to have different list_together values. Secondly, if a trigram is together and on the floor, it is not good enough to simply append text like "showing Tails, Heads, Heads (change)'' at inventory_stage 2 since the coins may be listed in a funny order: for example, in the order snake, robin, bison. In that event, the order the coins are listed in doesn't correspond to the order their values are listed in, which is misleading. So instead CoinsLT takes over entirely at inventory_stage 1 and prints out the list of three itself, returning true to stop the list from being printed out by the library as well.) To resume: whenever coins are listed together, they are grouped into gold and silver. Whenever trigrams are visible they are to be described by either Trigram(GoldClass) or Trigram(SilverClass):
Array gold_trigrams -->   "fortune" "change" "river flowing" "chance"
                          "immutability" "six stones in a circle"
                          "grace" "divine assistance";
Array silver_trigrams --> "happiness" "sadness" "ambition" "grief"
                          "glory" "charm" "sweetness of nature"
                          "the countenance of the Hooded Man";
[ Trigram cla i k state;
  objectloop (i ofclass cla)
  {   print (Face) i; if (k++<2) print ","; print " ";
      state=state*2 + (i.way_up-1);
  }
  if (cla == GoldCoin) i=gold_trigrams; else i=silver_trigrams;
  print "(", (string) i-->state, ")";
];
(These interpretations of the coins are quite bogus.) Finally, we have to make the six actual coins:
GoldCoin ->   "goat"    with name "goat";
GoldCoin ->   "deer"    with name "deer";
GoldCoin ->   "chicken" with name "chicken";
SilverCoin -> "robin"   with name "robin";
SilverCoin -> "snake"   with name "snake";
SilverCoin -> "bison"   with name "bison";

Back to the exercise in section 23
Mechanically translated to HTML from third edition as revised 16 May 1997. Copyright © Graham Nelson 1993, 1994, 1995, 1996, 1997: all rights reserved.