Feedback on consolidating NPC movement

The way Inform reports character movement is that each report is given its own line, like this:

Lewis goes west.

Linnea goes west.

It would look neater if these two lines were consolidated:

Lewis and Linnea go west.

To this end, I’ve been trying achieve this by stripping down the code from the “Patient Zero” example. However, I don’t understand everything the code is doing; all I’ve done is to keep taking parts of it out and to make sure it compiles and works as it should. Here’s what I have so far:

code
"Consolidated Actor Movement Test"

The current actor is a person which varies.

Last every turn:
	now the last person named is the player;
	now the last thing named is the player;
	now every person is active.
	
Last every turn:
	if player is active, follow the character movement rules.

A person can be active or passive. The player is passive.

The character movement rules are a rulebook.

The first character movement rule:
	now group size is 1;
	now the last person named is the player;
	now the last thing named is the player;
	now the player is passive.

A character movement rule:
	repeat with mover running through other people:
		now the current actor is the mover;
		now the current actor is passive;
	follow the movement reporting rule.

To decide whether movement has not yet occurred:
	if the player is passive, no;
	yes.
	
Definition: a person is other if it is not the player. Definition: a person is another if it is other.

A person has some text called walk style. The walk style of a man is usually "stride". The walk style of a woman is usually "strut".

Table of Visible Exits
character	second	third	heading chosen	total
a person	a person	a person	a direction	a number
with 10 blank rows.

Table of Visible Entrances
character	second	third	heading chosen	total
a person	a person	a person	a direction	a number
with 10 blank rows.

To clear (current table - a table name):
	repeat through current table:
		blank out the whole row.

To tidy departures of (current table - a table name):
	let next direction be up;
	repeat through current table:
		if heading chosen entry is next direction:
			let accomplice be character entry;
			choose row with heading chosen of next direction in the current table;
			if total entry is 1:
				now second entry is accomplice;
				now total entry is 2;
			if total entry is 2:
				unless the second entry is accomplice:
					now third entry is accomplice;
					now total entry is 3;
			choose row with character of accomplice in the current table;
			blank out the whole row;
		otherwise:
			let next direction be heading chosen entry.

A door has a person called last opener.

Report someone opening a door:
	now group size is 1;
	now the last opener of the noun is the person asked;
	if the person asked is visible, say "[The person asked] opens [the noun]. [run paragraph on]" instead;
	otherwise say "[The noun] opens from the other side. [run paragraph on]" instead.

Report someone going through a door (called route):
	if the person asked is not the last opener of the route, continue the action;
	if the person asked is the last person named, say "[The person asked as pronoun]";
	otherwise say "[The person asked]";
	say " [if the person asked is in the location]comes[otherwise]goes[end if] through[if the last thing named is not the route] [the route][end if]." instead.

The last thing named is a thing that varies. Before printing the name of something (called target) which is not a person: now the last thing named is the target.

Report someone going a direction:
	if the person asked is in the location,
		choose a blank row in the table of visible entrances;
	otherwise choose a blank row in the table of visible exits;
	now character entry is the person asked;
	now total entry is 1;
	if the person asked is in the location,
		now heading chosen entry is the opposite of the noun;
	otherwise now heading chosen entry is the noun;
	stop the action.

This is the movement reporting rule:
	sort the Table of Visible Entrances in heading chosen order;
	tidy departures of the table of visible entrances;
	sort the Table of Visible exits in heading chosen order;
	tidy departures of the table of visible exits;
	let total row count be the number of filled rows in the Table of Visible Entrances plus the number of filled rows in the Table of Visible Exits;
	if total row count is 0, rule succeeds;
	generate descriptions from the Table of Visible Entrances;
	generate descriptions from the Table of Visible Exits;
	clear the Table of Visible Entrances; clear the Table of Visible Exits.

