Relations, verbs, and defining object properties

I’ve been reading Declaring a new table to be populated - #56 by EphemeralHorror with great interest because I’ve been learning a lot about the power of relations, which as a beginner in Inform7 I had neglected so far.

As it happens, in the draft story I’m writing to learn about Inform7 I have developed an extensive table-based “book system”. This is basically a list of titles, authors and some other properties that is there purely for “scenery” purposes (you can find «a copy of This And That Book by Such And So Author»). Given the variety of the books I’ve had to basically devise a “subparser” to detect if the user is talking about said books, which works sufficiently well thanks to the fact that I only have to worry about a very specific subset of commands.

Reading the aforementioned thread made me think that maybe I can make the “book system” a bit more sophisticated (and hopefully get rid of the ad-hoc parsing) by using relationships instead, so I basically nerd-sniped myself into writing my first extension, which I’m calling “Artists and their Works”, and I’m starting to feel like I bit off more that I can chew.

One of my issues is when to use relations and when to use properties. For the relation artist >=> work, I opted for relations, which allows me to have both multiple works from the same authors and multiple authors for the same work (collaborative writing). So far, so good.

The next thing I intend to do is to separate the work in the abstract from its tangible incarnations, following the principle that a novel is not the book it is printed on, and that you might want to have multiple copies of the same work in the story. And this is where the problems begin.

The idea is that I would like story writers to be able to say «The interesting book is a copy of Lesser Known Novel in the Library» (where Library is a room and Lesser Known Novel is a previously defined work by some artist), but also «If the noun is a copy of Lesser Known Novel: ...» or get the list of visible copies of Lesser Known Novel.

For the writer-friendly syntax, the property seems to be the best choice, since it allows me to enforce that each incarnation must have a corresponding work (is there a way to enforce this with relations?), and I can define tell Inform7 that The verb to be a copy of means the work property and then do

The interesting book is a tangible work in the Library.
The interesting book is a copy of Lesser Known Novel.

which is a bit verbose, but almost as good as I would like (is it possible to do better?). However, this has the downside that I can’t use being a copy as a relation in conditionals or object descriptions. I can work around this by using a different verb, but it would be nice if I could use the same (I actually expected it to work automagically, TBH, from the information that being a copy of refers to the given property).

Moreover, I haven’t found in the documentation a way to allow this kind of syntax to set multiple properties at once. For example, if a tangible work can be original, my understanding is that I cannot define something that allows me to, say, write The interesting painting is the original Famous Painting and tell inform that not only the paining is a tangible work of the given Famous Painting, but also that it is original. Or did I miss it?

Am I asking too much of the source text parser?

I don’t have any answers for you at this moment, but I do have a response to one little thing you said.

Properties are a type of relation[1], so there’s really no difference between using a property and a one-to-one or many-to-one relation.

To be clear, the following two definitions are, as far as I know, 100% equivalent:

A book is a kind of thing.
A book has some text called title.
The verb to be called means the title property.

and

A book is a kind of thing.
Entitlement relates many books to one text (called its title).
The verb to be called means the entitlement relation.

  1. This may be untrue in the technical internals, but for high-level purposes it’s correct ↩︎

3 Likes

That’s very interesting.

One of the benefits of properties is that they enforce existence in a way that relations, AFAICS, do not. In my “relation instead of property” version of the incarnation >=> work relationship, I still have to separate being a copy from being in a room because Inform7 doesn’t like being told multiple relations about an object, but now I don’t have a guarantee that each incarnation has a corresponding work, which makes accessing the work of an incarnation harder to get (I have to get a list and check that it’s not empty).

1 Like

Ah, true, so there is one small difference between the two. You can still enforce existence to some degree with a relation using a statement like Every book is called a title., but I think that only works when the relation is between objects (in other words, the example sentence just now would not compile). Furthermore, that line enforces that the matching one is unique for each book, which might not be the correct answer.

Yeah, I actually tried that with the work, but it turns out that defined a different work for each incarnation, called something like “the book’s work” —definitely not what I wanted. So I guess that for this particular case the property might be the correct choice.

Unfortunately, I imagine that what you want (to create entire new ways of defining objects in one fell swoop) is something baked pretty deeply into the Inter core of Inform 7.

Is there any chance we can see more of the code at play here? The original moment of defining the “work” property and such?

…But this might work, if it’s what you want!

A tangible work is a kind of thing.

A work is a kind of value. The works are Apples and Leaves. Every tangible work has a work. The verb to be a copy of means the work property.

The Garden is a room.
The gilded copy of Leaves is a tangible work in the garden. The gilded copy of leaves is a copy of Leaves.
The plain copy of Leaves is a tangible work in the garden. The plain copy of Leaves is a copy of Leaves.
The marked copy of Apples is a tangible work in the garden. The marked copy of Apples is a copy of Apples.

