Commanding multiple actors at the same time

Hi ya’ll. Is there a way to command multiple actors to do something, for example “Bob and Dan, attack the dragon”?

Not without a serious hack of the parser, I don’t think. See this discussion; the parser as it exists isn’t set up to accommodate multiple nouns before the comma.

Hmmm. Thanks.

Well, just for kicks I hacked up a different approach to making this work. This is in 6G60 (the older version of Inform), because it relies on Ron Newcomb’s Editable Stored Actions extension, and I still have some 6G60 projects that use it that I may want to update so I don’t want to update my version of the extension. There are also some more quirks:

[spoiler][code]Include Editable Stored Actions by Ron Newcomb.

The list of commanded actors is a list of persons that varies. The list of commanded actions is a list of stored actions that varies.

Commanding is an action applying to one visible thing and one topic. Understand “have [things] [text]” as commanding. [Basically, when the player types this, we store the list of people in one list and the command that was typed in a text. Then the next turn, no matter what’s typed that turn, we parse this typed command and apply it to all the people in our list.]

Executing a multicommand is a truth state that varies. Executing a multicommand is usually false. [A flag that tells us whether we’re in the mode where we’re about to throw out whatever is typed, parse the command we stored last turn, and apply it to all those people.]
The multicommand text is an indexed text that varies.

Check commanding when executing a multicommand is false:
repeat with item running through the multiple object list: [the multiple object list is the list of things that were processed by a “things” command]
if item is not a person, say “You can only have something animate do something.” instead. [If we let things that weren’t animate into the list of things that were going to perform the action next turn, it would be bad. This can wind up printing the error message far too many times; if we were going to make this work for real we’d want to make sure it only printed once a turn.]

Carry out commanding when executing a multicommand is false: [This sets up all the stuff we need to actually have the actions happen next turn]
now executing a multicommand is true; [so we know that next turn we do the stuff]
now the list of commanded actors is the multiple object list; [this is the list of things that were understood by the [things] token]
now the multicommand text is “[the topic understood]”; [this is the text understood by the text token; so when the player types “have sam and dave soothe me” the multiple object list is {Sam, Dave} and the topic understood is “soothe me”]
now the command prompt is “Please type a letter and press Return.”

After reading a command when executing a multicommand is true:
change the text of the player’s command to “[the multicommand text]”. [This changes the text of the player’s command to whatever we stored last turn. Then we can parse it as a command. Reparsing the command in one turn would take some crazy parser hacking that I’m not at all capable of. Unfortunately, if the player just hits return without typing anything, the “for reading a command” rule catches it and prints the I beg your pardon parser error without giving us a chance to change the text. That’s why the command prompt says to type a letter. There are I6 hacks that let you work around this, but I didn’t feel like trying to implement them right now.]

First before when executing a multicommand is true:
now executing a multicommand is false;
now the command prompt is “>”; [these make sure we go back into ordinary interaction mode]
now the list of commanded actions is {}; [now we make a list of actions to execute]
repeat with the agent running through the list of commanded actors:
let the temporary action be a stored action;
now the temporary action is the current action; [the one that got parsed from the command]
change the request part of the temporary action to true;
change the actor part of the temporary action to the agent; [we’ve used the Editable Stored Actions extension to turn the action that we originally processed from something that the player would do into something that the agent would do, and we’ve set a flag so that it gets processed as a request from the player rather than as an autonomous action by the agent]
add the temporary action to the list of commanded actions; [so that there’s one action on the list for every commanded actor]
repeat with the happening running through the list of commanded actions:
try the happening; [now we’re actually carrying out all those requests]
stop the action. [this prevents Inform from actually trying out the action we parsed]

First before commanding when executing a multicommand is true: stop the action. [This means that when we’re running through the multiple object list after entering the “Have Sam and Dave soothe me” command we don’t go through the previous rule and prematurely reset the executing a multicommand flag]

