Kinds in Tables?

I would like to be able to reference kinds in table entries. Is there any way to make this possible? The following is why I want to do this (this is an example, I’m not really making a game about smoothies, but my actual game code/content is under heavy construction so I won’t be sharing real values here):

A raspberry is a kind of thing.
A banana is a kind of thing.
A strawberry is a kind of thing.
A vanilla is a kind of thing.
An orange is a kind of thing.
A raspberry blast is a kind of thing.
An orange you glad is a kind of thing.
A strawberry delight is a kind of thing.
	
Table of Smoothies
item1 (kind)	item2 (kind)	item3 (kind)	result (kind)
raspberry		banana		orange		raspberry blast
orange		banana		vanilla		orange you glad
strawberry		banana		vanilla		strawberry delight

The above doesn’t work. This is very annoying because then I have to do this:

A category is a kind of value.

A raspberry is a kind of thing. raspberry-category is a category.
A banana is a kind of thing. banana-category is a category.
A strawberry is a kind of thing. strawberry-category is a category.
A vanilla is a kind of thing. vanilla-category is a category.
An orange is a kind of thing. orange-category is a category.
A raspberry blast is a kind of thing. raspberry-blast-category is a category.
An orange you glad is a kind of thing. orange-you-glad-category is a category.
A strawberry delight is a kind of thing. strawberry-delight-category is a category.

Table of Smoothies
item1 (category)		item2 (category)		item3 (category)		result (category)
raspberry-category	banana-category		orange-category		raspberry-blast-category
orange-category		banana-category		vanilla-category		orange-you-glad-category
strawberry-category	banana-category		vanilla-category		strawberry-delight-category

Since a “kind” is already a “category,” this redundancy is very inefficient, both for writing code and for application performance when in the real game there are way more kinds/categories than in this example. Any thoughts?

Also… how do you keep tables formatted properly when copy/pasting from Inform to the board?

I7 tables cannot contain kinds.

On the other hand, while the category system is tedious to type out, it shouldn’t be a big deal for application performance.

Why do you need to keep kinds in tables? Your example doesn’t show that–what are you going to use the kind name for later?

If you’re using dynamic objects, you can’t create an object from a kind: you need another instance of that kind to “clone”. In that case, make the prototypes you need (which don’t even need to be kinds) and store those in the table.

If you’re using your “prop system”, why bother with kinds at all? You can’t change those during play. Just use an enumerated value.

I’m not doing generic props anymore… after lots of experimentation, shunting the burden from kinds to texts doesn’t gain anything, and only loses doing things the normal way. Inform just can’t do the randomized content I wanted to do, so I’m working at being slightly more traditional with it… I guess. In any case, I am still using kinds and assemblies, etc… just not to the extent that there are only 1 kind of thing anymore.

I got this (mostly) working using a bit of I6 code I think eu gave me… I can’t find the original post, so I think it was eu… anyway, that code is also here, as well as a way to add third nouns from a post by ChristianB, and using an example from the documentation called “What Makes You Tick” for applying an action to two things and comparing two lists to get a result…

Phew, I never imagined it would be so complicated to just put three things together in an array and run a function on a match… anyway, this works, except for the lists don’t seem to sort alphabetically, so unless you know the order in the list in the code, it doesn’t work. How can I get these lists to sort the same way?

To say the kind of (O - an object): (-
	if ({O} provides KD_Count) {
		print (I7_Kind_Name) (KindHierarchy-->(({O}.KD_Count) * 2));
	} else {
		print "object";
	}
-).


The third noun is an object that varies. The third noun variable translates into I6 as "third".

	The understand token third something translates into I6 as "THIRD_NOUN_TOKEN".

	[cf. DM4, p. 489]

	Include (-
	Global third;
	-) after "Definitions.i6t".

	Include (-
	[ THIRD_NOUN_TOKEN  x;
		x  =  ParseToken(ELEMENTARY_TT,  NOUN_TOKEN);
		if  (x  ==  GPR_FAIL  or  GPR_REPARSE)  return  x;
		third  =  x;  return  GPR_PREPOSITION;
	];
	-).

The prop-room is a room.

The kitchen is a room.

A thing can be smoothie-ingredient. A thing is usually not smoothie-ingredient.

A raspberry is a kind of thing. A raspberry is usually smoothie-ingredient.
A banana is a kind of thing. A banana is usually smoothie-ingredient.
A strawberry is a kind of thing. A strawberry is usually smoothie-ingredient.
A vanilla is a kind of thing. A vanilla is usually smoothie-ingredient.
An orange is a kind of thing. An orange is usually smoothie-ingredient. The printed name of an orange is usually "orange".
A raspberry blast is a kind of thing.
An orange you glad is a kind of thing.
A strawberry delight is a kind of thing.

