Name of an individual worn item and its qualities

Hi! I’ve had the idea to program an EAMON-like (text-based RPG) for a while now, and have settled upon I7 as my tool to do this.
I’ve had some experience with I7, and decided to pick it back up for this project, but already I’ve run into problems (of course.)
It seems I’ve defined some new actions correctly, (that is, I don’t get any errors with those (yet) when I (attempt) to run my code), but new qualities of objects seem to be my bane. Or rather, knowing the code to recognize and output them.

My question to you learned minds of I7 is, quite simply, “Why doesn’t this work when it looks to me like it should work?” (A rather unique question most assuredly never asked before, I might add!)

What I’ve done in the code is given the player a weapon, which has a list of attacks possible with it and is wearable.
For testing purposes, every turn (if the player has it worn), I’d like to print the name of the weapon and that list of attacks.
The way I’ve got it set up doesn’t seem to be doing much of anything except throwing errors.

My code is here:


The arena is a room.
A skeleton is in the room.
[waking up the monsters and reticulating splines]

A weapon is a kind of thing. A weapon has a list of text called an attacktypelist. A weapon is wearable.
[Here is defined a weapon and how it interacts with the player.  The player can only attack with it in the fashions defined in its "attacktypelist"]

A longsword is a kind of weapon. The attacktypelist of the longsword is {"hack","slash","stab"}.

A rapier is a kind of weapon. The attacktypelist of the rapier is {"slash","stab"}.

