Combat System problem.

Hi everybody,

I copied and pasted the Lanista 2 combat system with a few edits:

[code]An enemy is a kind of person.

A person has a number called maximum hit points. A person has a number called current hit points.

The maximum hit points of the player is 120.

When play begins:
repeat with victim running through people:
now the current hit points of the victim is the maximum hit points of the victim.

Definition: a person is dead if his current hit points are less than 0.

Diagnosing is an action applying to one visible thing. Understand “diagnose [something]” as diagnosing.

Check diagnosing:
if the noun is not a person, say “You can only diagnose people.” instead.

Carry out diagnosing:
say “[if the noun is the player]You have[otherwise][The noun] has[end if] [current hit points of the noun] out of a possible [maximum hit points of the noun] hit points remaining.”

A weapon is a kind of thing. A weapon has a number called the maximum damage. The maximum damage of a weapon is usually 25.

Understand the commands “attack” and “punch” and “destroy” and “kill” and “murder” and “hit” and “thump” and “break” and “smash” and “torture” and “wreck” as something new.

Attacking it with is an action applying to one visible thing and one carried thing. Understand “attack [someone preferably held] with [something]” as attacking it with.

Understand the commands “punch” and “destroy” and “kill” and “murder” and “hit” and “thump” and “break” and “smash” and “torture” and “wreck” as “attack”.

The attacking it with action has a number called the damage inflicted.

Setting action variables for attacking something with something:
if the second noun is a weapon:
let the maximum attack be the maximum damage of the second noun;
now the damage inflicted is a random number between 1 and the maximum attack.

Check an actor attacking something with something (this is the can’t attack with something that isn’t a weapon rule):
if the second noun is not a weapon:
if the actor is the player, say “[The second noun] is not a weapon.”;
stop the action.

Check an actor attacking something with something (this is the can’t attack a non-person rule):
if the noun is not a person:
if the actor is the player, say “You can’t kill the [The noun], because [The noun] has no life to lose.”;
stop the action.

Carry out an actor attacking something with something (this is the standard attacking it with a weapon rule):
decrease the current hit points of the noun by the damage inflicted;
if the noun is dead, remove the noun from play.

Report attacking a dead person with something (this is the death-report priority rule):
say “You attack with [the second noun], killing [the noun]!” instead.

Report attacking someone with something (this is the normal attacking report rule):
say “You attack [the noun] with [the second noun], causing [damage inflicted] point[s] of damage!” instead.

Report someone attacking the player with something when the player is dead (this is the player’s-death priority rule):
say “[The actor] attacks you with [the second noun], killing you.”;
end the game in death;
stop the action

Report someone attacking the player with something (this is the standard report someone attacking the player with rule):
say “[The actor] attacks you with [the second noun], causing [damage inflicted] point[s] of damage!” instead.

Report someone attacking something with something (this is the standard report attacking it with rule):
say “[The actor] attacks [the noun] with [the second noun], causing [damage inflicted] point[s] of damage!” instead.

Every turn (this is the enemy-attack rule):
if an enemy is not dead, try the enemy attacking the player with a random weapon which is carried by the enemy.[/code]

However, I get this error:

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

Problem. You wrote ‘if an enemy is not dead, try the enemy attacking the player with a random weapon which is carried by the enemy’ , but ‘enemy attacking the player with a random weapon which is carried by the enemy’ is too vague to describe a specific action.

It has to be an exact instruction about what is being done, and to what. For instance, ‘taking the box’ is fine, but ‘dropping or taking something openable’ is not.

See the manual: 7.4 > Try and try silently

I was trying to match one of these phrases:

  1. try (enemy attacking the player with a random weapon which is carried by the enemy - an action)

  2. try (enemy attacking the player with a random weapon which is carried by the enemy - stored action)

This was what I found out:

enemy attacking the player with a random weapon which is carried by the enemy = a condition
[/code]

I don’t get it. How could it be more specific?

P.S. Sorry for the humoungous amount of code I posted, I just don’t know exactly where the problem is in the code.

It looks to me as though the problem is that you need to be more specific about who you want to try attacking the player. If there were two enemies in the location, the line “try the enemy attacking…” wouldn’t be able to have both enemies attack you, for instance.

Try this (untested):

