Indefinite Article Lost When Using "Custom Descriptions"

I’m trying to rewire things so that things can be both supporters and containers at the same time. I don’t care if this is a good idea or not, I’m just interested in solving the puzzle of the loss of indefinite article recognition when doing so and also customizing the way things report what is on/in them as seen in the code below. I am not sure why, but this causes the indefinite article to disappear. The code below is incomplete to accomplish all I want it to eventually accomplish in terms of grammar and logic for listing, and is extracted from the rest of my application, but I think it isolates the basic issue here with enough insight into why I want to use it to ask the forum how to fix it to restore the indefinite article.

the kitchen is a room.

The player is in the kitchen.

A thing has a text called id.

A prop is a kind of thing.

A prop is a kind of supporter.

A supporter is a kind of container.

The printed name of a thing is usually "[id]";

To say list of things on the item described:
	let i be 0;
	repeat with X running through list of things on the item described:
		if X is in the item described:
			next;
		otherwise:
			increment i;
			if i > 0:
				say ", on which is [run paragraph on]";
			say "[the printed name of X]";

To say list of things in the item described:
	let i be 0;
	repeat with X running through list of things in the item described:
		if i is 0:
			say ", in which is [run paragraph on]";
			say "[the printed name of X]";
		otherwise:
			say " [the printed name of X]";
		increment i;

Rule for writing a paragraph about a thing:
	say "[the printed name of the item described][list of things on the item described][list of things in the item described].";

100 props are in the prop-room.

When play begins:
	repeat with X running through props in the prop-room:
		now X is in the kitchen;
		now the id of X is "test";
		break;

Your example is way overcomplicated. If you’d cut it down more I think you would have seen what’s going on.

The Kitchen is a room.

The rock is in the Kitchen. The printed name of the rock is "stone".

When play begins:
	say "The printed name of the rock is: [the printed name of the rock]."

[ ==> "The printed name of the rock is: stone."]

The printed name of the rock is a text, not an object. When you print it, you get it as-is. There are special substitutions “[the (object)]”, “[a (object)]” which apply articles to objects – but there’s no such magic for “[the (text)]”. The “the” is a null word there.

OK:

  1. I know you said you didn’t care, but this doesn’t seem like a good idea. If the point is that the props might be supporters or might be containers,but you don’t know which, you can just define some prop supporters and some prop containers and do it that way.

  2. Or if you want stuff that really acts both as containers and supporters, check out the “U-Stor-It” example.

  3. Seriously, messing with the built-in kind hierarchy seems likely to end in tears.

  4. I am not at all sure what your intended output from that test code is…

  5. But when I reduce it to one prop, and add some stuff to put in the prop, it looks like I can get indefinite articles to show up by replacing “[the printed name of X]” with “[a X]”, thus:

[code]the kitchen is a room.

The player is in the kitchen. The player carries a knife, a fork, and a spoon. The id of the knife is “knife”. The id of the fork is “fork”. The id of the spoon is “spoon”.

A thing has a text called id.
A prop is a kind of thing.

A prop is a kind of supporter.

A supporter is a kind of container.

The printed name of a thing is usually “[id]”;

To say list of things on the item described:
let i be 0;
repeat with X running through list of things on the item described:
if X is in the item described:
next;
otherwise:
increment i;
if i > 0:
say “, on which is [run paragraph on]”;
say “[a X]”;

To say list of things in the item described:
let i be 0;
repeat with X running through list of things in the item described:
if i is 0:
say “, in which is [run paragraph on]”;
say “[a X]”;
otherwise:
say " [a X]";
increment i;

Rule for writing a paragraph about a thing:
say “[the printed name of the item described][list of things on the item described][list of things in the item described].”;

One prop is in the kitchen. The id of a prop is usually “test”.[/code]

yielding

  1. However, you will notice that this makes it “in which” even though it should be “on”; I’m pretty sure this is because you can tell Inform that a supporter is a kind of container, but that won’t let it distinguish between the stuff that’s in something and the stuff that’s on it; it’s all just contents.

@zarf: I am sorry, but it wasn’t as obvious to me where the issue was stemming from. I didn’t know if it was because I was using the [id] as the printed name, or if it was the writing a paragraph rule, or a problem in the to say the list. I’m not very good with this language so it wasn’t as obvious to me as you :slight_smile: that’s why the question.

@matt and @zarf: I understand the problem now. I didn’t know I could put the article in the object reference after the fact like “[a x]”. This has cleared this up, thank you!

