top expert

a biting cat website

Let’s Make IF: Handling Excess Nouns

one noun or two?

Last time, I talked about the magic system in my new project, which is hopefully simpler for both players and author alike. In the old system, a second noun (indirect object) was required for the INVESTING IT WITH action. Since this action could only be performed with one noun at any given time, this was redundant. I thought: the command should really only require a direct object, and the system will use whatever magic is at hand, first checking the player’s current acquired magic (defined by a value in a table), then checking to see if there is any magic available in the current location.

In playtesting, new players found this system easy to use, even if they had little experience with parser games. However, players habituated to my earlier work expected things to work as they did in Repeat the Ending. I thought that I should handle this with discouraging messages, pushing players to use the new system. However, I quickly learned that the implementing these messages were no less time consuming than simply honoring the player’s commands.

preliminary arrangements

Things always seem to start with a table. I’ll keep my magics in one.

Table of magics
magic	diagstring	pname	wname
tinert	"You bear no darkness beyond your own."	"Inert"	--
exploding	"You bear the power of *CRASHING DARKNESS*: the power of force, of striking."	"*CRASHING DARKNESS*"	crashing darkness
damp	"You bear the power of *SEEPING DARKNESS*: the power of water, of covering."	"*SEEPING DARKNESS*"	seeping darkness
gooey	"You bear the power of *SUFFOCATING DARKNESS*: the power of blotting, of choking."	"*SUFFOCATING DARKNESS*"	suffocating darkness

What is all this?

  • magic: a value assigned to the player for tracking the magic currently available to them.
  • diagstring: a printable text used for player feedback.
  • pname: the printed name for use in other sorts of output.
  • wname: the noun associated with the value. The player acquires magic by interacting with specific nouns. we’ll be hooking into this for processing our new actions.

The normal flow of things is that the player will simply *XYZZY [something]*. If the player has absorbed some magic, they will cast it at the [something]. If they do not and magic is available in the location, they will first gather that magic, then proceed. If there is no magic available, a failure message will be returned.

The question here is “what if somebody types in *XYZZY [something] with [something else]*? In the old model, players carried around an invisible noun that would be used in such cases, but that isn’t happening here. In order to honor such commands, we’ll need to take their command, check the table, then turn it into something useful. Here are some specific scenarios to deal with:

  • Player gets some magic, walks to another room, then uses it.
  • Player tries to use some magic that isn’t the one they currently possess.
  • Player tries to use something that isn’t magic.
  • Player tries to use a different magic, rather than the one they possess.

We’ll walk through the possibilities, one at a time. First, some general rules:

does the player mean xyzzying something with something:
	it is very unlikely.

We do not want the player to ever be prompted for extra nouns. If players want to type them in, that’s their choice, but we want the game to work without them.

Second, let’s do a scoping rule. Those can be a lot of trouble, so we’ll have to keep an eye on this one!

after deciding the scope of the player when the current action is xyzzying something with something magical:
	place the second noun in scope.

I’ve done my best to keep this narrow, which only seems wise. If the player is performing this very specific action with very specific nouns, sources of magic will be placed in scope.

the can't reach inside rooms rule does nothing when the current action is xyzzying something in the location with something magical.

Again, restraint and constraint will spare us a lot of trouble. In this case, players can only treat these out-of-room things as “touchable” when the first noun is in the player’s location and the second noun is a source of magic.

Whew! Again, these scoping rules are powerful. Be sure and test thoroughly.

Case #1: trying to use a non-magical item as a source of magic

first before xyzzying something with something that is not magical when the player is tinert:
	say "The [second noun] is not a viable source of magic." instead.
	
first before xyzzying something with something that is not magical when the player is not tinert:
	try assaying the player instead.

I identify two cases here. The distinction is that, in the first instance, the player has no magic on-hand. In that case, a simple failure message will do. In the second case, since the player does have some magic available, I’ll just redirect to reporting what that magic is via the “assaying” action instead.

case #2: trying to use magic when the player has no magic

There are two scenarios that I can think of (so far) to account for. In the first one, the player tries to use magic that is in their location, even though they haven’t gathered it. Elsewhere, I have already solved part of this problem: if the player has no magic, they will gather some if it is nearby.

Check xyzzying when the player is tinert:
	if a magical thing is in the location:
		let the target be a random magical thing in the location;
		say "(first gathering the [target])";
		try gathering the target;
		continue the action;
	otherwise:
		say "a failure message";
		stop the action.

Now, if I had a location with two sorts of magic, I’d have to handle that as a special case (using an instead or before rule), but this should be the most common situation.

For us, then, it’s a simple matter of shuffling things around.

first before xyzzying something with something magical when the player is tinert:
	if the second noun is in the location:
		try xyzzying the noun instead;
	otherwise:
		say the parser error internal rule response (E) instead.

Note the “parser error” output for the second condition. Since we’ve placed all sorts of magic in-scope, we don’t want to confirm that something the player hasn’t seen exists. So we’ll print a generic “can’t see that here” message to avoid tipping our hand.

case #3: the player has some magic

The player has some magic. Does it match the named magic in the command? We’ll have to check.

first before xyzzying something with something magical when the player is not tinert:
	choose row with a wname of the second noun in the table of magics;
	if the magic of the player is the magic entry:
		try xyzzying the noun instead;
	otherwise:
		if the second noun is held by the location:
			say "Currently, you possess the power of the [pname entry]. You must use it (*XYZZY [bk]something[cb]) or else disperse it (*DISPERSE*) before using another form of magic." instead;
		otherwise:
			say the parser error internal rule response (E) instead.

This is the most complex scenario, since we’ll have to match the player’s current state against the noun in the command. Hence, a table lookup. If there’s a match, the rule will redirect the command to the existing rule (direct object only). If there is not a match, the player will be told to use what they have (if their noun is in the room). Otherwise, they will receive a generic “can’t see that” message.

why “first before?”

That may not be necessary at all. It’s used as a precaution that will end/redirect actions related to scope changes. Since such rules can lead to unexpected problems, I’m simply containing them. They’d likely work fine as simple “instead” rules, but I like knowing exactly when they will fire.

This all requires more testing. Perhaps I will find problems between now and the next post!

what’s next

I need to write a ton of descriptive text for the project, which doesn’t really fit here in the blog. But I do have some weird cases to discuss, picking up on a previous thread about collapsing rooms after a set number of turns. See you soon!