Every turn (this is the enemy-attack rule): repeat with bad guy running through enemys in the location: [note: maybe the Inform compiler understands how to make the plural of "enemy," and there's probably a way to make it understand, but I don't have time to test it right now] if bad guy is not dead: try bad guy attacking the player with a random weapon which is carried by bad guy.

Another thing to note is that “the enemy” doesn’t do what you probably want it to – Inform understands it as
“an enemy.” So if you write something with “the enemy” and it compiles, there’s no guarantee that it will refer back to the enemy you were talking about.

matt w, I tried your code and there seems to be a problem with the indentation.
Here are the errors:

[code]Problem. The phrase or rule definition ‘Every turn (this is the enemy-attack rule)’ is written using the ‘colon and indentation’ syntax for its 'if’s, 'repeat’s and 'while’s, where blocks of phrases grouped together are indented one tab step inward from the ‘if …:’ or similar phrase to which they belong. But the phrase ‘repeat with bad guy running through enemies in the location’ , which ought to begin a block, is immediately followed by ‘if bad guy is not dead’ at the same or a lower indentation, so the block seems to be empty - this must mean there has been a mistake in indenting the phrases.


Problem. The phrase or rule definition ‘Every turn (this is the enemy-attack rule)’ is written using the ‘colon and indentation’ syntax for its 'if’s, 'repeat’s and 'while’s, where blocks of phrases grouped together are indented one tab step inward from the ‘if …:’ or similar phrase to which they belong. But the phrase ‘if bad guy is not dead’ , which ought to begin a block, is immediately followed by ‘try bad guy attacking the player with a random weapon which is carried by bad guy’ at the same or a lower indentation, so the block seems to be empty - this must mean there has been a mistake in indenting the phrases.


Problem. The phrase or rule definition ‘Every turn (this is the enemy-attack rule)’ is written using the ‘colon and indentation’ syntax for its 'if’s, 'repeat’s and 'while’s, where blocks of phrases grouped together are indented one tab step inward from the ‘if …:’ or similar phrase to which they belong. But the tabs here seem to be misaligned, and I can’t determine the structure. The first phrase going awry in the definition seems to be ‘repeat with bad guy running through enemies in the location’ , in case that helps.

This sometimes happens even when the code looks about right, to the eye, if rows of spaces have been used to indent phrases instead of tabs.
[/code]

Can someone fix the indentation problem?

Sorry, I typed the code straight into the comment box so there aren’t any tab stops – just spaces. So if you copy-paste the code you have to fix the indentation by hand.

It should go something like this:

Every turn (this is the enemy-attack rule): [one tab stop] repeat with bad guy running through enemys in the location: [note: maybe the Inform compiler understands how to make the plural of "enemy," and there's probably a way to make it understand, but I don't have time to test it right now] [two tab stops]if bad guy is not dead: [three tab stops]try bad guy attacking the player with a random weapon which is carried by bad guy.

By the way, if you just copy-paste code from one of these messages the tab stops will always get messed up and you’ll have to redo them by hand. Most of the time if you want to try to reproduce the tab-stops, you should hit “reply,” which will give you a message with the original code enclosed in tab stops. If you copy-paste that the tab stops will remain intact. But that only works if the original poster copy-pasted code from Inform; if they just typed it into the forum, the way I did, you’ll always have to fix the tabs yourself.

Uuum… I know that this is a noobish question, but what is a tab stop?

Hitting the “tab” key creates a tab stop; it looks like a series of spaces, but to the computer it’s different. Think of a tab stop as an invisible marker in the code.

It’s a variant on just saying “tab,” or in other words, you have to use the “tab” key on your keyboard instead of just hitting “space” enough times, since Inform can be picky about spacing. (By the way, if getting the tabs right is a problem for you, like if you are blind and using a screen reader, there is an alternate syntax that someone who is not me can explain.)

Thanks everybody! The code works now!

kthxbaifornow

Actually, I have another question.

I would like to make it so that a “gun” would be a kind of weapon that would basically work just like a normal weapon, except it would have a number called “ammo”, and it would have different reports for killing things with a gun.

How would I make a number for ammo?

A gun is a kind of weapon. A gun has a number called ammo. The ammo of a gun is usually 6.

And go from there.

Sorry, I should have worded that better. I know how to make a number, it’s just that I want to make it so that whenever you use a gun, it will decrease from the ammo.

Well, just code that.

