Assigning Player Name and then stop assigning

Hi! I’ve been trying to use Inform to write a text adventure. I’m having significant trouble with giving the player a name. What I have takes input nicely, and puts it in the status bar, but it then also assigns every subsequent command to the name.

the player name is some text that varies. 


To decide whether collecting names:
	if the command prompt is "What will your name be?  ", yes;
	 no.

When play begins:
	now the command prompt is "What will your name be?  ";
	
After reading a command when collecting names:
	now the player name is "[the player's command in title case]";	
	now the command prompt is "> ";
	move the player to the location;
	reject the player's command.

I can’t figure out why it continues to assign to the name. The condition on the “after reading a…” isn’t true, and the command prompt goes back to it’s initial value, but everything I type is put in the name variable.

Thanks in advance.

The trick is that “[the player’s command in title case]” is saving a reference to the variable, rather than copying its value. So whenever the game needs to print the player’s name it looks at the current value of “the player’s command” and uses that to create the name it uses.

If you instead use “the substituted form of…” that copies the text by value rather than by reference.

Since this just came up twice in a week or so, I asked and self-answered a question about it at IFAnswers. Feel free to give a better answer!

Actually, I was thinking “since this just came up twice in a week or so, maybe it’s the sort of think that should somehow be re-thought or better documented”. It is, after all, a very easy mistake to make! What could be more natural than to say that now a string is “[the current value of some property]”? If I wanted to achieve the opposite effect, which people are falling into now, I’d direct the string to another string. “Now the player name is players_name”, where players_name is a string I change when needed. Or something.

Well, I just noticed that in the 6L02 documentation the Identity Theft example contains this bug. Could someone check whether this is also true in 6L38, and if it is, file it in the bug tracker?

Yes, this most likely pops up from time to time because the documentation example contains the bug that causes it, and it’s pretty hard to spot. It’s reported here.

Oh. It’s a bug? I thought it was by design, the new way of doing things.

It’s a bug in the example–the code that’s given in the example doesn’t do what you’d want the example to do. It’s not a bug that the code does that, it’s just the wrong code for the example, if that makes sense.

It makes perfect sense. Cheers!

Heh, sorry guys. I posted this, found the other post about 3 minutes later, and couldn’t figure out how to rescind the thing.

Coming from… a real programming language… cough… C… cough… I find Inform 7 to be less than rigorously specified, and perhaps a bit sloppy. Differentiating between references and values seems like a pretty critical thing to me.

Anyways, I noticed another problem concerning the title case, in jzip, it doesn’t work if you put it in the brackets, like this:


now the player name is the substituted form of "[the player's command in title case]";
[the name will not display in jzip, running from the command line, or probably anywhere else]

now the player name is the substituted form of "[the player's command]" in title case;
[this, on the other hand, works as expected.]

To supply a bit of background:
[rant=Details]Texts in Inform 7 are somewhat different from strings in other programming languages. When you write

say "You have scored [score] out of [maximum score] points."

that’s roughly the equivalent of

print "You have scored ";
print score;
print " out of ";
print maximum_score;
print "points.\n";

So far so good. This is a nice little bit of syntactic sugar, which has analogues in other languages (such as format-strings in C).

The difference comes in, however, when you then assign that text to a variable. If you say something like

now the description of the clock is "It is [time of day]."

that actually creates the equivalent of a small function, and sets the description of the clock to a pointer to that function. Sort of like (pseudo-C++11)

clock.description = [](){ print "It is "; print time_of_day; print ".\n"; };

This is a very useful feature to have when writing IF, as it means the value of clock.description doesn’t actually need to change whenever time_of_day does. But the major limitation is that you can’t do things like taking a substring, or converting to uppercase, or separating into words. You can assign a new text to a variable during play, but every text you want to use needs to be compiled into the game. You can’t create new ones as you go.

So until very recently (pre-version 6L02), Inform 7 had a separate type called “indexed text” (which I will hereafter call “strings” for brevity), which was the equivalent of a char[] string: literally an array of numbers representing characters. A string couldn’t contain bracket-substitutions like a text could, but you could manipulate it in all sorts of ways. In this example, the player’s name would have been assigned to a string (since it’s being created from a sequence of characters which aren’t known at compile-time). Text could be “cast” to strings by switching the output stream to that string, then evaluating the text, then switching back (though I7 did all this automatically behind the scenes when necessary), and strings could be printed within text using a bracket-substitution.

Version 6L02, however, removed this distinction. The “text” type is now a pointer which can point either to a text (function) or to a string (char array). By default everything starts out as text. Then if you try to do something to the text which would require a string, it casts it into a string, and it stays that way from then on. This is usually good enough. But in some cases you need to be more explicit about whether you want text or a string: such as when saving one particular command the player types in. “The substituted form of…” is a function which takes a text and returns the string equivalent. You can see this distinction by checking whether your variable is “substituted”: for a text this will be false; for a string, true.[/rant]

I might be wrong, but I’ve always worked with the assumption that I7’s semantics are that of your typical dynamic OO language, eg Ruby. Which is to say, everything is an object and therefore everything is a reference; you have no access to the underlying machine primitives.

The way I think of the explanation that’s been rant-boxed below is that Inform’s post-6L handling of text is sloppy in the way you say, deliberately so. Most of the time for Inform 7 authors it’s easier to have quoted strings slide back and forth between strings and functions than to have to carefully keep track of which is which and keep casting one to the other.