Pushing and pulling my brand new leopard-skin pillbox hat

Confused and back again! Although i’m not confident this time that there is a functional solution to this problem.

i’m using the Leopard-skin example from the recipe book. The sequence i want the player to follow involves pulling/pushing a lever, and pushing two buttons. These three objects are all devices.

i have some “understand” aliases so that you can pull the lever to switch it off, and push each button to switch it on (instead of typing “switch on button,” “switch off lever,” etc, which would be unnatural).

The sequence i want the player to follow looks a bit like this:

When play begins: add switching off the large lever to the controls-sequence; add switching on the green button to the controls-sequence; add switching on the large lever to the controls-sequence;

The problem is that it works if i input the sequence exactly as prescribed:

… but it doesn’t work if i input aliases:

So CAN it ever work? Or does my player have to enter commands exactly as prescribed? Or do i have to create a bunch of different sequences to check against (all of which essentially say the same thing)?

Don’t use “understand” aliases for this sort of thing. Rely on the standard grammar, and write “check” or “before” rules to catch actions and trigger other actions. E.g

Check pulling the lever: instead try switching on the lever.

(or however it should be set up.)

I’m going to guess that you’re trying something like this (it helps to paste your code, ahem ahem).

[On preview: zarf is correct that you shouldn’t be using “Understand” aliases, but on the other hand if you were using “Understand” aliases you wouldn’t be having the problem, and if you do it the right way you do get the problem since the list of stored actions won’t be what you want; so I’m going to proceed with this. Anyway: Please do paste in your code!]

[code] “Leopard-skin”

The Fur-Lined Maze is a room. “Not actually fur-lined anymore.”

The large lever is a device in the Fur-Lined Maze. The green button is a device in the Fur-Lined Maze.

Instead of pushing the large lever: try switching on the large lever.
Instead of pulling the large lever: try switching off the large lever.
Instead of pushing the switched on green button: try switching off the green button.
Instead of pushing the switched off green button: try switching on the green button.

The controls-sequence is a list of stored actions that varies.

When play begins:
add switching off the large lever to the controls-sequence;
add switching on the green button to the controls-sequence;
add switching on the large lever to the controls-sequence;

The attempted-sequence is a list of stored actions that varies.

Every turn when the player is in the Fur-Lined Maze:
truncate the attempted-sequence to the last two entries;
add the current action to the attempted-sequence;
showme the attempted-sequence;
if the attempted-sequence is the controls-sequence:
say “That does it! You are instantly transported from the maze!”;
end the story finally.[/code]

I think you’re right that this particular implementation won’t work with synonyms. When you get to the “Every Turn” rules, the current action is the top-level action for the turn, that is, the one that was generated from the player’s command. So it won’t catch that this action was equivalent to the one on the list.

Here’s a workaround, though. Every time a new action gets tried from within another, the usual action rules for it run; in particular, the Before rules will always run. So we build up a list of every action that got tried in a turn, by making a Before rule that will add the current action to that list. We make the attempted-sequence into a list of these lists of actions, and then instead of checking whether the attempted-sequence is the control-sequence, we write a phrase that checks whether every entry in the control-sequence can be found in the corresponding entry of the attempted-sequence (the corresponding entry itself will be a list of actions).

So like this:

[code]“Leopard-skin”

The Fur-Lined Maze is a room. “Not actually fur-lined anymore.”

The large lever is a device in the Fur-Lined Maze. The green button is a device in the Fur-Lined Maze.

Instead of pushing the large lever: try switching on the large lever.
Instead of pulling the large lever: try switching off the large lever.
Instead of pushing the switched on green button: try switching off the green button.
Instead of pushing the switched off green button: try switching on the green button.

The controls-sequence is a list of stored actions that varies.

When play begins:
add switching off the large lever to the controls-sequence;
add switching on the green button to the controls-sequence;
add switching on the large lever to the controls-sequence;

The actions tried this turn is a list of stored actions that varies.

The attempted-sequence is a list of lists of stored actions that varies.

First before: add the current action to the actions tried this turn.

Every turn when the player is in the Fur-Lined Maze:
truncate the attempted-sequence to the last two entries;
add the actions tried this turn to the attempted-sequence;
if the attempted-sequence could be the controls-sequence:
say “That does it! You are instantly transported from the maze!”;
end the story finally;
truncate the actions tried this turn to 0 entries. [reset it for the next turn]

To decide whether (meta-L - list of lists of stored actions) could be (L - list of stored actions):
if the number of entries in L is not the number of entries in meta-L, no;
repeat with N running from 1 to the number of entries in L:
if entry N of L is not listed in entry N of meta-L, no;
yes. [/code]

You might want to look at §11.16 if the “yes/no” stuff in the last phrase is confusing.

So, there’s a way around the issue without creating everything by hand, but it takes a little work! Also I haven’t tested it very robustly.

Thanks so much, gang.

The yes/no stuff isn’t confusing, because i grok the concept of failing conditionals and falling through the structure. But iterating through arrays in Inform7 (and especially arrays of arrays) looks completely bizarre to me, and again, it would have taken me years to arrive at this solution on my own (if ever). Thanks for showing me the way!

My game is almost finished, and this bit, i think, is the final and most complex piece of it. Expect less harassment soon. But i must say, for all of the challenges i’ve had with the documentation, i have been mightily impressed with the community here - the responsiveness and the willingness to help. It’s been a dream.

Thanks!

The way I iterated through the lists there, and used a list of lists, is kind of unusual for Inform; I have a penchant for doing weird things with lists and tables sometimes. Although I’m afraid that the more Informy way of doing things will be even less grokkable for someone with your programming background.

Often when you’re iterating through lists you’d do something like this:

Repeat with dummy action running through the controls-sequence:

What that will do is create a temp variable called “dummy action” and set up a loop where dummy action first takes on the value of the first entry in the controls-sequence, then of the second entry, and so on. But in this case I couldn’t do that because I wanted to check two lists at once–I wanted to match entry 1 of L against entry 1 of meta-L, entry 2 of L against entry 2 of meta-L, and so on. So it was a lot better just to set up a counter and use that to look up the entries in the two lists.

The other tricky thing, I guess, might be this:

if entry N of L is not listed in entry N of meta-L, no;

What’s going on here is that L might be something like {switching off the lever, switching on the button, switching on the lever}, while meta-L might be {{switching off the lever}, {pushing the button, switching on the button}, {pushing the lever, switching on the lever}}. So when N is 2, for instance, that code would boil down to:
if switching on the button [entry 2 of L] is listed in [the list] {pushing the button, switching on the button} [entry 2 of meta-L]
which comes out true. But it is a somewhat convoluted bit of code.

(Also, it might look like what happened is that I took the code and just added this workaround, but what really happened was that I took the code, totally changed the approach so that the game tried to keep a list of the actions you still had to perform and reset the list if you messed up, encountered a run-time error that I’d never seen before and didn’t understand, tried to work out where that error came from, failed, gave up and tried a different approach where you used a counter to keep track of where you were in the sequence of actions, got that working, started writing something about how that didn’t work in certain edge cases, realized those edge cases were actually not edge cases, and then thought of the workaround I posted. So it’s not like even somewhat experienced folks don’t have issues sometimes.)