Code to Limit Verb Guesses, with a bug

I wrote a bit of example code that was designed to put a cap on the number of times you guessed a verb – but it has a bug, which I’ll describe below.

The idea is that, if there’s a certain action that the player is supposed to perform with an object, after a certain number of attempts the game will just perform the action – even if the player has been entering non-standard verbs that would ordinarily get an “I don’t know how to do that” response. You can think of it as, if the PC struggles with the object enough, eventually they’ll accidentally perform the right action.

It has a bug I can’t quite figure out, though, as you can see if you try “Test weird” on the code below. The game is supposed to print a message and end in victory once you try “Throttle thingummy” for the third time, but instead it prints a message and gives you a command prompt; then ends the game in victory as soon as you enter the next command. Any idea what’s going on here? If it’s something that only happens when you’re ending the game in victory, that’d be easy to work around, but if it arises with other activities that could be very bad.

Anyway, code follows:

[code]
“Fiddle.”

The Bare Room is a room. “No apparent exit, nothing here but a thingummy sticking out of the floor.” The thingummy is scenery in the Bare Room. “It must have some purpose, but you can’t tell what to do to it.” The thingummy is fixed in place.

Twisting is an action applying to one thing. Understand “twist” as twisting.

Instead of twisting:
If the noun is the thingummy:
say “The thingummy twists around and locks into place with a loud click. You see the wall slide open and beyond it, sweet freedom.”;
end the game in victory;
otherwise:
say “That can’t be twisted.”

Instead of turning the thingummy:
try twisting the thingummy.

The fiddle-count is a number which varies. The fiddle-count is usually 0.

Rule for printing a parser error when parser error is not a verb I recognise:
if the player’s command includes “[thingummy]”:
say “You struggle with the [thingummy].”;
try fiddling with the thingummy;
otherwise:
say “I’m not sure how to do that.”

Before doing something other than turning or twisting or examining or fiddling with to the thingummy:
say “You struggle with the thingummy.”;
try fiddling with the thingummy;
stop the action.

Fiddling with is an action applying to one thing.

Instead of fiddling with the thingummy:
increase the fiddle-count by 1;
if the fiddle-count is 3:
try twisting the thingummy;
stop the action;
otherwise:
say “It wiggles provocatively but doesn’t move in any productive way.”;
stop the action.

Counting is an action applying to nothing. Understand “count” as counting.

Carry out counting:
say “The fiddle-count is [the fiddle-count].”

Test me with “throttle thingummy/ count/ ride it/ count/ take it”.
Test weird with “take thingummy/ count/ ride it/ count/ throttle it/ look”.
test normal with “twist thingummy”.[/code]

Of course, you should feel free to use this code if it’s helpful and not irrevocably bugged. You could also use it for evil, by making fiddling result in failure – “The thingummy breaks off in your hand. Guess you should’ve read the manual before starting to fiddle with it.” But that would be evil.

The problem is that when there is a parser error, the normal turn rules don’t apply as they usually would. Those include for example every turn rules, advancing the turn count and checking whether to end the game, which is what’s missing here. The game does the check during the next normal turn (the LOOK command). You could run the check manually but lacking the other rules would be a problem if you intend to do something else other than ending the game.

You could instead trap the non-understood commands with the “[text]” token:

[code]“Fiddle.”

The Bare Room is a room. “No apparent exit, nothing here but a thingummy sticking out of the floor.” The thingummy is scenery in the Bare Room. “It must have some purpose, but you can’t tell what to do to it.” The thingummy is fixed in place.

Instead of turning the thingummy:
say “The thingummy twists around and locks into place with a loud click. You see the wall slide open and beyond it, sweet freedom.”;
end the game in victory;

Fiddling is an action applying to one topic. Understand “[text]” as fiddling.

The fiddle-count is a number which varies. The fiddle-count is 0.

Instead of fiddling:
if the player’s command includes “[thingummy]” and the player can touch thingummy:
say “You struggle with the [thingummy].”;
increase the fiddle-count by 1;
if the fiddle-count is 3:
try turning the thingummy;
otherwise:
say “It wiggles provocatively but doesn’t move in any productive way.”;
otherwise:
say “I’m not sure how to do that.”

Before doing something other than turning or examining to the thingummy:
try fiddling.

Counting is an action applying to nothing. Understand “count” as counting.

Carry out counting:
say “The fiddle-count is [the fiddle-count] and the turn count is [turn count].”