1 raspberry is in the kitchen. 
1 banana is in the kitchen.
1 strawberry is in the kitchen.
1 vanilla is in the kitchen.
1 orange is in the kitchen.
1 raspberry blast is in the prop-room.
1 orange you glad is in the prop-room.
1 strawberry delight is in the prop-room.

The player is in the kitchen.

After reading a command:
	if the player's command includes "combine":
		if the player's command includes "and":
			replace the matched text with "plus";

Combining it with is an action applying to two things.

Check combining it with (this is the make smoothie rule):
	let smoothie-success be a truth state;
	if the noun is smoothie-ingredient and the second noun is smoothie-ingredient and the third noun is smoothie-ingredient:
		let L be a list of texts;
		add "[the kind of the noun]" to L;
		add "[the kind of the second noun]" to L;
		add "[the kind of the third noun]" to L;
		sort L;
		repeat through table of smoothies:
			let x be the components list entry;
			sort x;
			say "[x] should be [L][paragraph break]";
			if L is x:
				now the noun is in the prop-room;
				now the second noun is in the prop-room;
				now the third noun is in the prop-room;
				repeat with y running through things in the prop-room:
					if "[the kind of y]" exactly matches the text "[result entry]", case-insensitively:
						now y is in the location;
						say "You made a [result entry]!";
						now smoothie-success is true;
						break;
		if smoothie-success is false:
			say "Those ingredients don't seem to be a part of a valid smoothie recipe.";

Understand "combine [something] with [something] plus [third something]" as combining it with.

Table of smoothies
components list				result
{"banana","raspberry","orange"}	"raspberry blast"
{"banana","orange","vanilla"}	"orange you glad"
{"strawberry","banana","vanilla"}	"strawberry delight"

Since you haven’t said what you actually need this for this may not apply, but it would probably be easier to have the combining action apply to only one thing, understand “combine [things]”, then compare the lists of ingredients to the multiple item list (see the “Left Hand of Autumn” example).

I’m not certain if that example will work for what I’m doing or not, but even if it does, it will still require sorting the list the same way as the player entry.

What I posted here is only a single use case. I will have lots of different things, with lots of possible combinations, that can be combined. The same items can be used in different combinations. Again, doing it the way I have done above or some modification of the Left Hand of Autumn example will still require the sorted lists that are compared to be sorted in the same order.

When I add the player’s command to a list and then sort it, the sorting order doesn’t seem to ever match the sorting order of the items in the list in the code. That’s the problem. In the documentation, it looks like you should be able to sort lists… but are you only able to sort lists numerically? I need to be able to sort a list alphabetically is what I’m asking.

Otherwise this happens:

>Combine raspberry with banana and orange
Those ingredients don't seem to be part of a valid smoothie recipe.

When in fact, raspberry, banana, and orange ARE part of a valid smoothie recipe, just not in that order. I need it to recognize the list as the same regardless of how the player entered it. I’m not sure how to get that working with the Left Hand of Autumn example because the player doesn’t enter the commands, the items just “are there” and then examined. It’s not quite the same use case.

Why can’t I sort the list alphabetically?

Sorting depends on the type of list. Lists of numbers sort numerically, lists of texts sort alphabetically, and lists of objects sort by (I believe) a sort of internal index which roughly corresponds to order of definition in the source file.

The important thing isn’t how it’s sorted, though, so long as it’s consistent. Just sort all the lists in your table when play begins, then sort the multiple item list before comparing.

I’ve simplified the example to show the issue. Everything else works, except that sorting the list of the user’s inputs doesn’t result in anything being sorted, in any way, alphabetically or otherwise. Am I missing something?

To say the kind of (O - an object): (-
	if ({O} provides KD_Count) {
		print (I7_Kind_Name) (KindHierarchy-->(({O}.KD_Count) * 2));
	} else {
		print "object";
	}
-).


The third noun is an object that varies. The third noun variable translates into I6 as "third".

	The understand token third something translates into I6 as "THIRD_NOUN_TOKEN".

	[cf. DM4, p. 489]

	Include (-
	Global third;
	-) after "Definitions.i6t".

	Include (-
	[ THIRD_NOUN_TOKEN  x;
		x  =  ParseToken(ELEMENTARY_TT,  NOUN_TOKEN);
		if  (x  ==  GPR_FAIL  or  GPR_REPARSE)  return  x;
		third  =  x;  return  GPR_PREPOSITION;
	];
	-).

The kitchen is a room.

A raspberry is a kind of thing. 1 raspberry is in the kitchen.
A banana is a kind of thing. 1 banana is in the kitchen.
An orange is a kind of thing. 1 orange is in the kitchen.

