Preference an action during a scene

Otis’ "[any navigable object]" above is a clever way to express allowed things in one grammar token, and it obviates the need for putting things in scope manually as in my example.

I think the easiest way to handle this would be to do something like this. (Sorry, I don’t have time right now to put a properly functional version together, or indeed to test whether or not this is nonsense.)

Understand [COMMANDS] as landmark_navigating when [SCENE] is happening.
Understand [COMMANDS] as room_navigating.
Understand [COMMANDS] as landmark_navigating.

I think that should lead to the grammar lines for landmark_navigating taking priority during SCENE, but not at other times.

Sadly not, unless all the [COMMANDS] are identical for room_navigating and landmark_navigating, since the presence of a condition has the lowest priority of all apart from source text order when the compiler is ordering grammar lines.

There are hacky ways of forcing priority on the compiler, but as suggested earlier in this thread, IMHO this whole approach really isn’t a good way to try to implement game mechanics.

The compiler orders things the way it does to optimise sensible parser responses to a wide range of input, which is probably at odds with interfering to drive game mechanics.

As is generally the case with Inform, if you’re fighting the system you’re probably missing a better way of achieving your goal.

I’m experimenting with combining room_navigating and landmark_navigating. Then since this added more and longer grammar lines, climbing_something took precedence and had to be combined as well. So the strategy of one navigation action to rule them all ends up having tons of grammar lines and tons of conditions (though Otis’ Carry out navigating a room could help).

Navigating is an action applying to one thing.
Understand
	"go back/-- to/near/by/-- [any reachable room]",
	"go back/-- to/near/by/-- [any elusive_landmark]",
	"walk back/-- to/near/by/-- [any reachable room]",
	"walk back/-- to/near/by/-- [any elusive_landmark]",
	"run back/-- to/near/by/-- [any reachable room]",
	"run back/-- to/near/by/-- [any elusive_landmark]",
	"return to/near/by/-- [any reachable room]",
	"return to/near/by/-- [any elusive_landmark]",
	"follow [any reachable room]",
	"follow [any elusive_landmark]",
	"climb on/onto/in/into/over/through/under/-- [visible thing]", 
	"climb up in/into/on/onto/-- [visible thing]",
	"hop on/onto/in/into/over/through/under/-- [visible thing]", 
	"hop up in/into/on/onto/-- [visible thing]",
	"scale on/onto/in/into/over/through/under/--  [visible thing]", 
	"scale up in/into/on/onto/-- [visible thing]",
	"jump on/onto/in/into/over/through/under/-- [visible thing]", 
	"jump up in/into/on/onto/-- [visible thing]",
	"cross up/on/onto/in/into/over/through/under/-- [visible thing]",
	"go up/on/onto/in/into/over/through/under/to/-- [visible thing]"
	as navigating.

This approach violates my sense of programming elegance, and it might be hard to manage. This is a possibility, but is it a good idea? Is it the most elegant, modular, extensible approach? Originally I wanted to find a solution to my small problem without digging in deeply to these already working solutions, but now that I have, I’m willing to consider what a good approach would be.

I’ve just clocked that there is an inbuilt debugging verb for looking at grammar lines (of course there is!)

showverb go

does the trick!

1 Like

I’m not sure what you’re gaining by combining actions together that don’t share verbs (and therefore can’t be ambiguous to the parser)?

As a separate issue, it’s probably not good style to introduce constraints to your grammar tokens (such as [visible thing] instead of [thing]) unless there really is no other way of achieving what you want.

General rule of thumb is to keep things as broad as possible at parser level so that any vaguely sensible player input is accepted by the parser, then sort out details in action-processing where you have complete and transparent control of logic and responses.

The parser not matching [visible thing] gets you the default blank ‘You can’t see any such thing’ response, whereas ‘Before navigating something invisible:’ allows you to take full control.

As a further aside, the differences between [thing] (a thing in scope for the actor) and [visible thing] (a thing visible to the player) are subtle, unless the actor is not the player… (see here)

