/* footnote.t -- simple footnote allocation library
written by david etherton (
[email protected])
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]);
}
}
;