/* footnote.t -- simple footnote allocation library written by david etherton (etherton@sdd.hp.com) do whatever you want to with this. requires TADS 2.1 or later because of the use of the 'modify' feature. footnotes are really easy to overuse, so be careful out there! common sense says that anything in a footnote should be able to be safely ignored by the player. */ /* example usage: desk: fixeditem, surface noun = 'desk' adjective = 'fine' 'oak' location = startroom sdesc = "fine oak desk" ldesc = { "The desk is stained a deep brown color, and has that wonderful rustic appeal of a Norman Rockwell painting. "; makeNote('In fact, this entire room looks like an explosion at a Normal Rockwell factory.'); } ; >examine the desk The desk is stained a deep brown color, and has that wonderful rustic appeal of a Norman Rockwell painting. [3] >footnote 3 [3]. In fact, this entire room looks like an explosion at a Norman Rockwell factory. */ /* local static state for footnote library. */ fnState: object highest = 0 /* highest footnote allocated so far */ badTries = 0 /* number of times bad footnote number tried */ text = [] /* accumulated footnote text */ ; /* makeNote is a function which accepts footnote text and produces, as a side effect, the resulting footnote reference number in brackets. Its main purpose is to associate a block of text with a dynamically assigned footnote number which can be retrieved later with the 'footnote' verb defined below. Passing the same block of text always produces the same footnote number as output. */ makeNote: function (noteText) { local foundNum; /* see if the footnote has already been allocated. */ for (foundNum:=1; foundNum<=fnState.highest; foundNum++) if (noteText = fnState.text[foundNum]) /* already seen? */ break; /* yes, leave loop */ /* allocate a new footnote if this is the first time it's been seen */ if (foundNum >= fnState.highest) { ++ fnState.highest; /* get next note number */ fnState.text += [noteText]; /* save text in a list */ } /* display the reference number in brackets. */ "["; say(foundNum); "]"; } /* footnote is a new verb we're declaring. The verb and sdesc fields are pretty standard; the former supplies the actual words the players can type to get this verb, and the latter is used by the parser itself occasionally. action(actor) defines what happens when the verb is supplied with no direct or indirect objects; in this case, we want to inform the player of the proper usage. Finally, doAction defines what method in the direct object (in this case, the generic number object) gets called to handle this verb; in this case, 'doFootnote' will be the method which is called. */ footnote: deepverb verb = 'footnote' 'note' sdesc = "footnote" action(actor) = "You need to include a footnote number." doAction = 'Footnote' ; /* basicNumObj is an object supplied by TADS in adv.t which we are modifying to include support for new footnotes. The verDoFootnote method indicates that this object knows how to handle the footnote verb; therefore, 'footnote lamp' would produce a parser error since a lamp would probably not inherit from basicNumObj and as such would not define a verDoFootnote method. On the other hand, 'footnote 4' would cause basicNumObj (actually, numObj, which directly inherits from it) to receive a verDoFootnote message--which it knows how to handle! Since verDoFootnote produces no output, the parser will automatically call the doFootnote method to complete processing. The doFootnote method checks to see if the footnote is in range; if it is not in range, it prints an error message. If the user has obviously been trying a lot of bad footnote numbers, it also offers a suggestion to cease and desist. On the other hand, if the reference is valid, we display the footnote number along with its associated text. In either case, we do nothing special besides return to the parser, so the footnote is counted as a normal turn. If you don't want footnotes to count as a turn, make 'footnote' about inherity from sysverb instead of deepverb. */ modify basicNumObj verDoFootnote(actor) = { } /* always allowed */ doFootnote(actor) = { /* footnote out of range? */ if (self.value < 1 or self.value > fnState.highest) { if (++fnState.badTries = 5) "Footnotes aren't assigned until they are encountered in the game. Repeatedly guessing footnotes will accomplish nothing."; else "No such footnote."; } else { /* display the footnote reference & text */ "["; say(self.value); "].\ "; say(fnState.text[self.value]); } } ;