Constant Story "Puzzle^";
Constant Headline "An Interactive Quickie implemented by Andrew Schepler^";
Constant TASKS_PROVIDED;
Constant MAX_SCORE 30;
Constant NUMBER_TASKS 4;

Array task_scores -> 5 5 10 10;

Include "Parser";
Include "Verblib";

Property weight;

Object  towertop "Top of a Tower"
with   description "This is a room high in a tower, with one window
           and a locked door. Two boxes are secured to a rope that
           runs over a pulley. One is on the ground, and the other is
           right outside the window.",
       before [;
        Jump: "It's a long way down.";
       ],
       d_to "You can't see any safe way down.",
       out_to "You can't see any safe way down.",
has    light;

Object  door1 "door" towertop
with   description "The door is securely locked.  You can't get out
           that way.",
       name "door",
       with_key 0,
has    lockable locked openable scenery;

Object  scale "scale" towertop
with   name "scale",
       initial "A scale is attached to the floor in one corner.",
       before [;
        Receive, Enter:
           if (child(self) ~= nothing)
               "Only one thing can be weighed at a time.";
       ],
       after [;
        Enter:
           "You weigh 120 pounds, thanks to that recent diet.";
        Receive:
           if (noun provides weight)
               print_ret (The) noun, " weighs ", noun.weight, "
                   pounds.";
           print_ret (The) noun, " does not weigh enough to register
               on the scale.";
       ],
has    static enterable container open supporter;

Object  boy "your brother" towertop
with   name "brother" "boy" "child",
       describe [x;
           x = parent(self);
           if (x == box1 or box2)
               x = parent(x);
           if (x == location)
               x = -1;
           switch (x)
           {
            -1:
               "Your younger brother is here, looking scared and
               waiting for you to fix things.";
            towertop:
               "Your brother looks down from the tower, waiting for
               you to get him down too.";
            ground:
               "Your brother looks up to find out what he should
               do.";
           }
       ],
       description [;
           print "Your little brother is frightened, but looks to you
               for help";
           if (child(self) ~= nothing)
           {
               print ".  He is carrying ";
               WriteListFrom(child(self));
           }
           ".";
       ],
       weight 60,
       life [;
        Ask: "He thinks YOU should know everything.  He just shrugs his
           shoulders.";
        Attack, ThrownAt, Kiss: "Your little brother makes a wrinkly
           face at you and sticks out his tongue.";
        Tell: "Your brother listens to your every word, but is unable
           to help.";
        Give, Show:
           if (noun == dog)
           {
               move dog to location;
               "Your brother laughs when the dog licks his face,
               then sets his dog down.";
           }
           move noun to self;
           print_ret "Your brother takes ", (the) noun, " from you.";
        NotUnderstood: "Your brother just gives you a confused
           look.";
        default: "Your brother is too frightened to listen.";
       ],
       orders [;
        Go: if (towertop == parent(self) or parent(parent(self)))
            "~But we can't get out!~";
           "~I can't get help, I'm lost!~";
        Enter:
           if (noun == box1 or box2)
           {
               if (self hasnt general)
               {
                   give self general;
                   "Your brother looks over the edge warily. ~I don't
                   wanna,~ he decides.";
               }
               move self to noun;
               "Your brother cautiously enters the box, trusting
               you.";
           }
           if (noun == scale)
               "He hops on the scale, and right back off. He weighs
               60 pounds.";
        Exit:
           if (noun == 0 or parent(self))
           {
               move self to parent(parent(self));
               "~Okay!~  He climbs out of the box.";
           }
        Take:
           if (noun has scenery) rfalse;
           if (noun in self) "Your brother already has that.";
           move noun to self;
           print_ret "Your brother takes ", (the) noun, ".";
        Drop:
           if (noun notin self) "He doesn't have that.";
           move noun to parent(self);
           print_ret "~Okay!~  Your brother drops ", (the) noun, ".";
        Give:
           if (noun notin self)
               "He doesn't have that.";
           move noun to player;
           print_ret "Your brother gives you ", (the) noun, ".";
        Insert, PutOn:
           if (noun notin self)
               "He doesn't have that.";
           if (second == scale && boy in towertop && child(scale) == nothing)
               print_ret "Your brother puts ",(the) noun," on the
                   scale and reads ~",noun.weight," pounds.~ Then he
                   picks it up again.";
           if (second == box1 or box2)
           {
               move noun to second;
               print_ret "Your brother places ",(the) noun," in the
                   box.";
           }
       ],
has    animate male transparent proper;

Object  treat "dog biscuit" boy
with   name "biscuit" "treat";

Object  dog "dog" towertop
with   name "dog" "puppy",
       life [;
        Give:
           if (noun == rock)
               print_ret "The dog sniffs at the rock, but is not
                   interested.";
           if (noun == treat)
           {
               move treat to self;
               "The dog happily munches on the doggie treat.";
           }
        default:
           "Woof!";
       ],
       orders [;
           "The dog never seemed to learn a thing at obedience
           school. The only way you know of getting his attention is
           whistling.";
       ],
       weight 30,
       stat 0,
       daemon [;
           if (TestScope(self,treat) && treat notin player or boy)
           {
               if (self in parent(treat))
               {
                   move treat to self;
                   "The dog happily munches on the doggie
                   treat.";
               }
               else switch(parent(treat))
               {
                scale:
                   move self to scale;
                   "The dog, seeing the treat, hops on the scale.  He
                   weighs 30 pounds.";
                box1, box2:
                   move self to parent(treat);
                   "The dog sees the treat and hops into the box.";
               }
           }
           if (parent(self) ~= scale or box1 or box2)
           {
               self.stat = 0;
               return;
           }
           if (self.stat == 0)
           {
               self.stat++;
               return;
           }
           self.stat = 0;
           if (parent(self) == scale)
           {
               move self to towertop;
               "The dog decides to hop off the scale.";
           }
           move self to parent(parent(self));
           "The dog decides to jump out of the box.";
       ],
       before [;
        Take:
           move self to player;
           "You lift the dog, who licks your face.";
       ],