After wearing a weapon, say "You hold the [the weapon which is worn by the player] in your hand."
[this is mainly for testing purposes, to see if the player's weapon can be said.]	

every turn:
	say "The weapon is: [the weapon which is worn by the player]. The attacks available are [list of texts in the attacktypelist of the weapon which is worn by the player]."
[this is also for testing, to see if the attacktypelist of the player's weapon can be said.]

The player carries a longsword.
The player carries a rapier.
[giving the items to the player]

Hacking it in the is an action applying to two  things. [e.g., "hack the skeleton in the arm"]
Stabbing it in the is an action applying to two things.
Slashing it in the is an action applying to two things.

Understand "hack [something] in the [something]" as hacking it in the.
Understand "stab [something] in the [something]" as stabbing it in the.
Understand "slash [something] in the [something]" as slashing it in the.

[Before hacking it in the, unless hack is in the attacktypelist of the current weapon, say "You can't attack that way with a [the current weapon]."; otherwise, say "You hack [the noun]."

Before slashing it in the, unless slash is in the attacktypelist of the current weapon, say "You can't attack that way with a [the current weapon]."; otherwise, say "You slash [the noun] in the [the second noun]."

Before stabbing it in the, unless hack is in the attacktypelist of the current weapon, say "You can't attack that way with a [the current weapon]."; otherwise, say "You stab [the noun] in the [the second noun]."]

[the above commented-out code is a whole 'nother beast, somehow.][/code]

And the errors given to me are here:

[code]This is the report produced by Inform 7 (build 6G60) on its most recent run through:

Problem. You wrote 'say "The weapon is: [the weapon which i [...] apon which is worn by the player]."'  , and in particular 'the weapon which is worn by the player': but this asked to say something which describes items too vaguely, and so does not (or not in an elementary enough way) tell me exactly which thing or room should have its name printed.

I was trying to match one of these phrases:

1. say ""The weapon is: " - text" 
2. say "[the weapon which is worn by the player - object]" 
3. say "weapon which is worn by the player - text" 
4. say "[weapon which is worn by the player - number]" 
5. say "[weapon which is worn by the player - unicode character]" 
6. say "[weapon which is worn by the player - sayable value]" 
7. say "". The attacks available are " - text" 
8. say "[list of texts in the attacktypelist of the weapon which is worn by the player - description of objects]" 
9. say "list of texts in the attacktypelist of the weapon which is worn by the player - text" 
10. say "[list of texts in the attacktypelist of the weapon which is worn by the player - number]" 
11. say "[list of texts in the attacktypelist of the weapon which is worn by the player - unicode character]" 
12. say "[list of texts in the attacktypelist of the weapon which is worn by the player - sayable value]" 
13. say ""." - text" 

This was what I found out:

weapon which is worn by the player = a description of weapons
texts in the attacktypelist of the weapon which is worn by the player = a description of texts
list of texts in the attacktypelist of the weapon which is worn by the player = an instruction to work out a value, which results in a value

--------------------------------------------------------------------------------

Problem. You wrote 'say "You hold the [the weapon which is worn by the player] in your hand."'  , and in particular 'the weapon which is worn by the player': again, this asked to say something which describes items too vaguely.

I was trying to match one of these phrases:

1. say ""You hold the " - text" 
2. say "[the weapon which is worn by the player - object]" 
3. say "weapon which is worn by the player - text" 
4. say "[weapon which is worn by the player - number]" 
5. say "[weapon which is worn by the player - unicode character]" 
6. say "[weapon which is worn by the player - sayable value]" 
7. say "" in your hand." - text" 

This was what I found out:

weapon which is worn by the player = a description of weapons

So, from the code and the errors given, what could be my problem? I appreciate any and all of you who look into this or give me a sharp smacking of “RTFM”!

I’ve not looked fully at your code, but this jumped out at me. You need to add “random” before referring to a specific weapon, like so.

every turn: say "The weapon is: [a random weapon which is worn by the player]. The attacks available are [list of texts in the attacktypelist of a random weapon which is worn by the player]

You see, when you say “Weapon”, I7 doesn’t understand you are talking about a specific weapon (the one held by the player), not the weapon kind. “Random” helps it pick out a specific weapon each time.

PS

Alternatively you could do this:

every turn when the player wears a weapon (called the instrument of death): say "The weapon is: [the instrument of death]. The attacks available are [list of texts in the attacktypelist of the instrument of death]

This identifies a temporary variable in your condition itself, allowing you to specifically refer to the weapon the player is carrying.

P.P.S. Victor Gijspers(?) has a great RPG extension called Inform Attack.

I can see how that works. Thanks for the tip!

And I’ve heard of Attack (Kerkerkruip was quite fun!), but I’m aiming for a more user-controlled combat experience (little to random numbers) so I don’t think it would do for my purposes.

Hmm…altering the every turn code to your suggestion still gives an error:

Problem. You wrote 'say "The weapon is: [the current weapon [...] cktypelist of the current weapon]."'  , and in particular 'list of texts in the attacktypelist of the current weapon': but this asked to say something of a kind which can't be said, or rather, printed. Although this problem can arise when you use complicated text substitutions which come in variant forms depending on the kinds of value used, far more often what this means is just that you tried to use a substituted value (e.g., in 'say "The dial reads [V]."') of a kind which could not be printed out. For instance, if V is a number or a piece of text, there is no problem: but if V is a parsing topic, say an entry in a 'topic' column of a table, then this problem will arise.

I was trying to match one of these phrases:

1. say ""The weapon is: " - text" 
2. say "[the current weapon - object]" 
3. say "current weapon - text" 
4. say "[current weapon - number]" 
5. say "[current weapon - unicode character]" 
6. say "[current weapon - sayable value]" 
7. say "". The attacks available are " - text" 
8. say "[list of texts in the attacktypelist of the current weapon - description of objects]" 
9. say "list of texts in the attacktypelist of the current weapon - text" 
10. say "[list of texts in the attacktypelist of the current weapon - number]" 
11. say "[list of texts in the attacktypelist of the current weapon - unicode character]" 
12. say "[list of texts in the attacktypelist of the current weapon - sayable value]" 
13. say ""." - text" 

This was what I found out:

current weapon = a temporary named value, holding a weapon
texts in the attacktypelist of the current weapon = a description of texts
list of texts in the attacktypelist of the current weapon = an instruction to work out a list of Ks, which results in a list of Ks

The problem is the player can wear multiple things, and so as the message points out you’re not being specific enough; you’d have to say “a random weapon worn by the player” or similar. fake edit: Hi WSMartin!

I should also mention that your weapons have lists of texts, but your commented out text at the bottom only refers to hack, stab, and slash without quotes. Incidentally, it would probably be best to define attacks as kinds of value rather than texts anyway, to prevent tricky bugs and keep your code cleaner and more literate (in the Knuth sense).

Also you probably don’t want to say “the [a description of objects]”, because it produces the a strange result. “[the description of objects]” usually works best.

Instead of “list of texts in the attacktypelist of…” just try “attacktypelist of…” (I mean it when I say “try it”; I’m not sure it will work.) The attacktypelist is already a list, so you shouldn’t have to add “list” to it. I think this will still work if you make attacks kinds of value, as ChrisC suggests.

Also, it seems to me that your “Before” rules don’t actually stop the player from hacking if their weapon doesn’t hack. You’ll want to add “instead” before the semicolon in those lines; that will stop the action from carrying through.

(I think the reason “list of texts in attacktypelist” doesn’t compile is that you don’t say that an element is “in” a list, you say that it’s “listed in” a list; see section 20.4 of the documentation. There’s an outside chance that “list of texts listed in attacktypelist” would compile, though I’m really not at all sure here. Anyway, that would be needlessly convoluted.)

…or “the list of weapons worn by the player”, if there might actually be several.

Another approach would be to define a separate “wielded by” relation for weapons, such that each person can only wield one weapon at a time, something like this:

Being wielded by relates one thing (called the wielded weapon) to one person. The verb to wield (he wields, they wield, he wielded, it is wielded, he is wielding) implies the reversed being wielded by relation.

Definition: a person is armed if he is wielding anything.
Definition: a person is unarmed if he is not wielding anything.

Definition: a thing is wielded if it is wielded by the player.

After printing the name of something wielded while listing contents of yourself, say " (wielded)".

Then you’d also need to define a “wielding” action that assigns a weapon to its wielder, and a few rules to take care of bookkeeping details like ensuring that dropped weapons are unwielded.

In fact, after an earlier discussion on a similar topic, I wrote a simple extension to do just that. Using it, you could implement your example scene like this:

"Hack and slash"

The story headline is "An interactive example".

Include Wieldable Weapons by Vyznev Xnebara.

Section - Weapons

A weapon is a kind of thing. A weapon is usually wieldable.
An attack is a kind of value. A weapon has a list of attacks called the attack types.

Report examining yourself:
	if the player is unarmed:
		say "You are armed with nothing but your fists.";
	else:
		let the weapon be the wielded weapon of the player;
		say "You wield [the weapon] to better [the attack types of the weapon] your enemies with."

Section - Body parts

A body part is a kind of thing. The head, the torso, the left arm, the right arm, the left leg, the right leg, the left foot and the right foot are body parts.

[For simplicity, we assume that all people have all body parts. If we wanted, we could define a relation between people and body parts and disallow attacks to body parts that the person does not have.]

Section - Attacks

The attacks are hack, slash and stab.

Definition: A weapon is hacky if hack is listed in the attack types of it.
Definition: A weapon is slashy if slash is listed in the attack types of it.
Definition: A weapon is stabby if stab is listed in the attack types of it.

Hacking it in is an action applying to one thing and one visible thing. [e.g., "hack the skeleton in the arm"]
Slashing it in is an action applying to one thing and one visible thing.
Stabbing it in is an action applying to one thing and one visible thing.

Understand "hack [someone] in [any body part]" as hacking it in.
Understand "stab [someone] in [any body part]" as stabbing it in.
Understand "slash [someone] in [any body part]" as slashing it in.

Instead of hacking, slashing or stabbing when the player is unarmed:
	say "With what, your bare hands?"

Check hacking when the player does not wield a hacky weapon:
	instead say "You can't hack with [the wielded weapon of the player]."
Check slashing when the player does not wield a slashy weapon:
	instead say "You can't slash with [the wielded weapon of the player]."
Check stabbing when the player does not wield a stabby weapon:
	instead say "You can't stab with [the wielded weapon of the player]."

Report hacking: say "You hack [the noun] in [the second noun] with your [wielded weapon of the player]."
Report slashing: say "You slash [the noun] in [the second noun] with your [wielded weapon of the player]."
Report stabbing: say "You stab [the noun] in [the second noun] with your [wielded weapon of the player]."

Section - Setting

The Arena is a room. The player is in the arena. The skeleton is a person in the arena.

The longsword is a weapon. The attack types of the longsword are {hack, slash, stab}.
The rapier is a weapon. The attack types of the rapier are {slash, stab}.

The player carries the longsword and the rapier.

Test me with "x me / wield rapier / x me / wield longsword / x me".

Test attack with "wield fists / hack skeleton / head / yes / wield longsword / hack skeleton in the head / wield rapier / hack skeleton in the head / stab skeleton in the arm / right".

Wow! The response on this is phenomenal! That extension is really useful, Vyznev, and I appreciate your example code.
This has helped me understand how things work more, and as always I’ll keep chugging along in the manual!
One small step on a rather long road to completion. Thanks, guys! (I’m sure I’ll be back with more questions!)