I7: Cutting off a player's commands separated by periods

So in the following bit of code, I want to cut off the commands once you are transferred to Actionville.

In other words, z.z.z.z.z should have the final “z” cut off so that the unsuspecting player doesn’t wait in Actionville when he doesn’t want to.

Ignoring possible design questions (which are interesting in their own way,) is there any way to do this? Does it require under-the-hood tinkering?

[code]“waiting” by Andrew

Waitingville is a room.

Actionville is a room.

when play begins:
say “Z.z.z.z.z doesn’t (yet) work the same as z.z.z.z here.”

every turn:
if turn count >= 4 and player is in waitingville:
say “You are in Actionville now!”;
now player is in Actionville.

check taking inventory:
decrement the turn count;

check waiting in waitingville:
say “Yup, not much else to do here.” instead;

check waiting in actionville:
say “BANG! You get hit by a bus and die.”; [This unfairly punishes z.z.z.z.z at the moment.]
end the story instead;

test unfair with “z.z.z.z.z”[/code]

The library already has a system to cut off multiple actions of the form “take all”. (If taking a Portkey moves you to Actionville, further takes are cancelled.) It doesn’t cover this case, though.

There is certainly an under-the-hood way of doing what you want, but my first clever idea didn’t work. Drat.

I think I’ve got a bit of it, but then another bit I’m less sure about.

My idea was, you can set a flag in the “after reading a command” rule and then take it off in the “every turn” rules, so it will keep track of whether you’re carrying out the first command in a dotted sequence. Set another flag when you move to Actionville, and you should be able to interrupt the actions when you’ve moved to Actionville but you aren’t carrying out the first command.

What I’m not too sure about is the way I’ve interrupted the command. I used a rule to interrupt the turn sequence rules before the generate action rule, but I have no experience in messing with the turn sequence, so I’m not sure if it’ll create unforeseen effects.

Anyway, here goes:

[code]“waiting” by Andrew

Executing first command is a truth state that varies. Moved to Actionville is a truth state that varies. After reading a command: now executing first command is true; now moved to Actionville is false. Every turn: Now executing first command is false. [Maybe this should go in a special rulebook after the every turn rulebook, since it really ought to be last last last.]

Waitingville is a room. “Nothing to do here but wait.”

Actionville is a room. “Waiting here would be a very bad idea!”

when play begins:
say “Z.z.z.z.z doesn’t (yet) work the same as z.z.z.z here. OR DOES IT?”

A turn sequence rule when moved to Actionville is true and executing first command is false (this is the interrupt the turn when moving to Actionville rule):
say “[one of]We’re holding off on any further actions because you’ve just moved to Actionville.[or][run paragraph on][stopping]” instead.

The interrupt the turn when moving to Actionville rule is listed before the generate action rule in the turn sequence rules.

every turn:
if turn count >= 4 and player is in waitingville:
say “You are in Actionville now!”;
now player is in Actionville;
now moved to Actionville is true.

Every turn: say “This rule shouldn’t fire after you’ve moved to Actionville in one command.”

check taking inventory:
decrement the turn count;

check waiting in waitingville:
say “Yup, not much else to do here.” instead;

check waiting in actionville:
say “BANG! You get hit by a bus and die.”; [This unfairly punishes z.z.z.z.z at the moment.]
end the story instead;

test unfair with “z.z.z.z.z”[/code]

[EDIT: Changed the message for saying that we’d interrupted the commands after moving to Actionville, because the last one didn’t work.]

Wow! I have to admit I still don’t see the nuts and bolts, but I’ve never played with the turn sequence rules before, so there is a lot to learn here. I really appreciate this. This is definitely sample code worth hanging onto.

Oh, small detail, it works great, too.

Matt W’s solution seems a little complex. This seems to solve the original problem without digging into turn sequence rules.

[code]“Waiting” by Andrew

Waitingville is a room.

Actionville is a room.

Every turn when the turn count is at least four and the player is in waitingville:
say “You are in Actionville now!”;
now player is in Actionville;
now wait hold is true.

After reading a command when wait hold is true: now wait hold is false.

Wait hold is a truth state that varies. Wait hold is false.

Check taking inventory:
decrement the turn count.

After waiting in waitingville:
say “Yup, not much else to do here.”.

