! physics.h
! Version 1.1
! by Sam Hulick <
[email protected]>
! This is a slight revision (not by much) of the old physics.inf example
! I released quite awhile ago. Please read through these comments here
! so you know exactly how it works.
! P.S.: I give Graham Nelson complete permission to add this into
! his next library release.
! When creating a game using physics.h, you must define a new player
! object, or directly modify the one in parser.h so it includes
! a 'max_space 100', in it, preferably near the 'capacity 100'.
! So if you make your own player obj, be sure to do this as the
! first line in Initialise():
!
! ChangePlayer(newself);
! followed by..
! player.max_weight = max_weight_carried;
! player.max_space = max_space_carried;
!
! Note that max_weight and max_space do NOT work on an object-by-object
! basis, but by weight #'s. That's the whole point of physics.h.
! Inform's capacity handling routines aren't very detailed, in that you
! could put three large rocks in a bag, and the bag will be full, but
! if you put three small pebbles in the bag, it is strangely full as
! well. This file will remedy that problem. When you define objects,
! give it a 'weight' and 'size', i.e.
!
! Object skull "human skull"
! with name "human" "skull",
! weight 8,
! size 6,
! ...
!
! Just figure a decent weight/size scale for your game, and think of
! what size or weight you would give it. I would give a shovel a
! weight of 10 or 13, perhaps, and a size of 15-20, maybe. It's
! just estimating. I give very small objects (pebbles, M&M's, etc.)
! a weight and size of 0, usually, because they're so small. Or
! you could up-scale your system, making M&M's size/weight both 1,
! then your shovel would more likely have a weight of 30, since you've
! up-scaled your values to compensate for the M&M's. There are no
! rights or wrongs: it's your game. I'm just providing the medium
! to control these weights and sizes.
! Now, on to more technical things. max_weight and max_space are
! used for containers and supporters. They can be values or
! routines (maybe for magical containers that expand). I think
! that is self-explanatory.
! too_big and too_heavy are a bit more complicated. They can simply
! be a string to print to the user when an object is too heavy or
! big to carry, or it can be a routine if you wish. But on a supporter
! or container, it really MUST be a routine. When too_heavy or too_big
! is called, 'action' contains either ##Take, ##PutOn, or ##Insert.
! Let's give an example:
! Object mcont "magic container"
! with description "You can put things on or in it, ooh.",
! name "magic" "container",
! size 5,
! weight 10,
! max_weight 30,
! max_size 30,
! too_heavy [;
! switch (action)
! {
! ##Take: "The container contains too many heavy things \
! for you to handle it.";
! ##PutOn: "However magical it is, it can't support the \
! weight of that.";
! ##Insert: "That object is too heavy, the magical \
! container would rip trying to carry that.";
! }
! ],
! .....
!
! And too_big works the same way, only it deals with the fact that
! the container can't handle the size of an object. If these things
! are unclear to you, you can skim through this file and read the
! source code. If you do not provide a too_heavy/too_big routine
! or string for an object, default messages will be printed, and
! you don't have to handle examining the 'action' variable. But
! you will most likely want to handle it yourself, since the default
! messages are.. well.. rather bland.
! IF YOU FIND ANY BUGS, or have any questions, e-mail me at
!
[email protected]. Thanks! Enjoy the code. Hope it adds some
! interesting depth to your games.
! P.S.: Don't forget to REPLACE RTakeSub, InsertSub, and PutOnSub,
! and include this file after parser and 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.";
! can the carrier take on the weight of obj? true/false return value
[ OkWeight carrier obj w;
w = ValueOrRun(obj, weight);
if ((WeightCarried(carrier) + w) > ValueOrRun(carrier, max_weight)) rfalse;
rtrue;
];
! can the carrier take on the size of obj?
[ 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 a rval;
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)
{
a = action;
action = ##Take;
rval = PrintOrRun(noun, too_heavy, 0);
action = a;
return rval;
}
if (OkSize(player, noun) == 0)
{
if (SACK_OBJECT~=0)
{ if (parent(SACK_OBJECT)~=player)
return ObjTooBig(noun);
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 ObjTooBig(noun);
}
else return ObjTooBig(noun);
}
move noun to player;
if (postonobj~=0)
{ k=action; action=##LetGo;
if (RunRoutines(postonobj,after)~=0) { action=k; rtrue; }
action=k;
}
rfalse;
];
[ ObjTooBig obj a rval;
a = action;
action = ##Take;
rval = PrintOrRun(obj, too_big, 0);
action = a;
return rval;
];
[ PutOnSub a;
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)
{
a = action;
action = ##PutOn;
if (RunRoutines(second, too_big) == 0)
{
! default message
print_ret (The) noun, " won't fit on ", (the) second, ".";
}
action = a;
if (ValueOrRun(noun, size) <= ValueOrRun(second, max_space))
return AdviseMoveIt(second);
rtrue;
}
if (OkWeight(second, noun) == 0)
{
a = action;
action = ##PutOn;
if (RunRoutines(second, too_heavy) == 0)
{
print_ret "You feel ", (the) second, " begin to give as you start to put ",
(the) noun, " on it. Maybe this isn't such a good idea.";
}
action = a;
if (ValueOrRun(noun, weight) <= ValueOrRun(second, max_weight))
return AdviseMoveIt(second);
rtrue;
}
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 a;
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)
{
a = action;
action = ##Insert;
if (RunRoutines(second, too_big) == 0)
{
print_ret "There's not enough room inside ", (the) second, " for ",
(the) noun, ".";
}
action = a;
if (ValueOrRun(noun, size) <= ValueOrRun(second, max_space))
return AdvisePullIt(second);
rtrue;
}
if (OkWeight(second, noun) == 0)
{
a = action;
action = ##Insert;
if (RunRoutines(second, too_heavy) == 0)
{
print_ret (The) second, " won't hold anymore weight.";
}
action = a;
if (ValueOrRun(noun, weight) <= ValueOrRun(second, max_weight))
return AdvisePullIt(second);
rtrue;
}
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);
];