To generate descriptions from (current table - a table name):
	let count be the number of filled rows in the current table;
	if count is 0, rule succeeds;
	let index be count;
	repeat through the current table:
		let accomplice be character entry;
		if character entry is a person, now character entry is marked for listing;
		if there is a second entry and second entry is a person, now second entry is marked for listing;
		if there is a third entry and third entry is a person, now third entry is marked for listing;
		let target be the room the heading chosen entry from the location;
		if total entry is 3, say "[The character entry], [the second entry][optional comma] and [the third entry] ";
		if total entry is 2, say "[The character entry] and [the second entry] ";
		if total entry is 1:
			if the character entry is the last person named, say "[The character entry as pronoun] ";
			otherwise say "[The character entry] ";
		if total entry is 1, say "[walk style of the character entry]s ";
		otherwise say "walk[if total entry is 1]s[end if] ";
		if the character entry is in the location:
			if location is indoors and target is indoors, say "over from ";
			if location is outdoors and target is indoors, say "out of ";
			if location is indoors and target is outdoors, say "in from ";
			if location is outdoors and target is outdoors, say "over from ";
		otherwise:
			if location is indoors and target is indoors, say "over to ";
			if location is outdoors and target is indoors, say "into ";
			if location is indoors and target is outdoors, say "out [if a door is visible][the random visible door][end if] to ";
			if location is outdoors and target is outdoors, say "over to ";
		if target is outdoors, say "[the heading chosen entry]";
		otherwise say "[the target]";
		if the total entry is 1 and count is 1 and accomplice carries something, say ", carrying [a list of things carried by the accomplice]";
		decrement index;
		make delimiter index of count, continuing;
		now group size is total entry;
	clear marked people;
	say paragraph break.

The last person named is a person that varies. Before printing the name of a person (called target): now the last person named is the target. 

Group size is a number that varies. Group size is 1.

To clear marked people:
	repeat with named party running through people:
		now the named party is not marked for listing.

Before listing nondescript items:
	if the number of people who are marked for listing is 0, make no decision;
	say "You can see [a list of people who are marked for listing] here.";
	now group size is the number of people who are marked for listing;
	now every marked for listing person is not marked for listing.

To say (named character - a man) as pronoun:
	if group size is 1, say "He"; if group size is 2, say "The latter"; if group size is greater than 2, say "The last".

To say (named character - a woman) as pronoun: if group size is 1, say "She"; if group size is 2, say "The latter"; if group size is greater than 2, say "The last".

A door is usually scenery.

To make delimiter (index - a number) of (count - a number), continuing or halting:
	if index is 0:
		if continuing, say ". [run paragraph on]";
		otherwise say ".";
	otherwise if index is 1:
		if count is 2, say " and ";
		otherwise say "[optional comma] and ";
	otherwise:
		say ", ".

To say optional comma:
	if the serial comma option is active:
		say ",".

And here’s a stripped down scenario, also from “Patient Zero,” to test it out:

code
Include Locksmith by Emily Short.

After going to an air-conditioned room:
	say "You step into the mercifully air-conditioned surroundings of...";
	continue the action.

After going from an air-conditioned room:
	say "You emerge from the air-conditioning into heat like a wall...";
	continue the action.

Instead of listening to an air-conditioned room:
	say "The air-conditioning hums softly."

The Alfred Cralle Pool Hall is a room. "The town's most popular gathering-place, the pool hall is decorated in honor of the inventor of the ice cream scoop." The air conditioner is a device in the Pool Hall. "[if switched off]An air conditioner sits in the corner, unhappily inert[otherwise]The air conditioner hums briskly[end if]."

The felt door is west of the Pool Hall. The felt door is a door. The felt door is open. The felt door is lockable and unlocked. The key to the city unlocks the felt door. The description of the felt door is "It has a prominent lock, designed for an old-fashioned key."

After locking a door with something in the presence of an other person (called audience):
	say "[The audience] looks a little non-plussed when you lock [the noun], but shrugs."

Nancy Johnson Memorial Square is west of the felt door. The description of Nancy Johnson Memorial Square is "Waves of August heat rise from the pavement: more than once you've had the fancy that your shoes are simply going to stick. At the center of the square, rubbed to a brownish polish by many adoring hands, is the statue of Mrs. Nancy Johnson of New Jersey."

