Create an action with three verbs

I am creating a lot of “internal” actions without an understand line, that will be used by the engine but not be user commands (as suggested by zarf here). The reason: using the stored actions feature to keep a list that will be performed later.

I’ve realized that I need to know which room these actions happen in. So I thought that perhaps I could put the room inside the action itself: ignite [thing] at [room]. But what about impact [thing] at [thing] at [room]?

After searching the docs and reading the thread Understanding the limitation of actions to two nouns, I know now that default Inform accepts only two nouns in an action (still true?).

The accepted solution from that thread is for a case too simple for me: two verbs with the same syntax that get rolled in the same verb and identified by pattern matching. I have a lot more values.

I have seen the code by @Draconis in Actions using three things. It might work, but it says: Note, however, that the third noun is not part of the action per se. Does this imply that I wouldn’t be able to include the third noun in a stored action? Because storing the action is the whole point.

I’d be thankful for any other idea. If there’s no practical way to put three nouns in a stored action, I’ll use a table with actions and rooms, but working with the table will be more fiddly than working with the list.

2 Likes

Correct, there’s no place to store it in a stored action.

You could roll your own stored actions. Make a kind of object with an action name property and three object properties. Use the method I described here Temporarily cloning objects - #6 by Zed to fake having dynamic objects. Be careful that the object properties will default to yourself… you’ll probably want to change that. Then you can make lists of these to your heart’s content. Just remember to recycle all the ones you don’t need anymore.

3 Likes

Thanks. That’s interesting, but your code reads like advanced quantum physics to me. I took a look at the Dynamic objects extension, which I understood better. But I have doubts about it. I’m a total Inform newbie with the goal of hacking it to work in ways it’s not supposed to. And, I may add, for a game design that is, a priori, a Very Bad Idea. The wrong tool, wrongly used, for the wrong goals*.

I’ll look into using dynamic objects to solve this three-noun problem a bit more, but it feels like a step too far. I find tables boring and irritating but simple.

*What my most successful game did.

I’m afraid the Third Noun extension won’t help with this. It allows the parser to recognize a third noun in a grammar line, but the “stored action” kind only has slots for two, so the third noun will get left out.

That said, a stored action remembers who is meant to do the action, and generally the location of that person will be where it happens. Or if you want to get really hacky, just repurpose the “actor” slot for the room, and voilà, three objects in a stored action.

(I’ve actually done something akin to that before, with the actor part of an action being the door that closes itself.)

4 Likes

I decided to try to do something simple to simulate stored actions having a third noun. It worked out kind of like most of my attempts to do something simple.

Include (-
Global third_noun;
-) after "Definitions.i6t".

Include (-
[ THIRD_NOUN_TOKEN x;
  x = ParseToken(ELEMENTARY_TT, NOUN_TOKEN);
  if (x == GPR_FAIL or GPR_REPARSE) return  x;
  third_noun = x;
  return GPR_PREPOSITION;
];
-).

The third noun is an object that varies.
The third noun variable translates into I6 as "third_noun".

The understand token third something translates into I6 as "THIRD_NOUN_TOKEN".

To say full action of/for (ac - action):
  say "action name: [action name part of ac].";
  say "actor: [actor part of ac].";
  say "noun: [noun part of ac].";
  say "second noun: [second noun part of ac].";
  say "third noun: ";
  if the action name part of ac is triplicate,
    say the thing to which ac relates by the triumvirating relation;
  else say "nothing";
  say ".[line break][line break]";

action-list is a list of actions that varies.

First after doing anything:
  add current action to action-list; continue the action.

Lab is a room.

[ action names can't have properties so this is our work-around ]
Tripling relates various action names to various things.
The verb to triple means the tripling relation.

[ To mark that a given action name takes a third noun,
we'll assert that `<action name> triples yourself`. 
There's no special significance to using `yourself`,
any object would do. But since we know `yourself` always
exists, it's the obvious choice. ]

To decide if (acn - action name) is triplicate:
  decide on whether or not acn triples a thing.

Fooing is an action applying to two things.
Understand "foo [something] in/on [something] with [third something]" as fooing.
The fooing action triples yourself.

[ for no good reason, you can't create a relationship with
`object`s as domain or range so we use `thing`s ]
Triumvirating relates various actions to one thing.
The verb to triumvirate means the triumvirating relation.

To decide what action name is the current action name:
  (- action -).

Setting action variables:
  if the current action name is triplicate, 
    now the current action triumvirates the third noun;

To decide what K is a/-- null (name of kind of value K): (- nothing -)

to decide what thing is the third noun of (ac - action):
  if ac relates to a thing by the triumvirating relation,
    decide on the object to which ac relates by the triumvirating relation;
  decide on the null thing.

before doing anything:
  say "current action: [current action]. third noun: [third noun of current action].".

instead of jumping:
repeat with ac running through action-list begin;
  say full action for ac;
end repeat;

test me with "foo me in me with me / x me / jump"
3 Likes

Thanks Zed. Did I tell you I’m using your Inform manual website all the time? It’s great.

On the other hand, I don’t understand anything that is going on in that code. :sweat:

2 Likes

Not my case. I’m storing the actions for things that are caused by the player but not done by anyone, and the player may leave the location before they happen, in which case I need to treat them differently (no narration).

How would you do it? Writing something like a room doing something gives a compilation error. How can you make Inform accept things or rooms in the actor? I looked at your code with the portal closing itself and I don’t understand how it happens.

Unless I’m mistaken, the “same” action with two separate third nouns will end up with only one entry in the relation storage, so >FOO X IN Y WITH M followed by >FOO X IN Y WITH N results in both entries in the action-list showing a third noun of N.

I think you should be able to say:

let the new action be the location jumping;

Strange. Testing it in Borogove, let the new action be the location jumping does work. But putting a real room name in there, like let the new action be the laboratory jumping, doesn’t!

Today or tomorrow I’ll try seeing if this works in my system for real. Thanks.

You can also use Editable Stored Actions to modify the actor part directly.

1 Like

Ah cool. I remembered looking at a extension that added new components to stored actions, but I didn’t remember it allowed editing them!

oops!

Aaaaand it worked. I don’t even think this outrageous hack has any downsides since I read the room and then change the actor back to “yourself” before trying the stored action.

Thanks!

1 Like