/* 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]);
			}
		}
;