This is the announce items from multiple object lists when not commanding rule:
if not commanding, follow the announce items from multiple object lists rule.
[Ordinarily when you do actions on multiple items, the announce items from multiple object lists rule says “Rock: Taken. Roll: Taken.” or something like that. We don’t want that to happen when we’re commanding so we write a rule that only prints that text if we’re not commanding. If we were in 6L02 there would be an easier way to do this.]

The announce items from multiple object lists when not commanding rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

Persuasion rule: persuasion succeeds. [This just means that people will try to do things we ask them to.]

[and here’s some stuff for them to do. not sure why I put in all these rooms]
The Command Center is a room.
A robot is a kind of person. Understand “robot” as a robot. Understand “robots” as the plural of a robot.
A persuasion rule: persuasion succeeds.
Auda, Iris, Sensa, Waldo, Whiz, and Poet are robots in the command center.

A marble is in the command center. The box is a container in the command center.
A leaflet is a kind of thing. Six leaflets are in the command center.

A brown hat is in the command center. A brown shoe is in the command center.

A room called the Weather Monitors is west of the command center.

A room called the Transit Monitors is south of the command center.

A room called the Hydroponics Monitors is east of the command center.

Instead of an actor kissing Iris:
say “Iris slaps [the actor].”;
rule succeeds.

Instead of Waldo kissing Iris:
say “Iris says, ‘oh you!’”;
rule succeeds.

Test me with “have poet and waldo kiss iris/y/have all robots get leaflet/y/ auda, get marble/have all robots put marble in box/y/whiz, get marble/have all robots put marble in box/y/auda, get leaflet/iris, get leaflet/poet, get leaflet/have auda and iris and poet and sensa put leaflet in box/y/have all robots drop leaflet/y”.
[/code][/spoiler]

One quirk you can see there is what happens when you ask all the robots to get the leaflet. The reason that only the first robot succeeds is that the command has been processed into an action on one particular leaflet, and all our action editing leaves every robot trying to pick up that one leaflet. If you wanted to be able to say “have all robots get leaflet” and have each pick up a different leaflet then you’d need to do some logic that figured out when you wanted to do that and changed the actions appropriately.

Also, the reason every robot succeeds in putting the marble in the box is that they all prepare themselves for putting the marble in the box by picking it up themselves. Again, you’d have to code something to prevent that.

This will also cause two turns to elapse every time you try this. I think solving that might be as simple as saying “Commanding is an action out of world applying to one visible thing and one topic.”

Ideally, to make this flow smoothly you’d somehow hack the input loop so that when executing a command is true the game doesn’t even ask for you to type something but just fills the command buffer with the multicommand text and processes it. This is probably doable by someone who knows how to do this more than I do. And it still won’t let you understand “Bob and Dan, attack dragon” rather than “have bob and dan attack dragon,” but maybe searching for a comma and editing the command appropriately would take care of that.

Anyway, this is pretty complicated and no doubt wheezy and I wouldn’t advocate trying this unless you’re pretty experienced. The code supplied here is for entertainment purposes only, really.

1 Like

Wow, thanks!

You’re welcome! This was fun.

It turns out that the code I just gave hangs up if you have to disambiguate the command (if you say “auda and iris, take brown”), because the “After reading a command” rule runs and changes whatever you type at the disambiguation prompt to the multicommand text. That’s bad! Here’s a fix where I set a flag to let Inform know that a disambiguation is in progress and it shouldn’t change the input:

[spoiler][code]Include Editable Stored Actions by Ron Newcomb.

The list of commanded actors is a list of persons that varies. The list of commanded actions is a list of stored actions that varies.

Commanding is an action applying to one visible thing and one topic. Understand “have [things] [text]” as commanding. [Basically, when the player types this, we store the list of people in one list and the command that was typed in a text. Then the next turn, no matter what’s typed that turn, we parse this typed command and apply it to all the people in our list.]

Executing a multicommand is a truth state that varies. Executing a multicommand is usually false. [A flag that tells us whether we’re in the mode where we’re about to throw out whatever is typed, parse the command we stored last turn, and apply it to all those people.]
The multicommand text is an indexed text that varies.

