Dialog choice mode question

is there a way to abort the display of a node label if there are no choices available?

i’m playing with choice mode as a way to manage NPC conversation. after all the topic choices have been exhausted, ideally it would say something like “There’s nothing else to discuss” and fall back to the parser. but, instead, dialog dutifully continues to display the label for the current node (the NPC label), even though there are no choices left.

similarly, if all the node choices have been exhausted, the player can still type “talk to X” and dialog will still display the NPC label and then a blank slate of choices. instead of getting a response like “You’ve already finished talking, blah blah”.

in short, “talk to X” will always display the NPC node’s label, which doesn’t make sense if there are no topics left.

it looks like the choice list is built from within (read-parse-act) but by the time this is called the label has already been displayed. so i’m worried that this isn’t fixable, that displaying the node label is sort of ‘hard wired’ in and can’t be interrupted?

The intended behavior is that, if a node offers no choices:

  • First, it checks ($ flows to $); if that succeeds, it switches to that node
  • Otherwise (as a default implementation of ($ flows to $)), it retreats to the previous node (the one we reached this node from)
  • If that variable isn’t set, or the new node also has no choices, it drops out into parser mode

What’s happening instead on your end?



(intro)
                "Test" 
			    (try [look])


#player
(current player *)
(* is #in #room)

(perform [talk to $NPC])
    (animate $NPC)
    (activate node $NPC)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#room
(name *)    generic room
(room *)
(room header *) #room
(look *)
    It's a room
#npc
(name *)    the NPC 
(animate *)
(appearance *)
    An NPC is here.
(disp *)   asking the NPC something:
(* offers #apple) 
(* offers #banana)
(* offers #orange)
(* is #in #room)

#apple 
(label *)   apple 
(disp *)    it's an apple 

#banana
(label *)   banana 
(disp *)    it's a banana

#orange 
(label *)   orange 
(disp *)    it's an orange

talk to the NPC. everything works fine until you’ve selected through all the options. but the game will output “asking the NPC something:” when there are no more options.

talk to the NPC again after all the options have been exhausted. the game will continue to print “asking the NPC something:”

this is messy and kind of a deal-breaker for using choice mode for NPC dialog. i would like to intervene at the point that there are no options left, give a message that there are no more options left, and preemptively interrupt (talk to […]) if there are no outstanding topics left.

and an errata: i said that the (label #NPC) keeps getting printed. it’s actually the (disp #NPC) that keeps being printed.

Ahh, I see. It correctly goes back to parser mode, but it prints the (disp $) first, and that’s what you want to remove?

yes.

AND i don’t want a later 'talk to npc" (when there are no more topics) to also print the (disp $) which it insists on doing.

I believe you can check that case with ($ is choice-exhausted), and intercept the TALK TO if so.

yay! yes, that works nicely to intercept a later ‘talk to’.

now if i could just get rid of the superfluous (disp $) at the end of the conversation (and ideally, make some mention of it).

So, the code to activate a node is this:

(activate node $Obj)
	(if) (current node $Previous) (then)
		(now) (previous node $Previous)
	(else)
		(now) ~(previous node $)
	(endif)
	(now) (current node $Obj)
	(display $Obj)
	(if) (object $Obj) (then) (now) ($Obj is exposed) (endif)
	(stop)

You want to prevent that (display $) call if the node offers no choices. I think the best way to do that is:

	(if) *($Obj offers $Choice) (available $Choice) (then)
		(display $Obj)
	(endif)

Though others might have a more elegant solution.

2/3rds there.

i can simply remove the (disp $) from the NPC entirely and move the “You’re asking so-and-so about…” text to the (perform [talk to …]) instead. duh. didn’t think of that before.

this will work, i think. if i were feeling greedy, though, i’d still like to intervene just after the last choice is exhausted and just before it drops back into the parser (to add some kind of ‘end of conversation’ prompt).

Actually, wait, this might be better.

(display $Node)
	~{
		*($Node offers $Choice)
		(available $Choice)
	}
	\[ There's nothing further to say to (the $Node) . \] (par)

Just make (display $) print your custom message instead if it’s exhausted. Up to you if this should override (display $) or (disp $); the difference only matters if you have (before disp $) and (after disp $) rules.

this one doesn’t work because it drops through after every choice, not just after the last one.

i haven’t checked your previous thought yet.

monkeying around with (disp $) works more elegantly than my hack.

1 Like

If you have a solution that works well, do post it here; this seems like it would be good behavior in general, honestly. I suppose the Standard Library just doesn’t do this in case nodes want to Make Things Happen before kicking the player back to the parser prompt.