As for making supporters containers, and the issues that might come along with that, I was exploring it because though it might create problems that need to be addressed with complex workarounds, those complex workarounds might be less complex than having to have different kinds. The reason is that kinds cannot be changed. The example I’m posting is an incomplete picture of what I’m trying to do just to isolate this indefinite article issue. If I have to make a distinction between container props and supporter props and pushable between room props and… well, the code to change the properties of the props to present as different things to the player gets exponentially more complex.

I just really still don’t have a better idea of how to give the illusion of thousands of things in the game world without actually making thousands of things, which make the game run like crap. People do keep telling me my approach seems flawed, but I still don’t have a simplified working example of a better approach to model mine after, so I don’t have much else to do but keep plugging along.

The reason you can’t have container-supporters is that objects are stored as a hierarchy. If the parent object has the “container” flag they’re listed as “in” it, if it has the “supporter” flag they’re listed as “on” it, if it has the “animate” flag they’re listed as “carried by” it, but they’re all stored the same way.

If you really want to change containers to supporters or vice-versa you can do it in I6, but they’ll still keep their I7 kinds.

And again, if the player’s not going to be interacting with thousands of objects at the same time, you don’t need thousands of objects. Look at Kerkerkruip. This is why things like backdrops are in the I7 library. You could put a “sun” object in every outdoor room, but the player will only see one at a time, so why not just use a single object and move it around?

Check out the Kinds tab of the index; that’ll tell you what’s in the kinds hierarchy and what isn’t. To avoid changing kinds on the fly, you should only need to set up separate container props, supporter props, none of the above props, maybe device props, and maaaaayyyybe vehicle props if you want to implement some vehicles. Stuff like “pushable between rooms” can be changed on the fly (see section 3.16 for this particular example). So you can preserve the kind hierarchy without having that many extra objects waiting off-stage.

OK, here’s an example of how you can do stuff:

[spoiler][code]Dungeon is a room. “A room of a dungeon.”

A direction can be cardinal. North is cardinal. West is cardinal. South is cardinal. East is cardinal.

A direction can be impassable or passable. A direction is usually impassable. [The directions you can go. There aren’t any real rooms or exits there, you just randomly generate the room again when you go.]

A plain prop is a kind of thing. There are 20 plain props.
A container prop is a kind of container. There are 20 container props.
A supporter prop is a kind of supporter. There are 20 supporter props.

The carrying capacity of the player is 10. The carrying capacity of a container is usually 5. The carrying capacity of a supporter is usually 5. [This should prevent the player from grabbing all the off-stage props without going to a ridiculous amount of effort.]

Definition: an object is proppy if it is a plain prop or it is a container prop or it is a supporter prop.

Definition: an object is loose if the player does not enclose it and it does not enclose the player and it is not the player and it is not the item-pushed-between-rooms and the item-pushed-between-rooms does not enclose it. [This excludes stuff the player is carrying, and stuff the player pushed, and their contents; it would also exclude any vehicles the player was riding in if we had any. I guess it wouldn’t exclude things that were in the vehicle so if you really wanted to implement vehicles you’d have to do a better job with this. Item-pushed-between-rooms is a global variable, I believe, which stores something that was pushed between rooms if you pushed something between rooms.]

When play begins: generate the location.

To generate the location: [This is what happens every time we simulate a new room.]
now every loose proppy thing is off-stage; [Back in the other room.]
if a random chance of two in three succeeds:
create a random off-stage plain prop;
if a random chance of one in two succeeds:
create a random off-stage container prop;
if a random chance of one in three succeeds:
create a random off-stage supporter prop;
now every direction is impassable;
let exits be a random number from 1 to 4;
repeat with counter running from 1 to exits:
now a random impassable cardinal direction is passable.

After looking: say “You can go [list of passable directions].”

Instead of going a passable direction:
generate the location;
try looking.

To create (item - a thing):
now the printed name of the item is the substituted form of “[random name]”; [I’m actually not quite sure whether you need to say “substituted form” here, but after the name is generated randomly it fixes it in place]
now the item is in the location;
if a random chance of 1 in 2 succeeds:
now the item is fixed in place;
if a random chance of 1 in 3 succeeds:
now the item is pushable between rooms;
if the item is a container:
let the secondary item be a random off-stage plain prop;
create the secondary item;
now the secondary item is not fixed in place;
now the secondary item is not pushable between rooms; [we need this because the code for generating the secondary item might have made it bulky or wheeled]
now the secondary item is in the item;
if a random chance of 1 in 2 succeeds:
now the item is openable;
now the item is closed;
if the item is a supporter:
let the secondary item be a random off-stage plain prop;
create the secondary item;
now the secondary item is not fixed in place;
now the secondary item is not pushable between rooms;
now the secondary item is on the item.