Check commanding when executing a multicommand is false:
repeat with item running through the multiple object list: [the multiple object list is the list of things that were processed by a “things” command]
if item is not a person, say “You can only have something animate do something.” instead. [If we let things that weren’t animate into the list of things that were going to perform the action next turn, it would be bad. This can wind up printing the error message far too many times; if we were going to make this work for real we’d want to make sure it only printed once a turn.]

Disambiguation in progress is a truth state that varies.

Carry out commanding when executing a multicommand is false: [This sets up all the stuff we need to actually have the actions happen next turn]
now executing a multicommand is true; [so we know that next turn we do the stuff]
now the list of commanded actors is the multiple object list; [this is the list of things that were understood by the [things] token]
now the multicommand text is “[the topic understood]”; [this is the text understood by the text token; so when the player types “have sam and dave soothe me” the multiple object list is {Sam, Dave} and the topic understood is “soothe me”]
now the command prompt is “Please type a letter and press Return.”;
now disambiguation in progress is false.

After reading a command when executing a multicommand is true and disambiguation in progress is false:
change the text of the player’s command to “[the multicommand text]”. [This changes the text of the player’s command to whatever we stored last turn. Then we can parse it as a command. Reparsing the command in one turn would take some crazy parser hacking that I’m not at all capable of. Unfortunately, if the player just hits return without typing anything, the “for reading a command” rule catches it and prints the I beg your pardon parser error without giving us a chance to change the text. That’s why the command prompt says to type a letter. There are I6 hacks that let you work around this, but I didn’t feel like trying to implement them right now.]

First before when executing a multicommand is true:
now executing a multicommand is false;
now the command prompt is “>”; [these make sure we go back into ordinary interaction mode]
now the list of commanded actions is {}; [now we make a list of actions to execute]
repeat with the agent running through the list of commanded actors:
let the temporary action be a stored action;
now the temporary action is the current action; [the one that got parsed from the command]
change the request part of the temporary action to true;
change the actor part of the temporary action to the agent; [we’ve used the Editable Stored Actions extension to turn the action that we originally processed from something that the player would do into something that the agent would do, and we’ve set a flag so that it gets processed as a request from the player rather than as an autonomous action by the agent]
add the temporary action to the list of commanded actions; [so that there’s one action on the list for every commanded actor]
repeat with the happening running through the list of commanded actions:
try the happening; [now we’re actually carrying out all those requests]
stop the action. [this prevents Inform from actually trying out the action we parsed]

First before commanding when executing a multicommand is true: stop the action. [This means that when we’re running through the multiple object list after entering the “Have Sam and Dave soothe me” command we don’t go through the previous rule and prematurely reset the executing a multicommand flag]

This is the announce items from multiple object lists when not commanding rule:
if not commanding, follow the announce items from multiple object lists rule.
[Ordinarily when you do actions on multiple items, the announce items from multiple object lists rule says “Rock: Taken. Roll: Taken.” or something like that. We don’t want that to happen when we’re commanding so we write a rule that only prints that text if we’re not commanding. If we were in 6L02 there would be an easier way to do this.]

The announce items from multiple object lists when not commanding rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

Before asking which do you mean when executing a multicommand is true:
now the command prompt is “>”;
now disambiguation in progress is true.

Persuasion rule: persuasion succeeds. [This just means that people will try to do things we ask them to.]

[and here’s some stuff for them to do. not sure why I put in all these rooms]
The Command Center is a room.
A robot is a kind of person. Understand “robot” as a robot. Understand “robots” as the plural of a robot.
A persuasion rule: persuasion succeeds.
Auda, Iris, Sensa, Waldo, Whiz, and Poet are robots in the command center.

A marble is in the command center. The box is a container in the command center.
A leaflet is a kind of thing. Six leaflets are in the command center.

A brown hat is in the command center. A brown shoe is in the command center.

A room called the Weather Monitors is west of the command center.

A room called the Transit Monitors is south of the command center.

A room called the Hydroponics Monitors is east of the command center.

