One Liner or Simple Actions: cry, breathe, stop, etc

Occasionally, I want to make the parser respond to a simple verb that has no other action than providing some text. I feel loathe to create a whole new action for it. The only solution I’ve found is Understand “something” as a mistake, as in:

Understand "make sandwiches/sandwich/lunch", "help with/make sandwiches/sandwich/lunch" as a mistake ("Aunt Mary already has you working on the assembly line making tuna sandwiches.").

These can be relatively complex using if statements and [one of] statements within the text:

Understand
	"sing [text]" or "hum [text]"
	as a mistake
	("[sing_action][run paragraph on]").

Instead of singing:
	say "[sing_action]".

To say sing_action:
	say "You make up a song about [one of]killer red ants that eat everyone
[or]picking blackberries until your fingers are bloody[or]riding the train 
out of town and living like a hobo[at random] [one of][or]to the tune of 
'When You Need a Friend'[or]to the tune of 'Baby I'm a Want You'
[or]to the tune of 'American Pie'[at random].";

This is a great way to define simple verbs without the overhead and effort of Checks, Reports, and Carry Outs.

That is find as far as it goes, but the say action is essentially out-of-world. It is treated by Inform as a mistake. I would like that mistake to continue to tick the game clock.

Any ideas?

2 Likes

I’m not sure you’re helping yourself as much as you think by defining new verbs as mistakes. It’s not necessary for an action to have check and report stages. If all you’re doing in response is saying text, as you would with a mistake, you can stick that in a lone carry out stage:

Singing is an action applying to one topic.

Understand "sing" or "hum" or "sing [text]" or "hum [text]" as singing.

Carry out singing:
	say "You make up a song about [one of]killer red ants that eat everyone
[or]picking blackberries until your fingers are bloody[or]riding the train 
out of town and living like a hobo[at random] [one of][or]to the tune of 
'When You Need a Friend'[or]to the tune of 'Baby I'm a Want You'
[or]to the tune of 'American Pie'[at random].";

Otherwise, if you want to silently tick over a turn normally without the parser having generated an action, you will need to call a long list of turn sequence rules. Note that invoking an action within a ‘mistake’ text by invoking code like ‘try waiting silently’ will run the requested action but still not run all the normal turn sequence rules, so everything remains ‘out-of-world’.

Other than that, there are complicated ways that you could ‘fool’ the parser into running a full turn sequence without input and generating a silent ‘do-nothing’ action, but I suspect that game is not worth the candle.

2 Likes

However, here’s a neat way to do what you’re asking- it sets a flag variable to temporarily disable the turn sequence rules which normally get and parse input then generate an action, but runs all the others in sequence (including any new ones added by extensions or source). Note this won’t work and will need editing if either of these these two Standard Rules have been renamed or replaced by an extension.

Incrementing turn is initially false.
The parse command rule does nothing when incrementing turn is true.
The generate action rule does nothing when incrementing turn is true.

Understand "make sandwiches/sandwich/lunch", "help with/make sandwiches/sandwich/lunch" as a mistake ("Aunt Mary already has you working on the assembly line making tuna sandwiches.[paragraph break][next_turn]").

to say next_turn:
	now incrementing turn is true;
	follow the turn sequence rules;
	now incrementing turn is false;

Every turn: say "turn count is [turn count]".

test me with "make lunch / help with sandwiches".	
1 Like

I very much endorse Peter Bates first idea as to how you should make these actions (his carry out singing example) and do not endorse his second idea of manipulating the time/turn mechanisms :slight_smile:

The first way is clean and simple and gets the job done, and is the kind of thing I do all the time.

Playing with the time/turn sequence mechanisms I view as unnecessarily dangerous in general. It’s not that you can’t do it when you need to (and if I need to, I generally turn to tried and tested extensions first e.g. Variable Time Control, which gives you a phrase you can put in your code whenever you don’t want time to pass, amongst other things) rather than roll my own solution. But if you don’t need to, I wouldn’t.

-Wade

2 Likes

What’s life without a little danger :laughing: But as you say, meddle at your own peril with the arcane workings of the parser and be prepared for unintended consequences! The method described appears benign, but…

Do you know of a tried and tested extension that will do this? ‘Variable Time Control’ won’t help with this scenario.

Although, I have to agree that defining new verbs as ‘mistakes’ is an ‘abuse’ of the intended purpose of the ‘mistake’ syntax as described in the documentation, where it is encouraged as a means to prod the player toward entering expected syntax, not to subvert the usual parsing->action-processing sequence.

2 Likes

Anyway, here’s a less scary solution that seems to work- simply by switching the I6 out-of-world flag off:

Out-of-world is a truth state which varies.
The out-of-world variable translates into I6 as "meta".
To say  continue the turn: now out-of-world is false.

Understand "make sandwiches/sandwich/lunch", "help with/make sandwiches/sandwich/lunch" as a mistake ("Aunt Mary already has you working on the assembly line making tuna sandwiches.[continue the turn]").

Every turn:
	say "turn count is [turn count]";

test me with "make lunch / help with sandwiches".	

Ha, I am not one who can talk about not abusing Inform’s intended ways! I resolve almost everything at the Check stage because my brain cannot stand the Carry Out / Report / After splits. I also make and use variables for all my own scene-tracking rather than the scene mechanism, which never quite seemed to be tight enough for my purposes.

-Wade

1 Like

The mistake declaration doesn’t subvert the usual parsing sequence. It’s really a normal out-of-world action under the hood, except that it notes which grammar line (mistake line) was triggered and prints the appropriate text in the action body.

(The mistake action is defined at the I6 level, so you can’t write your own rules for it. But it’s not processed much different from any other out-of-world action.)

That said, there’s no point in trying to define a mistake which isn’t out-of-world. Just define a regular action and use it. Messing around with the turn sequence rules is a deeply baroque and confusing way to accomplish that.

1 Like

The point, as expressed by the poster, is to enable a somewhat more terse definition of some verbs, perhaps more reminiscent of I6 ‘style’ than I7. e.g.

Understand "make sandwiches/sandwich/lunch", "help with/make sandwiches/sandwich/lunch" as a mistake ("Aunt Mary already has you working on the assembly line making tuna sandwiches.[continue the turn]").

vs.

Assisting is an action applying to nothing.
Understand "make sandwiches/sandwich/lunch", "help with/make sandwiches/sandwich/lunch" as assisting.
Carry out assisting: say "Aunt Mary already has you working on the assembly line making tuna sandwiches.";

However, as I said above, I’m also not really sure that this game is worth the candle.

1 Like

Modified Timekeeping by Daniel Stelzer.

1 Like

I don’t think this works, at least in part because it depends on running the specific action-processing rulebook, which doesn’t happen for mistakes.

Here’s another method that requires even less effort to generate responses to ‘mistakes’ (i.e. commands that can’t be matched with any other grammar line), simply by listing in a table the input text to match alongside the text to output:

Table of Simple_Actions
topic	text
"make sandwiches/sandwich/lunch" or "help with/make sandwiches/sandwich/lunch"	"Aunt Mary already has you working on the assembly line making tuna sandwiches."

Erring is an action applying to one topic.
Understand "[text]" as erring.

Carry out erring:
	if the topic understood is a topic listed in the Table of Simple_Actions:
		say "[text entry][paragraph break]";
	otherwise:
		say "[text of parser error internal rule response (A)]";

This catches any command not matching any other grammar with the catch-all token [text] and diverts this to an action called ‘erring’, which checks if the text can be matched with a line in the table of Simple_Actions and if so, issues the corresponding response-and if not, the standard parser response to text not understood.

This method involves neither I6 hacking or interference with the turn sequence rules, and reduces setting up the responses to an exercise in simple form-filling :grinning:

Thanks, all. I bit the bullet. I converted all my mistakes to actions. As a programmer, this kind of sets my teeth on edge. but there you go:

Planning is an action applying to nothing.

Understand "plan" as planning.

Carry out planning:
	say "Good idea. What have you come up with?";

Speaking of one of these suggestions:

Finding is an action applying to one topic.

Understand "find [text]" as finding.

Carry out finding:
	say "You'll have to be more specific. Perhaps if you stop and observe what's around you.";

Is there a source in the documentation that pulls together the fil-in-the-blanks words (something, thing, visible thing, text, topic, room, etc) used in the commands

Something is an action applying to ____

or

Understand "something [_____]" as...

There’s no all-on-one-page summary. It’s chapter 17 in general.

Those blanks are not identical. The first must be a kind (either “thing” or a kind of value); see 17.6. (With the complication that you can say “visible thing” to relax the touchability requirement.)

The second – blanks in brackets in an Understand declaration – are called grammar tokens. Again, chapter 17, several sections.

I drew up this summary of what’s in the Index (under Actions->Tokens) and what’s in Chapter 17, which I find helpful as a reference. The hotlinks in the Index page are very useful for browsing.

