Lists of Kinds of Things, and Permanent Inventories

I’m working on a respawning system for my Eamon-like, and have hit a roadblock (yet again!).

My first problem is having an “original inventory” for a monster. I define items as kinds of things, because I want there to be more than one Shiny Red Shield in the game. But evidently you can’t have a list of kinds-- still confused on this point, because I can have a monster carry a kind of thing, and isn’t an inventory/list of objects carried just a list?

This is what should happen:

When play begins, an iterator loops through the original inventory of every monster, and “now monster carries item.” (item is still in the original inventory list, but related to the monster via the containment relation-- or so I hope)
A monster drops its carried/worn items on its death, and then after a set number of turns comes back alive, now carrying/wearing its “original inventory”

What happens instead:

When play begins, code is instead in place so that (line by line) a monster carries a (kind of sword) and wears a (kind of armor).

A monster drops its carried/worn items on its death (using a modified “Puff of Orange Smoke”-esque system), and then after a set number of turns comes back alive, but without its items (this is to be expected-- the items are moved from the monster’s inventory to the location.)

The code below describes the issue in brief, in case my example isn’t sufficient.

[code]
a person has a list of things called the Original Inventory.
a person can be dead rather than alive. a person is usually alive.

an antelope is a kind of person.
A set of antlers is a kind of thing.
A shiny pelt is a kind of thing.

the original inventory of an antelope is {set of antlers, shiny pelt}.

when play begins:
repeat with a running through antelopes:
repeat with i running through the original inventory of a:
now a carries i;

devkill is an action applying to nothing. understand “devkill” as devkill.

Carry out devkill:
repeat with x running through antelopes in the location:
unless x is the player:
now x is dead;
repeat with i running through things carried by x:
move i to the location;
say “Poor Stephen :(.”

devspawn is an action applying to nothing. understand “devspawn” as devspawn.

Carry out devspawn:
repeat with x running through dead antelopes in the location:
now x is not dead;
repeat with i running through original inventory of x:
now x carries i;
say “Antelopes love it when you do this, especially behind their ears.”

the anteloparium is a room. “Ariums! Antelopes! What more could you ask for?”

the player is in the anteloparium. there are five antelopes in the anteloparium.[/code]

The code gives the errors:

Problem. The constant list 'set of antlers, shiny pelt'   contains an entry 'set of antlers' which does make sense, but isn't a constant (it's a set of antlers). Only constants can appear as entries in constant lists, i.e., in lists written in braces '{' and '}'.

Problem. The constant list 'set of antlers, shiny pelt'   contains an entry 'shiny pelt' which does make sense, but isn't a constant (it's a shiny pelt). Only constants can appear as entries in constant lists, i.e., in lists written in braces '{' and '}'.

Does anyone have any clue what’s going on, or how I can fix this issue/have a list of kinds that would make everything run smoothly?

I appreciate you guys help!

You’re confusing kinds and instances of kinds. When you say “every monster carries a sword”, that creates an object of the “sword” kind for each monster and puts it in its inventory. It doesn’t give them the kind itself.

The trick is that you can’t create things like this at run-time (i.e. within rules); the compiler needs to know how many objects to make space for, and (for the most part) you can’t get more later.

Try something like this.

A set of horns is part of every antelope. A shiny pelt is part of every antelope.

Or:

Every antelope incorporates a set of horns and a shiny pelt.

You can’t use the list syntax, but it shouldn’t be too bad for reasonably-sized inventories.

You could create a kind of “troll sword” then create several of them “a rusty blue blade is a troll sword. A sharp shank is a troll sword…” Then when play begins repeat through trolls and declare "now x carries a random off-stage sword. "

Well thanks to some extra tinkering around, and the Dynamic Objects extension (almost feel like cheating), I’m able to get things rolling. I appreciate you guys help and input!

Be careful with dynamic objects–as I imagine you’ve discovered, they can’t be modified or deleted once they’ve been created.

I have not, in fact, discovered that yet, Draconis. Hmmm. That throws a wrench in things, for sure, as these cloned objects need to be editable and deletable. Back to the drawing board, I guess.

It looks like you can’t do lots of fun stuff with kinds like putting them in lists or table columns, which makes some of this a bit challenging. But you can hack up a sort of simulation of that by creating archetypes for the kinds, creating a symbolization relation that relates the archetypes to the things in the kind, putting the archetypes in your list, and whenever you need to do stuff with the list find things that the archetypes symbolize.