Instead of an actor kissing Iris:
say “Iris slaps [the actor].”;
rule succeeds.

Instead of Waldo kissing Iris:
say “Iris says, ‘oh you!’”;
rule succeeds.

Test me with “have poet and waldo kiss iris/y/have all robots get leaflet/y/ auda, get marble/have all robots put marble in box/y/whiz, get marble/have all robots put marble in box/y/auda, get leaflet/iris, get leaflet/poet, get leaflet/have auda and iris and poet and sensa put leaflet in box/y/have all robots drop leaflet/y”.[/code][/spoiler]

I think there’s an extension which allows you to “party” multiple characters and issue group commands.

Thank you, Matt! Do you mind if I borrow a bit of this code?

One suggestion: make your parser hack a “for reading a command” rule so that the player doesn’t need to type anything next turn. If you make the commanding action out of world, the player won’t even see that it’s taking more than one turn. (C.f. “Art of Fugue”; four commands are parsed each “turn” by means of a “for reading a command” rule.)

Borrow it all, please!

Wow, now that I’ve looked at the Art of Fugue source code the “for reading a command” hack was far easier than I expected – I was expecting to have to do some crazy I6 magic but literally changing the word “After” to “For” worked. If we make commanding an action out of world we have to change the “Before commanding” rule to a “Check commanding” rule but that should be OK.

There’s still the problem about having “You can only have something animate do something” printing a huge number of times, but that’s solvable, and the issue about how to process “poet and waldo, kiss iris” into “have poet and waldo kiss iris,” but we’re a lot farther toward getting this done than I expected.

So here’s the current (6G60) code, with the business about the command prompt removed since we don’t need it anymore:

[spoiler][code]Include Editable Stored Actions by Ron Newcomb.

The list of commanded actors is a list of persons that varies. The list of commanded actions is a list of stored actions that varies.

Commanding is an action out of world applying to one visible thing and one topic. Understand “have [things] [text]” as commanding. [Basically, when the player types this, we store the list of people in one list and the command that was typed in a text. Then the next turn, no matter what’s typed that turn, we parse this typed command and apply it to all the people in our list. It’s an action out of world so it doesn’t take a turn; the turn happens when we execute the next command.]

Executing a multicommand is a truth state that varies. Executing a multicommand is usually false. [A flag that tells us whether we’re in the mode where we’re about to throw out whatever is typed, parse the command we stored last turn, and apply it to all those people.]
The multicommand text is an indexed text that varies.

Check commanding when executing a multicommand is false:
repeat with item running through the multiple object list: [the multiple object list is the list of things that were processed by a “things” command]
if item is not a person, say “You can only have something animate do something.” instead. [If we let things that weren’t animate into the list of things that were going to perform the action next turn, it would be bad. This can wind up printing the error message far too many times; if we were going to make this work for real we’d want to make sure it only printed once a turn.]

Disambiguation in progress is a truth state that varies.

Carry out commanding when executing a multicommand is false: [This sets up all the stuff we need to actually have the actions happen next turn]
now executing a multicommand is true; [so we know that next turn we do the stuff]
now the list of commanded actors is the multiple object list; [this is the list of things that were understood by the [things] token]
now the multicommand text is “[the topic understood]”; [this is the text understood by the text token; so when the player types “have sam and dave soothe me” the multiple object list is {Sam, Dave} and the topic understood is “soothe me”]
now disambiguation in progress is false.

For reading a command when executing a multicommand is true and disambiguation in progress is false:
change the text of the player’s command to “[the multicommand text]”. [This changes the text of the player’s command to whatever we stored last turn. Then we can parse it as a command. Reparsing the command in one turn would take some crazy parser hacking that I’m not at all capable of. And since this is the “for reading a command” rule, this has essentially taken over the loop where the game asks for a command and processes it, so the player won’t see that this is taking place on a different turn.]