The statue is scenery in Memorial Square. Understand "nancy" or "johnson" or "mrs" as the statue. The description of the statue is "Mrs. Johnson is pictured with a hand-cranked ice cream freezer tucked under one arm. Her other hand grips an ice cream scoop, ready to serve frozen dessert to the huddled masses." A hand-cranked ice cream freezer is part of the statue. The description is "The hand-cranked ice cream freezer was Mrs. Johnson's invention in 1846, though it was William Young who had the sense to patent the thing in 1848." The scoop is part of the statue. The description of the scoop is "An anachronism: Alfred Cralle would not invent the tool until 1897."

The Post Office is northwest of Nancy Johnson Memorial Square. "Service at the post office is on the slow side since everything went automated." The slot is scenery in the post office. The slot is a container. Carry out inserting something into the slot: now the noun is nowhere. Report inserting something into the slot: say "[The noun] falls out of sight, and you know you will never see it again."

Hamwi Street is northeast of an iron gate. "A U-shaped street running from Main Street around to the Memorial Square, Hamwi Street was recently added by ambitious city planners. The small and straggly line of trees has yet to grow enough to provide perceptible shade, so the street is even hotter and more unforgiving than the other parts of town."

The iron gate is northeast of Nancy Johnson Memorial Square. The iron gate is a door. It is lockable and unlocked.

Before printing the name of the iron gate while not opening or closing or locking or unlocking:
	if the person asked is the player:
		if the gate is open, say "open ";
	otherwise if the gate is locked:
		say "locked ";
	otherwise if the gate is closed:
		say "closed ".

Cold Comfort Ice Cream is north of a metal door. The metal door is north of Hamwi Street. A poster is fixed in place in Cold Comfort. "A poster fills one wall with the blazing promise of treats to come." The description of the poster is "Coming soon! Thai ice creams! Durian, jackfruit, taro, and coconut flavors!"

The metal door is a door. "A frosty metallic door separates [the location] from [the other side of the metal door]." The metal door is lockable and unlocked. The key to the city unlocks the metal door.

Marciony Street is southeast of Nancy Johnson Memorial Square. "A semi-circular terrace, named somewhat fancifully after one claimant to the invention of the ice cream cone -- though Hamwi Street competes for the same honor. There are wedges of cool shadow here and there thanks to the buildings, but for the most part the southern exposure keeps Marciony unpleasantly hot."

The Movie Rental Store is west of a glass door. The glass door is a door. It is west of Marciony Street. The glass door is lockable and unlocked. The key to the city unlocks the glass door.

Main Street is southeast of Hamwi Street. Main Street is northeast of some bronze gates.

The emergency box is in Main Street. The emergency box is fixed in place. "A fire-red box with a glass front faces the sidewalk, with 'In case of emergency, BREAK GLASS' lettered on it." The emergency box is closed and transparent. Understand "glass" as the box. Instead of attacking the closed emergency box: say "You hit the emergency box, which shatters open."; now the emergency box is open. Instead of attacking the open emergency box: say "The glass has already been thoroughly broken."

The syringe is in the emergency box. The description of the syringe is "It contains the cure for Gelato's Syndrome. You can inject anyone you like with it."

The bronze gates are northeast of Marciony Street. The bronze gates are a door. The bronze gates are lockable and unlocked. The description of the bronze gates is "Erected during the milk-taint revolution of 1937, they were designed to keep Main Street safe from the depredations of dairy-starved rioters."

The Public Library is east of Main Street. "Built in the 1920s during the height of the dairy boom, the public library has lush pink velvet seats, marble walls the color of fresh cream, and a motif of cherries carved around every doorframe. An incongruous sign hangs from the ceiling." The incongruous sign is scenery in the Public Library. The description of the incongruous sign is "Eating and drinking in the library is STRICTLY PROHIBITED."

Town Hall is southeast of Main Street. "Town Hall was built during the slow days of the ice-cream bust, and therefore it is as joyless and utilitarian as the Public Library is ridiculous. Unwilling to be reminded of their pain, the inhabitants steered clear of any decoration that might remotely be construed to resemble a scoop of anything: so there are no curves, only disciplined right angles." The key to the city is in Town Hall. It unlocks the iron gate. It unlocks the bronze gates. The description of the key to the city is "A skeleton key."

