Elegant way to test whether something is in a location (even if in a container)

I get so mixed up between ‘incorporates’ and ‘is incorporated by’. I usually just try one and test my game and flip it if it’s wrong.

This post is going straight to the pool room.

-Wade

2 Likes

Easy way is probably to remember that ‘is incorporated by’ means the same as the similarly-structured and more intelligible phrase ‘is a part of’.

So, if ‘is a part of’ makes sense, just use that, otherwise it’s ‘incorporates’.

2 Likes

Reading this post, I realise my own understanding of the system was still missing some of the more baroque nuances. Can we agree that the standard Inform world model serves mostly as an opportunity to have a laugh at the expense of people’s seemingly solid implementation attempts and that we are fools for even trying?

1 Like

What?

Though I note a “visible thing” doesn’t mean what anyone would reasonably assume it means. Correct?

As I understand it

Asking-about is an action applying to one visible thing.

applies to a thing that is in-play. While

if grandpa is visible:

is true if grandpa is visible to the player.

Is that right?

You are correct. The choice of the word ‘visible’ in action definitions to distinguish objects anywhere in the universe that the player is allowed to refer to, by way of contrast to those that are touchable or carried, is one of the more bizarre and confusing syntax features of Inform, compounded by the parallel existence of a visibility relation that makes use of the adjective ‘visible’ and which has a meaning that is both subtly different and more conventional. Any object, whether conventionally visible or not, that is brought ‘into scope’, as Inform puts it, is a ‘visible thing’ in the context of action definitions. If this were not the case, the player would never be able to invoke actions involving objects that are not physically enclosed by the same room as the player, the latter representing the absolute limits of conventional visibility.

Likewise the use of the word ‘thing’ in action definitions to mean ‘object’ when elsewhere ‘thing’ means a subgroup of objects that, in the basic world model, are not rooms, directions or regions.

In summary, in the context of action definitions, and action definitions alone, ‘visible thing’ actually means ‘any object the player is allowed to refer to’. or, in more technical Inform-speak, ‘any object in scope’ **

PS in play also has a technical meaning in Inform, which is that the object in question is enclosed by a room. Even objects that by this definition are out of play, such as directions, or other objects created ‘off-stage’ or ‘removed from play’ to ‘nowhere’ may be considered ‘visible things’ in the context of action definitions if the scoping rules decide that they are nevertheless ‘in scope’.

** note that the use of the qualifier ‘any’ applied to objects (or descriptions of objects) appearing in tokens of grammar lines, e.g. ‘[any door] or [any closed container]’, allows them to override the requirement for ‘visible things’ to be in scope. 'Understand “open [any closed container] as remote opening” thereby allows the action to be invoked on any closed container, in-or-out-of-play, anywhere in the game universe, whether in scope or not. Possibly more usefully, [any room], [any adjacent room] etc. therefore allow the player to invoke actions referring to rooms, which are never ordinarily in scope and thus are not ordinarily ‘visible things’.

2 Likes

The perverse and confusing terminology in action definitions is perhaps the thing I would most like changed in a future version of Inform 7 as a core language change. Replace “thing” with “object” and “visible thing” with “any object” or “object anywhere”, perhaps. It is very hard to keep track of the weirdness that is the use of “thing” and “visible thing” in action definitions.

I would also love it if the two different methods of declaring formal parameter names – one for actions

a container (called item)

and one for phrases

(item - a container)

…could be unified and made interchangeable, as I keep using one in the context of the other (I’ve reversed it both ways – it’s my single most common syntax error).

It’s perhaps not really ‘any object’ or ‘object anywhere’ because scoping rules are by default applied unless overridden by using ‘any’ in the relevant grammar token.

I assume ‘thing’ and ‘visible’ were chosen as more naturally intelligible terms than ‘object’, and ‘in scope’ so it’s unfortunate that they end up confusing because the former terms have more restrictive formal meanings elsewhere in Inform.

Personally, I think 'object in place of ‘thing’ would be OK (although ‘item’ would be an alternative) and I am struggling to think of a more intelligible synonym for ‘in scope’ that fully captures the sense of it. Candidates might be ‘accessible object’ or ‘available object’ or ‘mentionable object’. Perhaps, in the end, since ‘in scope object’ is formally what is meant here, that should be it!