I actually mean that, and not in a nasty way. :slight_smile: You know what you need to do: decrease the ammo, whenever you use a gun. So what do you need?

(1) A rule that fires whenever the player uses a gun.
(2) Within that rule, a line that decreases the ammo by 1.

And of course, we want something else:

(3) A rule that stops the player from using a gun if the ammo is 0.

Do you know how to do (1)? Do you know how to do (2)? Do you know how to do (3)? You might, actually, with just your pretty basic Inform knowledge. I’d say, try something, and if you get stuck, ask a more specific question. (Almost always, when you ask “How do I make it so that my game does X”, you haven’t been thinking hard enough; and what’s worse, the answer isn’t going to teach you anything. Useful questions generally have forms like “I don’t know how to make a rule that checks whether an action the player wants to take is possible or not.” – that is, a specific question about a specific problem you encountered while trying to implement something.)

Lol, ok VictorGijsbers, I’m following your advice.
Quick question. If I’m making the ammo number, should I say:

A gun has a number called ammo.

Or should I say:

 The player has a number called ammo.

?

That depends on what you want: you should the former if you want each gun to have its own ammo, the latter if you want the player to have a single stack of ammo for all guns. (If you have only one gun, there would be no difference.)

K, I have a problem.

For some reason, when I add in the code for the ammo, the gun apparently doesn’t do any damage, it doesn’t report me attacking or killing something, and the ammo system doesn’t even work.

The code:

[code]A gun is a kind of weapon.
A gun has a number called ammo.
The ammo of a gun is usually 6.

Check an actor attacking something with something (this is the can’t use an ammoless gun rule):
if the second noun is a gun:
if the ammo of the second noun is 0, say “You do not have any ammo left.”;
stop the action.

Carry out an actor attacking something with something (this is the standard attacking it with a weapon rule):
if the second noun is a gun:
decrement the ammo of the second noun;
decrease the current hit points of the noun by the damage inflicted;
if the noun is dead, remove the noun from play;
[otherwise]
decrease the current hit points of the noun by the damage inflicted;
if the noun is dead, remove the noun from play.[/code]

Please fix? I’ve spent all day working on this.

The way your Check rule is written, the condition “if the ammo of the second noun is 0” applies only to the following say phrase, and “stop the action” runs no matter what the gun’s ammo is. So your Carry out rule isn’t running at all. Use the colon-and-indentation format and make sure “stop the action” is also indented under the condition.

BTW, it’s probably better to write “Check attacking something with a gun” and “Carry out attacking something with a gun”; you might also want to make sure that these rules only apply to nouns with hit points.

Thanks a ton! Also:

Ok, I only wrote it that way so that it would fit in with the rest of the code. Also, I made so that everything has hit points, and that the default amount of hit points is 0.

Your logic structure doesn’t look right here. If this is your only carry out attacking rule, only guns will ever do any damage - your “otherwise” is commented out, and all of the damage-dealing is placed (twice) within the “if the second noun is a gun” clause. This is a perfect opportunity to use the power of rules-based programming. You can split this into two separate carry out rules and not have to do any “if” test at all:

[code]Carry out an actor attacking something with a gun (this is the attacking it with a gun rule):
decrement the ammo of the second noun;

Carry out an actor attacking something with something (this is the standard attacking it with a weapon rule):
decrease the current hit points of the noun by the damage inflicted;
if the noun is dead, remove the noun from play.[/code]

Also, somebody recently told me about a cool syntax for giving verbs to properties just like for relations:

[code]The verb to be loaded with implies the ammo property.

Check attacking something with a gun that is loaded with 0:
say “You do not have any ammo left.”;
stop the action.[/code]

In this case, a simpler solution might be more readable, though:

[code]Definition: a gun is loaded rather than unloaded if the ammo of it is at least 1.

Check attacking something with an unloaded gun:[/code]

Don’t worry, that isn’t my only carry out attacking rule. Also, thanks, I’ll use that that new code.

I have a problem. I’m trying to make it so that when the player dies, instead of removing the player from the game(causing an error), it will simply end the game in death.

Here’s the code:

Check an actor attacking the player with something when the player is dead (this is the player's-death priority rule): if the actor is an enemy: say "[The actor] attacks you with [the second noun], killing you."; end the game in death; stop the action.

However, it still causes an error when I die, and it removes the player from the game instead of ending the game properly.

Help please.