Player's command including a (text) variable

I feel like this should be super simple, but I can’t make it work to save my life.

It’s a simple case of finding a password, and telling someone the right password in order to advance.

PasswordSeed is a number that varies.
Password is a text that varies.

When play begins: 
	now PasswordSeed is a random number between 1 and 30;
		if PasswordSeed is 1, now Password is "AMERICANO";
		if PasswordSeed is 2, now Password is "BARCAROLA";
		if PasswordSeed is 3, now Password is "SERENISSIMA";
		if PasswordSeed is 4, now Password is "DOGE";

And so on. The game is correctly selecting a new random password with each playthrough. The problem is it doesn’t work when I ask the player to provide that password:

After reading a command when the guard is engaged:
	if the player's command is "[Password]":
		now the meetingplace is discovered;
		move meetingplace to Street;
		say "The man nods and points somewhere to the south-east.";
		now the command prompt is ">";
		now the guard is unengaged;
	otherwise:
		say "The man didn't understand that. Try again.";
		now the command prompt is ">";
		now the guard is unengaged.

This isn’t worknig. It’s very irksome because it DOES work if I try it with a static word ("if the player’s command is “XYZZY”) but when it’s a variable, it just doesn’t recognize it as correct.

I know the problem is with the variable because if instead of "player’s command IS “password” I use "player’s command INCLUDES “password”, then it doesn’t even compile:

Problem. I was unable to understand what you meant by the grammar token 'Password' in the sentence 'if the player's command includes "[Password]"'  .

You DO understand what that grammar token is, Inform, because you’re printing it on demand.

Why is it a problem understanding it when it’s the player who inputs it?

Should I just give up and have the password be one static word, always the same?

This is a quick and dirty possibility, if you don’t mind regular expressions:

when play begins:
	now password is "rannygazoo";

after reading a command:
	if the player's command matches the regular expression "^[password]$", case insensitively:
		say "1.";

This knocks out, say, RANNYGAZOOX. If you wanted the word anywhere in the command, then “\b[password]\b” would work. (\b = word boundary)

3 Likes

I don’t mind regular expressions (TBH I’m not quite sure what they are :stuck_out_tongue: ), but sadly this solution is working: my code still isn’t recognizing the correct password as, err, correct. I don’t think it’s a typo problem… I have a “feeling” Inform has trouble linking [Password] with the text inside [Password], and somehow it’s because it’s a variable… idk :neutral_face:

You can ask whether the player’s command matches password, but not whether it is. This is one of the few places where the difference between snippets, topics, and texts matters and it’s always a pain.

2 Likes

It sure is giving me a massive headache. In Dancing with Fear, having a variable combination for the strongbox was super easy… while here, having a variable password is proving impossible. I guess it’s the blasted “player’s command” thing. Very tempted to just nuke it.

The substituted form is your friend here:

PasswordSeed is a number that varies.
Password is a text that varies.

When play begins: 
	now PasswordSeed is a random number between 1 and 4;
	if PasswordSeed is 1, now Password is "AMERICANO";
	if PasswordSeed is 2, now Password is "BARCAROLA";
	if PasswordSeed is 3, now Password is "SERENISSIMA";
	if PasswordSeed is 4, now Password is "DOGE";
	say "<password = [Password]>[line break]".

Giving the password is an action applying to one topic. Understand "[text]" as giving the password.

Report giving the password:
	let PC be the substituted form of "[player's command]";
	now PC is PC in upper case;
	if PC is Password, say "<MATCH>[line break]";
	otherwise say "<no match>[line break]".

Test me with "americano / barcarola / serenissima / doge".

See WWI 20.7 Making new text with text substitutions.

5 Likes

The good news, it works! :smiley:

The bad news is… it seems to have totally kidnapped the parser, and now I’m having trouble “restricting” that password-giving thing to “only when asked by the guard”.

The general approach is

Understand "[text]" as giving the password when... 

The “when” condition could be “scene is happening” or just a combination of global variables.

1 Like

Sorry for any confusion: That code was just a quick shell I slapped around the text comparison logic. I assumed you would continue to use your After reading a command... rule.

If you want to use the action-based approach, restricting the grammar line to a scene would be a good idea, as zarf suggests. (Or just ... when the guard is engaged, the alternate global variable approach you seem to already be using. Or make use of an answering it that action instead of a special-purpose action. Or…)

1 Like

Oof, yes, you’re right, of course, zarf. My brain is so fried with all this, I wasn’t thinking straight, trying to add complicated conditions to the code instead of refining the “Understand (…) when (…)” condition.

Otistdog, thank you a bunch! It works wonderfully, and yes, the “guard is engaged” condition does the trick, since I’m switching him back to unengaged after each interaction. I’ve swapped my whole shitty block of code for yours. Really appreciated, folks! :smiley:

1 Like

Generally, parsing the player’s command directly in an After reading a command.. rule should be a last resort, but should you need to do something similar in future, know that you were unlucky enough to choose one of the few forms that doesn’t work. All the following do:

	if the player's command matches Password:             [player's command (snippet) matches (text)]
	if  "[the player's command]" is Password:             [(substituted text) is (text)]
	if  "[the player's command]" is "[Password]":         [(substituted text) is (substituted text)]
	if  "[the player's command]" is the substituted form of "[Password]":   [(substituted text) is (text)]
	if  "[the player's command]" exactly matches the text Password:         [(substituted text) exactly matches the text (text)]
	if  "[the player's command]" exactly matches the text "[Password]":     [(substituted text) exactly matches the text (substituted text)]
	if  the player's command exactly matches the text Password:       [player's command (snippet) automatically cast (converted) to text exactly matches the text (text)]
	if  the player's command exactly matches the text "[Password]":   [player's command (snippet) automatically cast (converted) to text exactly matches the text (substituted text)]
	if  the substituted form of "[the player's command]" is Password:       [(text) is (text)]
	if  the substituted form of "[the player's command]" is "[Password]":   [(text) is (substituted text)]
	if  the substituted form of "[the player's command]" is the substituted form of "[Password]":     [(text) is (text)]
	if  the substituted form of "[the player's command]" exactly matches the text Password:    [(text) exactly matches the text (text)]
	if  the substituted form of "[the player's command]" exactly matches the text "[Password]":    [(text) exactly matches the text (substituted text)]