A room can be indoors or outdoors. The Post Office, the Alfred Cralle Pool Hall, the Store, Cold Comfort, Town Hall, and the Library are indoors.

After looking in an outdoors room:
	let started printing be false;
	now every proximate door is not mentioned;
	if an indoors room is adjacent:
		let started printing be true;
		say "From here you can head into [the list of adjacent indoors rooms][if a proximate door is not mentioned], or go through [the list of proximate doors which are not mentioned][end if]. [run paragraph on]";
	if an outdoors room is adjacent:
		say "You could[if started printing is true] also[end if] go ";
		let count be the number of adjacent outdoors rooms;
		let index be count;
		repeat with next room running through adjacent outdoors rooms:
			let way be the best route from the location to the next room;
			say "[way] to [the next room]";
			decrement index;
		make delimiter index of count, continuing;
	if a proximate door is not mentioned:
		let started printing be true;
		say "[if started printing is true]Also available[otherwise]Your available exits[end if] [is-are the list of proximate doors which are not mentioned].";
	otherwise:
		if started printing is true, say paragraph break.

Definition: a door is proximate:
	if the front side of it is the location, yes;
	if the back side of it is the location, yes;
	no.

Before exiting when the player is in an indoors room:
	if the player can see a door (called nearest exit), try entering the nearest exit instead;
	repeat with way running through directions:
		let next room be the room way from the location;
		if the next room is a room, try going way instead.

Vanessa is a woman in Cold Comfort.

Francine is a woman in the Public Library.

Lewis is a man in the Alfred Cralle Pool Hall. 

Gene is a man in Nancy Johnson Memorial Square.

Rhoda is a woman in Marciony Street. 

Martin is a man in Main Street. 

Antony is a man in Movie Rental. 

Shelby is a man in the Town Hall.

Christopher is a man in the Library.

Linnea is a woman in the Alfred Cralle Pool Hall.

Ned is a man in the Movie Rental Store.

The walk style of Gene is "[one of]wander[or]stroll[purely at random]". The walk style of Francine is "waddle". The walk style of Antony is "scamper". The walk style of Rhoda is "sashay".

After examining another person who is carrying something: say "[if the noun is female]She[otherwise]He[end if] is carrying [a list of things carried by the noun]."

Definition: a room is air-conditioned:
	if it is outdoors, no;
	if it is the Pool Hall and the air conditioner is switched off, no;
	if it is protected by a door, yes;
	no.

Protection relates a door (called X) to a room (called Y) when the front side of X is Y or the back side of X is Y. The verb to protect means the protection relation.

[to make people move]

A person has a room called the destination. The destination of the player is usually the Alfred Cralle Pool Hall.

When play begins:
	repeat with traveler running through other people:
		now the destination of traveler is a random room which is not the location of traveler;

Every turn:
	repeat with traveler running through other people:
		if the destination of traveler is not the location of traveler:
			let thataway be the best route from the location of traveler to the destination of traveler, using doors;
			if thataway is not nothing:
				try traveler going thataway;
		otherwise:
			now the destination of traveler is a random room which is not the location of traveler;

It kinda works, but I’d like some feedback on if it can be improved upon, and how. Thanks!

So the main load-bearing bits of your code are this rule:

This is the movement reporting rule:

And this phrase:

To generate descriptions from (current table - a table name):

The phrase uses two empty tables to generate the descriptions. It stores the names of people in the Table of Visible Exits and the Table of Visible Entrances, as well as the direction they’re headed in. This allows the description to group up to three people going or coming from the same way at the same time. It would need to be extended with more columns if it were possible for four or more people to go together at the same time.

The movement reporting rule empties out this table and refills it at the end of every turn. It does this by a series of rules and statements, starting with this:

Last every turn:
	if player is active, follow the character movement rules.

