Defining nested object properties

Is there a way to initialize nested object properties without creating a named object first? For example:

Test is a room.

A range is a kind of object.
A range has a number called min.
A range has a number called max.
The default range is a range with min 2 and max 5.

A pot is a thing.
A pot has a range called led.
Led is a range with min 3 and max 7. [ <- This does not work. ]

When game begins, say "Led: [min of led of pot] to [max of led of pot]"

The statement

A pot has a range called led.

sets up the name of a property of the pot, not the name of a range object. The idea is that you can then refer to the “led of the pot” and get the associated range, as in your When game begins rule.

I could not figure out a way to get the compiler to accept an anonymous range as part of a declaration. It would accept:

Pot-range is a range with min 3 and max 7.
The led of the pot is pot-range.

EDIT: This also works, and allows a range that is not specifically named:

There is a range. The led of the pot is it. It has min 3. It has max 7.
1 Like

Thanks. I thought maybe I am missing something. It would be neat if that would work though.

A slightly more compact version that works in 10.1.2 (but not 6M62):

There is a range with min 3 and max 7. The led of the pot is it.
1 Like

There are three problems here.

  1. A range needs to be a kind of thing. You can create a kind of object, but Inform doesn’t seem to understand what to do with it.
  2. The line you point out doesn’t work fails because you’ve already created the led object. It will work if you create led with the min and max values, then specify it is part of a pot.
led is a range with min 3 and max 7. led is a part of a pot.
  1. Finally, while led is part of a pot, it isn’t a property of a pot, so to display the min value of the pot’s led, you simply say “[min of led]”. If there will be several different things with an LED display, you’d have to give a unique name to each LED

Just saw your edit. Wow! The wording is so baroque. I would not have thought of that!

“Part of” is meant to be used for physical assemblies in the game world, stuff that the player can interact with. (“The knocker is part of the oaken door.”) Using it as a substitute for a property is baroque.


Sorry, what I found baroque was “There is a range. The led of the pot is it.”

As you may be discovering, abstracting a range as an object with its own pair of number values to be assigned as a property to various objects may not be the best way to go about storing information for an object in Inform.

You might consider just making range values a generic property of things:

A thing has a number called min range.
A thing has a number called max range.

Definition: A thing is ranged rather than unranged if the min range of it is at least 1.

That way, anything without a declared range property will get a default min range of 0 and be considered unranged. Your rules can easily discriminate between ranged and unranged things, as in:

Check throwing something unranged at:
	say "[regarding the noun][Those] [aren't] the kind of thing[s] you can throw." instead.

You might also consider a new kind of value for ranges, if the numbers won’t be getting very large:

A range is a kind of value. 99-99 specifies a range with parts min and max.

Then you can refer to the parts of a range:

A pot is a thing.
The pot has a range called led. The led of the pot is 03-07. 

When game begins, say "Led: [min part of led of pot] to [max part of led of pot]"

You could also use an arithmetic kind of value, which is basically a struct (in C terms): a collection of numbers that can be treated as a single value.

Notably, it’s not an object, which means you can create them and pass them around at run-time just like you could with integers.

1 Like

Oh, right. Yeah, Otis’s first suggestion reads easier:

Pot-range is a range with min 3 and max 7.
The led of the pot is pot-range.

You have to specify a name for the object (rather than just saying “it”), but verbose is readable.

1 Like

Good point. I am using unit types already for the date type I was working on.

As you said, using an object for a range is probably not worth it. But some interesting ideas in here. I will give those a try. Will also look into using a table, since for what I have in mind a bunch of ranges would be needed. I hoped I can get some abstraction that would make it easier to match a set of values against a set of ranges.

It’s usually helpful to explain exactly what you’re trying to accomplish in general.

You can easily use a table to establish ranges for a group of items:

Some things are defined by the Table of Ranged Items.

Table of Ranged Items
thing	minimum range	maximum range
pot	3	7

Just add more rows for other items. This sets the values up as separate named properties of all things but only assigns non-zero values from the table.

It’s also easy to set up phrases to help evaluate specific conditions, but without more information about what you mean by the quote above, it’s hard to say what would work best for your needs.


Basically what I am trying to accomplish is this: Let’s say we have a device with eight dials. Each dial can be set by the player to a whole number value between 1 and 16. Then we have a list of predefined fuzzy patterns. A pattern has a name and a list of 8 min/max ranges. A pattern matches the actual settings of the device when each dial is set to a value within the corresponding range of the pattern. So the task would be to find a matching pattern for the current actual settings of the device, or fail if no pattern matches.

Here’s a quickie implementation to serve as an outline:

"The Machine"

Place is a room.

The Machine is a device in Place. The Machine is switched on.

A dial is a kind of thing. A dial has a number called current setting.

When play begins:
	repeat with D running through dials:
		now the current setting of D is a random number between 1 and 16.

Some dials are defined by the Table of Dial Ranges.

Table of Dial Ranges
dial	minimum range	maximum range
dial A	3	7
dial B	1	8
dial C	4	12
dial D	13	16
dial E	2	6
dial F	4	9
dial G	6	11
dial H	14	14

Every dial is part of the Machine.

Definition: A dial is set correctly if its current setting is at least its minimum range and its current setting is at most its maximum range.

Definition: The Machine is set correctly if every dial incorporated by it is set correctly.

Every turn when the Machine is set correctly:
	say "Something interesting is happening involving The Machine."

Numerically setting it to is an action applying to one thing and one number. Understand "set [something] to [number]" or "turn [something] to [number]" or "dial [something] to [number]" as numerically setting it to.

Carry out numerically setting a dial to:
	now the current setting of the noun is the number understood.

Report numerically setting a dial to:
	say "[We] [turn] [the noun] to [the number understood]."

Please feel free to ask questions about any specific parts.

1 Like

You definitely want to use tables for this. It’s much easier to loop through rows and compare values. In fact, you wouldn’t even need to define your patterns with the 8 ranges. Your table could have a row for every possible dial combination and the matching pattern.

1 Like

And for a generic pattern matching part, something along the lines (as mentioned by A J Mako):

A range is a kind of value. 99-99 specifies a range with parts min and max.

To decide whether (N - number) is inside the range of (R - range):
	if N is at least the min part of R and N is at most the max part of R, yes;

A pattern is a kind of object.

Pattern 1 and Pattern 2 are patterns.

Table of Valid Patterns
pattern	dial	allowed range
pattern 1	dial A	3-7
pattern 1	dial B	1-8
pattern 1	dial C	4-12
pattern 1	dial D	13-16
pattern 1	dial E	2-6
pattern 1	dial F	4-9
pattern 1	dial G	6-11
pattern 1	dial H	14-14
pattern 2	dial A	9-12
pattern 2	dial B	3-4
pattern 2	dial C	6-10
pattern 2	dial D	1-7
pattern 2	dial E	8-16
pattern 2	dial F	15-15
pattern 2	dial G	8-10
pattern 2	dial H	1-15

Definition: A pattern (called P) is activated:
	repeat through the Table of Valid Patterns:
		unless the pattern entry is P, next;
		let D be the dial entry;
		unless the current setting of D is inside the range of the allowed range entry, no;

Every turn:
	repeat with P running through activated patterns:
		say "[P] conditions are met."

might serve.


That looks great, thank you so much! I will try this out.

I had some time to try this out. The code works perfectly. It is short and easy to understand and does exactly what I was looking for. Thanks again!