/* Copyright (c) 2000 by Kevin Forchione. All Rights Reserved. */
/*
* TADS LIBRARY EXTENSION
* TMORPH.T
* version 3.0
*
* tmorph.t provides a simple randomised "text morphing"
* mechanism for TADS users. (Text morphing is the production
* of randomised print strings).
*
*
* Random Setting
* --------------
*
* To use this function embed the text morphing syntax within the text
* string you wish to display. For example:
*
* "[|A ball/Balls] of searing flame burst[s/]
* out of your magic ring, rebound[s/] off of the ground, and
* vaporize[s/] the kni[fe/ves] before [it/they]
* can reach you.";
*
* Place the elements to be morphed within [] brackets. No string
* notation should be used inside of the brackets, as everything is
* assumed to be text.
*
* Each separate element of the morphing text should be separated by
* the '/' delimeter. If you do not wish to display any text simply
* leave the element blank, for example: [silver/gold/] watch."
* consists of 3 morphing elements, which would display:
*
* gold watch
* silver watch
* watch
*
* You can and should initialise the random generation at the beginning
* of a display sequence by putting the '|' initialiser at the beginning
* of the morphing sequence, e.g. [|apple/pear/peach]. The value used
* by subsequent text morphing syntax will use the value set by the
* initialiser.
*
* Note that the sequence generated is random unless you specify a
* sequencer_name and style in the initialisation section. For example,
*
* MorphSequencer
* --------------
*
* [ringseq seq|A ball/Balls/A mighty fireball]
*
* will dynamically create a sequencer object with the noun property of
* 'ringseq'. This object will be initialized with a value of 1, which
* means that your text morphing string will begin with #1 in its
* morphing element list and sequentially progress each time the
* text switch with the initialiser is called. When the end of the list
* is reached the last value in the list is displayed from that point
* on. In our example the 1st time, 'A ball' is displayed; the 2nd,
* 'Balls' displays, and all subsequent displays are 'A mighty
* fireball'.
*
* MorphRandomizer
* ---------------
*
* [ringrnd rnd|A ball/Balls/A mighty fireball]
*
* will dynamically create a sequencer object with the noun property of
* 'ringrnd'. Display is produced in a completely random fashion.
*
* MorphModulus
* ------------
*
* [ringmod mod|A ball/Balls/A mighty fireball]
*
* will dynamically create a sequencer object with the noun property of
* 'ringmod'. This object will be initialized with a value of 1, which
* means that your text morphing string will begin with #1 in its
* morphing element list and sequentially progress each time the text
* switch with the initialiser is called. When the end of the list
* is reached display starts over from the beginning.
*
* MorphRedRndSeq
* --------------
*
* [ringrrs rrs|A ball/Balls/A mighty fireball]
*
* will dynamically create a sequencer object with the noun property of
* 'ringrrs'. This object works with a self-reducing random selection
* list that then returns the last displayed element when the list has
* been exhausted.
*
* MorphRedRndMod
* --------------
*
* [ringmod mod|A ball/Balls/A mighty fireball]
*
* will dynamically create a sequencer object with the noun property of
* 'ringmod'. This object works with a self-reducing random selection
* list that then resets the list when the list has been exhausted.
*
* Dynamic Control
* ---------------
*
* For more dynamic control, based on game-state, you should first set
* the value of global.randomHold and remove any initialiser from the
* text morph. For example:
*
* global.randomHold = object.knifeCount;
* [A ball/Balls/A mighty fireball]
*
*----------------------------------------------------------------------
* REQUIREMENTS
*
* + HTML TADS 2.2.6 or later
* + Should be #included after ADV.T and STD.T or WorldClass.t or
* pianosa.t
*
*----------------------------------------------------------------------
* IMPORTANT LIBRARY INTERFACE AND MODIFICATION
*
* None.
*
*----------------------------------------------------------------------
* COPYRIGHT NOTICE
*
* You may modify and use this file in any way you want, provided that
* if you redistribute modified copies of this file in source form, the
* copies must include the original copyright notice (including this
* paragraph), and must be clearly marked as modified from the original
* version.
*
*------------------------------------------------------------------------------
* REVISION HISTORY
*
* 20-Feb-00: Creation.
* 21-Feb-00: Modified to include init in the function call.
*/
/*
* morphFilter: function(str)
*
* Set this filter in commonInit(). It will continue to pass str to the
* formatMorphText() function until the function returns nil.
*
* setOutputFilter(morphFilter);
*/
morphFilter: function(str)
{
local ret;
ret = formatMorphText(str);
while(ret)
{
str = ret;
ret = formatMorphText(str);
}
return str;
}
/*
* formatMorphText: function(str)
*
* This function locates the first occurrence of a "text switch" and
* replaces it with the generated switch value from tm().
*/
formatMorphText: function(str)
{
local i, f1, f2, bit, len, val, ret, grp, newstr = '';
// Find the "text switch"
ret = reSearch('%[([^%[]*/+[^%[]*)%]', str);
if (ret == nil) return nil;
f1 = ret[1];
f2 = ret[2];
// Get the information within the brackets
grp = reGetGroup(1);
bit = grp[3];
// Search for '|' initialiser symbol and set init val
ret = reSearch('(.*)%|', bit);
if (ret != nil)
{
grp = reGetGroup(1);
if (grp != nil)
{
if (grp[2] > 0)
val = grp[3];
else val = 0;
}
else val = nil;
// strip initialiser symbol and any val from bit
bit = substr(bit, ret[2]+1, length(bit));
}
// Translate switches into a single value
bit = tm(bit, val);
// Build new string
if (f1 != 1)
newstr += substr(str, 1, f1-1);
newstr += bit;
if (f1+f2 != length(str))
newstr += substr(str, f1+f2, length(str));
return newstr;
}
/*
* tm: function(str, val)
*
* This function creates a list of single-quote strings from the str
* parameter, using '/' as delimiters. It also sets the
* global.randomHold used to maintain morphing consistency.
*/
tm: function(str, val)
{
local i, s, w = '', list = [];
for (i = 1; i <= length(str); ++i)
{
s = substr(str, i, 1);
if (s == '/')
{
list += w;
w = '';
}
else w += s;
}
list += w;
if (val == 0)
global.randomHold = val;
else if (val != nil)
global.randomHold = morphTracker(val, length(list));
/*
* morphTracker: function(str, len)
*
* Function creates a dynamic object using the sequence_name provided
* by the initialisation area of the text morph. This object is
* initialised with val and given the noun vocabulary of the
* sequence_name.
*
* If no val was provided then the object is initialised for position
* 1 in the list of morphing elements.
*/
morphTracker: function(str, len)
{
local tokenList, typeList, objList, mt, tk, ty, o;