After waiting in actionville when wait hold is false:
say “BANG! You get hit by a bus and die.”;
end the story.

Test unfair with “z.z.z.z.z / z”.[/code]

Hope this helps.

[UPDATE: climbingstars’ solution seems to work for this particular case, but I think mine is more robust – and if preventing time from passing when you reject a command in Waitingville is important, it seems to do that.]

Well, I wouldn’t put too much stock in it until it’s been looked over by someone who really understands what’s going on. But here’s what I think is going on, looking at the chart of what rules are consulted in what order:

Ordinarily, the turn sequence rulebook starts with the “parse command” rule, which in turn begins by running the “reading a command” activity and then does other parsing. Then the turn sequence rulebook runs the “generate action” rule, which among other things runs the before rulebook, the instead rulebook, and the specific action-processing rulebooks (check/carry out/after/report for the action in question). Then in the turn sequence rulebook we have the “every turn” rulebook, and other stuff.

However when you have a bunch of commands joined together by dots, it seems as though the “reading a command” activity only happens once, even though the “parse command” rule fires every time through the turn sequence rulebook.

[spoiler]Try this:

[code]
Lab is a room. After reading a command: say “Command: [the player’s command].”

This is the new parse command rule:
say “Parsing!”;
follow the parse command rule.

The new parse command rule is listed instead of the parse command rule in the turn sequence rules.

Test me with “z. jump. sing . get foo. x me”.[/code]
As you can see, the new parse command rule fires once for each command, but the after reading a command rule only fires once. You can also see that the parser error interrupts the chain of commands.[/spoiler]

So what I did was set “executing first command” to true in the “after reading a command” stage, to make sure it stayed true the first time through the turn sequence rules. Then I set “executing first command” to false in the every turn rules, so that if we go through the turn sequence rules again without going through the “reading a command” activity again, “executing first command” will be false. This should only happen when we’re executing the second or later command in a dot sequence, I hope.

Of course it doesn’t matter whether we’re executing a dot sequence unless the rule that moves us to Actionville has run, so I used the “moved to Actionville” truth state to keep track of that.

Then I wanted to interrupt the turn sequence if we’d moved to Actionville and weren’t executing the first command. That’s what the “interrupt the turn when moving to Actionville” rule does – and since I want it to stop everything, I put it in the turn sequence rules instead of in the action-processing rules. So the “instead” in that rule stops the whole turn sequence rulebook. (This happens for each dotted command, which is why we need the business with “stopping” in the message that gets printed.) So the every turn rules don’t run, the advance time rule doesn’t run, none of that stuff.

One issue is that if you trigger a parser error, like “z.z.z.z.z.z.z.foo”, the parser error message will still print. That’s because parser errors happen in the “parse command” rule, and that fires before the “interrupt the turn” rule. (I tried putting the “interrupt the turn” rule before the “parse command” rule, but it led to an infinite loop; which may be because I didn’t take care in setting the initial values of my flags.) You could take care of that by writing a special rule for printing a parser error when moved to Actionville is true and executing first command is false, but you’d have to make sure that it prints out the relevant text if and only if you haven’t already printed it with the interrupt turn rule.

Well, I hope that made some sense, and anyone who understands this better than I did should totally chime in.

Wow–the discussion has sort of jumped ahead of me, but that’s good! The thing is, I’ve often been more than willing to accept what I think Inform’s limits are, given its power to Do What Those Infocom Guys Did and then some–but I don’t realize even more can be done, and I often shut down my vision for better stuff, so I’m glad people are looking into this.

There are still rules/rulebooks I haven’t had the time to explore, and the rules chart (which I’ve seen before) has taught me there’s still stuff I can learn, but I think I see the big picture, though.

And I’m glad to see it wasn’t just a lazy oversight on my part.

I may just have to cut/paste code like this and stare at it til I really understand what’s going on, but it’s going to help a lot.

Well, like I said, I don’t really understand what’s going on myself (but looking at the Index tab helped a lot in figuring out what to do).

One thing I realized is that my code is definitely too complicated – if “moved to Actionville” is true any earlier in the turn sequence rules than the every turn rulebook, then we must already have executed a command, so I don’t need an “executing first command” flag that’s set separately. Though it might be nice to have a general recipe for telling whether you’re executing the first command in a string.