This tells the game to follow the character movement rules at the end of each turn. The character rules are themselves a whole rulebooks of stuff that the game has to check, but what it’s mainly doing is seeing whether anyone is coming and going.

There’s a lot to unpick but that’s the core of it. Was there a way you wanted to improve on this reporting? All the walk style stuff could be edited or removed if it didn’t suit the feel of your story, as those are just ways of describing specific people’s movements.

1 Like

I remember doing something similar for Dead Man’s Hill to describe actors arriving:

The describe room gone into rule response (F) is "[An actor] came in from [the back way].
Before an actor going:
   group persons together.

Which was in past tense, of course. You could add a similar rule response for actors leaving.

1 Like

Ugh. I’ve taken a run at Patient Zero so many times trying to solve this same problem. Looking forward to seeing what you come up with.

2 Likes

How wonderful to know others share my Patient Zero woes. It does something that seems so simple, and I feel like I’m inches away from understanding it every time I look at it, but it remains inscrutable.

1 Like

I wonder if Versatile Listing could help here…this might be the chance to see if its recursion features actually work!

Time to try something.

Yes, I thought as much. My question was mainly if more of the code could be removed without significant loss of functionality. For example, I’m wondering about the purpose of this:

To decide whether movement has not yet occurred:
	if the player is passive, no;
	yes.

In the “Patient Zero” example, this phrase is defined but it’s not ever used anywhere else (at least, I couldn’t find another instance of it by using search).

I suppose all the stuff about the serial comma option could be taken out if you don’t use it. Also, the code doesn’t use completely adaptive code, so if you’re going to use something other than present tense, that’s something you’ll have to change.

You’re right @peach, that phrase doesn’t appear to be used and can be taken out. Also the walk style stuff can be removed, you’d just need to amend the description generator like so:

		say "go[if total entry is 1]es[end if]";

instead of:

if total entry is 1, say "[walk style of the character entry]s ";
		otherwise say "walk[if total entry is 1]s[end if] ";


@AvB , I tried this out but I don’t think grouping persons works for those kind of descriptions. (I was under the impression that grouping only works for describing the contents of things.)

See for example:

The Lounge is a room. The Hall is east of the lounge.

The butler is a man in the lounge. The maid is a woman in the lounge.

Every turn:
	try the butler going east;
	try the maid going east;
	try the butler going west;
	try the maid going west.
	
Before an actor going:
   group persons together.

Still ends up as:

Lounge
You can see a butler and a maid here.

z
Time passes.

The butler goes east.

The maid goes east.

The butler arrives from the east.

The maid arrives from the east.

Sorry for coming up with this from the top of my head. This was a long way back and I don’t seem to be able to compile it with my current inform version. I had a bunch of included extensions, too, which might or might not have come into play. I tried unsuccessfully replicating the exact setup for a while just now, but anyway: who knows, maybe it never worked in the first place? As I had to learn, I’m not infallible. It was tangential to the OP’s problem anyway.

1 Like

Also, if you take a close look at the rule that begins:

To generate descriptions from (current table - a table name):
[...]

Some lines below, there’s this:

[...]
		if total entry is 1, say "[walk style of the character entry]s ";
		otherwise say "walk[if total entry is 1]s[end if] ";

Why is the second line checking if the total entry is 1, when the “otherwise” makes it appear as if the text should only print if the condition that the total entry is 1 is false? Or am I missing something?

(shudders)

Nooooo, this may technically work but it’s really something that should be avoided. Instead, write such cases like this:

say "[go]";
say "[walk]";

This may require declaring the verbs beforehand like this:

To go is a verb.
To walk is a verb.

Though it’s possible one or both of them are declared in the standard rules. This form also requires making sure that the prior named object variable is set up correctly to hold the subject of the verb, which usually entails enclosing the name of the subject in square brackets or passing the subject to the regarding say phrase, though you can also set it with now.

Sure, but both Joey and I copied and pasted those from “Patient Zero.” It may be that the example was written that way because it was from before Inform added support for adaptive text, or possibly because the exact verb used depends on whether the total entry is 1, so it’s not as simple as just saying “[go]” or “[walk]”. Although I think you could use “[regarding N]” where N is a number, so this should work:

