viewing rule syntax

Is there a way to see the actual definitions of the standard rules? Like the “can’t take what’s already taken” rule? Basically, I’m trying to create my own rule with a new command “Use”. More specifically, I’m trying to make weapons, but I don’t want the player to be able to use a new weapon if he’s already carrying a current weapon. A description of the result would be something like:

USE SWORD.
You are now equipped with the sword.

USE SWORD.
You are already using the sword.

USE AXE.
You are currently equipped with the sword. You will have to drop the sword if you want to use the axe.

DROP SWORD.
Dropped.

USE AXE.
You are now equipped with the axe.

Additionally, the weapons have a number called AP (attack power). The player has a number called Power. If the player uses a weapon, it increases the player’s power. I think I know how to code this so that if the player drops it, the player’s power decreases. But if the player puts it in a container (say the holdall or some other container or gives it to someone), the player’s power still remains the same as if he’s still using the weapon. I’m guessing I could code it twice (both for carrying out “dropping the weapon” or “putting the weapon into”), but I just know there’s got to be some way to catch everything for when the player stops using/carrying the weapon in any fashion.

You can open the Standard Rules in the IDE. Just click on “Open installed extension” in the File tab; you’ll get a list of extension authors, and you want Graham Nelson. (This is for the Windows IDE; I assume it’s similar for Mac, but a bit more complicated for Unix.)

Searching for the rule you want, you’ll find

Check an actor taking (this is the can't take what's already taken rule):
	if the actor is carrying the noun or the actor is wearing the noun:
		if the actor is the player:
			say "[We] already [have] [regarding the noun][those]." (A);
		stop the action.

Not everything is in the Standard Rules extension, though. Some rules are found in the template layer, which is part of I7 but written in I6. You’ll find the template files in a subfolder called I6T somewhere in your Inform 7 folder. Others rules are native to I6 itself, and can be found in the I6 library (I guess they can, anyway—I can’t say I’ve looked there).

There’ll gererally be a line in the Standard Rules saying something like

The little-used do nothing rule translates into I6 as "LITTLE_USED_DO_NOTHING_R".

to tell you what to look for (but sadly, not where to look for it).

To respond to your specific problem, since you’re preventing the player from carrying two weapons at once, I suggest you might as well dispense with a special “using” action, and just assume that the current weapon is whatever weapon the player currently holds.

A weapon is a kind of thing. The sword is a weapon. The axe is a weapon.
Understand "wield [a weapon]" as taking.

To decide which object is the current weapon:
    if the player carries a weapon:
         decide on a random weapon carried by the player;
    otherwise:
         decide on nothing.
To decide whether the player is armed:
     if the current weapon is nothing:
           decide no;
     decide yes.

Check taking a weapon when the player is armed:
     say "You'll need to drop your [current weapon] first." instead.

After taking a weapon:
     say "You're now equipped with [the current weapon]."

A side comment: I’d avoid encouraging the player to type the verb “use”. It’s too general, and they’ll wonder why, if they can “use” a weapon, they can’t “use” everything in the game. Then “use X” is in danger of becoming “take whatever action might be appropriate in this situation with X”, which impoverishes the language of the game, as well as being a nightmare to code.

I seem to be running into some compiling errors when I try this code. I’m currently using version 6M62. Is this the most recent version?

Sorry, I posted the bugged version instead of the working version. I’ve edited it, so try it again.

Thanks, jrb! With your code, I was able to get my mechanic to work where the attack power of the player increases once they are holding the weapon, as well as create a nice combat scenario.

As for as the “use” command goes, that was sort of the plan. I got the idea from “Treasures of a Slaver’s Kingdom” where the actions of the player are limited to only a few commands. I liked this because then the player didn’t have to keep on guessing what command to type in various situations. But as I’m creating the game, I’m realizing that requires me to block all the currently accepted commands that I don’t want the player to use…

You could make the “current adjusted power” into a function call (in Inform 7, a “decide” phrase), like so:

To decide what number is the current adjusted power: let N be the power of the player; if the player is carrying a weapon (called wielded item): let N be N plus the AP of the wielded item; decide on N.

Then all you need to worry about is setting the base power of the player and the AP of each weapon. When you need to know what the current adjusted power is, you can calculate it on the fly.

Here’s a quick working example:

[code]A person has a number called power. The power of a person is usually 5.

A weapon is a kind of thing. A weapon has a number called AP. The AP of a weapon is usually 3.

Instead of taking a weapon when the player is carrying a weapon (called the wielded item):
say “You are already wielding [the wielded item]; you will need to drop it if you want to wield [the noun].”

The Training Room is a room.

