DefaultAnyTopic (adv3Lite)

I may need to email Eric Eve about this, but I figured I’d start here, on the off-chance that someone may have a wonderful suggestion.

One of the things a player ran into in my Comp game is that after the wizard is asleep, commands that are not understood by the parser will always trigger his DefaultAnyTopic. This happens because the Actor’s ActorState mechanism is still active. Here’s an example from my test game. First the output:

The Lab
A not entirely sterile room filled with bubbling retorts, oscilloscopes, and discarded candy wrappers. 

You can see a trash can, a duck, a hammer, and a plank here.

A hamster is curled in the corner, snoring gently. 

>talk to hamster
You now have the hamster’s attention. 

>whistle at duck
The hamster is snoring. Best leave him alone.

The line, “You now have the hamster’s attention,” indicates that the hamster’s conversation nodes have been activated. In the test scenario, that’s a second problem, but we can ignore that. The problem is the last response. Here’s the code:

 + hamster: Actor 'hamster; cute little; rodent critter'
    "It's cuddly. "
;
++ hamsterSnoozing: ActorState
    isInitState = true
    specialDesc = "A hamster is curled in the corner, snoring gently. "
    stateDesc = "Not unlike the proverbial dormouse, the hamster appears to be
        fast asleep. "
;
+++DefaultAnyTopic
    "The hamster is snoring. Best leave him alone. "
;

I tried replacing the DefaultAnyTopic with a DefaultAskTellTopic and a DefaultGiveShowTopic, but that doesn’t help. The parser still tries to route the not-understood input to the hamster, but because he no longer has a DefaultAnyTopic, now the response to “whistle at duck” is, “The hamster does not respond.” Arrggh!

I don’t know enough about adv3Lite’s internals to figure this out. Stepping through stuff in Workbench is possible, but extremely tedious. Also humbling, when you realize the library goes through easily a hundred calls to methods before the output is printed.

It seems to me the basic issue is that the conversation doesn’t end. For example, I tested your scenario:

The Lab

A not entirely sterile room filled with bubbling retorts, oscilloscopes, and discarded candy wrappers.

The duck is here.

A hamster is curled in the corner, snoring gently.

talk to hamster

You now have the hamster’s attention.

whistle at duck

The hamster is snoring. Best leave him alone.

goodbye

You’re not talking to anyone.

whistle at duck

I don’t understand that command.

So I don’t think this is necessarily a bug, but a situation where a conversation is sort of half-implemented – starting, but never stopping. Unless the not-understood input should never be routed to the actor in conversation? That is to say, what’s valid conversational input?

This is an ask/tell/give/show framework. It ought NEVER to trap inputs that don’t begin with ‘ask’, ‘tell’, ‘give’, or ‘show’. When it does so, the practical result is that the player will see a nonsensical response unless the player explicitly says goodbye to the NPC first – and there is no clue at all in the game transcript that would suggest that such a step would be needed. Besides which, forcing the player to do that would be boundlessly annoying.

I might have an idea of what’s happening here; see this section of the adv3lite manual, Actors - Special Topics:

What happens here is that while there’s a conversation in progress between the player character and another actor the parser tries to interpret any command it can’t otherwise understand as the topic object of a SAY command, which allows a SayTopic to be triggered even if the player didn’t explicitly type SAY at the start of the command.

I’m sure you’re right … and I think it’s a bad design idea.

Eric has a fondness for the idea that conversations with NPCs should be modeled using greeting protocols. That is, if the PC walks into a room where the NPC is, there is no conversation going on until the PC greets the NPC. (It’s very British, I think. Not the breezy American thing at all.) And the conversation is presumed to continue until the PC leaves the room, at which point the library allows the author to set the number of turns that will pass before the NPC falls out of the InConversationState.

It’s ugly, in my opinion, but I’ve never tasked him about it because it never seemed important. But now that I see what can go wrong, I’m afraid I’m getting a bit less enchanted with the whole conversation framework.

You can trap say topics with DefaultSayTopic, so perhaps you could redirect non-understood player input from within that topic. I’m too new to adv3lite though to know how you would take that input and send it to the right “I don’t understand that” behavior.

This does seem like a common issue so I’d be surprised if Eric had overlooked it.

How would the same situation be handled in Adv3 (standard library)?

Fully concur and agree: Eric seems to have forgotten that there can be NPC which the player is already familiar…

Tangentially, I think that the charcoal burner of Heidi, esp. the, IMVHO unneeded introduction & learning his proper name complication is the steepest learning curve I noted in IF documentation I know.

Best regards from Italy,
dott. Piergiorgio.

1 Like

There are two separate issues here.

The first is a misunderstanding of the library design. Adv3Lite enables the use of conversational protocols (explicit hello and goodbye) but it doesn’t enforce them if a game author doesn’t want to use them. On the other hand, a game has to have some way of knowing when a current conversation has been concluded. If you don’t want this to happen only when the player char issues an explicit BYE command or leaves the room, you need to have the game end the conversation some other way, such as calling endConversation(reason) on the NPC or setting the NPC’s attentionSpan to a low number (possibly 1) so that the NPC breaks off the conversation when the player character stops conversing with him or her.

The second issue is the way in which any otherwise not understood input is treated as an implicit SAY command whenever a conversation is still in progress. This is sometimes the appropriate behaviour, but I can see that there be many occasions when it isn’t, so this is something I’ll attempt to address for version 1.6. I can see exactly where to insert another check in parser.t; I just need to think through what the best design should be. My initial thinking is to have the parser check a method on the current interlocutor to see whether it’s appropriate to treat input as an implicit SAY command, and to have that method return nil either if the NPC in question has no reachable SayTopics or according to the value of a user (game author) modifiable flag.

2 Likes