First before when executing a multicommand is true:
now executing a multicommand is false; [this makes sure we go back into ordinary interaction mode]
now the list of commanded actions is {}; [now we make a list of actions to execute]
repeat with the agent running through the list of commanded actors:
let the temporary action be a stored action;
now the temporary action is the current action; [the one that got parsed from the command]
change the request part of the temporary action to true;
change the actor part of the temporary action to the agent; [we’ve used the Editable Stored Actions extension to turn the action that we originally processed from something that the player would do into something that the agent would do, and we’ve set a flag so that it gets processed as a request from the player rather than as an autonomous action by the agent]
add the temporary action to the list of commanded actions; [so that there’s one action on the list for every commanded actor]
repeat with the happening running through the list of commanded actions:
try the happening; [now we’re actually carrying out all those requests]
stop the action. [this prevents Inform from actually trying out the action we parsed]

First check commanding when executing a multicommand is true: stop the action. [This means that when we’re running through the multiple object list after entering the “Have Sam and Dave soothe me” command we don’t go through the previous rule and prematurely reset the executing a multicommand flag]

This is the announce items from multiple object lists when not commanding rule:
if not commanding, follow the announce items from multiple object lists rule.
[Ordinarily when you do actions on multiple items, the announce items from multiple object lists rule says “Rock: Taken. Roll: Taken.” or something like that. We don’t want that to happen when we’re commanding so we write a rule that only prints that text if we’re not commanding. If we were in 6L02 there would be an easier way to do this.]

The announce items from multiple object lists when not commanding rule is listed instead of the announce items from multiple object lists rule in the action-processing rules.

Before asking which do you mean when executing a multicommand is true:
now disambiguation in progress is true.

Persuasion rule: persuasion succeeds. [This just means that people will try to do things we ask them to.]

[and here’s some stuff for them to do. not sure why I put in all these rooms]
The Command Center is a room.
A robot is a kind of person. Understand “robot” as a robot. Understand “robots” as the plural of a robot.
A persuasion rule: persuasion succeeds.
Auda, Iris, Sensa, Waldo, Whiz, and Poet are robots in the command center.

A marble is in the command center. The box is a container in the command center.
A leaflet is a kind of thing. Six leaflets are in the command center.

A brown hat is in the command center. A brown shoe is in the command center.

A room called the Weather Monitors is west of the command center.

A room called the Transit Monitors is south of the command center.

A room called the Hydroponics Monitors is east of the command center.

Instead of an actor kissing Iris:
say “Iris slaps [the actor].”;
rule succeeds.

Instead of Waldo kissing Iris:
say “Iris says, ‘oh you!’”;
rule succeeds.

Test me with “have poet and waldo kiss iris/have all robots get leaflet/ auda, get marble/have all robots put marble in box/whiz, get marble/have all robots put marble in box/auda, get leaflet/iris, get leaflet/poet, get leaflet/have auda and iris and poet and sensa put leaflet in box/have all robots drop leaflet”.
[/code][/spoiler]

Now this is still going to require some twiddling to make sensible things happen with multiple objects of the same kind; it’s still the case that “drop leaflet” has all the robots drop the same leaflet. Though hmmm, maybe we could make the reading a command activity do “auda, drop leaflet” etc. and parse them all in turn. I guess that’s what Art of Fugue does.

In “Suspended”, the only game I know of which uses something like this, the implementation seems to be something like this:

  • Does the command match “both [actor1] and [actor2], [verb] [noun]”?
  • Is the verb “move”? (verbs other than “move” get an error from the FCs)
  • Is the noun the one object in the game for which this syntax works? (nouns other than that one get an error from the FCs)
  • Can actor1 see noun?
  • Set a flag, then have actor2 try to move the noun.
    This leads to some odd glitches, such as “BOTH SENSA AND SENSA, MOVE IT” being accepted (it never checks whether actor1 and actor2 are the same). And since the action is only carried out once, it doesn’t really make sense except for the one time in the game this syntax is needed. (If I were designing it, I would have simply disallowed taking things from the cabinet unless Sensa is “holding” the flowswitch in place, thus requiring two robots without introducing awkward new syntax.)