Before printing the name of a fixed in place thing: say "bulky “. [just to let the player know what is going on]
After printing the name of a pushable between rooms thing while looking: say " with a convenient set of wheels”.

Understand the printed name property as describing a thing. [This lets the player typed the randomly generated name and refer to the thing.]

Section - Random Name Generator

Table of Consonants
consonant
“b”
“c”
“d”
“f”
“g”
“h”
“j”
“k”
“l”
“m”
“n”
“p”
“qu”
“r”
“s”
“t”
“v”
“w”
“x”
“z”
“sh”
“th”
“ch”

Table of Vowels
vowel
“a”
“e”
“i”
“o”
“u”
“y”

To say random consonant:
let n be a random number between 1 and the number of rows in the Table of Consonants;
choose row n in the Table of Consonants;
say the consonant entry.

To say random vowel:
let n be a random number between 1 and the number of rows in the Table of Vowels;
choose row n in the Table of Vowels;
say the vowel entry.

To say random name:
say “[random consonant][random vowel][random consonant][random vowel][random consonant]”.[/code][/spoiler]

Yielding output like this:

If you really wanted to create the illusion of a persistent dungeon, you’d want to use Aaron Reed’s Procedural Randomness (which looks like it works in the new I7, but I would stress test it a bit before trying). And you’d have to write some code to keep track of things that the player had taken or dropped in various rooms, so they don’t regenerate. And you’d have to come up with a less silly name generator. But this is maybe a kind of framework, and it doesn’t require many more objects than are around at a time.

Thank you for this, matt w. I appreciate the effort, and I am kind of embarrassed that your silly random letter generator dungeon you whipped up is kind of more playable than anything I’ve ever made, as I am still working through learning how to do things…

However, this isn’t exactly what I meant by “random loot and events” exactly. Things don’t actually have to be truly random… fluid, open-world, replayable, and psuedo-random, I suppose. The issue I have is that the scope of what I want to do will eventually (or immediately) cause performance issues with the game. I’ve already created “stress test” applications putting thousands of things into the game, or less things with much more complex texts to simulate things, and things start to really break down around 1200 things, no matter what settings.

So, in your demo above, you have the application creating random things. Eventually, if you create enough random things, the game will start to degrade in performance. What I am trying to do is recycle the same objects by changing the properties of the objects to appear as different objects. That’s what I mean by “prop” in that it can be used to be many different things, as a prop on stage might be.

Draconis has asked more than once why I need thousands of things. I don’t need thousands of things at once, but I need the game to be able to have the data for thousands of things in storage for access at a later time. If I want to create a few dozen characters, and have them all be richly programmed and immersed in their world, they will each have dozens of pieces of equipment, possessions, etc. Then what of the nameless characters, that I still want to have a dozen possessions each as the “loot” they might carry? If all of these are defined as discrete objects, there are way too many objects in the game, so that’s what I’m trying to work around.

I know the scope of this for a first time game is large, but it’s the only kind of game I am interested in making, so if I can’t, I can’t, but I don’t want to do anything else. I don’t know if I’ll ever finish learning this, much less the game, but if it takes me the rest of my life, I’ll keep coming back to it. I really would like to make a game someday, I have, I think, nifty ideas, but I can’t do a whole production with graphics by myself (or at all) so text-based is the way to go. I’ve already put a lot of effort into learning I7 so I’ll keep trying, but this engine wasn’t made with the kind of game I am trying to make in mind (there are other issues, but this is already an insanely long post, so I’ll leave it be).

I still don’t see why you need thousands of items. You just said you wanted the loot to be randomized. Why not just generate the items when they drop, and recycle any that the player doesn’t choose to take? That’s effectively what Matt’s sample code does–all the items are “props” off-stage at the beginning, which are randomized and added to the room when they are needed and taken away afterward. The carrying capacity limits keep the story from running out of props unless the player intentionally tries very hard to break it. But no items are ever created or destroyed, only repurposed.

Re the detailed characters: an NPC’s possessions don’t necessarily need to be implemented the same way as the PC’s, unless the player can somehow steal them and use them. From the player’s perspective, describing Bob the Fighter as using a sword in the descriptions is just the same as actually giving him an object called a sword. Even if theft is possible in your story, when the player takes the item you could just grab a prop and give it whatever properties you want.