[rant=fairly off-topic stuff about how a related issue crops up in one of my games]I’m going to have to do something like this for the next release of Tea and Toast; I defined bread slices and teacups as kinds of things and then tried to put them in the Table of Specific Associations, which compiles under 6G60 (won’t under 6L02) but effectively leaves that row blank. Fortunately the bugs this creates aren’t noticeable to anyone if I don’t point them out – some memories that should be triggered by anonymous instances of the bread slice/teacup kinds won’t be. To fix this I have to create the symbolization relation, make sure most things symbolize themselves but anonymous instances are symbolized by archetypes, and put the archetypes in a table column.[/rant]

Here’s what I came up with:

[code]
An archetype is a kind of thing.

a person has a list of archetypes called the Original Inventory.
a person can be dead or alive. a person is usually alive.

an antelope is a kind of person.
A set of antlers is a kind of thing. The plural of set of antlers is sets of antlers.
A shiny pelt is a kind of thing…

Symbolization relates one archetype to various things. The verb to symbolize means the symbolization relation.

The archetypal set of antlers is an archetype. The archetypal shiny pelt is an archetype.

The original inventory of an antelope is always {archetypal set of antlers, archetypal shiny pelt}.

First when play begins:
now the archetypal set of antlers symbolizes every set of antlers;
now the archetypal shiny pelt symbolizes every shiny pelt.

To give (spawn - an antelope) a/an (possession - archetype):
if the possession symbolizes an off-stage thing (called new possession):
now spawn carries new possession;
otherwise:
say “Warning! [Possession] has no off-stage representatives. Garbage collection routine goes here.”

when play begins:
repeat with spawn running through antelopes:
repeat with possession running through the original inventory of spawn:
give spawn a possession;

devkill is an action applying to nothing. understand “devkill” as devkill.