but the following don’t:

	if the player's command is "pop":          [ -no match made:  the player's command (snippet) is not a (text)]
	if the player's command is Password:       [ -no match made:  the player's command (snippet) is not a (text)]
	if the player's command is "[Password]":   [ -no match made:  the player's command (snippet) is not a (substituted text)]
	if the player's command matches "[Password]":    [ -non-compile: interprets and rejects [Password] as a grammar token]
	if the player's command matches the substituted form of "[Password]":   [-crashes the compiler (compiler bug)]

EDIT: There is a slight variation between version 9.3/6M62 and the latest version 10.1.2:
The following doesn’t work in 9.3/6M62

	if  "[the player's command]" is "[Password]":         [(substituted text) is **not** (substituted text) in 6M62/9.3]

I hadn’t noticed until now this subtle change in behaviour in 10.1.2- I was scratching my head thinking ‘This shouldn’t work! a substituted text is not a (separately defined) substituted text!’

EDIT3:

	if the player's command matches Password:          [player's command (snippet) matches (text)] [NOT in 9.3/6M62- RTP P29]

also doesn’t work in Version 9.3/6M62, leading to

*** Run-time problem P29: Attempt to see if a snippet of text matches something which is not a topic.

EDIT2: a literal text such as “pop” will work (or not work) wherever the plain text variable Password does or doesn’t work- except for, in Version 9.3/6M62, if the player's command matches Password: as noted above, where “pop” WILL work in Version 9.3/6M62