An action needs two things to anchor it fully in the game world:
(i) (Photographing) is an action applying to nothing/(one/two) (visible/touchable/carried/–) (thing(s)/value(s)) [and one…] [and requiring light]. → a framework for how the action works in the game world
NB 1 ‘thing’ here means object, so includes rooms, regions and directions.
NB 2 confusingly, ‘visible’ here means ‘within the universe’ not the more usual ‘visible to the actor’. So it includes for example the compass directions and objects out-of-play- although when parsing the player’s commands, by default objects not visible in the usual sense will generally be excluded from consideration by grammar lines (see below), usually with the retort ‘You can’t see any such thing.’. Without specifying ‘visible/carried’, ‘touchable’ is the default. ‘carried’ is a more restrictive form of ‘touchable’ and will ordinarily invoke a preliminary attempt to take an object not already held by the actor, announced by (first taking the …)
NB3 the ‘touchable’ criterion is applied only to things, not other objects such as rooms or regions, so perversely, in the case for example of a room, a ‘touchable thing’ in an action definition is sometimes allowed to be neither a thing nor touchable.
(ii) Understand “photograph [someone]” as photographing. → grammar line(s) to allow the parser to recognise the action in what is typed by the player
NB4 It is possible to create ‘untypable’ actions with no corresponding ‘Understand…’ lines, which are thus not directly accessible to the player via typed commands and the parser but can nevertheless be invoked by Inform code such as ‘Instead of taking the rose, try plucking the rose’
NB5 Since scope is only something of concern to grammar tokens and hence the parser- as are any other considerations imposed by tokens and grammar lines- actions invoked directly by Inform code need only comply with the basic framework outlined in (i). Thus we can legitimately write ‘try talking to the location’ even though rooms are ordinarily neither in scope nor persons to be talked to.

built-in tokens:
[something] → an object in scope for the actor § §§
[thing] → a thing in scope for the actor
[things] → a list of one or more objects in scope for the actor
[other things] → a list of one or more objects in scope for the actor which are not the other object mentioned (e.g. a container)
[things inside] → a list of one or more objects in or on the other object mentioned (e.g. a supporter/container) and in scope for the actor
[something preferably held] → as with [something], but choose a held object over others with same name, try implied take if present but not held
[things preferably held] → as with [things], but choose a held object over others with same name, try implied take if present but not held
[somebody] / [someone] → synonyms == a person §§§§§ in scope for the actor => the [second] noun (rather than ‘the person understood’)
[text] → an unparsed sequence of words => a snippet called ‘the topic understood’ §§§
[a time period] → a period of time §§§§ => a time called ‘the time understood’
[description of objects/values] → matching any description of objects ([open door]) in scope for the actor, or of values ([even number])
→ [description of directions] references directions. NB directions are ‘visible’ (in the sense of ‘in the universe’) but not ‘touchable’ (see above)
→ prefixing ‘any’ e.g. [any open door] removes the restriction that an object must be in scope for the actor
→ [any thing] will allow any thing, in or out of the game world == [anything]; similarly [anybody], [anyone], [any object]
→ [any (description of rooms/regions)] thus allows reference to rooms or regions, not otherwise mentionable in typed commands unless deliberately placed in scope
→ [anywhere] == [any room]
→ the Index indicates which built-in values have a corresponding Understand token
=> for values, a value called ‘the (kind) understood’
=> for objects, the [second] noun

§ ‘in scope for’ is a subtly different concept to ‘visible to’. Formally, an object is in scope for an actor if it can be referred to by the parser when creating an action for that actor from a typed command. Although most things an actor can see will be in scope and vice versa, there are exceptions- a common example being the actor’s possessions when in darkness, which are invisible but in scope.
See here and here.

§§ generally, grammar tokens refer to objects and are not restricted to things. Exceptions are [thing], [any thing] and (very confusingly) [any something], which are restricted to things. [things] also refers to objects rather than things! NB [object] is not itself a built-in token, although (again confusingly) [any object] and [objects] are…

§§§ this is something of an exception, for historical reasons, to the general ability to refer to a successfully-parsed grammar token as ‘the (kind) understood’, which here would otherwise be ‘the snippet understood’. The number representing ‘the topic understood’ snippet can be found in the I6 variable parsed_number. Using ‘the noun’ and ‘the second noun’ to refer to the first and second object parsed are also exceptions. But we say for example ‘the number understood’ or ‘the time understood’ or ‘the colour understood’ for values. There is also ‘the person asked’ for constructions such as ‘Bob, open the box’.

§§§§ this special token is provided because [a time], which follows the general [description of values] pattern, matches only specific times of day but does not match ‘21 minutes’ for example, even though this is also of kind time. However, the parsed value is still referred to as ‘the time understood’ rather than ‘the time period’ understood.

§§§§§ or more accurately, a person or an object which can be spoken to, i.e. one that has the Inform 6 attribute ‘talkable’. This distinction is not usually utilised in Inform 7, which does not ordinarily create ‘talkable’ objects that are not persons. The grammar token [person] is formally restricted to persons.

1 Like