The sword is a weapon in the Training Room.
The axe is a weapon in the Training Room. The AP of the axe is 7.
The feather duster is a weapon in the Training Room. The AP of the feather duster is -3.

The practice dummy is fixed in place, in the Training Room. “A training dummy stands nearby.”

To decide what number is the current adjusted power:
let N be the power of the player;
if the player is carrying a weapon (called wielded item):
let N be N plus the AP of the wielded item;
decide on N.

Calculating power is an action out of world. Understand “power” as calculating power.

Carry out calculating power:
say “Your current power is [current adjusted power].”

The block attacking rule does nothing when the noun is the practice dummy.

After attacking the practice dummy:
let dice be a random number from 1 to 10;
let damage be dice plus current adjusted power;
say “You hit the dummy[if the player carries a weapon] with [the random weapon carried by the player][end if], doing [damage] points of damage!”

Test me with “power / hit dummy / get sword / power / hit dummy / get feather duster / drop sword / power / get feather duster / power / hit dummy”.[/code]

So here is what I currently have. Assume all variables found below have already been defined (which they have, I just didn’t want to go looking through my code to find them all cuz i’m lazy :stuck_out_tongue:). I know this works, but can you (or anyone, for that matter) see if there’s any places in this code where issues might arise? Or am I good to go?

[code]
[preventing unwanted attacks]
The block attacking rule is not listed in the check attacking rulebook.
Check attacking something:
if the noun is not a person:
say “We do not attack that which is unable to defend itself.”

Check attacking someone:
Unless the noun is an enemy:
say “[The noun] is not your enemy.”;
the rule fails;
else:
continue the action.

[attack scenario]
The damage dealt is a number variable.
The damage received is a number variable.

Carry out attacking someone:
Let the damage dealt be a random number between the MinAP of the player and the MaxAP of the player;
Decrease the CurrentHP of the noun by the damage dealt;
say “You attack [the noun] for [damage dealt] points, leaving [it] with [CurrentHP of the noun] HP!”;
if the CurrentHP of the noun is 0 or the CurrentHP of the noun is less than 0:
say “You have defeated [the noun]!”;
now the noun is nowhere;
stop the action;
Let the damage received be a random number between the MinAP of the noun and the MaxAP of the noun;
Decrease the CurrentHP of the player by the damage received;
say “[The noun] attacks you for [damage received] points, leaving you with [CurrentHP of the player] HP!”;
if the CurrentHP of the player is 0 or the CurrentHP of the player is less than 0:
say “You have been killed by [the noun]!”;
end the story.[/code]

You might want to add an after rule as a “cleanup” stage, to set damage dealt and damage received back to 0 when you don’t need them anymore.

Ok, so:

After attacking someone:
    Let the damage dealt be 0;
    let the damage received be 0.

Right? I’m not sure I understand the point of this though. Aren’t the numbers going to change each type the player uses the “attack” command, anyway? Or is there some scenario in which not re-setting the damage numbers back to 0 will cause a bug?

There’s a subtle thing that may be going on here with the difference between “now” and “let,” and the difference between global and temporary variables.

Check this out:

[code]Lab is a room.

The boing is a number that varies. The boing is 2.

Before jumping:
let the boing be 4.

Instead of jumping: say “Boing: [boing].”[/code]

Output:

What happened? Well, when we said “The boing is a number that varies” we created a global variable (which we set to 2).

When we said “let the boing be 4” within the Before jumping rule we created a different temporary variable called “boing,” which lasts only as long as the code block it’s in. This got set to 4. But by the time we got to the Instead of jumping rule, we had discarded the temporary variable, and boing was back to being the global variable which is still 2.

The trick is that “let” does not work like it does in BASIC. “Let” creates a temporary variable. If you want to change the value of a global variable, you have to say “now the boing is 4.”

So… you don’t want to have both these lines:

The damage dealt is a number variable. The damage received is a number variable.

and

Let the damage dealt be a random number between the MinAP of the player and the MaxAP of the player;
Let the damage received be a random number between the MinAP of the noun and the MaxAP of the noun;

The first lines create global variables. The second lines create temporary variables with the same name. This can only lead to sadness and confusion. You should either delete the global variables or change those “let” statements to “now” statements.

Looking at the code you have, it looks fine to go with temporary variables, in which case you don’t need to (and can’t) reset the damage dealt and damage received variables, which will go away at the end of the code block they’re in.

Thanks matt w! I didn’t realize “let” was creating variables also. I had previously thought it needed a pre-existing variable or needed to be pre-defined to function.

To make this even more confusing, you can use “let” to change the value of a local variable that was previously defined using “let”.

Basically, use “let” for locals, and “now” for globals, and you should be good.