has    animate male;

Object  rock "rock" towertop
with   name "rock",
       weight 25;

Object  box1 "box" towertop
with   name "box" "basket" "pulley",
       describe [;
           if (child(self) == 0) rtrue;
           print "In the box by the window";
           WriteListFrom(child(self),ENGLISH_BIT + ISARE_BIT);
           ".";
       ],
       description [;
           print "The box is attached by means of a pulley to an
               identical box resting on the ground below.";
           if (child(self) == 0)
               " It is large enough to squeeze inside.";
           print "^In the box here";
           WriteListFrom(child(self),ENGLISH_BIT + ISARE_BIT);
           ".";
       ],
       daemon [top bot;
           top = box1;
           bot = box2;
           if (self in ground)
           {
               top = box2;
               bot = box1;
           }
           if (WeightOf(top) > WeightOf(bot) + 5)
           {
               if (player in top)
               {
                   deadflag = 1;
                   "The box you are in plummets quickly to the
                   ground.  Much too fast for comfort or safety.";
               }
               if (boy in top)
               {
                   deadflag = 3;
                   "The box zips down to the ground, and your brother
                   gets a few broken bones.  Later the paramedics
                   find you and take him to the hospital.";
               }
               if (dog in top)
               {
                   deadflag = 3;
                   "Amazingly, the dog survives a very quick trip
                   down, but he is so startled that he runs away
                   (with a limp). He runs home to get help, and the
                   city brings a cherrypicker to help you out. It
                   takes at least an hour, by which time dinner is
                   over.";
               }
               move top to ground;
               move bot to towertop;
               "The rope zips over the pulley as the box plummets to
               the ground.  You hate to think what would happen if
               anything more fragile than the rock were inside.";
           }
           if (WeightOf(top) > WeightOf(bot))
           {
               Achieved(0);
               move top to ground;
               move bot to towertop;
               if (parent(parent(boy)) == ground) Achieved(1);
               if (location == ground && boy in ground &&
                   parent(parent(dog)) == ground)
               {
                   Achieved(3);
                   deadflag = 2;
                   "The dog descends once more, and the three of you
                   happily leave in time for dinner.";
               }
               print "Since the weight difference is so small, the
                   boxes move slowly and swap positions safely.^";
               if (player in top)
               {
                   Achieved(2);
                   PlayerTo(parent(player));
               }
           }
       ],
       before [;
        Enter:
           if (self hasnt general)
           {
               give self general;
               "It's quite a distance; you'd better be sure that's a
               good idea.";
           }
       ],
has    enterable container open static;

Object  ground "By the Base of the Tower"
with   description "You made it! But not everyone is down and safe
           yet.",
       cant_go "You consider getting the police for help, but you've done
           so much already, and your brother would be very upset if
           you left him or even his dog behind.",
       out_to 0,
has    light;

Object  box2 "box" ground
with   name "box" "basket" "pulley",
       describe [;
           if (child(self) == 0) rtrue;
           print "In the box by the window";
           WriteListFrom(child(self),ENGLISH_BIT + ISARE_BIT);
           ".";
       ],
       description [;
           print "The box is attached by means of a pulley to an
               identical box resting on the ground below.";
           if (child(self) == 0)
               " It is large enough to squeeze inside.";
           print "^In the box here";
           WriteListFrom(child(self),ENGLISH_BIT + ISARE_BIT);
           ".";
       ],
       before [;
        Enter:
           if (box1 hasnt general)
           {
               give box1 general;
               "It's quite a distance; you'd better be sure that's a
               good idea.";
           }
       ],
has    enterable container open static;

[ Initialise;
   location = towertop;
   StartDaemon(box1);
   StartDaemon(dog);
   "^^As you, your little brother, and his dog enter the room, the
   door accidentally swings shut behind you. It is locked! And
   you're supposed to be home by dinner!";
];

[ InScope;
   if (scope_reason == TALKING_REASON or LOOPOVERSCOPE_REASON)
   {
       ScopeWithin(ground);
       ScopeWithin(towertop);
   }
   rfalse;
];

[ PrintTaskName ach;
   switch(ach)
   {
    0: "making the pulley system move slow";
    1: "getting your brother down safely";
    2: "reaching the bottom";
    3: "getting everyone safely down";
   }
];

[ WeightOf obj t i;
   if (obj provides weight) t = obj.weight;
   if (obj == player) t = 120;
   objectloop (i in obj) t = t + WeightOf(i);
   return t;
];

[ DeathMessage;
   print "You didn't make it home for dinner";
];

[ WhistleSub;
   if (location == ground && ground == parent(boy) or parent(parent(boy)))
   {
       if (box1 in towertop) move dog to box1;
       else move dog to box2;
       "The dog responds to your whistle.  Now experienced at
       riding the pulley system, he jumps into the box.";
   }
   "The dog listens, but doesn't understand what you want.";
];

Include "Grammar";

Verb "whistle"
   *                                   -> Whistle;