adv3lite: Advancing an EventList

I have two NPCs in one location. An important topic of conversation might be addressed to either of them, so each of them has a similar AskTellTopic, which is also a StopEventList. If the ask/tell is addressed to NPC #1, I want to advance the topic that belongs to NPC #2, and vice-versa. It would make no sense for NPC #2 to respond as if he hadn’t heard the preceding conversation (and vice-versa).

The problem is, I’m getting a stack overflow. I don’t know if this is a library bug, if it’s my bad code, or if it’s an inherent limitation of the StopEventList design. Below is the code (hidden, as it’s a sort of minor spoiler for the game). The first AskTellTopic is in the ActorState of NPC #1, the second in the ActorState of NPC #2.

[spoiler][code]++ floggLamborghiniResponse: AskTellTopic, StopEventList [lamborghini]
[
'I noticed that bright red Lamborghini out in the parking lot, you comment.
<.p>That fabulous little toy belongs to him, Flogg says, pointing his
bony thumb at Grabby.<<grabbyLamborghiniResponse.advanceState()>>
<.p>Grabby puffs out his chest proudly. Ain’t it a honey? It’s mine. I paid
cash, too, I’ll have you know. ',
'If you want to know anything more about that car, Flogg says, you may
as well ask him. ’
]
;

++ grabbyLamborghiniResponse: AskTellTopic, StopEventList [lamborghini]
[
'I noticed that bright red Lamborghini out in the parking lot, you comment.
<.p>Grabby<<floggLamborghiniResponse.advanceState()>> puffs out his chest
proudly. Ain’t it a honey? It’s mine. I paid
cash, too, I’ll have you know. ',

    '<q>You must be proud of that bright red sports car,</q> you say.
    <.p><q>Oh, I am, I am!</q> Grabby responds, practically bouncing up and down
    in his chair. <q>If anything happened to it, I just don\'t know what I\'d do.
    I\'d just about go crazy!</q> '
]

;[/code][/spoiler]
As far as I can see by looking at the library code, advanceState simply increments curScriptState. It shouldn’t be doing anything else. But it appears that somehow, in incrementing the state of the list, the library is also evaluating the embedded expression in the first item in the list. This shouldn’t be happening, should it?

If it’s an inevitable effect of the library’s code, how can I work around it? Possibly with an AltTopic…

My understanding is that the entire set of single-quoted responses in an eventList gets evaluated once, on first read of the list.

If you want the evaluation to take place each time the specific response is up in the rotation, use a double-quoted string…

eventList = 
[
   'some text',

    {:"...some text with <<an evaluated expression>>..."},

    'more text'
]

Jerry

Hmm. Could be true, but even so, I don’t quite see how that would cause a stack overflow at run-time, when all that’s happening is that advanceState is coded as ++curScriptState, which is what the library does. The first read of the first list should do nothing but advance the curScriptState variable of the second list – it shouldn’t trigger an evaluation of that list. In fact, given that that’s the only code in advanceState, I would tend to think it can’t cause an evaluation of the contents of the second list … and even if it did, again, that would only change a variable in the first list, it wouldn’t cause the first element of the first list to get evaluated again, because in a StopEventList the first element is only going to be triggered once, and at that point it has already been triggered.

Or something like that. Obviously I’m wrong, but I don’t understand how and why I’m wrong.

Anyway, I did solve the problem by using an AltTopic on each AskTellTopic and using the embedded expression to set the isActive value of the other AltTopic to true.

Jerry is right that all the strings in a list get evaluated at once. In fact this happens whenever there’s a reference to the list in code. This is a feature of the TADS 3 language and not specific to adv3Lite. There’s a warning about this in the section on “More on evaluation timing, and a warning on side effects” towards the end of the String Literal section of the System Manua (which isn’t very helpful if you don’t know it’s there). There’s also a discussion of this issue on pp. 141-3 of Learning TADS 3 with adv3Lite, and a warning about using embedded expressions in single-quoted strings in EventLists in the chapter on EventLists in the adv3Lite Library Manual.

What’s going in your code is, I suspect, a vicious loop. The eventList property of floggLamborghiniResponse contains a single-quoted string which contains the embedded expression <<grabbyLamborghiniResponse.advanceState()>>. This will be evaluated along with all the other strings in floggLamborghiniResponse.eventList as soon as any piece of code refers to floggLamborghiniResponse.eventList. The embedded expression almost certainly contains code that references grabbyLamborghiniResponse.eventList, which in turn will cause evaluation of the embedded expression <<floggLamborghiniResponse.advanceState()>> which in turn almost certainly contains code that references floggLamborghiniResponse.eventList, which in turn will cause evaluation of the embedded expression <<grabbyLamborghiniResponse.advanceState()>> and so on ad infinitum, thus setting up a viciously circular loop which causes a stack overflow. A rather subtle trap, perhaps, but this nonetheless is almost certainly what is happening.

That all said, the simplest solution to your problem may be to use a SyncEventList (also described in the EventLists chapter of the adv3Lite manual), since this appears to be the kind of situation for which it was devised.