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.