Copying relates a tangible work (called reproduction) to a work (called origin) when the reproduction is a copy of the origin. The verb to copy means the copying relation. The verb to be copied means the copying relation.

Carry out examining a tangible work:
	if the noun copies Leaves:
		say "Test complete!";
		rule succeeds;
		
First report Waiting:
	say "[The list of tangible works which copy Leaves]!";
	rule succeeds;

It’s hard to automate this aspect much. Especially when you’re doing it from the perspective of an Extension writer. What few methods I can think of would be just as much work as just defining things point-by-point to begin with.

A work is a kind of value. The works are Apples and Leaves. Every tangible work has a work. The work of a tangible work is usually Apples. The verb to be a copy of means the work property.

A p-Leaves is a kind of tangible work. The work of a p-Leaves is usually Leaves. A p-Apple is a kind of tangible work. [P for published!]

The Garden is a room.
The gilded copy of Leaves is a p-Leaves in the garden.
The plain copy of Leaves is a p-Leaves in the garden.
The marked copy of Apples is a p-Apples in the garden.

Maybe using sub-kinds with baked in assumptions or a table, I suppose. But again, that doesn’t help Extension-side.

Thanks @EphemeralHorror, that’s a very interesting example. The kind of value angle is one I haven’t explored yet, but it’s something that might be worth looking into. I’m guessing that as an extension writer the biggest obstacle is that one would want to delegate the actual allowed values to the story author, and Inform7 doesn’t allow “adding” values to a kind of value? I’ll try experimenting with this a bit. An advantage of using kind of values is that it would make it easier to implement the next step, which is to allow users to use the abstract work to refer to a copy of it.

1 Like

I used a kind of value because I couldn’t see the code you used but I wanted to cling fairly close to how I was envisioning it. I was having trouble getting things to work with a proper thing, but then realized I could fix that by making my work-property accept an object. Figured it out, though!

A solution involving a table might actually be worth considering for you as an Extension writer, as people who use your Extension can extend a table like so:

Table of User Styles (continued)

…Which will add onto an existing table, even one defined in an Extension. That would come across as fairly natural and you could then use it to pair works with tangible works!

Table of Work Reproductions
Reproduction Work (a tangible work)	Original Work (a work)
The gilded copy of Leaves	Leaves
The plain copy of Leaves	Leaves
The marked copy of Apples	Apples

A work is a kind of thing. A tangible work is a kind of work.
Every tangible work has an object called source. The verb to be a copy of means the source property.

Copying relates a tangible work (called reproduction) to a work (called reproductee) when the reproduction is a copy of the reproductee. The verb to copy means the copying relation. The verb to be copied means the copying relation.

Leaves is a work. Apples is a work.

The Garden is a room.
The gilded copy of Leaves is a tangible work in the garden. The plain copy of Leaves is a tangible work in the garden. The marked copy of Apples is a tangible work in the garden.

When play begins:
	repeat through the table of Work Reproductions:
		now the reproduction work entry is a copy of the original work entry;
		
First report waiting: [Once again, apologies for my bizarre choice of testing methods.]
	say "[The list of works which copy Leaves]!";
	rule succeeds;

False. There’s no such thing as a “closed” enumerated type in Inform 7 (other than some built-in ones). If you define a kind of value in an extension, the user of that extension can define a many of those values as they want.

1 Like

To give an idea of the kind of syntax I’m testing now on the story writer side, it would be something like this:

"Testing Artists" by Oblomov.

Include Artists and their Works by Oblomov.

Section 1 - Artists

Emilio Salgari is a male writer.
Théophile Gautier is a male writer.
Donatello is a male sculptor.

Section 2 - Works

Capitain Fracasse is a novel written by Théophile Gautier.
I misteri della jungla nera is a novel written by Emilio Salgari.
I pirati della Malesia is a novel written by Emilio Salgari.

Donatello's David is a statue sculpted by Donatello.
The printed name of Donatello's David is "David".


Section 3 - Concrete objects

The test room is a room.

The book is a copy of I misteri della jungla nera.
The book is in the test room.

The treasure is a copy of I misteri della jungla nera.
The treasure is in the test room.

The marvel is a copy of Donatello's David.
The marvel is original. [ Ugh ]
The marvel is in the test room.

This is pretty close to what I envisioned (at least for small lists; for larger ones of course a table would be better), and works provided that the connection between the (abstract) work and the reproduction is done with a relation, as this allows the is a copy of syntax to deduce that the new name refers to a reproduction. The only annoying thing currently is that defining originals is convoluted. Making the reproductions a subtype of the work would provide a rather clean solution, albeit not one satisfying my initial plan of considering the work and its physical embodiment as separate kinds. Maybe I will revisit that plan for the sake of simplicity, though.

Now first and foremost, I’m always iffy about trusting how Inform naturally orders things. That being said? If needing to define things over several lines bothered you? Like really, really bothered you? And you could ensure that there was 0 overlap here?

