How to remap literal action into a topic action?

I have a Consultable object which provides various kinds of information implemented as ConsultTopics. It’s a tablet and therefore some players tend to enter command “type on tablet” instead of "consult tablet about " so I’m wondering how can I remap TypeLiteralOn action into ConsultAbout action. The problem is that remap or replaceAction macros are not powerful enough. If I use replaceAction it expects that I know the object, but I have only a literal string which is not resolved into concrete object nor topic. Is there some sane way to stop current action and replace it with a completly new one I will provide as a string ('consult tablet about ’ + gLiteral) to be parsed from scratch? Thanks for suggestions.

dobjFor(TypeLiteralOn) { verify() { } action() { say(gLiteral); replaceAction(ConsultAbout, self, <what here?>); } }

One way to do it might be a StringPreParser() function.

Here’s one that turns a command-line entry of enter into a valid travel direction…

// treat Enter as go north if in someRoom StringPreParser doParsing(str, which) { if(gLocation == someRoom) { if(str.toLower() == 'enter') str = 'go north'; } return str; } ;

You’d have to do some string manipulation to break up the incoming str into words, and you’d have to anticipate word position in the command line to know which is the iobj and which is the dobj, so your intercept may not be 100% accurate 100% of the time, but with some diligent coding you might be able to come up with a workable solution.

Jerry

Unless you need the TypeLiteralOn action for some other purpose in your game, the easiest way to deal with this might be to define a TypeTopicOn action which commands of the form TYPE X ON Y use instead, or perhaps to define a new VerbRule that makes TYPE X ON Y use the ConsultAbout action (which modifying the existing TypeLiteralOn VerbRule so that nothing matches it).

Otherwise, I think you’d need to do something like the following:

class DynTopic: Topic
   construct(voc)
   {
       vocabWords = voc;
       inherited;
    }
;

Then your code would become:

 dobjFor(TypeLiteralOn)
    {
        verify() { }
        action()
        {
            say(gLiteral);
            replaceAction(ConsultAbout, self, new DynTopic(gLiteral));
        }
    }

But this is untested, and may require more tweaking to get it to work.

Thank you Jerry, I know string preparser and it’s a nice swiss army knife in some situations. But I doubt it’s a good solution in my case, because I’m really trying to catch and remap one specific situation on one object in one situation while I use TypeLiteral with other objects and other situations in standard way. In addition, I’m transposing my question into English, but I’m solving my problem in translated TADS and VerbRules are more complicated than in English. For those reasons I’m trying to find a solution at the action stage where the dirty work is already done by TADS’s parser and I know the action and object for sure. Trying to imitate this in preparser from scratch would be too fragile I’m afraid. Sorry, I should mention this beforehand.

No luck with this as such. But you kicked me into actually turning on my virtual machine with windows and debugger and as I’ve stepped through the library code and find out, that it fails in the actor.t around line 2871, where is this:[code] /*
* Match an individual item from our match list to the given
* ResolvedTopic object. We’ll check each object in the resolved
* topic’s “in scope” and “likely” lists.
/
findMatchObj(obj, rt)
{
/
check the “in scope” list */
if (rt.inScopeList.indexOf(obj) != nil)
return true;

    /* check the "likely" list */
    return (rt.likelyList.indexOf(obj) != nil);
}

[/code]
Problem is that meanwhile obj is the correct game object (suspiciousContainer), rt.inScopeList contains just the DynTopic so there is no match. Normally there should be Topics or resolved objects which match the literal. If I for example call replaceAction(ConsultAbout, self, suspiciousContainer); than it works, but that way I anticipate correct object without paying attention to literal player entered so that’s not good.

I don’t know exactly, but it seems to me that I can’t just pass DynTopic that way because it doesn’t get resolved to an actual game objects. This part is quite complicated and I still don’t understand it.

But as I’ve stepped through the debugger, I’ve probably found what I was instinctively searched for and so far it seems to work exactly as I need. That means I can replace action in a way that it gets reparsed again:[code]
dobjFor(TypeLiteralOn)
{
verify() { }
action()
{
/* tokenize the replacement command and get the rest of command line */
cmdTokenList = cmdTokenizer.tokenize('consult tablet about ’ + gLiteral);
nextCommandTokens = gAction.tokenList.sublist(gAction.lastTokenIndex + 1);

        /* retry parsing the edited token list */
        throw new RetryCommandTokensException(cmdTokenList + nextCommandTokens);
    }

[/code]

RetryCommandTokensException is normally used in oops situation to reparse corrected command line. It works even in situation, where I have a compound command like “type literal on tablet, then look around. inventory”. That means nextCommands doesn’t get lost. There is one situation I didn’t tested - in exec.t around line 242 there are nextCommandTokens and extraTokens. ExtraTokens are automatically added in the exception handler (exec.t, line 538) and I can’t figure out in which situation (what the player must type) extraTokens will be nonempty. Because in the example above (cmd1, then cmd2. cmd3) all is a part of one parser match so cmd2 and 3 get postponed in nextCommandTokens and not in extraTokens. So I’m not sure whetever I can’t trigger a situation when extraTokens got added twice.

Thank you both for your support.