Understanding by Relation

Still working on Pokémon-ish things - here’s the scenario I’m having trouble with:

Oak’s Lab
You can see a Poké Ball (closed), a Poké Ball (closed) and a Poké Ball (closed) here.

>take poké ball
Which do you mean, the Poké Ball containing Bulbasaur, the Poké Ball containing Charmander or the Poké Ball containing Squirtle?

>bulbasaur
Taken.

>take poké ball containing squirtle
Taken.

>take charmander’s poké ball
You can’t see any such thing.

I’m pretty sure I know where the problem is. I have the following code for understanding pokeballs:

A Poké Ball has some text called the captured.
Understand the captured property as describing a Poké Ball.
Understand "[something related by containment]" as a Poké Ball.
Understand "containing [something related by containment]" as a Poké Ball.
Understand "[something related by containment]'s Poké Ball" as a Poké Ball.
After printing the name of a Poké Ball while asking which do you mean: say " containing [the captured]".

It would seem that I can’t just tack 's onto the end of the relation statement. If I put a space after the statement but before the 's, it works (albeit the player would have to type a space before the 's, which is not at all intuitive). Clearly I’m not allowed to extend it in that way. Is there some way around this?

One graceless-but-effective plan is to use a “reading a command” rule to insert a space before “'s” in the player’s command. See chapter 18.33.

This would require some extra thought if you have, for example, a “Steller’s sea cow” in the game (in addition to all the pokemon.) Not to mention if T’Spring the Vulcan shows up. But it may still be helpful.

1 Like

I hadn’t thought of that. It’s a little bit ugly, but I think it could work. I can even make it more robust simply by doing the following:

After reading a command: 
	if the player's command includes "'s poké ball": 
		cut the matched text; 

This still works, thanks to:

Understand "[something related by containment]" as a Poké Ball.

Hopefully this won’t lead to too many problems down the road. Thanks for your help!

Actually, turns out this didn’t work for the reasons I thought it did. In some further testing I had changed the printed name to (for instance) “Bulbasaur’s Poké Ball”, and as we were understanding the printed name property as a pokeball, it appeared to be working. When I changed the printed name back, this fix stopped working.

I’ve got around this for the moment by giving pokeballs another property (the occupant) which includes the 's, and then understanding that at a pokeball as well. This all seems super-hacky and I’d love to be able to clean it all up if anybody has some ideas, but it’s at least working for now.

For those interested, I’ve been playing around with this for a bit, and I think I’ve found a solution that I’m happy with. Still open to alternative methods, as it’s always good to learn different ways of achieving these sort of things. Here’s what I settled on:

Part - Poké Balls

[ Defining Poké Balls ]
A Poké Ball is a kind of container.
A Poké Ball is usually closed and openable.
Understand "pokéball", "poke ball" and "pokeball" as Poké Ball.

[ Understanding Poké Balls in different ways... ]
	[ by Pokémon Occupant (i.e. take Bulbasaur) ]
A Poké Ball has some text called the Pokémon occupant.
Understand the Pokémon occupant property as describing a Poké Ball.
	[ by Pokémon Owner (i.e. take Bulbasaur's poké ball) ]
A Poké Ball has some text called the Pokémon owner.
Understand the Pokémon owner property as describing a Poké Ball.
	[ by Containment (i.e. take poké ball containing Bulbasaur) ]
Understand "containing [something related by containment]" as a Poké Ball.

[ Disambiguation of Poké Balls when it's unclear or when carried by the player ]
Before printing the name of a Poké Ball while asking which do you mean: say "[Pokémon owner] ".
Before printing the name of a Poké Ball carried by the player: say "[Pokémon owner] ".

[ Group Poké Balls in a room listing ]
Before listing contents of a room: group Poké Balls together.
Rule for grouping together a Poké Ball (called target):
	let source be the holder of the target;
	say "[number of Poké Balls held by the source in words] Poké Ball[s]".

Part - Off-Stage Cache

There are 100 Pokémon.
There are 100 Poké Balls.

Part - Encapsulating Things

[ Place something inside a Poké Ball ]
To encapsulate (P - a thing):
	let B be a random off-stage Poké Ball;
	now B is in the location of P;
	now the Pokémon owner of B is "[species of P]'s";
	now the Pokémon occupant of B is "[species of P]";
	now P is in B;

If the poké balls are particular to their pokémons, and can’t get interchanged, then you might be able to hijack the “names made in assembly” feature ( §4.16 of Writing with Inform).

A poké ball is part of every pokémon.

When play begins:
	repeat with P running through pokémons:
		let B be a random poké ball incorporated by P;
		now B is in the holder of P;
		now P is in B.

Now the poké ball containing Pikachu will automatically be known by Inform as “Pikachu’s poké ball”.

This is no good if we want to recognize poké balls by their current occupant though. There is a way of using the same feature, but it’s not very elegant and could easily be buggy. Zarf’s method is probably less trouble.

A possessive is a kind of thing. A possessive is part of every pokémon.  

Inclusion relates a poké ball (called M) to a possessive (called P) when P is enclosed by M.
Understand "[something related by inclusion]" as a poké ball.


[and a few precautions to help ensure that possessives are hidden from the player... ]

The printed name of a possessive is "[The holder of the item described]".

Before doing something when the noun is a possessive:
	now the noun is the holder of the noun.
Before doing something when the second noun is a possessive:
	now the second noun is the holder of the second noun.
1 Like

I could use this first approach that you mentioned, as once a pokemon is inside a pokeball it will never be in a different one, and no other pokemon will ever be in its one. The only issue here is that some pokemon can exist without a pokeball at all (i.e. wild pokemon). I haven’t tested it, but wouldn’t this code work somewhere later in the game rather than being forced on every bokemon when play begins?

Before walking in the tall grass:
    let P be the spawn of "Pikachu" at level 5 in Route 1; [ See my other topic linked below for the spawn phrase ]
    now a poké ball is part of P;
    let B be a random poké ball incorporated by P;
    now B is in the holder of P;
    now P is in B.

EDIT: Oh, I just realized why that won’t work. Maybe this instead:

Before walking in the tall grass:
    let P be the spawn of "Pikachu" at level 5 in Route 1; [ See my other topic linked below for the spawn phrase ]
    let B be a random off-stage poké ball;
    now B is a part of P;
    now B is in the holder of P;
    now P is in B.

I haven’t tested this today, but I’m reasonably sure that when you change the location of an object directly it also stops being part of whatever object it used to be part of (since after all it can’t be in two places at once), so I don’t think those things would work.

Wild pokemon wouldn’t be a problem for this sort of thing though – you could still create a pokeball for each pokemon and simply have some of them not inside it. When someone goes to catch a pokemon, instead of putting them into the actual pokeball that was thrown, you instead swap it with the pokemon’s “real” pokeball and put them into that instead.

Where that might fall down is if you want to model the different types of pokeball as well, and the trainer can choose which type of ball to throw to capture a particular pokemon (and have that remembered after it’s caught so that descriptions are consistent). Not impossible (you can copy/swap properties between the two), but likely getting a bit too silly.

1 Like

I’ll have to test this all out later on, but if changing the location of the pokeball is going to break the relationship, then that’s definitely a deal-breaker.

You’re right that I could do the swapping trick for catching wild pokemon, and it wouldn’t be too hard to copy the properties of the thrown ball to the real ball.

Nothing’s too silly for this project. I knew from the get-go that I was biting off more that I could probably chew, but it’s been an interestesting (if relatively short) journey so far, and I’m looking forward to seeing exactly how far I can get and how closely I can emulate a real pokemon game in I7. Maybe I’ll succeed and maybe I won’t, but either way I’m going to have fun and learn a lot, and that’s all I was looking to get out of this.

Well, the key thing in jrb’s suggestion doesn’t actually require the part of relation to continue to hold AFAIK – it’s just exploiting a side effect when originally creating items in the source text that are part of something else and otherwise unnamed; Inform will give them a default name of “parent’s thing” with understanding along with it. So it only works if you’re creating the pokeballs directly in the source text (using an implicit construction such as A pokeball is part of every pokemon), not inside a play begins rule or elsewhere anyway. You’ll need to use a different trick otherwise.

FYI to expand on zarf’s answer a little, there’s a pre-installed extension (Punctuation Removal by Emily Short) that gives an example (Ownership) of stripping apostrophes from user input in order to allow parsing of possessives.

I’ve had a bit of a play around with jrb’s soloution, and while I think it’s really cool and a very sneaky way of exploiting I7’s systems a little bit to get the desired result, it seems to be a little bit limited, in my testing at least, in that each Pokémon needs to be explicitly created (with an individual name) in the source.

If I was making something smaller in scope and more inline with traditional IF, then I think this is probably the way that I would go, but as I’m creating a whole bunch of unnamed Pokémon and then dynamically grabbing them and allocating names and stats to them later on, I don’t think that this is the right approach for me. Thanks very much for your input though @jrb. Much appreciated.

I’ve read the documentation for Punctuation Removal and that approach still seems a little bit risky. I’m sure that at some point down the track I would be kicking myself for removing apostrophes from player commands.

My approach of giving two new text properties to each pokeball as a pokemon is put inside them feels a little bit clunky to be sure, but I think it’s something that I’ll be able to have more control over later on.

That definitely does complicate things. For example, the more manual approach here also works:

Field is a room.

A pokeball is a kind of container.  Understand "pokeball" as a pokeball.
Understand "[something related by containment]" as a pokeball.
Understand "[something related by containment] pokeball" as a pokeball.
Understand "Bulbasaur's" as Bulbasaur when Bulbasaur is enclosed by a pokeball.
Understand "Geodude's" as Geodude when Geodude is enclosed by a pokeball.

There is a pokeball in field.  It contains Bulbasaur.
There is a pokeball in field.  It contains Geodude.

test me with "get geodude's pokeball / i / l".

Unfortunately understand text isn’t really text, it generates into I6 parsing code. So manipulating it isn’t straightforward in I7. It might be possible to write some custom I6 parsing code (although you can then turn this into a token that I7 recognises).


So yeah, having an extra property might be the simplest method to accomplish dynamic containment. Having said that, it should be possible to set them automatically, with something like this:

To decide which object is the occupant of (ball - pokeball):
	if the ball contains a thing (called critter), decide on critter;
	decide on nothing.

A pokeball has some text called the name of the pokemon within.
The name of the pokemon within of a pokeball is always "[occupant of the item described]".
A pokeball has some text called the possessive of the pokemon within.
The possessive of the pokemon within of a pokeball is always "[occupant of the item described]'s".

Understand the name of the pokemon within property as describing a pokeball when the occupant of the item described is not nothing.
Understand the possessive of the pokemon within property as referring to a pokeball when the occupant of the item described is not nothing.
Understand "empty" as a pokeball when the occupant of the item described is nothing.

(You would not believe how long it took me to find the correct syntax for item described. It appears in some examples but is not otherwise documented.)

The extra when clauses on the understand are to prevent it from parsing nothing's pokeball for an empty pokeball – but instead to allow you to call it an “empty pokeball”.

I’m not sure if there’s a more elegant way to do this, but it seems to work.

1 Like

Oh, that’s perfect! It’s nice to be able to have all that code in the one spot, rather than having to remember to set it with any new phrases I come up with that deal with putting Pokemon in/out of Pokeballs. Thanks very much Gavin!

Just for a little bit of extra fun:

A pokemon has some text called possessive name.
The possessive name of a pokemon is usually "[printed name]'s".

To say pokeball possessive name:
	let P be the occupant of the item described;
	if P is not nothing, say possessive name of P.

[instead of the definition above]
The possessive of the pokemon within of a pokeball is always "[pokeball possessive name]".

[So now you can:]
There is a pokeball in field.  It contains Gyarados.
The possessive name of Gyarados is "Gyarados[apostrophe]".

And now you have Gyarados' pokeball instead of Gyarados's pokeball.

Note that you have to use [apostrophe] here as otherwise a single quote appearing at the end of a word turns into a double quote.

The extra if clause in the possessive text is not strictly necessary due to the understand when conditions, but it’s a bit safer to keep it if there’s a chance (eg. showme command) that the property of an empty pokeball might get evaluated.

(Although I should probably add that this particular grammar rule of apostrophes is contested, so you may or may not want to actually do it depending on your preferences. But it demonstrates some flexibility of the system.)

1 Like

FWIW I think we tracked down why this happened… “item described” used to be documented somewhat in the last section of Chapter 5, which was a review of the chapter. Then the documentation was changed so that the review sections were eliminated, and “item described” was documented no more. Though I don’t know if its use within Understand statements was ever documented!

1 Like

The other thing that I was hoping would work, but doesn’t – and why I ended up writing the separate to say rule – is something like:

"[regarding (some complicated expression)][if it is not nothing][possessive name of it]"

i.e. that it would refer to whatever the most recent regarding pointed at, similar to the let phrase in the separate rule, to avoid calculating the expression twice.

Granted, nothing in the docs suggested that it would work, it’s just something that seems like it should. :slight_smile:

1 Like

It somehow got removed from the documentation (except for one example) between Inform 6Lwhatever and 6M62, but “prior named object” allows you to refer back to the thing that you are currently regarding.

Lab is a room.

A rock, some scissors, and a bun are in the Lab.

Every turn:
	say "[regarding a random thing that is not undescribed]You notice [the prior named object]. [They] [are] [if the prior named object is singular-named]an [end if]ordinary [prior named object]."

So that should let you do the thing you wanted.

1 Like

Ah! Then, while I’m not sure if this is actually any improvement in readability or not, you could amend my Gyarados example to use this (without the separate to say rule – and making use of both mostly-undocumented names):

The possessive of the pokemon within of a pokeball is always 
  "[regarding the occupant of the item described][if the prior named object is not nothing][possessive name of the prior named object]".
1 Like