Don't ask for clarification about going to unreachable locations

I have unconventional navigating within my story and so there is an action called room_navigating.

Room_navigating is an action applying to one thing.
Understand "go to/around/near/by [any room]", "go [any room]", "go back to [any room]", "return to [any room]", "walk --/to [any room]", "run --/to [any room]" as room_navigating.

I’ll spare you the carry out rule, but it works decently using the brilliant best route from x to y. Happy to add the entire rule here if it becomes relevant.

The challenge is with the “which do you mean” clarification. As much as possible the names have unique names and understand rules, but there are two discontinuous areas in the game that duplicate a couple of the locations. So predictably, I get a clarification:

> go to stone bridge
Which do you mean, Stone Bridge or Stone Bridge?

I understand that the user here has given an ambiguous request, and the parser is trying to clarify between two similarly named objects, unconstrained by whether they are visible or not. I only want to consider the location to which there is a continuous path.

I feel like I have all the puzzle pieces:

  • Rule for asking which do you mean
  • let heading be the best route from the initial location to the destination
  • if heading is not nothing

But I can’t yet think how to put them together. Any suggestions?

Something like this?

Definition: A room is unreachable if the best route from the location to it is nothing.

Does the player mean room_navigating an unreachable room: it is unlikely.

Another possibility that occurred to me is to add conditions to the understanding of the room name.

Definition: A room is reachable if the best route from the location to it is not nothing.

StoneBridge1 is a room. The printed name of StoneBridge1 is "Stone Bridge".
Understand "stone" and "bridge" as StoneBridge1 when StoneBridge1 is reachable.

StoneBridge2 is a room. The printed name of StoneBridge2 is "Stone Bridge".
Understand "stone" and "bridge" as StoneBridge2 when StoneBridge2 is reachable.
4 Likes

In addition to what bg has said, I’ll point out something about how ‘Does the player mean’ (DTPM) phrases work under the hood.

The DTPM rules assign scores to outcomes (e.g. on the positive scale, very likely scores higher than likely. ‘possible’ gives a neutral score, zero) and pick the outcome that has the highest score. However, if there is no unique highest score amongst outcomes, Inform gives up and asks the player to consider all the possibilities.

So the key, when you see the player being asked to distinguish between things that you don’t want them to be asked to distinguish between/amongst, is to write DTPM rules for those objects (or at least for one of them – this often does the trick, especially if there are only two) in the trouble context(s) so that one will always have a higher score in that context. Then it’ll always win and be chosen in that context.

This is usually possible to do, but the more objects compete for attention in a context and the more complex your game overall, it can certainly become impossible to guarantee the disambiguation list doesn’t ever appear in some messy (and unanticipated) situations.

-Wade

2 Likes

Rather than DTPM rules, you can take advantage of the fact that the parser never does disambiguation between grammar lines.

Definition: A room is reachable if the best route from the location to it is not nothing.

Understand "go to/around/near/by [any reachable room]" as room_navigating.

Understand "go to/around/near/by [any not reachable room]" as a mistake ("You can't find your way.").

However, there’s an additional problem. The “best route” phrase is relatively slow, and the grammar lines have to be checked against every room in the game – twice. You don’t always have to worry about code efficiency in Inform, but this is a situation where it could become a problem.

It would be better to define “reachable” in a way which can be checked quickly. Explicitly define the disconnected areas in your code rather than recomputing them at runtime. This is one way:

Definition: A room is reachable if the map region of it is the map region of the location.

Put each disconnected area in its own map region. If you’re already using map regions, you could define a property instead.

1 Like

Heh. My suggestion above is slightly wrong, because “mistake” grammar lines come out as higher priority for some reason. This will work:

Room_navigating is an action applying to one thing.
Fail_navigating is an action applying to one thing.

Understand "go to/around/near/by [any reachable room]" as room_navigating.

Understand "go to/around/near/by [any not reachable room]" as fail_navigating.

Carry out room_navigating:
	say "Nav [the noun]."

Carry out fail_navigating:
	say "You can't find your way."

These are all great solutions. I adapted Andrew’s solution…

Part - Room-Navigation

[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.

Room_navigating is an action applying to one thing.
Understand "go back/- to/around/near/by [any reachable room]", "go [any reachable room]", "return to [any reachable room]", "walk --/to [any reachable room]", "run --/to [any reachable room]" as room_navigating.

Check room_navigating:
	[say "(go from [location of player] to [the noun])[line break]";]
	if the noun is the location, say "Well, happily you're already here." instead;

Carry out room_navigating:
	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 "(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.

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

Fail_navigating is an action applying to one thing.
Understand "go back/- to/around/near/by [any not reachable room]", "go [any not reachable room]", "return to [any not reachable room]", "walk --/to [any not reachable room]", "run --/to [any not reachable room]" as fail_navigating.

Carry out fail_navigating:
	say cant_find_that;

Presumably this is because “mistake” grammar lines are tried first and only minimally parsed as far as is required to establish a match, with the parser then abandoning any attempts at further parsing and implementing the “mistake” ‘say phrase’ without searching for other grammar lines which might match. Just guessing, I haven’t delved into the parser to confirm this.

This is how the parser handles every grammar line. Mistake grammar lines are different only in that they go to an autogenerated out-of-world action which prints the mistake text.

They are listed before regular grammar lines of equivalent syntax, rather than after. This surprised me, but in fact it’s documented in 17.22.