EDIT PS The differences between [visible thing] as a grammar token (as in 'Understand “destroy [visible thing]” as destroying) and ‘visible thing’ in an action definition (as in ‘Destroying is an action applying to one visible thing’) are not so subtle. The former means ‘a thing the player can see’ (thing here having the sense of ‘an instance of the thing kind, or of one of its sub-kinds, e.g. people or women or doors or containers)’, the latter means ‘any object in the universe, including rooms, regions, directions and objects out-of-play, and (confusingly) whether the player or anyone else can see them or not’.

Christ, that would have been good to know. I recently discovered scope. Where are these documented?

To develop this idea further, I note that there are at least three or four possible solutions offered in this thread. Which is “best?” I am always interested in learning best practices. With I7, it sometimes feels like all the solutions are a bit hacky.

When I was learning Python, it was helpful that there was consensus on what practices are considered “pythonic,” that is, “ code that doesn’t just get the syntax right but uses the language in the way it is intended to be used. It improves the overall code quality from maintainability, readability and efficiency perspective.”

Is there a consensus on what could be termed “informic?”

Mostly in WI Ch. 24 sections 3-4. They’re all listed in the General Index under testing commands… except for glklist which is undocumented on purpose.

Hehe… probably not at the level of the problems you’ve shared in this topic. We probably all agree about stuff like when to not use an instead rule, etc. But at this topic’s level, you’re creating new logic specific to your game. We can subject the results of our attempts to create it the idea of being Informic, but less so the nature of the attempts themselves.

Looking at the suggestions to funnel everything through one grammar line (and maybe one action) – and remembering I suggested two of each – I thought about my WIP where I’m using two of each and tried to decide why I’m doing it the way I’m doing it (if I even know). And I also tried to work out, ‘Why haven’t I run into the problem Wes is having (yet)?’

Probably the reason I have two is evolutionary. I started with Emily Short’s Approaches extension, which works only for rooms. I then had to expand the mechanism to take in all Things in the game. So I added a new grammar and a new action. The new action responds to attempts to go to things, and ultimately if an attempt succeeds, it executes it via the approaching (going to a room) action. The room containing that thing.

Rooms are pretty bedrocky. They stay where they are, are usually referred to the same way, and don’t come and go. Things are moving all over the place and coming and going. Also, I mentally think of the approaching code (an action and a lot of activity rules) as a big self-contained unit. It’s easier for me to put in there only code dealing with finding the path to a room.

If the player tries to go to a thing, there are a mountain of extra checks involved. So many it’s mentally easier for me for that code to be one whole other self-contained unit. The action has to get through that to pass on to the approaching unit. So the separation may not be essential, code-wise, but it helps me think about the problem(s).

Why have I not run into annoying problems of grammatical overlap? It could be luck. The actions aren’t defined similarly. One is for visited rooms, one is for known things (known being a term from the Epistemology extension - meaning you’ve seen it or heard about it). It’s probably partly by design, too. I’m very careful in naming rooms and things.

My WIP also has a low cheat capacity. What I mean by that is – thanks to me including a command that lists everything you can interact with at any particular moment, I mostly can’t cheat things using prose alone. Things have to be in the world model where the player expects them to be for the LIST command to work right. All of my GO TO is based on rooms and things that are all really in the map someplace. i.e. I can’t use an abstract stand-in thing like your distant elusive_landmark, because its real position is in a container in a hidden room.

All I can say, my system is working really well, but it’s for a game that’s probably a lot more complex than yours. I could probably have done it all through one action, but the way it’s evolved into two actions that funnel to one of the actions is working for me. When I look over this topic now, I think a one-grammar-line solution will probably be best for you.

-Wade

1 Like

Not really. Other things being equal, approaches that result in code that reads well as natural language is considered more Informic than those that don’t. Approaches centering rulebooks and relations would be considered more Informic than using lots of to-phrases.

The docs will try to tell you that relying on I6 inclusions is un-Informic, but if one takes Informic to mean what experienced users of Inform do an extraordinarily large amount of, then there’s nothing more Informic.

4 Likes

The documentation gives numerous hints, caveats, warnings and admonitions about how to ‘best’ use the language- ranging in strength from ‘you might consider this good style’ to ‘you don’t really want to do this. No, really, you really, really don’t want to do this. Oh alright, if you must- but don’t say you weren’t warned, and don’t come crying to me when I change things so this doesn’t work any more.’

It must be acknowledged, as Mr Nelson does, that no experienced coder can receive a gift without immediately wondering how they can subvert its original purpose and bend it to their will. It’s often said that to a man with a new hammer, every problem looks like a nail: but experienced coders seem to immediately wonder what else they could hit with it- maybe it could be just the answer to that clanking heating pipe in the loft if it’s hit in just the right way…?

I know I am particularly susceptible to hammering away at the language to get it to do things my way, enjoying that as a satisfying challenge in itself- rather than saving a lot of time and trouble by changing my approach to fit more snugly with what Inform makes it easy to do. When two roads diverge in a yellow wood, I always want to take the one less traveled by… As Zed has suggested, this approach frequently leads one into I6 inclusions, which can be a lot fun in itself but not necessarily conducive to getting quickly on with the job of producing a work of IF.

I think probably the most universally accepted advice on this forum is don’t mess with the parser- it’s bigger, tougher and smarter than you. That extends even to thinking very long and hard before resorting to ‘after reading a command’ to directly examine and/or interfere with player commands, or even sidestep the parser entirely. Elegantly covering your bases with anything a player might reasonably type is a minefield, particularly when considering the possibility of chained commands (a sequence of commands typed in one go, separated by full stops, commas or ‘then’).

I think other good general advice is to avoid falling into the habit of side-stepping the full action processing sequence, with all its checks and balances (particularly for inbuilt actions) by making everything an Instead rule. Instead (ha ha) consider whether what you’re doing would fit naturally into one of the other action rule-books before reaching for Instead…

Most of all, I’d reiterate the advice I gave earlier in this thread- if what you’re trying to do seems to be cutting across Inform’s grain, you may well be missing something and it’s worth going back to analysing the fundamentals of the story effect you’re looking for (particularly the visible effect, not the elegance and accuracy of any underlying simulated world) and brainstorming new approaches, and/or sifting through the documentation or extensions for an established solution. I’m still rediscovering new things daily in the documentation that I’d forgotten entirely, or perhaps skipped over in previous readings.

4 Likes

This is a lot, but I wanted to close the loop on this. Here’s a summary of some choices I made and why:

  • I combined many similar navigation or movement actions into one navigation action - this helped prevent similar grammar lines from uncontrollably competing with each other
  • It was suggested not to use any in grammar lines - however, I wanted the action to catch these possibilities to give an error in the check rule that made sense for the kind of thing and action
  • It was suggested not to use qualifiers in grammar lines so you wouldn’t get the dreaded “The noun does not make sense in this context” - I took this to heart, but also used some definitions (described below) that helped
  • I used definitions to keep grammar lines from being triggered when I didn’t want them to, i.e., [any relevant elusive_landmark]
  • I was careful to put grammar lines I wanted to be preferentially triggered before others (if the number of grammar options is the same, the parser is first come, first served)

So here is the final code that takes the advice in this thread, plus the choices above:

Chapter - Navigation to Rooms and Landmarks

Part - Lost_stuff, Elusive_Landmarks, & Landscape_Features

lost_stuff_storage is a container.
The printed name is "Lost Stuff Storage".
lost_stuff_storage is in Limbo.

An elusive_landmark is a kind of thing.
An elusive_landmark is mentioned scenery.
An elusive_landmark can be distant.

landmark_nav_counter is a number that varies. landmark_nav_counter is 0.

[ Create richer generative Dark Woods locations with rises and downslopes, incidental details, etc. ]
A landscape_feature is a kind of thing.
An landscape_feature is scenery.

Does the player mean examining distant elusive_landmark:
	It is unlikely.

Does the player mean examining not distant elusive_landmark:
	It is likely.

When play begins:
	Let this_landmark be a random elusive_landmark in Limbo;
	Now this_landmark is in Room_Dark_Woods_South;
	Let next_landmark be a random elusive_landmark in Limbo;
	Now next_landmark is distant;
	Now next_landmark is in Room_Dark_Woods_South;
	[ landscape_features ]
	Let this_feature be a random landscape_feature in Limbo;
	Now this_feature is in Room_Dark_Woods_South;

Part - Reachability & Interactivity

[Basically, if the player and the room are in Region_Dreams OR the player and the room are both not in Region_Dreams, than the room is reachable.]
Definition: A room is reachable
	if it is reachable_in_dreams or
		it is reachable_IRL.

[Everywhere within Region_Dreams is contiguous -- and discontiguous with everything outside of it.]
Definition: A room is reachable_in_dreams
	if the map region of it is Region_Dreams and
		the map region of the location is Region_Dreams.

[Everywhere NOT within Region_Dreams is contiguous -- and discontiguous with everything inside of it.]
Definition: A room is reachable_IRL
	if the map region of it is not Region_Dreams and
		the map region of the location is not Region_Dreams.

Definition: A thing is interactive
	if it is climbable or it is a supporter or it is an enterable container.

Definition: An elusive_landmark is relevant
	if Scene_Lost is happening.

Part - Navigating

[ navigating means moving from one room to another, moving to an elusive_landmark, or on/in to a supporter or container ]

Navigating is an action applying to one thing.
Understand
	[ rooms and landmarks ]	
	"go to/near/by/-- [any relevant elusive_landmark]",
	"go to/near/by/-- [any room]",
	"walk to/near/by/-- [any relevant elusive_landmark]",
	"walk to/near/by/-- [any room]",
	"run to/near/by/-- [any relevant elusive_landmark]",
	"run to/near/by/-- [any room]",
	"return to/near/by/-- [any relevant elusive_landmark]",
	"return to/near/by/-- [any room]",
	"follow [any relevant elusive_landmark]",
	"follow [any room]",
	[ interactive things ]
	"climb on/onto/in/into/over/through/under/-- [interactive thing]", 
	"climb up in/into/on/onto/-- [interactive thing]",
	"hop on/onto/in/into/over/through/under/-- [interactive thing]", 
	"hop up in/into/on/onto/-- [interactive thing]",
	"scale on/onto/in/into/over/through/under/--  [interactive thing]", 
	"scale up in/into/on/onto/-- [interactive thing]",
	"jump on/onto/in/into/over/through/under/-- [interactive thing]", 
	"jump up in/into/on/onto/-- [interactive thing]",
	"cross up/on/onto/in/into/over/through/under/-- [interactive thing]",
	"go up/on/onto/in/into/over/through/under/to/-- [interactive thing]"
	as navigating.

[ landmark navigating ]

Check navigating elusive_landmark:
	[ say "(DEBUG: check nav elusive_landmark: [noun])"; ]
	if noun is not visible:
		say "(DEBUG: [noun] not visible?)";
		say cant_find_that instead;
	else if noun is not distant:
		say "Well, that's right here." instead;

Carry out navigating elusive_landmark:
	[ say "(DEBUG: carry out nav elusive_landmark: [noun])"; ]
	increment landmark_nav_counter;
	move_within_dark_woods;

[ room navigating ]

Check navigating room:
	[ say "(DEBUG: Check navigating room: [noun])"; ]
	if the noun is the location:
		say "Well, happily you're already here." instead;
	else if the noun is not reachable:
		say cant_find_that;

Carry out navigating room:
	[ say "(DEBUG: Carry out navigating room: [noun])"; ]
	if noun is not reachable:
		say cant_find_that;
	else:
		let initial location be the location;
		let the destination be the noun;
		if the initial location is the destination,
			say "." instead;
		let heading be the best route from the initial location to the destination;
		[ say "(DEBUG navigating: heading toward [noun] is [heading])[line break]"; ]
		if heading is nothing:
			say cant_find_that instead;
		else:
			now player is not discouraged_from_compass_navigating;
			try going heading;

[ navigating to climbable things, supporters, containers, & waterbodies]

Check navigating interactive thing:
	[ say "(DEBUG: check navigating interactive thing: [noun])"; ]
	if noun is not touchable:
		say cant_find_that;

Carry out navigating interactive thing:
	[ say "(DEBUG: carry out navigating interactive thing: [noun])"; ]
	if the noun is climbable:
		[ say "You climb [the noun]."; ]
		try climbing the noun;
	else if the noun is an enterable container:
		[ say "You climb into [the noun]."; ]
		try entering the noun;
	else if the noun is a supporter:
		[ say "You climb onto [the noun]."; ]
		try entering the noun;
	else if the noun is a waterbody:
		try doing_some_swimming;
	else:
		say fail_navigation;

[ some things we say about navigation ]

To say cant_find_that:
	say "You're no longer sure how to get there. [looking_for_available_exits]";

To say fail_navigation:
	say "You can't really figure out how to go about that.";


Part - Moving Within Room_Dark_Woods

To say movement_in_woods:
	say "[one of]You stumble around in the dark woods[or]You carefully make your way through the forest[or]You follow an uncertain path through the wood[or]You bushwhack your way through the underbrush[at random].".

To move_within_dark_woods:
	say movement_in_woods;
	[ elusive_landmarks ]
	Let near_landmark be a random not distant elusive_landmark in Room_Dark_Woods_South;
	Let distant_landmark be a random distant elusive_landmark in Room_Dark_Woods_South;
	Let next_landmark be a random elusive_landmark in Limbo;
	Now near_landmark is off-stage;
	Now distant_landmark is not distant;
	Now next_landmark is in Room_Dark_Woods_South;
	Now next_landmark is distant;
	[ landscape_features ]
	Let old_feature be a random landscape_feature in Room_Dark_Woods_South;
	Let new_feature be a random landscape_feature in Limbo;
	Now old_feature is off-stage;
	Now new_feature is in Room_Dark_Woods_South;
	[ deal with dropped stuff ]
	Repeat with item running through stuff_you_brought_here:
		if item is visible and item is not held:
			move item to lost_stuff_storage;
	try looking;

The can't reach inside rooms rule does nothing if navigating a room.
2 Likes