Test me with “throttle thingummy/ count/ ride it/ count/ take it”.
Test weird with “take thingummy/ count/ ride it/ count/ throttle it/ look”.
test normal with “twist thingummy”.[/code]
This acts as if fiddling were an actual action and not a parser error, so it will run the appropriate rules as well.

Thanks! That seems like a pretty bad bug in the original code – if I’d paid attention to the status line I might have noticed that the turn-count wasn’t advancing.

If I may pick your brains a bit more:

We want fiddling to be an action applying to one topic because we want to preserve the literal text of the command, right? So what this essentially does is make the null text the part of the command that tells you to fiddle, and then preserves the entire text of the command as the topic – though I suppose we never use that topic.

Also, the reason that more sensible commands don’t get interpreted as fiddling even though they match the “[text]” template is that the parser tries to interpret commands in a more specific way before a less specific way, right? So an action defined by “Understand [text] as blahing” will always be invoked only when there isn’t any more specific way to understand the text? I’ve been a little confused about how understanding works there.

Finally, is there any way to manipulate when the every-turn rules apply – say, if I want some actions (like looking) not to take any in-game time – or should I just create a new rulebook of “Every meaningful turn” rules that don’t get invoked when you look, if that’s the effect I’m going for?

I think it might be more accurate to say that we just want to have any input parse as a command and [text] matches anything the player might type. Note that the drawback of this method is that now everything the player types is considered an action, not just the something related to that one item.

That’s the gist of it, yes.

Check out the example “Timeless” in the manual, that should do just that.

We can get around this problem by externalizing the internal conditions of the fiddling action to the circumstances of its being recognized by the parser. In other words, we only allow a topic to be understood as fiddling when the player can see the thingummy, and when the player’s command actually refers to the thingummy–instead of checking for those conditions after converting an invalid command to fiddling. Here’s what I mean:

[code]“Fiddle.”

The Bare Room is a room. “No apparent exit, nothing here but a thingummy sticking out of the floor.” The thingummy is scenery in the Bare Room. “It must have some purpose, but you can’t tell what to do to it.” The thingummy is fixed in place.

Test is north of the Bare Room.

Instead of turning the thingummy:
say “The thingummy twists around and locks into place with a loud click. You see the wall slide open and beyond it, sweet freedom.”;
end the game in victory;

Thingummy-fiddling is a truth state variable. Thingummy-fiddling is false.

After reading a command:
now thingummy-fiddling is false;
if the player’s command includes “[thingummy]”:
now thingummy-fiddling is true.

Fiddling is an action applying to one topic. Understand “[text]” as fiddling when thingummy-fiddling is true and the player can touch the thingummy.

The fiddle-count is a number which varies. The fiddle-count is 0.

Instead of fiddling:
say “You struggle with the [thingummy].”;
increase the fiddle-count by 1;
if the fiddle-count is 3:
try turning the thingummy;
otherwise:
say “It wiggles provocatively but doesn’t move in any productive way.”;

Before doing something other than turning or examining to the thingummy:
try fiddling.

Counting is an action applying to nothing. Understand “count” as counting.

Carry out counting:
say “The fiddle-count is [the fiddle-count] and the turn count is [turn count].”

Test me with “throttle thingummy/ count/ ride it/ count/ take it”.
Test weird with “take thingummy/ count/ ride it/ count/ throttle it/ look”.
test normal with “twist thingummy”.[/code]

Mark, this is a cool idea. One thing you’d probably want to do in a real game is inform the player somehow that their command wasn’t actually understood. Otherwise, they may think they’ve found a command that works and be disappointed when it has no effect elsewhere in the game…

–Erik

Thanks guys! Juhana, thanks for the pointer to “Timeless” – I’ve only worked through chapter 17 of the documentation (as you may be able to tell from my example code), and that’s exactly what I’m looking for.

Erik, good point about the message to the player – maybe something like “You’re not sure how exactly how to [verb] the thingummy, but you struggle with it for a while.” Which would probably require a little work to cut “thingummy” from the command text, and would yield results for things like “throw the thingummy at the recalcitrant epigone,” but should be reasonable workable. Also, I see that your text gives default messages for actions like “hit thingummy” and “take thingummy”; if we want to suppress them (which I kind of do) I think we need to change “Before doing something other than turning or examining to the thingummy:” to an “Instead” rule.