| /* DupDobj.t */ | |
| /* | |
| * DupDobj.t | |
| * Version 1.2 (18-Jul-04) | |
| * by Eric Eve | |
| * | |
| * To use this module, simply include it in your list of TADS 3 source files. | |
| * | |
| * This file is Freeware and may be incorporated into other software, distributed, | |
| * and modified at will. The author (contactable on eric.eve@hmc.ox.ac.uk) would | |
| * nevertheless be grateful to receive any bug reports or suggestions for | |
| * improvements. | |
| * | |
| * The function of this module is to control the handling of | |
| * duplicate direct objects in commands. In particular it allows | |
| * duplicate objects to me removed so that, for example: | |
| * | |
| * >X CHAIR, BOX AND CHAIR | |
| * | |
| * would be treated as simply: | |
| * | |
| * >X CHAIR AND BOX | |
| * | |
| * This may be particularly useful when a Decoration object, say, exists | |
| * under several synonyms. For example suppose we have a Decoration defined thus: | |
| * | |
| * Decoration 'leaves/twigs/branches' 'leaves' @forest | |
| * "The branches and twigs hereabouts are laded with reddening autumnal leaves. " | |
| * | |
| * We don't really want this: | |
| * | |
| * >X LEAVES, TWIGS AND BRANCHES | |
| * leaves: The branches and twigs hereabouts are laded with reddening autumnal leaves. | |
| * leaves: The branches and twigs hereabouts are laded with reddening autumnal leaves. | |
| * leaves: The branches and twigs hereabouts are laded with reddening autumnal leaves. | |
| * | |
| * But this would be the standard library behaviour. By removing the duplicates direct | |
| * objects, as this module does, we get simply: | |
| * | |
| * >X LEAVES, TWIGS AND BRANCHES | |
| * The branches and twigs hereabouts are laded with reddening autumnal leaves. | |
| * | |
| * However, there may be occasional instances where you want a minimally implemented | |
| * object to represent several different items, for example passing small animals | |
| * mentioned only in an atmosphereList. In such a case you may simply want an Unthing | |
| * that reports that the object in question isn't here. E.g., you might ideally like | |
| * A single Unthing which can generate: | |
| * | |
| * X OWL AND FOX | |
| * owl: it's not in sight. | |
| * fox: it's not in sight. | |
| * | |
| * For this purpose this module defines a MultiName class for which duplicates are | |
| * not removed from the list of direct objects. | |
| * | |
| * | |
| */ | |
| ModuleID | |
| name = 'Duplicate Dobj Handler' | |
| byLine = 'by Eric Eve' | |
| htmlByLine = 'by <A href="mailto:eric.eve@hmc.ox.ac.uk">Eric Eve</a>' | |
| version = '1.1' | |
| // showCredit { "<<name>> <<htmlByLine>>"; } | |
| ; | |
| /* Define an extra property and method for use with MultiName. This is to allow | |
| * MultiName objects to be reset at the start of every turn. */ | |
| modify libGlobal | |
| multiNameList = [] | |
| resetNameList { | |
| foreach(local cur in multiNameList) | |
| { | |
| cur.names = []; | |
| cur.nameIdx = 0; | |
| } | |
| } | |
| ; | |
| /* | |
| * You can control whether any duplicate direct objects are culled from the list by | |
| * setting gameMain.allowAllDuplDobjs to nil | |
| * There's probably not a lot of point in including this module at all if you set this | |
| * gameMain.allowAllDuplDobjs to true, unless you wanted to offer it as an interface | |
| * option for players, and hence to include a command that toggles this value. | |
| */ | |
| modify GameMainDef | |
| allowAllDuplDobjs = nil | |
| ; | |
| /* Cache a list of MultiName objects for fast processing each turn */ | |
| PreinitObject | |
| execute | |
| { | |
| local obj; | |
| for(obj = firstObj(MultiName) ; obj <> nil; obj = nextObj(obj, MultiName)) | |
| libGlobal.multiNameList += obj; | |
| } | |
| ; | |
| /* Set up a prompt daemon to reset each MultiName object each turn */ | |
| InitObject | |
| execute { new PromptDaemon(libGlobal, &resetNameList); } | |
| ; | |
| /* A MultiName is an object whose name is always identical to the | |
| * words the player enters to refer to it (provided the player's | |
| * entry matches its vocabulary). So for example, if we define: | |
| * | |
| * MultiName, Unthing | |
| * vocabWords_ = 'red blue green ball' | |
| * desc = "\^<<theName>> isn't here. " | |
| * ; | |
| * | |
| * Then >X RED BALL will result in "The red ball isn't here", while | |
| * >X BLUE BALL will result in "The blue ball isn't here." | |
| * | |
| * Moreover >X RED BALL AND BLUE BALL would result it: | |
| * red ball: The red ball isn't here. | |
| * blue ball: the blue ball isn't here. | |
| * | |
| * Note that MultiName objects are NOT removed from the list of direct | |
| * objects, even when they are duplicated in the list. | |
| * | |
| * Note also that if the standard Thing Template is used with | |
| * a MultiName, the name property defined via the template will | |
| * almost be overridden. | |
| * | |
| */ | |
| MultiName : Thing | |
| /* Use matchNameCommon to build a list of the names by which | |
| * the player has referred to this item as the direct object | |
| * of a command. | |
| */ | |
| matchNameCommon(origTokens, adjustedTokens) | |
| { | |
| local newname = ''; | |
| foreach(local tok in adjustedTokens) | |
| { | |
| if(dataType(tok) == TypeSString) | |
| newname += (tok + ' '); | |
| } | |
| newname = (newname.substr(1, newname.length - 1)).toLower; | |
| names += newname; | |
| return inherited(origTokens, adjustedTokens); | |
| } | |
| /* The next two properties are used internally as part of the | |
| * implentation and should not be overriden. Note that they | |
| * are in any case reset to these initial values at the start | |
| * of each turn. | |
| */ | |
| nameIdx = 0 | |
| names = [] | |
| /* The rename method is called by TAction.doActionMain each | |
| * time it encounters this object in its dobjList. This ensures | |
| * that each time this object is referenced, it has the name | |
| * the player used to refer to it. It should not be necessary | |
| * to call this method in your own code. | |
| */ | |
| rename { name = names[++nameIdx]; } | |
| /* We set includeDuplicateDobjs to true to prevent the modified TAction from | |
| * removing multiple instances of the same MultiName from its list of | |
| * direct objects. | |
| */ | |
| includeDuplicateDobjs = true | |
| ; | |
| /* This modification to TAction causes duplicate direct objects to be removed | |
| * from the list of direct objects before processing, unless their | |
| * includeDuplicateDobjs property is true. | |
| */ | |
| modify TAction | |
| /* | |
| * The removeDuplDobjs can be set to nil on specific Action classes to force | |
| * particular actions always to act multiple times on a multiply supplied | |
| * direct object. E.g., if a puzzle involves pushing a series of buttons | |
| * in a given sequence, then you would not want a command like | |
| * | |
| * >PRESS RED BUTTON, GREEN BUTTON, BLUE BUTTON, RED BUTTON | |
| * | |
| * To have the second instance of "red button" removed from its list of direct | |
| * objects. One way to ensure that it was not would be to set PushAction.removeDuplDobjs | |
| * to nil. Note, however, that you can also control what classes of objects or individual | |
| * objects the duplicate direct object removal applies to. | |
| */ | |
| removeDuplDobjs = true | |
| replace doActionMain() | |
| { | |
| /* Note that the reason we cannot simply use | |
| * dobjList_ = dobjList_.getUnique here is that this would not | |
| * cater for direct objects where duplicates are allowed (i.e. for which | |
| * includeDuplicateDobjs is true). | |
| */ | |
| /* What this rather complicated expression does is to replace | |
| * The existing dobjList_with a subset of those objects for | |
| * which includeDuplicateDobjs is true, or which are the | |
| * the first instances of a particular object in the list. | |
| * | |
| * This is complicated by the fact that dobjList_ contains a | |
| * list, not of objects, but of ResolveInfo objects, which will | |
| * all be distinct even if the game objects to which they refer | |
| * are not. We therefore have to look at the obj_ property of | |
| * these ResolveInfo objects, and not just the ResolveInfo objects | |
| * themselves. | |
| */ | |
| if(removeDuplDobjs && !gameMain.allowAllDuplDobjs) | |
| dobjList_ = dobjList_.subset({x: x.obj_.includeDuplicateDobjs | |
| || dobjList_.indexOf(x) == | |
| dobjList_.indexWhich({y: y.obj_ == x.obj_}) }); | |
| /* | |
| * Set the direct object list as the antecedent, using the | |
| * game-specific pronoun setter. Don't set pronouns for a | |
| * nested command, because the player didn't necessarily refer | |
| * to the objects in a nested command. | |
| */ | |
| if (parentAction == nil) | |
| gActor.setPronoun(dobjList_); | |
| /* we haven't yet canceled the iteration */ | |
| iterationCanceled = nil; | |
| /* run through the sequence once for each direct object */ | |
| for (local i = 1, local len = dobjList_.length() ; | |
| i <= len && !iterationCanceled ; ++i) | |
| { | |
| /* make this object our current direct object */ | |
| dobjCur_ = dobjList_[i].obj_; | |
| /* This statement added to deal with MultiName objects */ | |
| if(dobjCur_.ofKind(MultiName)) | |
| dobjCur_.rename; | |
| /* announce the object if appropriate */ | |
| announceActionObject(dobjList_[i], len, whichMessageObject); | |
| /* run the execution sequence for the current direct object */ | |
| doActionOnce(); | |
| /* if we're top-level, count the iteration in the transcript */ | |
| if (parentAction == nil) | |
| gTranscript.newIter(); | |
| } | |
| } | |
| ; | |
| /* By default we leave all duplicate direct objects in the direct object list | |
| * unless they're Decoration or Distant objects. This automatically ensures that | |
| * commands of the type >PUSH RED BUTTON, GREEN BUTTON, BLUE BUTTON, RED BUTTON | |
| * will be executed as expected, while also taking care of the >X LEAVES, TWIGS AND | |
| * BRANCHES case, where 'leaves', 'twigs' and 'branches' are three names for the name | |
| * Decoration object. | |
| * | |
| * These defaults may be overriden as desired to make them appropriate for a particular | |
| * game. Simply define includeDuplDobjs to be true on all classes and/or objects for | |
| * which you want duplicates left in the list of a command's direct objects, and nil | |
| * on all those for which you want duplicates suppressed. | |
| */ | |
| modify Thing | |
| includeDuplDobjs = true | |
| ; | |
| modify Decoration | |
| includeDuplDobjs = nil | |
| ; | |
| modify Distant | |
| includeDuplDobjs = nil | |
| ; | |
Xet Storage Details
- Size:
- 10.4 kB
- Xet hash:
- 930efe052deae42308affc7f76375d9e97b8403467887f1c71c3669d87fa5b45
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.