"Lanista, Part One"
The Arena is a room. "Sand, blood, iron. These festivals are normally held on hot days, but the sun has gone behind a cloud and fat drops of rain now and then spatter the arena floor." The gladiator is a man in the Arena. "A bare-chested Scythian gladiator faces you, wielding a trident."
We start by recording, for each person, a maximum number of points of damage the person can sustain when starting from health, and the current number of points remaining. In the tradition of role-playing games, these are referred to as hit points.
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 35. The maximum hit points of the gladiator is 25.
The current hit points of the player is 35. The current hit points of the gladiator is 25.
Now our rule for the actual attack. We want first to calculate how much damage the player's attack does, inflict that damage, and remove the enemy if he's dead; then, if he doesn't die, the enemy counter-attacks, also for a randomized amount of damage, and if this kills the player, the game ends in defeat.
Instead of attacking someone:
let the damage be a random number between 2 and 10;
say "You attack [the noun], causing [damage] points of damage!";
decrease the current hit points of the noun by the damage;
if the current hit points of the noun is less than 0:
say "[line break][The noun] expires, and is immediately carried away by the Arena slaves!";
now the noun is nowhere;
end the story finally;
stop the action;
let the enemy damage be a random number between 2 and 10;
say "[line break][The noun] attacks you, causing [enemy damage] points of damage!";
decrease the current hit points of the player by the enemy damage;
if the current hit points of the player is less than 0:
say "[line break]You expire!";
end the story.
This last bit is a refinement to help the player keep track of how the contest is going:
When play begins:
now the left hand status line is "You: [current hit points of player]";
now the right hand status line is "Gladiator: [current hit points of gladiator]".
Test me with "hit gladiator / g / g / g".
Suppose we want to let the player kill characters, leaving behind corpses.
"Puff of Orange Smoke"
Paraguay is a room. Bolivia is north of Paraguay. Lydia is a woman in Paraguay. "Lydia is, as usual, here." The description of Lydia is "Long, long legs and a sarcastic attitude." Instead of touching Lydia: say "'Watch it, sailor,' she snaps."
A body is a kind of thing. A body is a part of every person. Instead of touching a body: say "[The noun] is grotesquely inert."
The description of Lydia's body is "Long, long legs and no attitude at all." The initial appearance of Lydia's body is "Lydia's corpse is sprawled at your feet."
Using our "part of every person..." line, we've conveniently assigned one body per person. Since we're going to separate people from their bodies when the bodies die, though, we also want a more permanent relation that will help us keep track of which bodies used to belong to which people:
Spirit-possession relates one person to one body. The verb to be owner of means the spirit-possession relation.
When play begins:
repeat with victim running through people:
let the corpse be a random body which is part of the victim;
now the victim is owner of the corpse.
When Lydia is alive, we want >TOUCH LYDIA'S BODY to mean the same thing as >TOUCH LYDIA, so we use the setting action variables rules as a convenient point at which to reassign the action:
Setting action variables when the noun is a body which is part of a person (called owner):
now the noun is the owner.
Setting action variables when the second noun is a body which is part of a person (called owner):
now the second noun is the owner.
This doesn't change Inform's idea about what action is being performed; just about the object it's being performed on. The rest of the action will now proceed as if the player had typed >TOUCH LYDIA.
Along similar lines, once Lydia is dead, we want >MOVE LYDIA to mean >MOVE LYDIA'S BODY if the body is in view:
Setting action variables when the noun is a dead person and the noun is owner of a visible body (called the mortal remains):
now the noun is the mortal remains.
The trick is, though, that >MOVE LYDIA will only be understood if there is something called Lydia that the player can see and refer to, even after she's dead. There are various ways to do this, but the least painful here will be to make the deceased Lydia permanently visible, by putting her in an always-accessible backdrop. The backdrop itself will never be mentioned in the game, and we should make its name something that the player is unlikely to type casually; we don't want the player to interact with it directly. So:
The worldview is a privately-named backdrop. It is everywhere. The spirit-world is a privately-named transparent closed unopenable container. It is part of the worldview.
Definition: a person is dead if he is in the spirit-world.
It's also possible that the player will type something like >X LYDIA when Lydia's corpse is not in view, so we should have an appropriate answer to that as well:
Before doing something to a dead person:
say "[The noun] is dead; or had you blocked that out?" instead.
Because the before rules happen after the setting action variables rules, this will only ever happen if the corpse is not visible.
Now we define the attack itself, which should discard the body, move the spirit to its eternal resting place, and describe the event to the player:
Instead of attacking someone:
let the corpse be a random body which is part of the noun;
move the corpse to the location;
move the noun to the spirit-world;
say "With a single blow, you rid the world of [the noun]."
And finally a trick borrowed from the chapter on understanding, so that we can refer to "Lydia's body" while Lydia is alive, but "Lydia's corpse" only after Lydia has died:
Understand "corpse" as a body when the item described is not part of a person.
Test me with "x body / x lydia's body / touch lydia's body / x corpse / kill lydia / look / x lydia's body / x lydia's corpse / x corpse / x lydia / touch lydia / lydia, hello / n / x lydia / touch lydia / lydia, hello".
Back in the chapter on randomization, we explored a way to create a randomized combat system. That system didn't allow for multiple weapons, though. Here we explore how to create an ATTACK IT WITH action that will let the player choose between weapons with different maximum powers.
We're also going to rewrite that original "instead of attacking:" rule into an attacking it with action that can be performed equally by the player or by any of the player's enemies.
"Lanista, Part Two"
The Arena is a room. "Sand, blood, iron. These festivals are normally held on hot days, but the sun has gone behind a cloud and fat drops of rain now and then spatter the arena floor." The gladiator is a man in the Arena. "A bare-chested Scythian gladiator faces you, wielding [a list of weapons carried by the gladiator]."
Section 1 - Hit Points
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 35. The maximum hit points of the gladiator is 25.
In our simpler version of this example we set the current hit points by hand, but in a game with many characters this would get dull and repetitive, so here we'll use a "when play begins" to set all current hit point values automatically to maximum:
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.
Section 2 - Diagnosis
Diagnosing is an action applying to one visible thing. Understand "diagnose [something]" as diagnosing.
Check diagnosing:
if the noun is not a person, say "Only people can have diagnoses." 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."
Section 3 - Weapons
A weapon is a kind of thing. A weapon has a number called the maximum damage. The maximum damage of a weapon is usually 4.
The gladiator carries a weapon called a trident. The maximum damage of the trident is 5. The gladiator carries a weapon called a net. The maximum damage of the net is 1.
The player carries a weapon called a mace. The maximum damage of the mace is 3.
Section 4 - Attacking it with
In our new system, we want to specify what is being used for an attack. This means that we need to create a new "attacking it with" action, and also that we should disable the existing "attacking..." command.
Here's why: If we leave the default attack command in place, Inform will continue to accept commands like >ATTACK GLADIATOR, but reply foolishly with the default "Violence is not the answer..." response.
A somewhat better approach would be to change the reply of >ATTACK GLADIATOR to say something like "You must specify a weapon to attack with." But this is still less than ideal, because it means that the player has to then rewrite his entire command. If, on the other hand, we take out "ATTACK GLADIATOR" entirely, the game will always prompt "What do you want to attack the gladiator with?" -- which teaches the player the correct command structure for this particular game, and avoids pretending to understand any command that is not meaningful within this game.
This is a little bit of work because ATTACK has a lot of synonyms in the default library, but if we look through the actions index we can find them all:
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.
Now we make our new command:
Attacking it with is an action applying to one visible thing and one carried thing. Understand "attack [someone] with [something preferably held]" as attacking it with.
Note that we've specified "one carried thing", because we want the player to pick up a weapon to use if necessary. And now we assign all the old attack vocabulary to apply to the new command:
Understand the commands "punch" and "destroy" and "kill" and "murder" and "hit" and "thump" and "break" and "smash" and "torture" and "wreck" as "attack".
This may seem counter-intuitive, but order of source code matters here: we first get rid of the old, default vocabulary, then define our new action, then make the vocabulary apply to that new action. Inform will now understand >HIT GLADIATOR WITH TRIDENT, >BREAK GLADIATOR WITH TRIDENT, and so on.
Our new action is also a perfect place to use an action variable: we're going to need to choose an amount of damage done and refer to that several times in our action rules. So let's set that up first:
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] does not qualify as 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 "[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 and the noun is not the player:
now the noun is nowhere.
Though our checks and carry-out rules are similar regardless of who is acting, we're going to want actions to be described differently for different actors, so we'll use separate "report attacking" and "report someone attacking" rules. We'll also make some special cases for when the character has died as a result of the attack:
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], finishing you off!";
end the story;
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.
When play begins:
now the left hand status line is "You: [current hit points of player]";
now the right hand status line is "Gladiator: [current hit points of gladiator]".
Every turn (this is the gladiator-attack rule):
if the gladiator is not dead, try the gladiator attacking the player with a random weapon which is carried by the gladiator.
Test me with "hit gladiator with mace / kill gladiator / drop mace / attack gladiator / attack gladiator with mace / g / g".
Those devoted to role-playing will note that our form of randomization is still pretty naive: most RPG systems use multiple dice in order to create more interesting probability curves. For a system that simulates actual dice-rolling, see the full "Reliques of Tolti-Aph" game.
Suppose our game features a detailed simulated combat between the player character and his opponent. He might have several weapons available, and several types of attack available; and at any given time he might be perched up in the rigging of his ship, standing on the open deck, or boxed in between some barrels. His options will vary depending on his position, and obviously it would detract from the pacing to make the player keep LOOKing in the middle of combat in order to remind himself where he is. Instead, we'll roll this information into the command prompt:
"Don Pedro's Revenge"
The Deck of the Helene Marie is a room. "The two crews are embattled all around you, but your attention is reserved for your particular enemy: Don Pedro."
Table of Random Prompts
position
|
prompt
|
boxed
|
"So securely boxed-in that you can really only parry or thrust, you try to "
|
boxed
|
"Trapped between your barrels, you decide to "
|
perched
|
"Able to slice at your attackers but not to advance or retreat, you choose to "
|
perched
|
"Perched up here with the advantage of height (but little mobility), you attempt to "
|
free
|
"Out on the open deck with no impediments, free to advance or retreat, you decide to "
|
When play begins: reset the prompt.
Every turn: reset the prompt.
To reset the prompt:
sort the Table of Random Prompts in random order;
repeat through the Table of Random Prompts:
if the position entry is the placement of the player:
now the command prompt is prompt entry;
stop.
After reading a command: say conditional paragraph break.
A placement is a kind of value. The placements are boxed, perched, free. The player has a placement. The player is free.
Understand "retreat" or "parry" as retreating. Retreating is an action applying to nothing.
Check retreating:
if the player is perched, say "You can't move backward or parry very successfully from this position." instead.
Carry out retreating:
now the player is boxed;
say "You protect yourself, but end up wedged in between two barrels."
Understand "thrust" or "advance" as advancing. Advancing is an action applying to nothing.
Check advancing:
if the player is perched, say "You can't move forward from here, only slash." instead.
Carry out advancing:
now the player is free;
say "You push forward aggressively, making your way to the open deck."
Instead of jumping:
now the player is perched;
say "You leap and swing yourself boldly up into the rigging, leaving your attackers beneath you."
Instead of jumping when the player is perched:
now the player is free;
say "You leap down from your position, into the middle of the deck."
Test me with "advance / jump / advance / retreat / jump / retreat / retreat / advance".
Of course, this won't be much fun until we also provide the player with a few weapons, some more fighting maneuvers, and, most of all, a Don Pedro to defeat.
"Technological Terror"
The Decomposition Ray Gun is a thing carried by the player.
First we need to define our shooting action:
Shooting it with is an action applying to two things.
Check shooting something with something:
if the player is not carrying the Ray Gun, say "You are pathetically unarmed!" instead;
if the second noun is not the Ray Gun, say "[The second noun] does not fire." instead;
if the noun is the Ray Gun, say "Nice trick if you can do it!" instead;
if the noun is the player, say "That would be disastrous!" instead.
Next, some grammar to allow the player to use this action:
Understand "shoot [gun] at [something ungunlike]" as shooting it with (with nouns reversed).
Definition: a thing is ungunlike if it is not the gun.
Understand "shoot [something ungunlike] with [gun]" as shooting it with. Understand "shoot [something] with [something]" as shooting it with.
Understand "shoot [something] at [something]" as shooting it with (with nouns reversed). Understand "fire [gun] at [something ungunlike]" as shooting it with (with nouns reversed). Understand "fire at [something ungunlike] with [gun]" as shooting it with. Understand "fire at [something] with [something]" as shooting it with.
Strictly speaking, we only need these last grammar lines (with "understand shoot something...") in order to define an action that the player can take. Adding more grammar lines means that Inform will try to match the most specific ones first, which is useful when the player types something ambiguous and there is one choice that obviously fits this action better than the others. See the chapter on Understanding for a further discussion.
Here we get to use "now..." to give it its destructive effect:
Carry out shooting something with something:
say "ZAP! [The noun] twinkles out of existence! [if something is part of the noun][The list of things which are part of the noun] clatter to the ground! [end if][paragraph break]";
now every thing which is part of the noun is in the location;
now the noun is nowhere.
The Deathbot Assembly Line is a room. "Here is the heart of the whole operation, where your opponents are assembled fresh from scrap metal and bits of old car." The dangerous robot is a thing in the Assembly Line. "One dangerous robot looks ready to take you on!" A robotic head, a drill arm, a needle arm, a crushing leg and a kicking leg are parts of the dangerous robot.
Instead of examining something when something is part of the noun:
say "[The noun] consists of [a list of things which are part of the noun]."
Test me with "x robot / shoot robot / fire at kicking leg / shoot gun at drill arm / look".