say "[regarding the total entry][walk] "; 
1 Like

Okay, I have written a new and (slightly) improved version of the “Patient Zero” example I posted earlier. This one attempts to remove redundant code, and also makes the text adaptive. (Or tries to. Adaptive text isn’t my strong point.)

code
"Consolidated Actor Movement Test"

The current actor is a person which varies.

Last every turn:
	now the last person named is the player;
	now the last thing named is the player;
	now every person is active.
	
Last every turn:
	if player is active, follow the character movement rules.

A person can be active or passive. The player is passive.

The character movement rules are a rulebook.

The first character movement rule:
	now group size is 1;
	now the last person named is the player;
	now the last thing named is the player;
	now the player is passive.

A character movement rule:
	repeat with mover running through other people:
		now the current actor is the mover;
		now the current actor is passive;
	follow the movement reporting rule.

Definition: a person is other if it is not the player. Definition: a person is another if it is other.

To walk is a verb. To stride is a verb. To strut is a verb.
A person has a verb called the walk style. The walk style of a person is usually the verb walk. The walk style of a man is usually the verb stride. The walk style of a woman is usually the verb strut.

Table of Visible Exits
character	second	third	heading chosen	total
a person	a person	a person	a direction	a number
with 10 blank rows.

Table of Visible Entrances
character	second	third	heading chosen	total
a person	a person	a person	a direction	a number
with 10 blank rows.

To clear (current table - a table name):
	repeat through current table:
		blank out the whole row.

To tidy departures of (current table - a table name):
	let next direction be up;
	repeat through current table:
		if heading chosen entry is next direction:
			let accomplice be character entry;
			choose row with heading chosen of next direction in the current table;
			if total entry is 1:
				now second entry is accomplice;
				now total entry is 2;
			if total entry is 2:
				unless the second entry is accomplice:
					now third entry is accomplice;
					now total entry is 3;
			choose row with character of accomplice in the current table;
			blank out the whole row;
		otherwise:
			let next direction be heading chosen entry.

A door has a person called last opener.

Report someone opening a door:
	now group size is 1;
	now the last opener of the noun is the person asked;
	if the person asked is visible, say "[The person asked] [open] [the noun]. [run paragraph on]" instead;
	otherwise say "[The noun] [open] from the other side. [run paragraph on]" instead.

To come is a verb.

Report someone going through a door (called route):
	if the person asked is not the last opener of the route, continue the action;
	if the person asked is the last person named, say "[The person asked as pronoun]";
	otherwise say "[The person asked]";
	say " [if the person asked is in the location][come][otherwise][go][end if] through[if the last thing named is not the route] [the route][end if]." instead.

The last thing named is a thing that varies. Before printing the name of something (called target) which is not a person: now the last thing named is the target.

Report someone going a direction:
	if the person asked is in the location,
		choose a blank row in the table of visible entrances;
	otherwise choose a blank row in the table of visible exits;
	now character entry is the person asked;
	now total entry is 1;
	if the person asked is in the location,
		now heading chosen entry is the opposite of the noun;
	otherwise now heading chosen entry is the noun;
	stop the action.

This is the movement reporting rule:
	sort the Table of Visible Entrances in heading chosen order;
	tidy departures of the table of visible entrances;
	sort the Table of Visible exits in heading chosen order;
	tidy departures of the table of visible exits;
	let total row count be the number of filled rows in the Table of Visible Entrances plus the number of filled rows in the Table of Visible Exits;
	if total row count is 0, rule succeeds;
	generate descriptions from the Table of Visible Entrances;
	generate descriptions from the Table of Visible Exits;
	clear the Table of Visible Entrances; clear the Table of Visible Exits.

