Heads-up regarding reveal tags

This could very well have been mentioned (or at least implied) in the TADS docs concerning output streams and menu systems… but I’m going to go ahead and say that it caught me completely off guard because I wasn’t looking for there to be complications.

Don’t use <.reveal> tags within actual hint text! I had an entire hint section programmed to not open unless a certain string (let’s call it someTag) was gRevealed. And… it never got opened (even in the post-comp release :confused: )Turns out that:

['This is a vague hint about the boogey monster.',
'This is a more obvious hint about the boogey monster.',
'This is an overt solution to the boogey monster. <.reveal someTag>']

will never add someTag to the gRevealed table (different output stream, I guess?) To add insult to injury:

['This is a vague hint about the boogey monster.',
'This is a more obvious hint about the boogey monster.',
'This is an overt solution to the boogey monster. <<gReveal('someTag')>>']

will reveal the tag, but it will do it the first time this menu is ever accessed, because it will evaluate all of the contents in its menuContents list. someTag will be revealed as soon as they see the “vague hint”, and not deferred to the time of the “overt solution”.

I know @jjmcc was, like me, using a pretty customized version of the stock Hint system, so a friendly heads-up to anyone that’s doing similar things!

5 Likes

the trouble of multiple evaluations inside lists &c. can be circumvented with an elegant exploitation of the ternary operator; in your case, the ternary operator should check if is actually at the last element of the list.

Best regarda from Italy,
dott. Piergiorgio.

2 Likes

I’m not sure if I follow, @Piergiorgio_d_errico … at any rate it was no use for me to track the ‘lastDisplayed’ property of the menu because my hints are more complex than what’s shown, and some of them will never show if the player has fulfilled certain conditions before the hint menu is accessed.
I’ve come up with a workaround, but only by extending the customness of an already customized display system…

2 Likes

sorry, when I was replying the young cat decides that needs quality time together, so I don’t have the needed concentration for giving an example code…

First an actual case (sorry for the very mild spoiler in the var programmatic name…):

"<<first time>><<etuye.luvkno++ ? "" : "">><<only>>

whose, I hope, don’t need explanation.

in the specific case of checking the actual end-of-list (whose is more probable an event list…):

BEWARE UNTESTED:

"<<first time>><<curScriptState = eventListLen ? "whenTrue()" : "whenFalse">><<only>>

HTH and
Best regards from Italy,
dott. Piergiorgio.

2 Likes

Ah, I see what you’re saying, but unfortunately this is in the hint menu, so it’s not actually implemented as an EventList, nor has a curScriptState property. There is an integer lastDisplayed property to the menu object, but this doesn’t help me either, because my system checks each individual hint for still being pertinent before it shows it, so different players, accessing this hint menu at different times, may see differing numbers of hints preceding the one in question, and lastDisplayed becomes meaningless as a means to know when this particular hint’s turn has come (in order to gReveal something at the right time).

I’ve shared this with @jjmcc , who is using his own flavor of customized hinting, but if anyone else is interested, this is the idea.

A typical hint menu is a list of strings, which the stock system will show one at a time as the player hits Enter, indicating that they want a more detailed hint. I modified the system so that if one of the elements, rather than being a string, is written as a List (within the greater list as a whole), the following options are available:
The first element of this sublist is again a string, the text of the hint.
The second element is a condition, written as a short-form anonymous function, which determines whether this hint is even necessary to be shown at the point in time that the player is opening the hint menu. Very often for a hint menu to be thorough, you need to include lead-up instructions which, however, the majority of players will have already taken care of before they’re driven to the hints. With this second list element, the player does not have to wade through two or four extraneous suggestions every single time they look at a new hint category.
The third element (if supplied) is yet another List (third-layer) naming other Goal objects to be opened. Stock Hint objects can do this, but I found it undesirable and cumbersome to split out and name individual hints just for this functionality. Re: the subject of this post, what I have done is added the ability to include strings in this third-element list, rather than just Goal identifiers. If a string is found, that string is a tag that will be gRevealed the moment the hint is actually player-accessed (it will be immune to the evaluation of the whole menuContents list).
The fourth element, if supplied, is a condition (expressed by another short anon func) which will “freeze” the hint menu until the condition is fufilled. That particular hint might say something like "You need to take care of the worble-wanger before getting any more hints about the frozzle-flinger. " Because often it’s desirable to create as few submenus as possible, but later hints may make no sense (and be outright spoilers to undiscovered content) until a certain earlier hint has been attended to. I found several places in Prince Quisborne where this hint-freezing was a great help to adding sanity to the difficult hint system.
Here’s a sample from the Prince Quisborne intro:

++ glasshouseGoal: Goal 'How do I get in the glasshouse?' [
	'You\'ll need to find the key. ',
	'The key is somewhere in the bailey. ',
	['There\'s a clue in the cottage. ', {: oogLetter.beenRead }, [oogGoal] ],
	['Read the letter on the table for a hint. ', {: oogLetter.beenRead } ],
	['Oogerstane\'s letter says his nephew likes to run off with the glasshouse key. Where might Quinkie like to run off to?', {: treehouseLoc.seen } ],
	['Have you looked closely at the large tree by the pond? ', {: bailTree.described } ],
	['You need to get up in the treehouse. ', {: treehouseLoc.seen}, [treehouseGoal], {: treehouseLoc.seen } ],
	...,
	...,
	'Unlock the glasshouse with the pewter key and go inside. '			]
	closeWhenSeen = glasshouseLoc
	;

So, if the player looks for a hint after they’ve gotten inside the cottage and read the letter, the “clue in the cottage” hint and the “Read the letter” hint will never even show. If they have not been in the treehouse, when they get to the “get up in the treehouse” hint, a new hint topic will be added to the hint menu regarding how to get in the treehouse, and furthermore, because of the fourth element in this list, this particular hint menu (about getting in the glasshouse) won’t show any more hints until the player has in fact gotten into the treehouse, because the following hints it would give are meaningless (and spoilery) to the player… if the player only wants a nudge about the next step for the glasshouse, they may not want to accidentally see blatant answers to what they’ll do once they’re up in the treehouse.

For a game like Prince Quisborne, whose hint system alone took me probably a month or more, these modifications were lifesavers!

2 Likes