About parsing it once verses parsing it multiple times: I suppose it really comes down to what behavior you want for ambiguous commands. In a game with lots of timed sequences it might be fairer to only parse once, so that a clever player can’t “cheat” by causing multiple disparate actions on the same turn. But in a game where the actors can be in different rooms, parsing only once could lead to a lot of “can’t reach into…” errors.

Okay, this was much messier than I had expected it to be. But here’s an implementation that parses each command separately. If you include my extension “Modified Timekeeping” a multi-command takes only one turn, as it ought to, rather than one turn for each actor.

Include Editable Stored Actions by Ron Newcomb.

Commanding it to is an action out of world applying to one visible thing and one topic. Understand "tell [things] to [text]" or "command [things] to [text]" as commanding it to.

The multicommand text is text that varies. The multicommand actor list is a list of objects that varies. The multicommand action list is a list of stored actions that varies. The multicommand flag is initially false. The multicommand disambiguation flag is initially false. The multicommand stored actor is initially nothing.

Check commanding someone to a topic when the multicommand flag is true (this is the multicommand mutex rule): stop the action.

Carry out commanding someone to a topic when the multicommand flag is false (this is the set up multicommand list rule):
	if the multiple object list is empty: [This is empty if only one noun was specified.]
		now the multicommand actor list is {};
		add the noun to the multicommand actor list;
	otherwise:
		now the multicommand actor list is the multiple object list;
	now the multicommand text is the substituted form of "[topic understood]";
	now the multicommand stored actor is the player;
	now the multicommand flag is true.

[Rule for reading a command when the multicommand flag is true (this is the replace command with multicommand rule):
	let T be text;
	repeat with the subject running through the multicommand list:
		let U be T; [Store it separately for a moment.]
		let T be the substituted form of "[U][subject], [multicommand text]. "; [Add the subject to the command, so "TELL ALICE AND BOB TO PUSH THE BUTTON" turns into "ALICE, PUSH THE BUTTON. BOB, PUSH THE BUTTON. "]
	change the text of the player's command to T;
	say "([T])[command clarification break]";
	now the multicommand flag is false.]

Rule for reading a command when the multicommand flag is true and the multicommand disambiguation flag is false (this is the replace command with multicommand rule):
[	say "DBG: changing to [entry 1 in the multicommand actor list].";	]
	now the player is entry 1 in the multicommand actor list;
[	say "DBG: changing command to [multicommand text].";	]
	change the text of the player's command to the multicommand text.

Before asking which do you mean when the multicommand flag is true (this is the multicommand begin disambiguation rule): [So as not to replace commands while disambiguation is in progress...]
	say "(for [the printed name of player])[command clarification break]";
	now the multicommand disambiguation flag is true.

After reading a command when the multicommand disambiguation flag is true (this is the multicommand end disambiguation rule):
	now the multicommand disambiguation flag is false.

First before doing anything when the multicommand flag is true (this is the cut off multicommand actions rule):
	let the parse result be a stored action;
	now the parse result is the current action;
	now the actor part of the parse result is entry 1 in the multicommand actor list;
	now the request part of the parse result is true;
	add the parse result to the multicommand action list;
[	say "DBG: removing [entry 1 in the multicommand actor list].";	]
	remove entry 1 from the multicommand actor list;
[	say "DBG: changing back to [multicommand stored actor].";	]
	now the player is the multicommand stored actor;
	if the multicommand actor list is empty: [Time to execute these actions!]
		repeat with the order running through the multicommand action list:
		[	say "DBG: trying [the order].";	]
			try the order;
		now the multicommand actor list is {};
		now the multicommand flag is false;
		silently try waiting; [To make one turn go by.]
[	say "DBG: stopping.";	]
	stop the action.

The announce items from multiple object lists rule does nothing when the multicommand flag is true.

Note that this is 6L02 code, but it would be much the same in 6G60. My first attempt is commented out; it would have been much easier, but Inform parses a command like “ALICE, JUMP. BOB, JUMP.” as “asking alice to try jumping” followed by “answering alice that ‘bob, jump’”.

