Creating lists of things subject to a condition

Hi,

I’m repeatedly running up against a syntax problem within my code, which I’m sure is just a failure to understand how Inform wants me to word the phrase, but is proving very frustrating.

I’m trying to iterate through a list of objects that satisfy certain conditions, namely where a property of a kind satisfies particular conditions. I know that I can create a “list of open doors”, for example, but when I try and create a more nuanced iterator I keep running into problems where Inform doesn’t understand what I’m trying to say.

As an example of what I mean, I’ve written the below. I’m looking for a way to gather all the paintings of a certain colour together as a list that can be iterated over, or used in other rules. I’ve tried multiple ways of saying “list of paintings that have impression equal to red”, but I simply cannot get it to work.

Colour is a kind of value. The colours are red, yellow, green and purple.

A painting is a kind of thing. Every painting has a colour called the impression. The description of a painting is usually "This painting just seems to be a big splodge of [the impression] paint on the canvas."

The gallery is a room. "The clean white walls of the gallery seem the perfect foil for contemplating the art with surgical critical precision."

The still life is a painting. The impression of the still life is yellow. The still life is in the gallery.
The landscape is a painting. The impression of the landscape is green. The landscape is in the gallery.
The portrait is a painting. The impression of the portrait is red. The portrait is in the gallery.
The battle scene is a painting. The impression of the battle scene is red. The battle scene is in the gallery.

Every turn:
	Repeat with p running through the list of paintings that have impression equal to red:
		say "[P] is a red painting."

Any ideas on how to solve this would be much appreciated - as I said, I keep trying to use a formulation like this throughout my code and it’s creating a whole heap of ugly work arounds!

Thanks!

One way of doing that is to use the kind of value directly as a property:

Colour is a kind of value. The colours are red, yellow, green and purple.

A painting is a kind of thing. Every painting has a colour. The description of a painting is usually "This painting just seems to be a big splodge of [colour] paint on the canvas."

The gallery is a room. "The clean white walls of the gallery seem the perfect foil for contemplating the art with surgical critical precision."

The still life is a yellow painting. The still life is in the gallery.
The landscape is a green painting. The landscape is in the gallery.

[You can declare a "<colour> painting" directly or in a separate sentence:]
The portrait is a painting. The portrait is red. The portrait is in the gallery.
The battle scene is a red painting. The battle scene is in the gallery.

Every turn:
	Repeat with p running through red paintings:
		say "[The p] is a red painting."

See 4.9. Using new kinds of value in properties.

Thanks, that’s helpful in some cases and is a definite improvement on my original scenario. It doesn’t quite cover what I’m trying to do though (my fault for the simplified example). I want to do something like the following - i.e. I don’t know what precise value I’m trying to filter my list for when I’m writing the code.

Every turn:
	Repeat with c running through colours:
		Repeat with p running through the list of paintings with impression of c:
			say "[The p] is a [c] painting."

With my code from above, the following works:

Every turn:
	Repeat with c running through colours:
		Repeat with p running through paintings which are c:
			say "[The p] is a [c] painting."

It feels as though you ought to be able to say:

Repeat with p running through paintings of which the impression is c:

but Inform does not support this form of adjectival phrase, so I think it has to be broken out into a separate condition if you want to filter on a named property:

Every turn:
	Repeat with c running through colours:
		Repeat with p running through paintings:
			if the impression of p is c:
				say "[The p] is a [c] painting."

We can make it, on a case-by-case basis – but I wouldn’t exactly call it a good idea:

To repeat with (loopvar - nonexisting Painting variable) running through paintings that have an/-- impression of/-- (c - Colour) begin -- end loop:
	(- objectloop({loopvar} ofclass (+ painting +) && {loopvar}.(+ the property impression +) == {c}) {-block} -).

Every turn:
	Repeat with p running through paintings that have an impression of red:
		say "[P] is a red painting."

(Again, please don’t do this – or at least don’t say I didn’t warn you if it goes wrong in all kinds of hard-to-diagnose ways.)

What I’m really trying to do is get a list of objects based on named properties that I could pass to, say, the complex listing extension to print out, or to iterate over in order to test some other condition. I’ve been constructing this on a case by case basis by iterating through loops as suggested, but this feels messy and cumbersome. I guess, though, that this is what I’m left with! Thanks for the input all.

You can define such an adjective if you use a global variable.

The global-colour is a colour variable.

Definition: a painting is globally-coloured if the impression of it is global-colour.

Every turn:
	let global-colour be red;
	repeat with p running through globally-coloured paintings:
		say "... [p].";
	say "Or, [the list of globally-coloured paintings].";

Then I think you’d have to either define an adjective based on a named property to reflect the condition you want to filter on, as in zarf’s example, or build the list ‘by hand’ through a loop as you have been doing, -if it’s truly important that the properties are specifically named.

Inform is really willing you here to either use implicitly-named properties to create or filter your list (so that they can be used as adjectives as in St John Limbo’s example) or define your own adjectives (as in zarf’s example)

I worked out a generalized version with an only slightly awkward syntax. Would you like to see it?

After some more thought I came up with the following:

To decide whether (O - object) has (P - property) set to (V - value):
	(- (GProperty(OBJECT_TY, {O}, {P}) == {V}) -).

To decide what list of Ks is (full list - list of values of kind K) filtered by (P - property) being (V - value):
	let the filtered list be a list of Ks;
	repeat with item running through the full list:
		if the item has P set to V, add the item to the filtered list;
	decide on the filtered list.

Every turn:
	Repeat with p running through the list of paintings filtered by the property impression being red:
		say "[P] is a red painting.";
	say "[paragraph break]Or...: [the list of paintings filtered by the property impression being red]";

Sure, let’s see yours as well :smiley:

1 Like

Virtually identical to mine for the functional parts, and I like your syntax better! (I did guard against the possibility that an inapplicable property would be used. Also, mine checks whether the value is appropriate for the property.)

To decide whether the value held by (P - L valued property) of (X - value of kind K) is (V - value of kind L):
    (- (GProperty(OBJECT_TY, {X}, {P}) == {V}) -).

To decide which list of Ks is those (desc - description of values of kind K) that have/has a/an/-- (P - L valued property) of (V - value of kind L):
    let collection be a list of Ks;
    repeat with X running through Ks:
	    if X provides P and the value held by P of X is V:
		    add X to collection;
    decide on collection.

Every turn:
    let C be a random colour;
    say "Looking for [C] paintings...";
    Repeat with P running through those paintings that have an impression of C:
	    say "[P] is a [C] painting."
1 Like

Should this be

repeat with X running through desc:

FWIW, my suggestion for syntaxes… :wink:

To decide whether the/-- (P - L valued property) property of (X - value of kind K) is (V - value of kind L):
	(- (GProperty(OBJECT_TY, {X}, {P}) == {V}) -).
		
To decide which list of Ks is those (desc - description of values of kind K) having a/an/-- (P - L valued property) of (V - value of kind L):
	let collection be a list of Ks;
	repeat with X running through desc:
		if X provides P and the P property of X is V:
			add X to collection;
	decide on collection.
	
To decide which list of Ks is those (desc - description of values of kind K) that/which/who have a/an/-- (P - L valued property) of (V - value of kind L):
	decide on those desc having P of V.