Yes, as Draconis says, my code doesn’t create random things. When I declare the twenty of each kind of prop at the beginning, that’s all the objects that are ever created in the game. (To create new objects at runtime you have to use an extension called Dynamic Objects by Jesse McGrew, which I’m not sure is even updated for 6L02 – anyway it’s not something you see in most I7 code.) When a prop gets moved on-stage its properties get set, but when the player leaves the room the prop gets moved back off-stage so it can be recycled later. And the demo showed how you can change the props so sometimes they’re fixed in place, sometimes they’re pushable, etc.

Now, my demo creates random things for each room, which means that if you go north from the room with the lyquysh and go back south you won’t find the lyquysh again. The way I’d suggest to get around this is by using the Procedural Randomness extension, which I mentioned but didn’t explain. What that does is let you generate random numbers consistently from certain seeds. So you could keep track of the coordinates of the room, use that as a seed for the random number generator, and generate the properties that the stuff in the room has each time. So when you walk into the room at (3, 1) the game asks itself “What’s at (3,1)? A lyquysh.” Then you go north and south again and once again the game asks itself “What’s at (3,1)? A lyquysh.” That way you don’t have to store all the data for the randomly generated props; you can re-generate it each time from a simple seed. And you could do something similar with NPCs. (I have a really simple demo of this but I’m not on my computer right now.)

The tricky thing here would be keeping track of changes in the world. What I would do here is have some kind of table keeping track of that stuff; store every room the player visits with some kind of note keeping track of “the player took object 3 from this room” or “the player dropped object 5 from this room in this other room.” Then when it comes time to generate the location again you can check which native objects have been removed and which non-native objects are there, and go through the routine to generate their properties again. This would be challenging, but hey, that’s the fun of it.

Or you could come up with some sort of justification for the objects you moved “de-spawning” before you return (a la the Thief in Zork).

Aha, I think I misunderstood the “create” function to mean you were trying to create new objects. :blush:

Ok, so, this is essentially what I am trying to do, but instead of creating random properties and names, I am needing to draw from existing data. There might be “limited randomness” in that specific properties of an item may fall in a range, and different things are more or less likely to be one thing than another, but each “kind” of thing (not using Inform kinds, but different categories of what the props present as to the player) need to have specific information.

So, the way it looks to me, if I follow your example, I’d need a specific “create” function for each item, or else use complex tables for each item that reference rules to set different properties. Actually, I think only the tables will work, because I need to be able to change an item over time (the stats of the item, like it’s condition, enchantments, uses, etc.) and retrieve that later for when the prop “reappears”…

I hope my rambling makes sense. Now that I understand your example better, matt, it is helpful, but when applying it to real data… I’m not asking you to write my program for me, but I’m just wondering what the simplest approach would be for the real item information when the items are not just actually entirely random names and properties, but pre-defined with some random parts?

Ah yes, “create” is just a phrase I defined in the source text to explain what’s going on. I could have changed the name to “florp” throughout and it’d behave the same.

Hmmm… well, it seems to me that the issue isn’t necessarily much more complicated than it would be if you were really creating and defining thousands of objects at startup instead of simulating them on the fly. Although one thing that might be useful is that you can assign rules to things, and change which rules are assigned to things, thus:

[spoiler][code]A thing has a rule called the activation rule. [The default value is “the little-used do nothing rule” or something along those lines.]

Activating is an action applying to one thing. Understand “activate [something]” as activating.

Instead of activating:
say “You try to activate [the noun]…”;
follow the activation rule of the noun.

Lab is a room. A wand is in the lab. A table is in the lab. A philtre is in the lab. A metamaterial is in the lab.

This is the sparkly rule: say “The wand sparkles!”

This is the uglification rule:
say “You feel ugly.”;
now the description of the player is “As ugly as ever.”

This is the prettification rule:
say “You feel pretty.”;
now the description of the player is “As good-looking as ever.”

This is the philtre-changing rule:
if the activation rule of the philtre is the uglification rule:
now the activation rule of the philtre is the prettification rule;
otherwise:
now the activation rule of the philtre is the uglification rule.

The activation rule of the wand is the sparkly rule. The activation rule of the philtre is the uglification rule. The activation rule of the metamaterial is the philtre-changing rule.

Test me with “activate wand/activate table/x me/activate philtre/x me/activate metamaterial/activate philtre/x me/activate metamaterial/activate philtre/x me”.[/code][/spoiler]

So if you’ve got objects that run rules when used, you can just have your code for the props change the rules as needed. You could probably even do this with rulebooks.

Just use Inform 7 kinds! Then you can have a fix properties rulebook which applies the properties based on what kind you are creating. If you want to predefine but not precreate objects then have a person spawning rulebook which will then create the clothes they’re wearing and give them the correct properties.