Carry out devkill:
repeat with x running through antelopes in the location:
unless x is the player:
now x is dead;
repeat with i running through things carried by x:
move i to the location;
say “Poor Stephen :(.”

devspawn is an action applying to nothing. understand “devspawn” as devspawn.

Carry out devspawn:
repeat with x running through dead antelopes in the location:
now x is not dead;
repeat with possession running through the original inventory of x:
give x a possession;
say “Antelopes love it when you do this, especially behind their ears.”

the anteloparium is a room. “Ariums! Antelopes! What more could you ask for?”

the player is in the anteloparium. there are five antelopes in the anteloparium. There are 20 sets of antlers. There are 20 shiny pelts.[/code]

Note that I’m not creating any new pelts or antelopes dynamically; I created a supply of them off-stage and move the off-stage ones on-stage as needed. If you run out of your off-stage supply of stuff you have to figure out a way to garbage collect by moving some on-stage stuff back off-stage (like, some of the antlers that are in another room could disappear off the floor). If that’s not practical you probably have to figure out something with Dynamic Objects or an even more baroque workaround; if you’ve got the kind of design where the player could in theory farm respawning enemies so that there could be thousands of sets of antlers on stage you’ll really need to think hard. Nuku Valente, who does crazy amazing stuff using Inform to make massive RPGs, says he simulates bunches of objects by not using them as things – he just uses values to keep track of the number of a certain kind of object that the player owns.

PS Note that you need to use “or” rather than “rather than” when you’re defining the dead/alive property, and you need to say what the plural of “set of antlers” is or Inform will probably think it’s “Set of antlereses.” Also you need to write 20 as a number in “There are 20 shiny pelts”; I hit a bit of a roadblock when I wrote “there are twenty shiny pelts” and Inform thought I was creating one object called “twenty shiny pelts.” There’s actually a warning about this specific thing in the documentation somewhere; I think you can write out numbers up to twelve and with 13 or more you have to use numbers.

This is exactly the kind of design I have going, and exactly the inventory system I implemented a while back, or tried to implement, before I6 ran out of memory for some reason and I freaked and deleted the system because I didn’t know how to fix it and thought the system was the problem. It won’t be difficult to create again, and is probably overall the best way to go. Thanks for your help!

The idiosyncrasies of Inform!

So this is what I’ve come up with. I don’t /think/ it has any problems, because I’ve tested the daylights out of it, but could it be written better/coded more efficiently?

PART 1 - I6 CODE

[from Kerkerkruip]
Include (-

! Find the kind of an object
[ KindOfObj obj;
	return KindHierarchy-->( ( obj.KD_Count ) * 2 );
];

! Test if a kind is a subkind of another kind
[ TestSubkind subclass superclass	i;
	! These classes are outside the kind heirarchy and must be dealt with first
	if ( subclass == Class or Object or Routine or String or VPH_Class )
		rfalse;
	
	while (1)
	{
		if ( KindHierarchy-->i == subclass )
			return KindHierarchy-->( KindHierarchy-->(i + 1) * 2 ) == superclass;
		i = i + 2;
	}
];

-).

To decide what object is the kind of (obj - object):
	(-  KindOfObj( {obj} ) -).

PART 2 - NEW INVENTORY MANAGEMENT SYSTEM	

a thing has a number called the bundle number. the bundle number of a thing is usually 1.


[instead of moving it to the location, dropping an item moves it offstage]
[items dropped by enemies (given the dropped-item adjective) that are not picked up before moving to the next room are moved offstage]

Instead of dropping something (called the chosen object):
	say "If you drop [the noun], it will be gone forever. Do you wish to continue?";
	if the player consents:
		if the bundle number of the chosen object is at least 2:
			decrement the bundle number of the chosen object;
		otherwise:
			now the noun is off-stage;
			say "We just moved [noun] off-stage; now it's ready to be used by someone."

Before going somewhere:
	repeat with di running through dropped-item things in the location:
		now di is off-stage;
		now di is not dropped-item;
		say "We just move [di] off-stage; now it's ready to be used by someone."

Instead of taking something (called the chosen object):
	let cokind be the kind of the chosen object;
	repeat with i running through things carried by the player:
		let ikind be the kind of i;
		if cokind is ikind:
			increment the bundle number of i;
			now the chosen object is off-stage;
			say "you already have one of these, so we just moved [chosen object] off-stage; now it's ready to be used by someone.[line break]";
			stop;
	move the chosen object to the player;
	say "You didn't have one of these before, so we just moved the actual object to you.[line break]"

after printing the name of something (called the item) while taking inventory:
	say "(x[bundle number of the item])"
	
An archetype is a kind of thing.

a person has a list of archetypes called the Original Inventory.
a person can be dead or alive. a person is usually alive.

a thing can be dropped-item. a thing is usually not dropped-item.

an antelope is a kind of person.
A set of antlers is a kind of thing. The plural of set of antlers is sets of antlers.
A shiny pelt is a kind of thing.. 

Symbolization relates one archetype to various things. The verb to symbolize means the symbolization relation.

The archetypal set of antlers is an archetype. The archetypal shiny pelt is an archetype. 

The original inventory of an antelope is always {archetypal set of antlers, archetypal shiny pelt}.

First when play begins:
	now the archetypal set of antlers symbolizes every set of antlers;
	now the archetypal shiny pelt symbolizes every shiny pelt.
	
To give (spawn - an antelope) a/an (possession - archetype):
	repeat with i running through things carried by spawn:
		if possession symbolizes i:
			stop; [if they already have one (i.e., they didn't drop it when they died) don't give them another one]
	if the possession symbolizes an off-stage thing (called new possession):
		now spawn carries new possession;
	otherwise:
		say "Warning! [Possession] has no off-stage representatives. Garbage collection routine goes here." 

when play begins:
	repeat with spawn running through antelopes:
		repeat with possession running through the original inventory of spawn:
			now spawn owns symbol-wise possession;
			give spawn a possession;
			
devkill is an action applying to nothing. understand "devkill" as devkill.

The worldview is a privately-named backdrop. It is everywhere. The spirit-world is a privately-named transparent closed unopenable container. It is part of the worldview. 

Carry out devkill:
	repeat with x running through antelopes in the location:
		unless x is the player:
			now x is dead;
			move x to the spirit-world;
			repeat with i running through things carried by x:
				if a random chance of 1 in 20 succeeds:
					now i is dropped-item;
					move i to the location;
	try looking;
				
devspawn is an action applying to nothing. understand "devspawn" as devspawn.

Carry out devspawn:
	repeat with x running through dead antelopes in the spirit-world:
		now x is not dead;
		move x to the location;
		repeat with possession running through the original inventory of x:
			give x a possession;
	try looking;

after examining someone:
	say "Carrying [list of things carried by the noun]"
	
PART 3 - THE SCENARIO

the anteloparium is a room. "Ariums! Antelopes! What more could you ask for?"

the frozen northern room is north of the anteloparium. The printed name of the frozen northern room is "The Frozen North". The description of the frozen northern room is "Pretty chilly, what with all the absolute cardinal direction laying about."

the player is in the anteloparium. 
Antelope 1 is an antelope in the anteloparium.
Antelope 2 is an antelope in the anteloparium.
Antelope 3 is an antelope in the anteloparium.

There are 6 sets of antlers. There are 6 shiny pelts. [in off-stage storage, ready to be given out-- at least two for every haver of the item, one for on-stage and one for off-stage]

Thanks again for your help/review!