The (called item) syntax is also the one used in ‘Definition:’ declarations, conditions, and the declaration of relations, whereas as far as I can recall the (item - container) is only used in phrase declarations? If so, at least it’s just the exception for phrases that has to be remembered :thinking:

And if we are fantasizing… as Inform7 changes, it would be nice if it recognized the old syntax as an error and pointed you to the new syntax in the messages it produced ala git.

While revising old code it took me a while to realize that procedural rules had been deprecated. I was irritated that the compiler didn’t offer a friendly note about that

1 Like

Hm. There was (and still may be) a use option for your source like this:

Use no deprecated features.

I remembered its existence and using it in version 6G60 of Inform, but searching for ‘deprecated’ in the docs now returns one results, and nothing about this option. So I don’t know if it has become undocumented, or if it’s been deprecated itself. But until someone who knows that chimes in, maybe add it and see if it throws complaints about procedural rules in your source.

-Wade

1 Like

Procedural rules went beyond deprecated and were removed entirely… [http://inform7.com/changes/CI_7_10.html]

While we’re on the topic of what could kindly be termed ‘idiosyncracies’ in Inform, others have previously expressed frustration at the bizarre way that ‘includes’ for snippets is equivalent to ‘matches’ for texts, while ‘matches’ for snippets is equivalent to ‘exactly matches’ for texts- in phrases such as 'if the player’s command matches “take aardvaark”, replace the matched text with “take anteater”.

This can be fixed by adding the following to source text, which also adds phrases to allow the negation of conditions matching regular expressions to texts:

To decide if (s - a snippet) matches (t - a topic):
	if s includes t, yes;
	no.
To decide if (s - a snippet) does not match (t - a topic):
	if s includes t, no;
	yes.
To decide if (s - a snippet) exactly matches (t - a topic):
	if s includes t :
		if the matched text is s:
			yes;
	no.
To decide if (s - a snippet) does not exactly match (t - a topic):
	if s does not include t :
		yes;
	if the matched text is not s:
		yes;
	no.
[these phrases align the syntax for matching snippets to that for matching texts- ordinarily 'matches' for snippets == 'exactly matches' for texts, and 'includes' for snippets=='matches' for texts]
To decide if (t - a text) does not match the regular expression (r - a text):
	if t matches the regular expression r, no;
	yes.
To decide if (t - a text) does not exactly match the regular expression (r - a text):
	if t exactly matches the regular expression r, no;
	yes.
[this is a syntax inexplicably missing from Inform- without these phrase definitions compiler will throw an error as it tries to set up a match between a snippet and a topic (as in 'the player's command does not match "room [number]") rather than a text with a text, not helped by the absence of a logical 'not' in complex conditional phrases- so we can't say 'if X and not Y ...' or even 'if X and unless Y...']

4 Likes

I think you just wrote an Extension, once some documentation is written. Hint Hint Hint.

…or if you don’t want to, I can make that into an extension.

…snippet weirdness has been on my mind because I’ve been wrestling horribly with snippets lately. There is some high weirdness with rules which have a snippet involved.

Ordering it that is an action applying to one thing and one topic.
Riposteing it that is an action applying to one thing and one topic.
Understand "instruct [someone] to [text]" as ordering it that.
Understand "answer [text] to [someone]" as riposteing it that (with nouns reversed).
Check riposteing something (called item) that (this is the riposte redirect to order rule):
	try ordering item the topic understood;

The try doesn’t compile. I may just be missing a piece of syntax, but I haven’t figured out a way to do it.

I had an interesting exchange on this topic (ha ha) here- Topic variables and text in I7

If you haven’t already hit on it, what you’re looking for is

	try ordering item that the topic understood;
1 Like

Thank you very much. This deciphered a syntax puzzle for me and I now have it passing through a chain of checks properly…

…it’s amazing how deep into the code I’ve gotten trying to get “giving orders to NPCs” to work cleanly with multiple synonyms and good errors, while still making it easy enough for the game author to override. I’m far from done, but my hope is that a more generous parser and more comprehensible errors will give a better “feel” to NPCs even if the NPCs remain very simple. Work to date is in my Compliant Characters extension.

Addendum- understanding the behaviour of Inform’s spatial relations.

This is an addendum to my earlier post above regarding Inform 7’s spatial relations.

That has also been edited to:

(i) clarify and expand some passages
(ii) correct a number of inaccuracies, particularly with regard to regions
(iii) add some further useful undocumented information

Although there are a number of quirks to the implementation of Inform’s many spatial relations, in large part these are explicable by an understanding of the underlying implementatation model.

Objects in the Inform World Model are arranged into an Object Family Tree, within which any object can only be directly connected to one parent, sibling and/or child. This simplified description does not take account of incorporation, which uses similar ideas but is differently implemented and will be discussed later. Furthermore, in practice the Object Tree is typically broken up into a number of separate trees, usually with a room as the ‘top’ parent in each, and sometimes even with isolated objects that have no parents, siblings or children.

Library                                      Nebulous Thingumajig
   |
   | <-contains
   v
Bookcase----->Writing Desk----->Sherlock Holmes----->Green Door
   |               |                  |
   | <-contains    | <-supports       |<-carries
   v               v                  v
Dictionary       Lamp               Pipe----->Deerstalker(worn)

In the Object Tree, objects are connected only in these three basic one-to-one correspondences- parent, sibling and child. Although formally an object only has one child and/or sibling by direct connection in the Object Tree, they are also talked about as groups of siblings and children, each in a group of siblings having the same parent, of which they are the children. In the above diagram, the child of the Library is the Bookcase and the children of the Library are the Bookcase, Writing Desk, Sherlock Holmes and the Green Door. The sibling of Sherlock Holmes is the Green Door and the siblings of Sherlock Holmes are the Bookcase, Writing Desk and Green Door. The parent of Sherlock Holmes is the Library. Although hidden deep within Inform 7, the structure of the Object Tree occasionally reveals itself. For example, when listing miscellaneous items in a room description, these are generally listed with the ‘eldest’ child of the room location first, then in sibling order. The ‘eldest’ sibling is the one most recently moved to its parent. When an object is moved to a parent, it therefore becomes the child of that parent, and the previous eldest child becomes its sibling. Knowing this allows the order of printing of miscellaneous items to be controlled- even if an object is already in the location, moving it to the location moves it to the top of the list for printing. You will notice that taking then dropping an object in the location has the same effect, and for the same reason.

Note that rooms do not have siblings or a parent. They are connected to other rooms by mapping relations and to regions via their ‘map region’ property, neither of which are part of the Object Tree.

Considering how parent, child and sibling connections are manifest in Inform’s basic spatial relations, the latter are determined by the kind of the parent object. A room or container’s children are contained by it. A supporter’s children are supported by it. A person’s children are carried by it, unless they have the I6 ‘worn’ attribute (in I7 terms, somebody wears them), in which case they are worn rather than carried. Put the other way round, something is contained if it is one of the children of a room or container, supported if it is one of the children of a supporter and worn or carried if it is one of the children of a person. An object such as the Nebulous Thingumajig in the above diagram is said to be ‘off-stage’ or ‘nowhere’.

It should now be clear why the basic spatial relations covered so far are mutually exclusive. Since the only way to know how a child relates to its parent is the kind of its parent, the parent cannot be allowed to be more than one of a room, a supporter, a container or a person. If an object were to be at the same time a supporter, a container and a person, Inform has no way of knowing if its children are being supported, contained or carried. Furthermore, an object cannot be both worn and carried, because the state of the either-or attribute ‘worn’ determines which it is. Also, since an object can have only one parent, it cannot be contained/supported/carried or worn by more than one object.

  <--Estate                                 Nebulous Thingumajig
  .     |
r .     | <-holds, contains & encloses-++++++++++
e .     v                                       |
g <--Mansion-------------------->Gardens    encloses
i .     |                                       v
o .     | <-holds, contains & encloses-++++++++++
n .     v
a <--East Wing------------------>West Wing
l .     .
l .     . (via 'map region')
y .     . <-contains (**but does not hold**)
  .     v
c .->Library                                
o .     | 
n .     | <-contains & holds
t .     v
a .->Bookcase----->Writing Desk----->Sherlock Holmes---->Green Door
i .     |               |                  |
n .     | <-contains    | <-supports       |<-carries/wears
s .     |   & holds     |   & holds        |  & holds & has
  .     v               v                  v    
  .->Dictionary        Lamp               Pipe---->Deerstalker(worn)

Above is the previous object tree extended to show some regions. Regions exist in one or more object trees of their own, separate from other objects. In Inform, without exception every parent holds each of its children. Therefore rooms, containers, supporters and people hold their children as well as containing/supporting/carrying or wearing them. It also follows that regions hold their child regions, but do not support/carry or wear them. Regions also therefore enclose (directly or indirectly hold) their child regions and their grandchild regions etc. but never rooms, since regions can never hold a room. Although regions do contain any regions they hold, testing for this in Inform is awkward and often confusing due the the ambiguity (between containment and regional-containment) of the terms ‘in’ and ‘contains’ when talking about regions (see post 7 above). Generally it’s best to use the holding relation for regions.

Object trees of regions are connected to rooms and rooms’ object trees not by parent/child connections but through a property provided by every room- its map region. A room’s map region may be nothing, in which case it is not in any region, but if the property is a region, that establishes a connection which by a special rule means the said region contains that room. This is the only situation in which an object contains something it does not hold. It also means that the same region, and that region’s parent (if any), and grandparent, and great-grandparent etc. regionally-contain the room and the room’s entire object tree. It does not mean that the region holds the room- it does not- holding applies only to parent/child connections.

Writing Desk
  :      |                                
  :      | <-supports
  :      |   & holds
  :      v               
  :     Lamp
  :
  : <-incorporates & holds
  v
Left Drawer==========>Right Drawer====>Inkwell
  :     |                                 |
  :     | <-contains & holds              | <-contains & holds
  :     v                                 v
  :    Pen                               Ink
  :
  : <-incorporates & holds
  v
Secret Compartment
         |
         | <-contains & holds
         v
        Key

It remains to describe the implementation of incorporation. Above is an expansion of the Writing Desk encountered in the preceding example object tree. As well as supporting the Lamp, it incorporates two drawers and an Inkwell, containing some Ink. The left drawer contains a Pen but also itself incorporates a Secret Compartment, which contains a Key. Thus an extensive additional object tree is hung off the Writing Desk through the top-level incorporation relation. This does not break the object tree rule that an object has at most one child by direct connection, because the incorporation relation is not implemented within the main object tree model but through three I6 properties provided by things that either incorporate something or are part of something else: component_parent, component_sibling and component_child. These properties do exactly what their names suggest- they hold a reference to the thing (if any) that is the property-providing thing’s parent, sibling or child by incorporation. These relationships are shown by double-dotted lines in the above object tree- so the Left Drawer has component sibling of the Right Drawer, component parent of the Writing Desk and component child of the Secret Compartment. Although incorporation is implemented slightly differently and separately to the main object tree, it remains the case that a component parent holds its component children (as well as incorporating them) and that an object can have only one parent, which holds it, either through one of the four types of relation represented by the main object tree (containment/support/carrying or wearing) or through incorporation. Similarly, objects enclose all objects within an object tree they incorporate, so in the above example the Writing Desk encloses the Ink. Indeed, so does the Library- the ‘cascade of enclosure’ is not broken by incorporation.

It should now be evident how Inform’s holding and possession relations work: holding exactly represents any parent/child relationship (including being a parent/child through incorporation), and enclosure any unbroken cascade of parent/child relationships (including through incorporation). Possession represents the parent/child relationship (not including incorporation) between a person and its children.

Understanding the Object Tree also provides some insight into the quirky spatial relationships of doors and backdrops. An object can only ever have one parent and therefore can only occupy one place in the object tree. How then can doors and backdrops appear in more than one room? The answer is ‘by sleight of hand’. Inform keeps a record of (or knows how to work out) which rooms a door or a backdrop are found in, and if the player enters one of those rooms, quickly moves all relevant doors and/or backdrops to the player’s location before anything is printed, creating the illusion that they had had been there all along. This quick-change-act is ordinarily only triggered when the player moves to a new location, which for doors (being always static) is fine, but it can be caught out if between moves of the player some condition changes that means a backdrop should now suddenly be present in or absent from the player’s current location (e.g. the moon coming out from behind a cloud). This is the reason that Inform provides the phrase ‘update backdrop positions’ so that backdrops can be moved around the object tree between turns or even mid-turn if necessary. All this explains why despite being found in more than one room, a door or a backdrop has, at any given time no more than one location, which usually holds and contains it (see very small print on the location of two-sided doors in previous post). That will usually be the most recent location the door/backdrop was moved to- being generally the last room occupied by the player in which the door/backdrop is to be found. As noted previously, a backdrop is the only kind of object not to be enclosed by an object it is held by.

9 Likes

Dr Peter Bates, phd. Inform Studies.

3 Likes