| #charset "us-ascii" | |
| #include "adv3.h" | |
| #include "en_us.h" | |
| /* | |
| Tads-3 Memory | |
| Steve Breslin, 2004 | |
| email: versim@hotmail.com | |
| ==== | |
| Licence: | |
| Everyone is free to use this, but please provide me with all | |
| improvements and modifications. | |
| ==== | |
| About this module: | |
| This module makes Actors remember the last place they saw an object. | |
| This is all taken care of automatically without any extra work from the | |
| user. | |
| Also, we add a verb 'objects' (which lists all the movable objects that | |
| the player has come across, along with each one's remembered location, | |
| which of course does not necessarily reflect the current game state). | |
| Unfortunately, we don't model really robust memory. Other things we | |
| might remember in the future: which key goes with which door; whether | |
| the lamp was on or off, last we checked; and so on. At present it's | |
| just object-location last we knew. | |
| Note: | |
| If some actor takes an object in the presence of other actors, and the | |
| other actor.canSee(object) then returns nil by virtue of the object | |
| being in some other actor's inventory, he doesn't remember where the | |
| object has gone. We don't know if this is ideal behavior or not, but | |
| we've erred on the side of simplicity, as this is fairly easy to fix or | |
| customize as desirable. | |
| */ | |
| modify Actor | |
| /* a table for location memory. the key is the object, and the | |
| * value is the object's last known location. If you want to | |
| * check where the actor thinks an object is, just check | |
| * actor.locMemTab[object]. | |
| */ | |
| locMemTab = static new LookupTable | |
| /* When an actor sees an object, he remembers its location. */ | |
| setHasSeen(obj) | |
| { | |
| updateLocMem(obj); | |
| inherited(obj); | |
| } | |
| /* update the memory table if the object has a location. Don't | |
| * remember myself or objects located in me, and don't remember | |
| * objects that cannot be moved. | |
| */ | |
| updateLocMem(obj) | |
| { | |
| /* We don't add myself or locationless objects to the table. */ | |
| if (obj == self || !obj.location) | |
| return; | |
| /* We remember only objects which are portable, except we do | |
| * remember Actors. | |
| */ | |
| if (!obj.ofKind(NonPortable) || obj.ofKind(Actor)) | |
| { | |
| locMemTab[obj] = obj.location; | |
| } | |
| /* We recurse through contents also. */ | |
| foreach(local child in obj.contents) | |
| { | |
| if (locMemTab[child] != obj) | |
| if (canSee(child)) | |
| updateLocMem(child); | |
| } | |
| } | |
| /* Forget an object (because we no longer know where it is). | |
| * Note that we don't forget its containment, since we still | |
| * remember objects located within it, even if we don't know | |
| * where it is. | |
| */ | |
| forgetLocMem(obj) | |
| { | |
| locMemTab.removeElement(obj); | |
| } | |
| ; | |
| modify Thing | |
| /* when a thing moves, update the memory table for witnesses to the | |
| * move. | |
| * further, if it's an actor that moves, update his memory table | |
| * for information available in the new location. | |
| */ | |
| notifyMoveInto(newContainer) | |
| { | |
| inherited(newContainer); | |
| memoryErase(); | |
| } | |
| notifyInsert(obj) | |
| { | |
| inherited(obj); | |
| obj.memoryUpdate(); | |
| } | |
| /* memoryErase: called immediately before baseMoveInto(). | |
| * | |
| * Each actor who can see the moving object forgets its memory of | |
| * the object's location. | |
| */ | |
| memoryErase() | |
| { | |
| for (local actor = firstObj(Actor) ; actor ; | |
| actor = nextObj(actor, Actor)) | |
| { | |
| if (actor.canSee(self)) | |
| actor.forgetLocMem(self); | |
| } | |
| } | |
| /* memoryUpdate: called immediately after baseMoveInto(). | |
| */ | |
| memoryUpdate() | |
| { | |
| /* Each actor who can see the object in its new location | |
| * remembers that object in its new location. | |
| */ | |
| for (local actor = firstObj(Actor) ; actor ; | |
| actor = nextObj(actor, Actor)) | |
| { | |
| if (actor.locMemTab[self] != self.location) | |
| if (actor.canSee(self)) | |
| actor.updateLocMem(self); | |
| } | |
| /* Finally, if it's an actor that's moving, we update its | |
| * location memory based on what new information is provided | |
| * by the new location. | |
| */ | |
| if (ofKind(Actor)) | |
| { | |
| locMemTab.forEachAssoc( | |
| new function(key, val) | |
| { | |
| /* Only perform this operation if locMemTab[key] | |
| * no longer has the correct value. | |
| */ | |
| if (val != key.location) | |
| { | |
| /* if we can see the key, update its | |
| * remembered location. | |
| */ | |
| if (canSee(key)) | |
| updateLocMem(key); | |
| /* if we cannot see the key, but we can see its | |
| * value (its remembered location), we may need | |
| * to remove the key from the table, since we | |
| * no longer know where it is. However, we only | |
| * update the memory if we can tell that our | |
| * current memory information is outdated. | |
| */ | |
| /* Note that this update fails in the rare case | |
| * that we can see the contents of val but | |
| * cannot see val itself. To make the code more | |
| * rigorous (and far more time cosuming), one | |
| * would delete the if statement in the | |
| * following line. | |
| */ | |
| else if (canSee(val)) | |
| { | |
| /* We need to figure out whether or not | |
| * the actor can detect that key is no | |
| * longer located in val. | |
| * | |
| * If the actor could see the object if it | |
| * were in val, the actor can tell that the | |
| * object is no longer in val. | |
| */ | |
| local curLoc = key.location; | |
| key.baseMoveInto(val); | |
| if (canSee(key)) | |
| forgetLocMem(key); | |
| key.baseMoveInto(curLoc); | |
| } | |
| } | |
| } | |
| ); | |
| } | |
| } | |
| ; | |
| /* the 'objects' verb provides the player a list of all movable objects | |
| * in the game, with their locations (last he remembers). | |
| */ | |
| DefineIAction(Objects) | |
| execAction() | |
| { | |
| gActor.locMemTab.forEachAssoc( | |
| new function(key, val) | |
| { | |
| /* We don't list objects in the actor who's issuing the | |
| * command. | |
| */ | |
| if (!key.isIn(gActor)) | |
| { | |
| /* first list the object (in the remembered | |
| * location). | |
| */ | |
| "<<key.theName>> (<<val.actorInPrep>> | |
| <<val.theName>>"; | |
| /* if val is non-portable, simply list its | |
| * outermost room. (We assume that non-portable | |
| * objects don't change their location.) | |
| */ | |
| if (val.ofKind(NonPortable) | |
| && val != val.getOutermostRoom) | |
| { | |
| val = val.getOutermostRoom; | |
| ", <<val.actorInPrep>> <<val.theName>>"; | |
| } | |
| else | |
| { | |
| local oml = val; | |
| /* list the last remembered outermost location | |
| * of val if it differs from val. | |
| */ | |
| while (gActor.locMemTab[oml]) | |
| oml = gActor.locMemTab[oml]; | |
| if (val != oml) | |
| { | |
| if (oml.ofKind(NonPortable)) | |
| oml = oml.getOutermostRoom; | |
| ", <<oml.actorInPrep>> | |
| <<oml.theName>>"; | |
| } | |
| } | |
| ")\n"; | |
| } | |
| } | |
| ); | |
| } | |
| ; | |
| VerbRule(Objects) | |
| 'objects' | |
| : ObjectsAction | |
| verbPhrase = 'objects/objectsing' | |
| ; | |
Xet Storage Details
- Size:
- 8.6 kB
- Xet hash:
- 6b50247a23e90b9e76ccd3b4b6dc8f4ff6eb0018b6e109d470217e18be36153d
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.