??ANSWER TO EXERCISE 35

We shall use a new property called weight and decide that any object which doesn't provide any particular weight will weigh 10 units. Clearly, an object which contains other objects will carry their weight too, so:

[ WeightOf obj t i;
   if (obj provides weight) t = obj.weight; else t = 10;
   objectloop (i in obj) t = t + WeightOf(i);
   return t;
];
Once every turn we shall check how much the player is carrying and adjust a measure of the player's fatigue accordingly. There are many ways we could choose to calculate this: for the sake of example we'll define two constants:
Constant CARRYING_STRENGTH = 500;
Constant HEAVINESS_THRESHOLD = 100;
Initially the player's strength will be the maximum possible, which we'll set to 500. Each turn the amount of weight being carried is substracted from this, but 100 is also added on (without exceeding the maximum value). So if the player carries more than 100 units, then her strength declines, but by dropping things to get the weight below 100 she can allow it to recover. If she drops absolutely everything, her entire strength will recuperate in at most 5 turns. Exhaustion sets in if her strength reaches 0, and at this point she is forced to drop something, which gives her strength a slight boost. Anyway, here's an implementation of all this:
Object weight_monitor
  with players_strength,
       warning_level 5,
       activate
       [;  self.players_strength = CARRYING_STRENGTH; StartDaemon(self);
       ],
       daemon
       [ w s b bw;
            if (location ~= Weights_Room) { StopDaemon(self); return; }
            s = self.players_strength
                - WeightOf(player) + HEAVINESS_THRESHOLD;
            if (s<0) s=0; if (s>CARRYING_STRENGTH) s=CARRYING_STRENGTH;
            self.players_strength = s;
            if (s==0)
            {   bw=-1;
                objectloop(b in player)
                    if (WeightOf(b) > bw) { bw = WeightOf(b); w=b; }
                self.players_strength = self.players_strength + bw;
                print "^Exhausted with carrying so much, you decide 
                    to discard ", (the) w, ": "; <<Drop w>>;
            }
            w=s/100; if (w==self.warning_level) return;
            self.warning_level = w;
            switch(w)
            {   3: "^You are feeling a little tired.";
                2: "^You possessions are weighing you down.";
                1: "^Carrying so much weight is wearing you out.";
                0: "^You're nearly exhausted enough to drop everything
                     at an inconvenient moment.";
            }
       ];
Notice that items are actually dropped with Drop actions: one of them might be, say, a wild boar, which would bolt away into the forest when released. The daemon tries to drop the heaviest item. (Obviously a little improvement would be needed if the game contained, say, an un-droppable but very heavy ball and chain.) Finally, of course, at some point the weight monitor has to be sent an activate message to get things going.

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