bl791's picture
download
raw
10.9 kB
/* Copyright (c) 2000 by Kevin Forchione. All Rights Reserved. */
/*
* TADS ADV.T/STD.T LIBRARY EXTENSION
* AGAIN.T
* version 2.0
*
* This module implements a solution to the <<again>> bug that
* exists in TADS 2. <<again>> is limited by the fact that TADS
* repeats the command based on command objects and not player
* command. This can cause problems with commands directed toward
* indistinguishable objects.
*
* You see two apples here.
*
* >eat apple
* That was delicious!
* >g
* You can't repeat that command.
*
* Again.t remedies this by capturing the command word list
* passed to preparseCmd(), then later converting it into a
* command string and prefixing it with the actor vocabulary.
*
* You see two apples here.
*
* >eat apple
* That was delicious!
* >g
* That was delicious!
* >g
* I don't see any apple here.
*
*
* NOTE that capturing the actual words used to address the actor
* would complicate the solution. There is, however, the possibility
* that a parser-generated error message for an "again" command
* that refers to an actor might use words not contained in the
* command. For example:
*
* >x baggins
* blah blah blah
* baggins has left the area.
*
* >g
* There is no bilbo baggins of hobbiton here.
*
*----------------------------------------------------------------------
* REQUIREMENTS
*
* + HTML TADS 2.5.0 or later
* + Should be compatible with ADV.T, WorldClass, Pianosa
* libraries. Alt users will find that version 1.0.6 implements
* a similar solution.
* + Should be #included after the main library modules.
*
*----------------------------------------------------------------------
* IMPORTANT LIBRARY INTERFACE AND MODIFICATION
*
* + preparseCmd()
* + preCommand()
* + compoundWords - special note, if you add a new compoundWord
* you must add an equivalent replaceWith() for it in the
* cvtFromCompound() method of the Stringizer class.
*
*----------------------------------------------------------------------
* 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
*
* 06-06-00: Creation.
* 16-06-00: Added conversion of compound words.
*/
#ifndef __AGAIN_MODULE_
#define __AGAIN_MODULE_
#pragma C+
/*
* The preparseCmd() function saves all command word lists except for
* <<again>> or <<g>> in global.cmdWordList. If the command is
* <<again>> or <<g>> we replace it with the stored global command
* string.
*
* It returns true to indicate that processing is to continue with the
* command unchanged.
*/
preparseCmd: function(cmd) {
if (length(cmd) == 1
&& (cmd[1] == 'g' || cmd[1] == 'again')) {
parserReplaceCommand(global.cmdString);
} else {
global.cmdWordList = cmd;
}
return true;
}
/*
* The preCommand() function builds the command string that is then
* stored on global.
*/
preCommand: function(actor, verb, doList, prep, iobj) {
// Build command string only if command was player generated.
if (length(global.cmdWordList)) {
local str;
str = Stringizer.buildCmdString(actor, global.cmdWordList);
global.cmdString = str;
}
}
/*
* The Stringizer class converts a word list to a string. In addition
* it handles the conversion of TADS special words and the appending of
* actor vocabulary to the front of the string to create a command
* string.
*/
class Stringizer: object
buildCmdString(actor, cmdWordList) = {
local actorWordList, actorString, cmdWordString, cmdString;
cmdWordList = self.cvtFromSpec(cmdWordList);
cmdWordString = self.stringize(cmdWordList);
cmdWordString = self.cvtFromCompound(cmdWordString);
/*
* NOTE: getActorVocab() assumes that the actor isn't numbered. If
* you find yourself having difficulty with this option #define
* USE_ACTOR_SDESC.
*/
#ifdef USE_ACTOR_SDESC
actorString = self.getActorSdesc(actor);
#else /* USE_ACTOR_SDESC */
actorWordList = self.getActorVocab(actor);
actorString = self.stringize(actorWordList);
#endif /* USE_ACTOR_SDESC */
cmdString = actorString + ', ' + cmdWordString;
return cmdString;
}
cvtFromSpec(wordList) = {
local i, len;
len = length(wordList);
for (i = 1; i <= len; ++i) {
switch(wordList[i]) {
case ',':
wordList[i] = 'and';
break;
case 'A':
wordList[i] = 'all';
break;
case 'X':
wordList[i] = 'but';
break;
case 'I':
wordList[i] = 'it';
break;
case 'T':
wordList[i] = 'them';
break;
case 'M':
wordList[i] = 'him';
break;
case 'R':
wordList[i] = 'her';
break;
case 'Y':
wordList[i] = 'any';
break;
case 'B':
wordList[i] = 'both';
break;
case 'N':
wordList[i] = 'one';
break;
case 'P':
wordList[i] = 'ones';
break;
}
}
return wordList;
}
cvtFromCompound(str) = {
str = replaceWith(str, '%<onto%>', 'on to');
str = replaceWith(str, '%<into%>', 'in to');
str = replaceWith(str, '%<inbetween%>', 'in between');
str = replaceWith(str, '%<downin%>', 'down in');
str = replaceWith(str, '%<downon%>', 'down on');
str = replaceWith(str, '%<upon%>', 'up on');
str = replaceWith(str, '%<outof%>', 'out of');
str = replaceWith(str, '%<offof%>', 'off of');
str = replaceWith(str, '%<i_wide%>', 'i wide');
str = replaceWith(str, '%<i_tall%>', 'i tall');
str = replaceWith(str, '%<waitfor%>', 'wait for');
str = replaceWith(str, '%<waituntil%>', 'wait until');
return str;
}
stringize(wordList) = {
local i, len, str = '';
len = length(wordList);
for (i = 1; i <= len; ++i) {
str += wordList[i];
if (i != len)
str += ' ';
}
return str;
}
getActorSdesc(actor) = {
local stat, str, actorWordList;
if (actor == parserGetMe()) {
actorWordList = self.getActorVocab(actor);
str = self.stringize(actorWordList);
} else {
stat = outcapture(true);
actor.sdesc;
str = outcapture(stat);
}
return str;
}
getActorVocab(actor) = {
local actorWordList = [];
actorWordList += getwords(actor, &adjective);
if (actor.isThem)
actorWordList += getwords(actor, &plural)[1];
else actorWordList += getwords(actor, &noun)[1];
return actorWordList;
}
;
#ifndef __REPLACEWITH_MODULE_
#define __REPLACEWITH_MODULE_
#define RW_REPLACE_ONCE 1
#define RW_MATCH_WORD 2
#define RW_MATCH_CASE 4
#define RW_RET_NIL 8
/*
* replaceWith(value, target, replacement, flags)
*
* The function searches the value string, replacing the target string
* with the replacement string.
*
* Bit-flags can be passed to control the search.
*
* RW_REPLACE_ONCE replace only one occurrence of the target in the
* value string.
*
* The default for replaceWith() is to replace all occurrences
* of the target in the value string.
*
* RW_MATCH_WORD target must match whole words. For example:
*
* target 'get in' will search for '%<get>% *%<in%>'
* which will match 'get in the chair', but not
* 'get into the chair'
*
* RW_MATCH_CASE target must match the case in value.
*
* The default for replaceWith() is case-insensitive. A target
* string of 'get into' will match on 'GET INTO THE CAR' as
* well as 'Get into the car' unless RW_MATCH_CASE is used.
*
* RW_RET_NIL function returns nil if no match for the target found
*
* The default for replaceWith() returns the value unchanged.
* Using RW_RET_NIL will return the value only if replacement
* occurred; otherwise the function will return nil.
*/
replaceWith: function(value, target, replacement, ...)
{
local ret, new_value = '';
local valuesave, targetsave, replacementsave;
local flags = 0;
if (argcount > 3) flags = getarg(4);
if ((flags & RW_MATCH_WORD)!= 0)
{
local tmptarget = '%<';
tmptarget += replaceWith(target, ' ', '%> *%<');
tmptarget += '%>';
target = tmptarget;
}
do
{
if ((flags & RW_MATCH_CASE) == 0)
{
valuesave = value;
targetsave = target;
replacementsave = replacement;
value = lower(value);
target = lower(target);
replacement = lower(replacement);
}
ret = reSearch(target, value);
if ((flags & RW_MATCH_CASE) == 0)
{
value = valuesave;
target = targetsave;
replacement = replacementsave;
}
if (ret)
{
local len, tmp = '';
len = length(value) + 1;
if (ret[1] - 1)
tmp += substr(value, 1, ret[1]-1);
tmp += replacement;
new_value += tmp;
if (len - (ret[1]+ret[2]))
value = substr(value, ret[1]+ret[2], len - (ret[1]+ret[2]));
else
value = '';
if ((flags & RW_REPLACE_ONCE) != 0) break;
}
else if ((flags & RW_RET_NIL)!= 0
&& new_value == '')
return nil;
}
while( ret != nil);
new_value += value;
return new_value;
}
#pragma C-
#endif /* __REPLACEWITH_MODULE_ */
#endif /* __AGAIN_MODULE_ */

Xet Storage Details

Size:
10.9 kB
·
Xet hash:
16487e4fa8722bafcd866d87f3b01870efe8fb9b39160904cfd05dd6ebdfa95c

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.