Understand "sort [something] with [something] plus [third something]" as sorting user input.

Sorting user input is an action applying to two things.

Check sorting user input (this is the test sorting user input rule):
	let L be a list of texts;
	add "[the kind of the noun]" to L;
	add "[the kind of the second noun]" to L;
	add "[the kind of the third noun]" to L;
	sort L;
	say "[L]";

Whatever you enter, this ends up as the “say” result for “L”. If you enter “sort raspberry with banana plus orange” the result is “raspberry, banana and orange”, if you enter “sort orange with banana plus raspberry” the result is “orange, banana and raspberry.” If this were sorting alphabetically, every time this action occurs in this test game, the resulting say should always be “banana, orange and raspberry.” Why isn’t this sorting alphabetically?

Sorry for the double post, but I think I see the problem… it isn’t sorting lists with text substitutions…

This works:

The kitchen is a room.

The player is in the kitchen.

When play begins:
	let x be a list of texts;
	add "c" to x;
	add "b" to x;
	add "a" to x;
	sort x;
	say "[x]";

This doesn’t:

The kitchen is a room.

The player is in the kitchen.

When play begins:
	let x be a list of texts;
	add "[printed name of player]" to x;
	add "[printed name of kitchen]" to x;
	add "z" to x;
	sort x;
	say "[x]";

How can I get it to work when there are substitutions?

Use “the substituted form of” your text, or just don’t use substitutions in this case (“add the kind of the noun to L”).

Thank you! I would never have had any idea to look for that phrase. I had a hard time figuring out how to use it even after you told me. I tried to insert it into the same line as declaring the text to be added to the list, and it gave some cryptic error. I had to do this:

		let L be a list of texts;
		let noun-shunt be the substituted form of "[the kind of the noun]";
		let second-noun-shunt be the substituted form of "[the kind of the second noun]";
		let third-noun-shunt be the substituted form of "[the kind of the third noun]";
		add noun-shunt to L;
		add second-noun-shunt to L;
		add third-noun-shunt to L;
		sort L;

Is this the best way to have written this? This works, but it seems like there should have been a way not to need the “shunts” to do this. In any case, if this is how you meant to write it, awesome, as this works! Phew…

Let L be a list of texts; add the printed kind of the noun to L; add the printed kind of the second noun to L; add the printed kind of the third noun to L; sort L.

Along with this slight addition to eu’s kind-name-printing code:

To decide which text is the printed kind of (O - object): decide on the substituted form of "[the kind of O]".

The reason you need the shunts if you’re not using the second snippet here is that [the kind of X] is a say-phrase, not a function returning a text, and they aren’t quite identical in cases like this. I’m not very good at I6, so I just left eu’s code as it was and added a “wrapper” to it.

I couldn’t get this to work unless I added the word “printed” to the decide phrase.

To decide which text is the printed kind of (O - object):
    decide on the substituted form of "[the kind of O]".

Is that right? Or did I miss some other way you had installed it around eu’s script?

[rant]Honestly, I have a hard time with these kinds of strongly-typed language issues, so I’m not sure if I missed something else, or if what I did above was the correct fix. If only there were as robust a platform, in terms of other functions Inform 7 has, for IF written in Javascript! I get very frustrated when a class can’t be a text can’t be a printed text can’t be an object can’t be a resolved/substituted text… argh! Oh well, keep plugging away with help from others…[/rant]

Sorry, I had a typo in my post. That is correct.

Inform 6 is actually much less strongly typed–for example, a property like “description” can be set to either a string or a routine. This is how I7 can have if-statements within text variables. That text is compiled to a routine with those comparisons in it, which can then be treated like any other string. Just an interesting bit of trivia.

The trick here is that Inform doesn’t quite know what you want. If you wrote something like this…

now the description of bar is "[description of foo]"; now the description of foo is "new description";
…do you want to copy foo’s description to bar, or are you telling Inform that bar’s description should always match foo’s (so it would change when you changed foo)?
In a case like this, unless the thing inside the brackets is about to expire (e.g. a “let” variable), Inform assumes you want to use a reference: bar’s description should not be the string which had been foo’s description, but rather a routine which checks foo’s description each time it is called.
If you want to copy the text instead, you could say “now the description of bar is the description of foo”.

But since the code giving you the kind name is a say-phrase rather than a function returning a text, it’s not considered to be a text for the purposes of things like this–it’s a function which prints the kind name and returns nothing, rather than a function which returns a text and can thus be considered equivalent to a text.

This is all rather confusing, and I’m not explaining very well. Basically it’s a quirk of Inform’s special handling of text with substitutions.