This causes an infinite loop if I “tell Alice to tell Bob to jump”, due to the mutex. Is there a good way to avoid this?

I don’t have time right now to readapt this to 6G60 – what does an “actions” trace get you in the infinite loop case? Is it getting turned into actions or what?

Alice keeps trying to command Bob to perform an action, but the mutex blocks it (because there’s already a commanding action going on), so the Before rule is never reached, so the mutex is never released.

Can you just set a flag so the mutex rule doesn’t fire when the actor/person asked isn’t the player? Or is actor/person asked not set for an action out of world?

If actor/person asked isn’t set for an action out of world, maybe it’d be better to ditch the “action out of world” stuff and use Modified Timekeeping to prevent the extra turn from being taken.

(It’s also worth thinking about how this will handle Undo, though one approach would just be to forbid undoing this stuff.)

Also on the other stuff I was envisioning multiparsed commands so you could do things like command every child to take a lunchbox, or >ALL N LISTEN FOLKS, DRAW SWORD WAVE, though in that case it’s not totally clear whether separate objects are called for (surely the swords are implemented separately, but is the “sword wave” just a kind of value?)

Here’s a rule that allows BOTH SENSA AND WALDO, MOVE FRED and ALL ROBOTS, REPORT:

After reading a command (this is the modified multicommand parsing rule):
	if the player's command includes "both" or the player's command includes "all": [This check is faster than attempting a regex on every command.]
		let T be "[the player's command]";
		replace the regular expression "^(both|all)\s((\w|\s)+)\," in T with "tell \2 to";
		change the text of the player's command to T;
		[say "DBG: modified command to '[T]'."]

It still can’t handle WALDO, IRIS, AND POET, GO TO SUB SUPPLY (or anything with commas in it, really), so you need to use the TELL syntax for that.

I’ve also found a solution to the “leaflet problem”, but it requires Modified Timekeeping to work. Is that acceptable?

EDIT: So ALL N LISTEN FOLKS, DRAW SWORD WAVE can now be parsed, with the proper Understand lines! (It becomes TELL N LISTEN FOLKS TO DRAW SWORD WAVE, which becomes DRAW SWORD WAVE for each northern listener.)

All rootie! Now we just need to implement the rest of that game.

EDIT: Is there a way to catch IRIS AND WALDO, MOVE FRED? Maybe looking for “and” before the comma, although I guess that’s slow?

If I try implementing this myself I think my solution might be just to convert everything of the form “foo, bar” to “tell foo to bar” and then redirect parser errors at the commanding stage to the answering it that expression, or if the solution to the leaflet problem just turns it back into “foo, bar” then that’ll be fine (as long as I don’t create an infinite loop, heh heh heh). Can’t speak for dootdoot but for any purposes I might have depending on Modified Timekeeping probably wouldn’t be a problem – where can I grab it?

That would work, but I’m not sure how to accomplish it–both the actor section and the action section can contain multiple commas, so how to find the right one? It will probably require some I6 hacking.

Modified Timekeeping is on GitHub here.

Well, I can this of two solutions: either pick the last comma (when would the action section have commas?) or politely tell the player not to use multiple commas. Or there could be a blend, where we pick the last comma and if the action winds up failing to parse (and the original command contains multiple commas) we politely tell the player not to put a comma in a multiparsed command.

Thanks for Modified Timekeeping! I was wondering if this could also be compatible with Variable Time Control, but it looks like in Variable Time Control even actions that take no time run the every turn rules, so that wouldn’t be useful here.

I was thinking of things like “WALDO, TAKE THE ROUGH DEVICE, THE SMOOTH DEVICE, AND THE BUBBLY DEVICE” (in which it’s the first comma that we need to look at).

Probably the best way would be to read from the beginning of the command until the parser hits a verb (something like “[things], [topic]” in an Understand line would be ideal, but you can’t Understand commas). I don’t know how commands to other actors are parsed right now, but it might be possible to add this in there.