Newsgroups: rec.arts.int-fiction
Path: nntp.gmd.de!Dortmund.Germany.EU.net!Germany.EU.net!howland.reston.ans.net!vixen.cso.uiuc.edu!usenet.ucs.indiana.edu!news.cs.indiana.edu!shulick@mango.ucs.indiana.edu
From: "Sam Hulick" <shulick@mango.ucs.indiana.edu>
Subject: Inform: MAJOR CODE (library 5/11 'capacity' replacement)
Message-ID: <1995Oct2.133029.25999@news.cs.indiana.edu>
Organization: Vallen Software
Date: Mon, 2 Oct 1995 13:30:24 -0500
Lines: 538


Enjoy! this is totally free.  I encourage Graham to add this to library
version 5/12.

---cut here---
! A new weight/space system for Inform.
! WILL Graham add this to library 5/12? :)  (please?)

! Explanation and notes:
! This is a replacement for the 'capacity' property in Inform lib5/11.
! This weight/space system is much more detailed and allows for more
! complex puzzles and situations to occur.  It would be really cool
! to see this implemented in 5/12 (or at least the concept, if not my
! actual code below).  If you are not sure of the purpose of this
! weight system, check out the following example: You have a box that
! has a capacity of 3.  So after you put three batteries into it, it's
! full.  And, strangely, after you put three tiny gems into the box,
! it's also full.  This weight & size/space system remedies this
! weirdness.

! Here is the general rule I follow when determining an objects size and
! weight.  For tiny things like pills, small stones, an M&M, I use a 
! weight of 0, because you could carry perhaps 20 or so of these, so 
! weight is not too important.  The 'size' would also be 0.  For larger
! things like a motorcycle helmet, I'd use a size of about 5 or 6, and
! a weight of about 10.  Just check out the examples below.  Sometimes
! I find the weight system a bit hard to use..it's tough to judge what
! should have which weight

! Note to Graham and Gareth: Feel free to modify this code as you wish
! before adding it to 5/12 (if that is your intention).  I admit this code
! isn't the best, but it does form a foundation for it.  One thing I would
! like to see is a way of handling things if objects exceed their max.
! For instance, a routine can be called if the player puts too many
! heavy things in a flimsy canvas sack.. i.e.

