| /* TMORPH2.T | |
| * This library imitates Kevin Forchione's tmorph.t library. However, it fixes | |
| * a major problem with the original library, which could not handle strings | |
| * with embedded code (i.e. code in <<>>). This version also handles recursive | |
| * expressions. | |
| * | |
| * For the copyright notice to the original tmorph.t, see the end of this | |
| * file. While this file is not simply a modified version of the original (I | |
| * wrote most of it from scratch), there are a few portions which are almost | |
| * direct copies. | |
| * | |
| * This library Copyright 2003 by Shadow Wolf. All Rights Reserved. Distribution | |
| * terms are the same as Kevin Forchione's original library: | |
| * | |
| * 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. | |
| */ | |
| /******************************************************* | |
| * Using TMORPH2.T | |
| * | |
| * Morph expressions are embedded within the text string you want to display, | |
| * using square brackets '[]' to delimit them. Each morph expression consists of | |
| * the following elements: | |
| * An optional initializer followed by a pipe '|': The initializer can either | |
| * be a number (typically generated by an embedded expression) or a name and | |
| * type pair. If the pipe is used without an initializer, a random value will | |
| * be used. If no initializer or pipe is used, then the most recently | |
| * generated value will be used. | |
| * | |
| * After the initializer is a list of alternative strings, separated by | |
| * slashes '/'. You can leave an element blank in order to not display any | |
| * text. | |
| * | |
| * This improved version of the text morphing library allows for recursive | |
| * expressions. The innermost morph expression is generated first, with its | |
| * result placed in the outer expression. Evaluated expressions (code in << >> | |
| * delimiters) are also evaluated before the morph expression containing them. | |
| * | |
| * This version also handles HTML tags (by ignoring them), if USE_HTML_PROMPT is | |
| * defined. (I figure anyone writing an HTML game is going to use HTML prompts as a | |
| * minimum.) | |
| * | |
| * Example: | |
| * | |
| * (From Kevin Forchione's original library) | |
| * "[|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."; | |
| * | |
| * The first expression "[|A ball/Balls] has the pipe to initialize the | |
| * sequence, and the remaining expressions use the same value. | |
| * | |
| * Dynamic Control: Since embedded expressions can be evaluated, simply | |
| * include the expression before the pipe: | |
| * | |
| * "[<<object.knifecount>>|A ball/Balls/A mighty fireball]" | |
| * | |
| * No need to modify global variables (I'm not using a global anyway :-) | |
| * | |
| * Recursive Example: | |
| * | |
| * magicRing: clothingItem | |
| * sdesc = "[|gold /magic /plain gold /]ring" | |
| * noun = 'ring' | |
| * adjective = 'plain' 'gold' 'magic' | |
| * putOnDesc = "[ringPutOnDesc rrm|%You% put%s% on | |
| * <<self.thedesc>>./<<caps()>><<self.thedesc>> fits neatly on %your% | |
| * finger./Worn.] " | |
| * location = startroom | |
| * ; | |
| * | |
| * Special Sequences: | |
| * | |
| * There are five types of sequences, encoded with seq, rnd, mod, rrs, rrm. | |
| * | |
| * MorphSequencer (seq) | |
| * -------------------- | |
| * | |
| * [myseq seq|A ball/Balls/A mighty fireball] | |
| * | |
| * Creates a sequence named 'myseq', which produces 'A ball', 'Balls', and | |
| * 'A mighty fireball' in that order, continuing with 'A mighty fireball' for | |
| * all subsequent calls. | |
| * | |
| * MorphRandomizer (rnd) | |
| * --------------------- | |
| * | |
| * [myrnd rnd|A ball/Balls/A mighty fireball] | |
| * | |
| * Produces output in a completely random fashion. Equivalent to not | |
| * specifying a sequence (i.e. pipe only). | |
| * | |
| * MorphModulus (mod) | |
| * ------------------ | |
| * | |
| * [mymod mod|A ball/Balls/A mighty fireball] | |
| * | |
| * Similar to MorphSeqencer, except it wraps around to the beginning when the | |
| * list is exhausted. | |
| * | |
| * MorphRedRndSeq (rrs) | |
| * -------------------- | |
| * | |
| * [myrrs rrs|A ball/Balls/A mighty fireball] | |
| * | |
| * Short for Reducing Random Sequence, I believe. When a particular selection | |
| * is used, it is removed from the list in subsequent calls. (Like dealing | |
| * from a deck). When the list is exhausted, the last displayed choice is used. | |
| * | |
| * MorphRedRndMod (rrm) | |
| * -------------------- | |
| * | |
| * [myrrm rrm|A ball/Balls/A mighty fireball] | |
| * | |
| * Like rrs above, except that when the list is exhausted it is re-shuffled. | |
| * | |
| */ | |
| #ifndef __TMORPH_MODULE_ | |
| #define __TMORPH_MODULE_ | |
| // The following module by Kevin Forchione is required for parsing the | |
| // initializer strings. Get it at www.ifarchive.org or mirrors, as | |
| // if-archive/programming/tads2/examples/parseword.t | |
| #include <parseword.t> | |
| #pragma C+ | |
| class morphExpr: object | |
| expr = '' // The current expression string | |
| evaluate = { | |
| local initial, str; | |
| local lst, ret, i, w, s, intag; | |
| // Split expression into initializer and list portion | |
| str = self.expr; | |
| ret = reSearch('%|', str); | |
| if (ret == nil) { | |
| initial = nil; | |
| } else { | |
| initial = substr(str, 1, ret[1] -1); | |
| str = substr(str, ret[1] + 1, length(str)); | |
| } | |
| // Create list of alternatives (basically copied from tmorph.t): | |
| lst = []; w = ''; intag = nil; | |
| for (i = 1; i <= length(str); i++) { | |
| s = substr(str, i, 1); | |
| #ifdef USE_HTML_PROMPT | |
| if (s == '<') {intag = true; w += s;} | |
| else if (s == '>' and intag) {intag = nil; w += s;} | |
| else | |
| #endif | |
| if (not intag and s == '/') { | |
| lst += w; w = ''; | |
| } else w += s; | |
| } | |
| lst += w; | |
| if (initial != nil) | |
| self.parseInitializer (initial, length(lst)); | |
| return lst[tmorph.choice]; | |
| } | |
| parseInitializer(str, len) = { | |
| // Much of this method is a near-copy of the morphTracker function | |
| // in Kevin's original tmorph.t | |
| local tk, o, mt = 'rnd'; | |
| local tokenList = parseWord(str); | |
| if (length(tokenList) < 1) { | |
| tmorph.choice = _rand(len); | |
| return; | |
| } | |
| tk = tokenList[1]; | |
| if (length(tokenList) == 2) mt = tokenList[2]; | |
| // You can use a number or evaluated expression as an initializer! | |
| if (cvtnum(tk) > 0) { | |
| o = cvtnum(tk) % len; | |
| if (o == 0) o = len; | |
| tmorph.choice = o; | |
| return; | |
| } | |
| o = tmorph.getSequence(tk); | |
| if (o == nil) { | |
| switch (mt) { | |
| case 'seq': | |
| o = MorphSequencer.instantiate(tk, len); | |
| break; | |
| case 'mod': | |
| o = MorphModulus.instantiate(tk, len); | |
| break; | |
| case 'rrm': | |
| o = MorphRedRandMod.instantiate(tk, len); | |
| break; | |
| case 'rrs': | |
| o = MorphRedRandSeq.instantiate(tk, len); | |
| break; | |
| default: | |
| tmorph.choice = _rand(len); | |
| return; | |
| } | |
| } | |
| tmorph.choice = o.getval; | |
| } | |
| ; | |
| // tmorph: | |
| // This object carries the necessary global state for the library. I could | |
| // have modified global, but I prefer not to clutter the namespace. | |
| tmorph: object | |
| choice = 1 // choice variable, set by user or | operator | |
| curr = nil // Current morph expression | |
| stack = [] // stack of previous morph expressions | |
| push = { | |
| // push current expression onto the stack, begin new expr | |
| if (self.curr != nil) | |
| self.stack = [self.curr] + self.stack; | |
| self.curr = new morphExpr; | |
| self.curr.expr = ''; | |
| } | |
| pop = { | |
| if (self.curr != nil) | |
| delete self.curr; | |
| self.curr = nil; | |
| if (car(self.stack)) { | |
| self.curr = car(self.stack); | |
| self.stack = cdr(self.stack); | |
| } | |
| } | |
| sequences = [] | |
| getSequence (tk) = { | |
| // This function is also mostly from tmorph.t | |
| local l = self.sequences; | |
| local c = car(l); | |
| while(c) { | |
| l = cdr(l); | |
| if (c.name == tk) return c; | |
| c = car(l); | |
| } | |
| return nil; | |
| } | |
| inTag = nil // in HTML tag | |
| ; | |
| morphFilter: function (s) | |
| { | |
| local print = ''; | |
| local ret, tmp; | |
| while (s != '') { | |
| #ifdef USE_HTML_PROMPT | |
| ret = reSearch('%[|%]|<|>', s); | |
| #else | |
| ret = reSearch('%[|%]',s); | |
| #endif | |
| if (ret == nil) { // finished | |
| if (tmorph.curr == nil) { | |
| print += s; | |
| return print; | |
| } else { | |
| tmorph.curr.expr += s; | |
| return print; // print the available part | |
| } | |
| } | |
| #ifdef USE_HTML_PROMPT | |
| if (tmorph.inTag) { | |
| tmp = substr(s, 1, ret[1]); | |
| s = substr(s, ret[1]+1, length(s)); | |
| if (tmorph.curr == nil) | |
| print += tmp; | |
| else | |
| tmorph.curr.expr += tmp; | |
| if (ret[3] == '>') tmorph.inTag = nil; | |
| } else if (ret[3] == '<') { | |
| tmorph.inTag = true; | |
| tmp = substr(s, 1, ret[1]); | |
| s = substr(s, ret[1]+1, length(s)); | |
| if (tmorph.curr == nil) | |
| print += tmp; | |
| else tmorph.curr.expr += tmp; | |
| } else if (ret[3] == '>') { | |
| tmp = substr(s, 1, ret[1]); | |
| s = substr(s, ret[1]+1, length(s)); | |
| if (tmorph.curr == nil) | |
| print += tmp; | |
| else tmorph.curr.expr += tmp; | |
| } else | |
| #endif | |
| if (tmorph.curr==nil and ret[3] == '[') // not in an expression | |
| { | |
| print += substr(s, 1, ret[1]-1); | |
| s = substr(s, ret[1]+1, length(s)); | |
| tmorph.push; | |
| } else if (tmorph.curr == nil and ret[3] == ']' ){ | |
| return '\b[ERROR: unbalanced square brackets]\b'; | |
| } else if (ret[3] == '[') { | |
| tmorph.curr.expr += substr(s, 1, ret[1] - 1); | |
| s = substr(s, ret[1]+1, length(s)); | |
| tmorph.push; // push current expr, begin a new one | |
| } else if (ret[3] == ']') { | |
| tmorph.curr.expr += substr(s, 1, ret[1] -1); | |
| s = substr(s, ret[1] +1, length(s)); | |
| tmp = tmorph.curr.evaluate; | |
| tmorph.pop; // pop the stack | |
| if (tmorph.curr == nil) { | |
| print += tmp; | |
| } else { | |
| tmorph.curr.expr += tmp; | |
| } | |
| } else { | |
| return '\b[ERROR: matched a non-bracket!]\b'; | |
| } | |
| } | |
| return print; | |
| } | |
| // MorphSequencer and its derivatives are taken with only slight modification | |
| // from the original tmorph.t by Kevin Forchione | |
| class MorphSequencer: object | |
| len = 0 | |
| val = 0 | |
| name = '' | |
| getval = { | |
| self.val++; | |
| if (self.val > self.len) self.val = self.len; | |
| return self.val; | |
| } | |
| instantiate(tk, l) = { | |
| local x = new MorphSequencer; | |
| x.len = l; | |
| x.name = tk; | |
| tmorph.sequences += x; | |
| return x; | |
| } | |
| ; | |
| class MorphRandomizer: MorphSequencer | |
| getval = { | |
| self.val = _rand(self.len); | |
| return self.val; | |
| } | |
| instantiate(tk, l) = { | |
| local x = new MorphRandomizer; | |
| x.len = l; | |
| x.name = tk; | |
| tmorph.sequences += x; | |
| return x; | |
| } | |
| ; | |
| class MorphModulus: MorphSequencer | |
| getval = { | |
| self.val++; | |
| if (self.val > self.len) self.val = 1; | |
| return self.val; | |
| } | |
| instantiate(tk, l) = { | |
| local x = new MorphModulus; | |
| x.len = l; | |
| x.name = tk; | |
| tmorph.sequences += x; | |
| return x; | |
| } | |
| ; | |
| class MorphRedRandMod: MorphSequencer | |
| rndList = [] | |
| getval = { | |
| local i, ln; | |
| ln = length(self.rndList); | |
| if (ln == 0) { | |
| // (re)build rndList | |
| ln = self.len; | |
| self.rndList = []; | |
| for (i = 1; i <= ln; ++i) | |
| self.rndList += i; | |
| } | |
| self.val = self.rndList[_rand(ln)]; | |
| self.rndList -= self.val; | |
| return self.val; | |
| } | |
| instantiate(tk, l) = { | |
| local x = new MorphRedRandMod; | |
| x.len = l; | |
| x.name = tk; | |
| tmorph.sequences += x; | |
| x.rndList = []; | |
| return x; | |
| } | |
| ; | |
| class MorphRedRandSeq: MorphSequencer | |
| rndList = [] | |
| getval = { | |
| local i, ln; | |
| ln = length (self.rndList); | |
| if (ln == 0) { | |
| return self.val; | |
| } | |
| self.val = self.rndList[_rand(ln)]; | |
| self.rndList -= self.val; | |
| return self.val; | |
| } | |
| instantiate(tk, l) = { | |
| local x = new MorphRedRandSeq; | |
| local i; | |
| x.len = l; | |
| x.name = tk; | |
| tmorph.sequences += x; | |
| x.rndList = []; | |
| for (i = 1; i <= l; ++i) | |
| x.rndList += i; | |
| return x; | |
| } | |
| ; | |
| #endif // TMORPH_MODULE | |
| // Below is the copyright information from the original tmorph.t module. | |
| /* Copyright (c) 2000 by Kevin Forchione. All Rights Reserved. */ | |
| /*---------------------------------------------------------------------- | |
| * 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. | |
| */ | |
Xet Storage Details
- Size:
- 12.1 kB
- Xet hash:
- 6a5c053e89911a6bf1c685f71a55750c28f6da8cd283ca6adc355817b027aa9c
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.