! SENSES An Inform Library by L. Ross Raszewski ! To handle sensory perception. Written in 5.5, ! Easily portable to 6.0 (I hope) ! Version 5/1 9-14-96 ! ! This is a library to handle perception of the senses of Hearing, Smell, Touch ! and Taste. (I figured sight is pretty well handled by the library.) ! Instalation is fairly simple; This file should be included before Grammar, ! and the following lines shoudl appear before Verblib: ! ! Replace TouchSub; ! Replace ListenSub; ! Replace TastSub; ! Replace SmellSub; ! ! The following lines should be added to the LibraryMessages: ! (These are rerally optional, without them, attempts to smell a visible but ! unsmellable object, for example, will yield the library default.) ! ! Smell: if (lm_n==4) print_ret "You can't smell ", (the) noun, " from here."; ! Listen: if (lm_n==4) print_ret "You can't hear ", (the) noun, " from here."; ! Taste: if (lm_n==4) print_ret "You can't taste ", (the) noun, " from here."; ! Touch: if (lm_n==4) print_ret "You can't touch ", (the) noun, " from here."; ! ! This library uses four attributes, which are sense-versions of the library's ! "Transparent" attribute. It also uses six properties (sorry), one for each ! sense, and two to handle sense "muting". One Global variable (Sensedepth) ! is used. It could have probably been done by using return values, but this ! was was more convenient for me. ! ! To use this library, give each object a string or routine for the properties ! "feel" "scent" "sound" and "taste". Objects without these will return ! the usual Library message. If an object's description depends on how deeply ! it is buried, a routine could check the sensedepth variable. Sensedepth is ! the degree of separation between the player and the object, an object in the ! room with the player has a sensedepth of 0. For example, a radio's sound ! routine could print "You hear some classical music" at a sensedepth of 0, ! and "You hear some muted music" at a sensedepth of 3. ! MaxSenseDepth is the deepest something can be "burried" while the parser ! still detects it. An object with a sensedepth greater than the MaxSenseDepth ! will not be noticed. This is important mostly for recursive senses, so that ! you don't get an anomalty like "Within the box you hear nothing unexpected" ! ! Smell and Listen recurse automatically; listening to an object will also ! listen to its contents, provided they are audible. The RecurseSense routine ! is provided to handle sense recursing. ! ! MaxSenseDepth has a default of 5, but can also be a routine, which checks ! the action varable, thus a perfumed radio (?) might only be smellable at ! a depth of 2, but could be heard as deep as 6. ! ! The Opacity of a container is its resistance to sensory transmittion. ! the default opacity is 1, but can be a routine as well. Opacity affects ! sensedepth: A radio in a box of opacity 2, which is inside a box of ! opacity 1 has a sensedepth of 3. Sensedepth recurses down the object ! tree, but not up, except to the parent of the player. ! Open containers do not affect sensedepth ! ! Because of the inclusion location, the player can not refer to an object ! that is not in normal scope. This is fairly logical, by my reconing, but ! I've made it easy if you want to add the ability to listen to the ! invisible radio: Add these lines AFTER Grammar: ! ! Extend "touch" * scope=TouchScope ->Touch; ! Extend "smell" * scope=SmellScope ->Smell; ! Extend "listen" * scope=HearScope ->Listen; ! Extend "taste" * scope=TasteScope ->Taste; ! ! There are two oddities I should mention; Unlike the other senses, containers ! are by default trasnsparent to sound. Give them soundproof to reverse this. ! Also, an object that is touchthru or tastethru is also smellthru, as I feel ! this is reasonably close to the way the world works. If you don't like this, ! have opacity return some huge number for action==##Smell. ! Attribute smellthru; !Transparent to smell Attribute touchthru; !Transparent to touch eg. has holes in it Attribute tastethru; !Transparent to taste Attribute soundproof; !Opaque to sound property feel; !Response to "Touch" or routine to print one property scent; !Same for smell property sound; !Same for listen property taste; !Same for taste !These next two can also be properties which return a number property opacity 1; !The amount that it obscures whatever's inside it property MaxSenseDepth 5; !The maximum opacity at which it can be observed Global sensedepth; !The sum of the opacities of the objects between the !player and the thing (s)he is examining ! First, a routine to check whether or not the object can be sensed in the ! needed way ! InSenseScope(thing,Object,Reason) Determines whether Object is in scope of ! Thing by the sense Reason [ InSenseScope thing obj reason i; sensedepth=0; i=SenseScope(thing,obj,reason,fl); if (sensedepth<=ValueOrRun(obj,MaxSenseDepth)) return i; rfalse; ]; ! In order for sensedepth to work right, I needed two routines, one to rezero ! sensedepth, and a recursing one to measure it. DO NOT call SenseScope ! directly, use InSenseScope instead [ SenseScope thing obj reason o flag i; o = parent(obj); i = parent(thing); if (o==thing) rtrue; if (IndirectlyContains(i,obj)==0 && i~=obj) rfalse; ! (Just in case a call is made to something that ! isn't in the room with the player) if (o==i or thing) rtrue; if (i==o or thing) rtrue; if (o hasnt open) sensedepth=sensedepth+ValueOrRun(o,opacity); flag = 0; switch(reason) { ##Touch: if (o has open || o has touchthru) flag=1; ##Smell: if (o has open || o has touchthru || o has smellthru || o has tastethru) flag=1; ##Taste: if (o has open || o has tastethru) flag=1; ##Listen: if (o has open || o hasnt soundproof) flag=1; }; if (flag==1) return SenseScope(thing,o,reason); rfalse; ]; ! RecurseSense(obj,sense) recurses through the tree from obj, printing their ! sense response, if they are in sensescope. [ RecurseSense obj sense o i; if (parser_trace>=3) print "[Recursing over the ", (name) obj, "]^"; if (ZRegion(obj.sense)==2 or 3 && InSenseScope(player,obj,action)==1 {PrintOrRun(obj,sense); i=1;}; objectloop (o in obj) {if (RecurseSense(o,sense)==1) i=1;}; if (i~=0) rtrue; rfalse; ]; ! The new Routines for Touch,Smell,Taste, and Listen [ TouchSub; if (InSenseScope(player,noun,##Touch)==0) return L__M(##Touch,4); if (ZRegion(noun.feel)==2 or 3) { PrintOrRun(noun,feel); rtrue;}; if (noun==player) return L__M(##Touch,3); if (noun has animate) return L__M(##Touch,1); L__M(##Touch,2); ]; [ SmellSub; if (noun==0) <>; if (InSenseScope(player,noun,##Smell)==0) return L__M(##Smell,4); if (RecurseSense(noun,scent)==1) rtrue; L__M(##Smell); ]; [ ListenSub; if (noun==0) <>; if (InSenseScope(player,noun,##Listen)==0) return L__M(##Listen,4); if (RecurseSense(noun,sound)==1) rtrue; L__M(##Listen); ]; [ TasteSub; if (InSenseScope(player,noun,##Taste)==0) return L__M(##Taste,4); if (ZRegion(noun.taste)==2 or 3) { PrintOrRun(noun,taste); rtrue;}; L__M(##Taste); ]; ! Scope-Checking routines in case you want to extend verb grammar [ TouchScope i; if (scope_stage==1) rfalse; if (scope_stage==2) { for(i=selfobj+1:i<=top_object:i++) if (InSenseScope(player,i,##Touch)==1) PlaceInScope(i);}; ]; [ SmellScope i; if (scope_stage==1) rfalse; if (scope_stage==2) { for(i=selfobj+1:i<=top_object:i++) if (InSenseScope(player,i,##Smell)==1) PlaceInScope(i);}; ]; [ HearScope i; if (scope_stage==1) rfalse; if (scope_stage==2) { for(i=selfobj+1:i<=top_object:i++) if (InSenseScope(player,i,##Listen)==1) PlaceInScope(i);}; ]; [ TasteScope i; if (scope_stage==1) rfalse; if (scope_stage==2) { for(i=selfobj+1:i<=top_object:i++) if (InSenseScope(player,i,##Taste)==1) PlaceInScope(i);}; ];