!  Object sack. .....
!   with  exceed_weight [;
!                ...move all objects to parent...
!                "The canvas sack rips and everything falls out.";

Switches xv5;

Constant Story "PHYSICS";
Constant Headline "^A More Detailed Object-Handler^Freeware by Sam Hulick^";
Constant MAX_CARRIED 30;

REPLACE RTakeSub;
REPLACE PutOnSub;
REPLACE InsertSub;

Include "parser";
Include "verblib";

Property max_weight alias capacity;    ! max weight something can hold
Property max_space;                    ! max space.....
Property weight;   ! can be a routine.  so can max_weight/max_space
Property size;     ! same for this one
Property too_heavy "That's too heavy for you to carry right now.";
Property too_big "That's too big for you to carry right now.";

Object newself "yourself"
 with  description "As good-looking as ever.", number 0,
       before NULL, after NULL, life NULL, each_turn NULL,
       time_out NULL, describe NULL, capacity 100, max_space 100,
       parse_name 0, short_name 0
 has   concealed animate proper transparent;

Object testroom "Test Room"
 with  description "This is the room for testing out this new system.  \
                    Here you see all sorts of objects, big and small, \
                    light and heavy.  Have at it!  You can order Frank and \
                    Biff to drop things and pick them up, to demonstrate \
                    their strengths. (Just for fun, try putting the raft \
                    inside the box or the hole, then inflating it.)"
 has   light;

Nearby wimp "Wimpy Frank"
 with  name "wimp" "wimpy" "frank",
       description [;
          print "He's a thin, lanky geeky guy with very little brawn.  He \
                 is carrying ";
          if (child(self) == 0) "nothing.";
          WriteListFrom(child(self), ENGLISH_BIT + RECURSE_BIT + TERSE_BIT);
          ".";
       ],
       life [ ow os;
        Ask, Answer, Tell: "~I don't care,~ he states plainly.";
        Order: if (action == ##Take && noun ~= nothing &&
                   noun hasnt animate && noun hasnt static &&
                   noun hasnt scenery)
               {
                  ow = OkWeight(self, noun);
                  os = OkSize(self, noun);
                  if (ow == 1 && os == 1)
                  {
                     print "Frank smiles crookedly as he picks up ",
                           (the) noun, " without much effort.^";
                     move noun to self;
                     rtrue;
                  }
                  print "Frank attempts to pick up ", (the) noun, ", then \
                         gives up with a sigh.  ";
                  if (ow == 0) print "~I'm not very strong.~  ";
                  else print "~It's just too big for me.~  ";
                  "He points to Biff.  ~Maybe you'd better ask him.~";
               }
               if (action == ##Drop)
               {
                  if (noun in self)
                  {
                     move noun to parent(self);
                     print "Frank drops ", (the) noun; ".";
                  }
                  "~But I don't have it.~";
               }
               "~I won't do that,~ he whines.";
       ],
       max_weight 10, max_space 10
 has   animate proper transparent;

Nearby biff "Biff"
 with  name "biff",
       description [;
          print "Now this is one bulky guy.  He looks as if he could lift a \
                 race horse.  He is carrying ";
          if (child(self) == 0) "nothing.";
          WriteListFrom(child(self), ENGLISH_BIT + RECURSE_BIT + TERSE_BIT);
          ".";
       ],
       life [ ow os;
        Ask, Answer, Tell: "He merely grunts.";
        Order: if (action == ##Take && noun hasnt animate &&
                   noun hasnt static && noun hasnt scenery && noun ~= nothing)
               {
                  ow = OkWeight(self, noun);
                  os = OkSize(self, noun);
                  if (ow == 1 && os == 1)
                  {
                     print "Biff picks up ", (the) noun, " and smiles.^";
                     move noun to self;
                     rtrue;
                  }
                  print "Biff tries to pick up ", (the) noun, ".  ";
                  if (ow == 0)
                     print "He struggles with its weight for a moment, \
                            giving it all he's got.  He eventually gives \
                            up and hits himself over the head.^";
                  else print "He manages in lifting it, but he stumbles \
                              a little awkwardly under ", (the) noun, "'s \
                              size.  He drops it and shouts an obscenity.^";
                  rtrue;
               }
               if (action == ##Drop)
               {
                  if (noun in self)
                  {
                     move noun to parent(self);
                     print "Biff sets ", (the) noun; " down.";
                  }
                  print "Biff scratches his head.  It takes him a moment to \
                         realize that he's not carrying ", (the) noun; ".";
               }!
               "He grunts and shakes his head.";
       ],
       max_weight 75, max_space 50
 has   animate proper transparent;

Nearby kegobeer "keg of beer"
 with  name "keg" "beer",
       description "It's a huge keg of beer.",
       ! there will be no max_weight or max_space since it's not a
       ! container
       weight 50, size 20,
       too_heavy "Yeesh, this thing is heavy!  There's no way you can pick \
                  it up.";

Nearby inraft "inflatable raft"
 with  name "inflatable" "raft",
       short_name [;
          if (self has general) print "inflated raft";
          else print "inflatable raft";
          rtrue;
       ],
       weight 5,
       size [;
          if (self hasnt general) return 4;
          else return 30;
       ],
       too_big [;
          if (self has general)
             "You find it too hard to carry since it's inflated.";
       ],
       article "an",
       description [;
          print "It's a life raft!  It has a small cord you can pull to \
                 either inflate or deflate it.  At the moment, it's ";
          if (self has general) "inflated, and quite big!";
          "deflated into a small little packet.";
       ],
 has   transparent;

Nearby litesphere "white sphere"
 with  name "white" "sphere" "light",
       list_together "spheres",
       description "It's a white sphere with the word ~LIGHT~ inscribed on \
                    it.",
       weight 4, size 3;

Nearby medsphere "blue sphere"
 with  name "blue" "sphere" "medium",
       list_together "spheres",
       description "It's a blue sphere with the word ~MEDIUM~ inscribed on \
                    it.",
       weight 20, size 3;

Nearby hsphere "black sphere"
 with  name "black" "sphere" "heavy",
       list_together "spheres",
       description "It's a black sphere with the word ~HEAVY~ inscribed on \
                    it.",
       weight 80, size 3;

Nearby msizedrock "medium-sized rock"
 with  name "medium" "sized" "rock" "medium-sized",
       weight 25, size 8;

Nearby largerock "large rock"
 with  name "large" "rock",
       weight 45, size 13;

Nearby glider "light-weight windglider"
 with  name "glider" "windglider" "wind",
       description "It's a hang-glider.  It's pretty huge, but made of all \
                    light-weight materials.",
       weight 17, size 60;

Nearby sbox "small box"
 with  name "small" "box",
       description [;
          print "A small wooden box that the raft came in.  It's currently ";
          if (self has open) "open."; "closed.";
       ],
       max_space 6, max_weight 10,
 has   container openable open;

Nearby hiw "hole in the wall"
 with  name "hole" "wall",
       description "It's a small hole in the wall.",
       max_space 4, max_weight 200,
       before [;
        Take: "Last time I checked, holes aren't portable.";
       ],
 has   container open static;

Object rcord "cord" inraft
 with  name "cord",
       description "It's the cord you pull to inflate or deflate the raft.",
       before [ ip;
        Pull: if (inraft has general)
              {
                 give inraft ~general;
                 "The raft deflates on its own.";
              }
              give inraft general;
              print "The raft hisses as it quickly inflates";
              if (inraft in player && OkSize(player, inraft) == 0)
              {
                 move inraft to parent(player);
                 "!  You find it suddenly a bit too big to hang onto.  \
                  You drop it.";
              }
              ip = parent(inraft);
              if (ip == hiw)
              {
                 remove inraft;
                 ".  It suddenly grows too large for the hole \
                  in the wall, and blows up into smithereens!";
              }
              if (ip == sbox)
              {
                 move inraft to parent(sbox);
                 ", becoming much too big for the box it's in.  The raft \
                  pops out of the box and finishes inflating.";
              }
              ".";
       ],
 has   static;

Object scale "scale" testroom
 with  name "scale",
       description [ wc sc;
          wc = WeightCarried(self);
          sc = SpaceCarried(self);
          print "The display on the scale reads: WEIGHT: ", wc, "   SPACE: ",
                sc;
          if (wc == 0)
          {
             if (player in self) ".  We know you weigh more than that, but \
                  the game doesn't care about your weight.  Try picking up \
                  an object or two.";
             ".  Try standing on it or putting something on it.";
          }
          ".";
       ],
       before [;
        Take: "Leave it on the floor.";
       ],
       max_weight 500, max_space 20
 has   enterable supporter static;

[ Initialise;
   ChangePlayer(newself);
   location = testroom;
!  This is incorrect.. use the MAX_CARRIED constant for player's weight
!  capacity..
!   player.max_weight = 30;
   player.max_space = 20;
   "^^^^^It feels like a different kind of Inform game.  Perhaps it has \
    something to do with the...^^";
];

[ OkWeight carrier obj w;
   w = ValueOrRun(obj, weight);
   if ((WeightCarried(carrier) + w) > ValueOrRun(carrier, max_weight)) rfalse;
   rtrue;
];

[ OkSize carrier obj s;
   s = ValueOrRun(obj, size);
   if ((SpaceCarried(carrier) + s) > ValueOrRun(carrier, max_space)) rfalse;
   rtrue;
];

[ WeightCarried obj o total;
   objectloop (o in obj)
   {
      total = total + ValueOrRun(o, weight);
      if (child(o) ~= 0)
         total = total + WeightCarried(o);
   }
   return total;
];

[ SpaceCarried obj o total;
   objectloop (o in obj)
      total = total + ValueOrRun(o, size);
   return total;
];

!! The reason SpaceCarried() isn't recursive is because it merely doesn't
! have to be.  WeightCarried() must be recursive, because if you put a
! huge heavy steel ball into a light sack and carry the sack, this doesn't
! mean the sack relieves your weight.  However, if you can manage to fit a
! very large object into a small sack, then your troubles are reduced. (a
! good example would be a huge Nerf(TM) beachball that is tough to carry
! around, but if you find a small, light box, you can open the box, stuff
! the Nerf(TM) ball into it, and close the box.  The weight carried is
! still the box plus the ball, but now your space carried has reduced.

[ AdviseMoveIt obj;
   print ".  Try moving some things off ", (the) obj; ".";
];

[ AdvisePullIt obj;
   print ".  Try removing some things from ", (the) obj; ".";
];

[ RTakeSub fromobj i j k postonobj;
  if (noun==player) return L__M(##Take,2);

  if (noun has animate) return L__M(##Take,3,noun);

  if (parent(player)==noun) return L__M(##Take,4,noun);

  i=parent(noun);
  if (i==player) return L__M(##Take,5);

  if (i has container || i has supporter)
  {   postonobj=i;
      k=action; action=##LetGo;
      if (RunRoutines(i,before)~=0) { action=k; rtrue; }
      action=k;
  }

  while (i~=fromobj && i~=0)
  {   if (i hasnt container && i hasnt supporter)
      {   if (i has animate) return L__M(##Take,6,i);
          if (i has transparent) return L__M(##Take,7,i);
          return L__M(##Take,8);
      }
      if (i has container && i hasnt open)
          return L__M(##Take,9,i);
      i=parent(i);
      if (i==player) i=fromobj;
  }
  if (noun has scenery) return L__M(##Take,10);
  if (noun has static)  return L__M(##Take,11);

  ! If it's too heavy, don't even bother with SACK_OBJECT. just because
  ! we put something in a sack doesn't make it any lighter.
  if (OkWeight(player, noun) == 0)
     return PrintOrRun(noun, too_heavy, 0);

  if (OkSize(player, noun) == 0)
  {
      if (SACK_OBJECT~=0)
      {   if (parent(SACK_OBJECT)~=player)
              return PrintOrRun(noun, too_big, 0);
          j=0;
          objectloop (k in player) 
              if (k~=SACK_OBJECT && k hasnt worn && k hasnt light) j=k;

          if (j~=0)
          {   L__M(##Take,13,j);
              keep_silent = 1; <Insert j SACK_OBJECT>; keep_silent = 0;
              if (j notin SACK_OBJECT) rtrue;
          }
          else return PrintOrRun(noun, too_big, 0);
      }     
      else return PrintOrRun(noun, too_big, 0);
  }
  move noun to player;

  if (postonobj~=0)
  {   k=action; action=##LetGo;
      if (RunRoutines(postonobj,after)~=0) { action=k; rtrue; }
      action=k;
  }
  rfalse;
];

[ PutOnSub;
  receive_action=##PutOn; 
  if (second==d_obj) { <Drop noun>; rfalse; }
  if (parent(noun)~=player) return L__M(##PutOn,1,noun);

  if (second>1)
  {   action=##Receive;
      if (RunRoutines(second,before)~=0) { action=##PutOn; rtrue; }
      action=##PutOn;
  }

  if (IndirectlyContains(noun,second)==1) return L__M(##PutOn,2);
  if (second hasnt supporter) return L__M(##PutOn,3,second);
  if (parent(second)==player) return L__M(##PutOn,4);
  if (noun has worn)
  {   L__M(##PutOn,5);
      <Disrobe noun>;
      if (noun has worn) rtrue;
  }
  if (OkSize(second, noun) == 0)
  { print (The) noun, " won't fit on ", (the) second;
    if (ValueOrRun(noun, size) <= ValueOrRun(second, max_space))
       return AdviseMoveIt(second);
    ".";
  }
  if (OkWeight(second, noun) == 0)
  {
     print "You feel ", (the) second, " begin to give as you start to put ",
           (the) noun, " on it.  Maybe this isn't such a good idea";
     if (ValueOrRun(noun, weight) <= ValueOrRun(second, max_weight))
        return AdviseMoveIt(second);
     ".";
  }

  move noun to second;

  if (AfterRoutines()==1) rtrue;

  if (second>1)
  {   action=##Receive;
      if (RunRoutines(second,after)~=0) { action=##PutOn; rtrue; }
      action=##PutOn;
  }

  if (keep_silent==1) rtrue;
  if (multiflag==1) return L__M(##PutOn,7);
  L__M(##PutOn,8,noun);
];

[ InsertSub;
  receive_action = ##Insert;
  if (second==d_obj ) <<Drop noun>>;
  if (parent(noun)~=player) return L__M(##Insert,1);

  if (second>1)
  {   action=##Receive;
      if (RunRoutines(second,before)~=0) { action=##Insert; rtrue; }
      action=##Insert;
  }
  if (second hasnt container) return L__M(##Insert,2);
  if (second hasnt open)      return L__M(##Insert,3);
  if (IndirectlyContains(noun,second)==1) return L__M(##Insert,5);
  if (noun has worn)
  {   L__M(##Insert,6);
      <Disrobe noun>; if (noun has worn) rtrue;
  }

  if (OkSize(second, noun) == 0)
  {
     print "There's not enough room inside ", (the) second, " for ",
           (the) noun;
     if (ValueOrRun(noun, size) <= ValueOrRun(second, max_space))
        return AdvisePullIt(second);
     ".";
  }
  if (OkWeight(second, noun) == 0)
  {
     print (The) second, " won't hold anymore weight";
     if (ValueOrRun(noun, weight) <= ValueOrRun(second, max_weight))
        return AdvisePullIt(second);
     ".";
  }

  move noun to second;

  if (AfterRoutines()==1) rtrue;

  if (second>1)
  {   action=##Receive;
      if (RunRoutines(second,after)~=0) { action=##Insert; rtrue; }
      action=##Insert;
  }
  if (keep_silent==1) rtrue;
  if (multiflag==1) return L__M(##Insert,8);
  L__M(##Insert,9,noun);
];

Include "grammar";
end;

---cut here---
-- 
--- Sam Hulick ------------- shulick@indiana.edu ---------------------
Systems Consultant        | Homepage:
Indiana College Placement |    http://copper.ucs.indiana.edu/~shulick/
  and Assessment Center   | PGP public key available on request