2 Likes

EDIT4:

Further complications!

Even in the latest version, 10.1.2,

if the player's command matches Password:          [player's command (snippet) matches (text)] 

only works if Password is a constant, not if it is a text which varies.

In the latter case, it fails in compilation due to the absence of an appropriate function to cast (convert) a text variable to a topic:

Problem. Something went wrong late in compilation, when working through the ‘pipeline’ of code-generation steps. (This should not normally happen unless your source text is making use of ‘(-’ and ‘-)’ and getting that wrong, or unless you are experimenting with non-standard pipelines.) The pipeline looks like so:

  1. shorten-wiring
    Problem: unable to find definitions for the following name(s): TEXT_TY_to_UNDERSTANDING_TY

I have reported this as a bug.

This would be simpler if you could make Password a topic variable. Inform doesn’t allow this, but the type system doesn’t inherently have a problem with the idea. You can see this if you create a topic property, which is allowed:

PWHolder is a thing. The PWHolder has a topic called the password.

Table of Passwords
topic
"AMERICANO"
"BARCAROLA"
"SERENISSIMA"
"DOGE"

When play begins: 
	choose a random row from the Table of Passwords;
	now the password of PWHolder is the topic entry;

After reading a command:
	if the player's command matches the password of PWHolder:
		say "That was it!";

The compiler is even able to understand topic constants in code if you give it the smallest nudge:

PasswordSeed is a number that varies.
PWHolder is a thing. The PWHolder has a topic called the password.

To decide what topic is the topic (T - topic): decide on T.

When play begins:
	now PasswordSeed is a random number between 1 and 4;
	if PasswordSeed is 1, now the password of PWHolder is the topic "AMERICANO";
	if PasswordSeed is 2, now the password of PWHolder is the topic "BARCAROLA";
	if PasswordSeed is 3, now the password of PWHolder is the topic "SERENISSIMA";
	if PasswordSeed is 4, now the password of PWHolder is the topic "DOGE";

I’d say the compiler’s restrictions on topic variables could be removed, really.

6 Likes

Ah, right, “matches” is for topics, for matching a text variable you need “matches the text”.

Even after a decade and a half I still get this wrong.

1 Like

With a little more subversion of Inform 7’s typing system, of course, it’s also possble to store topics in variables:

Lab is a room.

topic-holder is a number that varies.

To decide which K is (v - a value) as a/-- (name of kind of value K): (- {v} -).
To decide which topic is the topic (T - topic): decide on T.

Understand "Americano/Cappuccino" or "Double Espresso" or "Flat White" as "[coffee]".
When play begins:
	now topic-holder is the topic "[coffee]" as a number.

After reading a command:
	if the player's command includes topic-holder as a topic:
		say "Mmmm.... coffee!";
		reject the player's command.
2 Likes

… or make dynamic lists of them:

Lab is a room.

To decide which K is (v - a value) as a/-- (name of kind of value K): (- {v} -).
To decide which topic is the topic (T - topic): decide on T.

topic-holder is a number that varies.

Understand "Americano/Cappuccino" or "Double Espresso" or "Flat White" as "[coffee]".
When play begins:
	now topic-holder is the topic "[coffee]" as a number.

topic-list is a list of numbers that varies.

When play begins:
	add the topic "Lapsang souchong" as a number to topic-list;
	add the topic "Darjeeling" as a number to topic-list;
	add the topic "English Breakfast" as a number to topic-list;
	add the topic "Earl Grey" as a number to topic-list;
	add the topic "Assam" as a number to topic-list;

After reading a command:
	let beverage_found be false;
	if the player's command includes topic-holder as a topic:
		say "Mmmm.... coffee!";
		now beverage_found is true;
	repeat with t running through topic-list:
		if the player's command includes t as a topic:
			say "Tea.... lovely!";
			now beverage_found is true;
			break;	
	if beverage_found is true:
		reject the player's command.
1 Like