A blueprint is a kind of thing.
A tangible work is a kind of thing.

Leaves is a blueprint. Apples is a blueprint.

The Garden is a room.
The gilded copy of Leaves is a tangible work in the garden. The plain copy of Leaves is a tangible work in the garden. The marked copy of Apples is a tangible work in the garden.


Reprinting relates various tangible works to one blueprint. The verb to reprint means the reprinting relation. The verb to be reprinted means the reversed reprinting relation.
Originating relates a tangible work (called first print) to a blueprint. The verb to be originated means the originating relation. The verb to originate means the reversed originating relation.

Copying relates a tangible work (called reproduction) to a blueprint (called reproductee) when the reproduction reprints the reproductee or the reproduction is originated by the reproductee. The verb to copy means the copying relation. The verb to be copied means the copying relation.


When play begins:
	let L be the list of tangible works;
	repeat with blueprint-item running through blueprints:
		let L2 be L;
		let BIN be the substituted form of "[blueprint-item]";
		repeat with tangible-item running through L:
			let TIN be the substituted form of "[tangible-item]";
			if TIN matches the text BIN:
				if the first print of the blueprint-item is nothing:
					now the tangible-item is originated by the blueprint-item;
				otherwise:
					now the tangible-item reprints the blueprint-item;
				remove tangible-item from L2;
		now L is L2;
		
First report waiting:
	say "[The list of things which copy Leaves]!";
	rule succeeds;

This would seemingly take the first work defined which includes the blueprint in its printed name and mark it as the original, then would match everything after that as being a mere reprint. And both would be accepted as “copies” of that blueprint!

I don’t like relying on matching text, but it would just run once at the beginning of the game. I do seriously, seriously think it’s the nuclear option regardless. Still… food for thought, I suppose?

Edit: Accidentally left a vestigial “original” property in there. Fixed the example, still runs the same.

(The above is the most exaggerated version of this idea possible. A nice, stable version might involve, say, a table that the player would append onto. I’ve been idly toying with it since posting that.)

A blueprint is a kind of thing.
A tangible work is a kind of thing.

Table of TW
Print (a tangible work)	Holder (an object)
the gilded copy of Leaves	the garden
the plain copy of Leaves	the chair
the marked copy of Apples	--

Leaves is a blueprint. Apples is a blueprint.

The Garden is a room. The chair is a supporter in the garden. Some tangible works are defined by the table of TW.


Reprinting relates various tangible works to one blueprint. The verb to reprint means the reprinting relation. The verb to be reprinted means the reversed reprinting relation.
Originating relates a tangible work (called first print) to a blueprint. The verb to be originated means the originating relation. The verb to originate means the reversed originating relation.

Copying relates a tangible work (called reproduction) to a blueprint (called reproductee) when the reproduction reprints the reproductee or the reproduction is originated by the reproductee. The verb to copy means the copying relation. The verb to be copied means the copying relation.


When play begins:
	repeat with blueprint-item running through blueprints:
		let BIN be the substituted form of "[blueprint-item]";
		repeat through the table of TW:
			let PIN be the substituted form of "[print entry]";
			if PIN matches the text BIN:
				if the first print of the blueprint-item is nothing:
					now the print entry is originated by the blueprint-item;
				otherwise:
					now the print entry reprints the blueprint-item;
				if there is a holder entry:
					move the print entry to the holder entry;
				blank out the whole row;
		
First report waiting:
	say "[The list of things which copy Leaves]!";
	rule succeeds;

I actually thought this wouldn’t work, but maybe it was just lists that were dangerous to mess with while running through them. Surprisingly, everything seems to work just fine here. The idea is that you can just declare a tangible work and a location for it to end up (like the absolute minimum declarative statement you would want!) within the table and they would all be shuffled off as the game begins and assigned copy-status (and particularly original-status if they were the first tangible work to contain the name of a blueprint among the table). My concern with the table version, however, is that it might increase the difficulty of defining further qualities for its contents. Hmm.

Anyways! Hope my toying around with this to automate as much as possible could help in any way.

It has been very useful for brainstorming. I think I was subconsciously trying to avoid “post-processing” the data in When play begins, but there’s actually no reason to avoid that, and a lot of potential. It would also spare me the gimmick I’ve been using to work around the issue that one cannot ensure existence in relations as they can with properties. (At the very least, I can use When play begins to ensure that all work instances are “well defined” as in having a relation with a creative work.)

I also want to explore more the idea of creative works as a kind of value. This would make it easier to handle using the name of the creative work to reference the physical instances, including disambiguation, without having to “hack” the parser, which is the problem I’m trying to deal with now, since you can only use Understand the … property as describing when said property is for values, not when it’s for objects. Maybe the title of the work can be a value, rather than the work itself. Let’s see how much I end up tangling myself into a cascade of relations. The table for the definition will come in handy here, I think.