To generate descriptions from (current table - a table name):
	let count be the number of filled rows in the current table;
	if count is 0, rule succeeds;
	let index be count;
	repeat through the current table:
		let accomplice be character entry;
		if character entry is a person, now character entry is marked for listing;
		if there is a second entry and second entry is a person, now second entry is marked for listing;
		if there is a third entry and third entry is a person, now third entry is marked for listing;
		let target be the room the heading chosen entry from the location;
		if total entry is 3, say "[The character entry], [the second entry][optional comma] and [the third entry] ";
		if total entry is 2, say "[The character entry] and [the second entry] ";
		if total entry is 1:
			if the character entry is the last person named, say "[The character entry as pronoun] ";
			otherwise say "[The character entry] ";
		if total entry is 1, say "[adapt walk style of the character entry] ";
		otherwise say "[regarding the total entry][walk] ";
		if the character entry is in the location:
			if location is indoors and target is indoors, say "over from ";
			if location is outdoors and target is indoors, say "out of ";
			if location is indoors and target is outdoors, say "in from ";
			if location is outdoors and target is outdoors, say "over from ";
		otherwise:
			if location is indoors and target is indoors, say "over to ";
			if location is outdoors and target is indoors, say "into ";
			if location is indoors and target is outdoors, say "out [if a door is visible][the random visible door][end if] to ";
			if location is outdoors and target is outdoors, say "over to ";
		if target is outdoors, say "[the heading chosen entry]";
		otherwise say "[the target]";
		if the total entry is 1 and count is 1 and accomplice carries something, say ", carrying [a list of things carried by the accomplice]";
		decrement index;
		make delimiter index of count, continuing;
		now group size is total entry;
	clear marked people;
	say paragraph break.

The last person named is a person that varies. Before printing the name of a person (called target): now the last person named is the target. Group size is a number that varies. Group size is 1.

To clear marked people:
	repeat with named party running through people:
		now the named party is not marked for listing.

Before listing nondescript items:
	if the number of people who are marked for listing is 0, make no decision;
	say "[We] [can see] [a list of people who are marked for listing] [here].";
	now group size is the number of people who are marked for listing;
	now every marked for listing person is not marked for listing.

To say (named character - a man) as pronoun:
	if group size is 1, say "He"; if group size is 2, say "The latter"; if group size is greater than 2, say "The last".

To say (named character - a woman) as pronoun: if group size is 1, say "She"; if group size is 2, say "The latter"; if group size is greater than 2, say "The last".

A door is usually scenery.

To make delimiter (index - a number) of (count - a number), continuing or halting:
	if index is 0:
		if continuing, say ". [run paragraph on]";
		otherwise say ".";
	otherwise if index is 1:
		if count is 2, say " and ";
		otherwise say "[optional comma] and ";
	otherwise:
		say ", ".

To say optional comma:
	if the serial comma option is active:
		say ",".

One change is that a person’s walk style is now a verb, not a text. If you want to try it out, and you wish to change an NPC’s walk style, you can do so like this:

To sashay is a verb.
The walk style of Rhoda is the verb sashay.

For an extension, you’re correct, this should be handled more robustly to allow for changes of tense etc. But for game text in a game where it doesn’t change, you’d be doing a lot of unnecessary work individually defining all verbs that are merely referred to.


No, you’re not missing something. You’re correct that the original code has a redundant IF clause there. I think it’s quite likely that small errors like this have persisted because of the complexity of the example.

I guess it’s a matter of opinion whether it’s necessary, but… I’m pretty sure doing things this way would also be very helpful if, for example, you someday wanted to translate the game into French. Instead of working out the more complex grammar rules, you just need to translate the verb and the game more or less handles it all for you.

Maybe there are other reasons to do it as well, other than changes of viewpoint, tense, or language. I can’t think of any others off the top of my head though.

Agreed that if your story will stay in the same tense and language, there may not be a reason to use adaptive text. Even so, you have to watch for person and number.

The example “Frozen Assets” has this, for instance:

Instead of buying something free:
    say "[The noun] is yours already."

Resulting in:

buy myself
You is yours already.

Getting into the habit of using adaptive text all the time could reduce these errors, even if you have no intention of changing the story tense or viewpoint. (Although “You are yours already” isn’t much better.)

Aside: why doesn’t Inform allow the story tense to be in any of the progressive/continuous tenses?

1 Like