Every fight in the game -- the player's, and the characters' among themselves -- is one routine, DO_ATTACK, reached through ATTACK WITH (and STRIKE WITH and THROW AT). This page reads it line by line, then runs it: on its own, thousands of times, to see who can hurt whom, and in two real fights.

A blow, step by step

  1. SAME_SIDE: an attacker and a target that share a side (bits 4-6 of byte 4 of their records) do not fight -- except that the player attacking a friend first takes the friend off the player's side, for good.
  2. The weapon's noun, or FIST, is kept for the messages. A weapon that is in more than one place (a river, a door) cannot kill.
  3. The blow: the attacker's strength (byte 5) plus the weapon's, at most 255, then jostled by JOSTLE.
  4. FOR_REAL: a test ends here, so a character considering an attack decides only that it could.
  5. The guard: the target's defence (byte 6), jostled the same way.
  6. Guard no less than the blow: wasted, and the game says the defence was too strong.
  7. Blow more than 16 above the guard: one well-placed blow kills (KILL).
  8. Otherwise it is a wound: the margin, 1 to 16, picks a message from WOUNDS and wears the target's strength and defence down.

The dice are loaded

JOSTLE is meant to add a random -10 to +10 (RANDOM with a limit of 10) and keep the result to 0-255. Two things make it something else. RANDOM draws a byte, halves it until it is no more than twice the limit and takes the limit off, so a byte above 20 always lands in 10-20 and comes out as 0 to +10; only a byte of 0-9 gives a negative number. And JOSTLE's clamp is written for a result that overflowed upwards: after ADD A,B it takes the carry to mean out of range, and then gives 0 if the draw was negative, 255 if not. But adding a negative draw (a byte of $F6-$FF) to anything of 10 or more always carries -- that is just subtraction -- so every negative draw turns the whole value to 0. (Below 10 it fails the other way: no carry, and 5 - 8 wraps round to 253.)

Measured: JOSTLE called 5000 times with 128, on a machine taken from a game at its first prompt, RANDOM's state running on from call to call:

ResultAddedShare
00 (a negative draw)3.9%
128+05.8%
129+111.9%
130+212.1%
131+312.6%
132+412.2%
133+511.9%
134+66.5%
135+76.3%
136+85.5%
137+95.5%
138+105.7%

So a blow or a guard is its strength plus 0 to 10 -- plus 1 to 5 twice as often as the rest -- and about one time in 26 (3.9%) it is 0. A blow of 0 is always wasted; a guard of 0 lets anything with a strength of 17 or more kill with one blow. That, more than the strengths, is what decides many fights.

The cast

Strength, defence and side, from the records as the tape has them (characters alike in all three are one row). The short strong sword adds 64 to its bearer's blow.

CharacterStrengthDefenceSide
the player6464the player's
red golden dragon192192none
nasty goblin and five more like it7296the goblins'
gandalf112136the player's
thorin104120the player's
wood elf6448the elves'
elrond6464the player's and the elves'
butler32112the elves'
vicious warg5555none
gollum3264the goblins'
bard9696the player's
hideous troll and one more like it160160none

Who can hurt whom

DO_ATTACK itself, called 500 times for each pair on the machine above, with the records and variables put back after every blow and RANDOM's state left to run on. Each cell is the share of blows that killed, then the share that wounded; the rest were wasted. Same side is SAME_SIDE refusing (the player's own side is left out of that: the player may attack anyone).

Attacker (strength)the player (64)red golden dragon (192)nasty goblin and five more like it (96)gandalf (136)thorin (120)wood elf (48)elrond (64)butler (112)vicious warg (55)gollum (64)bard (96)hideous troll and one more like it (160)
the player, bare-handed (64)-3 / 04 / 04 / 04 / 045 / 514 / 414 / 05 / 894 / 393 / 03 / 0
the player, with the sword (128)-3 / 097 / 04 / 24 / 8795 / 097 / 041 / 5795 / 096 / 098 / 03 / 0
red golden dragon (192)97 / 0-97 / 094 / 098 / 096 / 096 / 096 / 096 / 096 / 097 / 095 / 0
nasty goblin and five more like it (72)6 / 876 / 0-2 / 03 / 093 / 34 / 882 / 055 / 42same side3 / 04 / 0
gandalf (112)same side4 / 040 / 56-same side96 / 0same side2 / 3895 / 096 / 0same side3 / 0
thorin (104)same side4 / 04 / 90same side-96 / 0same side4 / 196 / 097 / 0same side6 / 0
wood elf (64)3 / 384 / 04 / 04 / 03 / 0-same sidesame side8 / 883 / 404 / 04 / 0
elrond (64)same side3 / 03 / 0same sidesame sidesame side-same side8 / 885 / 40same side3 / 0
butler (32)4 / 04 / 04 / 04 / 04 / 0same sidesame side-5 / 04 / 05 / 02 / 0
vicious warg (55)3 / 14 / 02 / 05 / 04 / 04 / 873 / 02 / 0-3 / 04 / 02 / 0
gollum (32)4 / 03 / 0same side5 / 03 / 03 / 03 / 04 / 03 / 0-3 / 03 / 0
bard (96)same side3 / 04 / 41same sidesame side96 / 0same side3 / 097 / 097 / 0-3 / 0
hideous troll and one more like it (160)98 / 06 / 094 / 095 / 295 / 094 / 097 / 097 / 096 / 096 / 096 / 0-

Read down a column for how safe a character is. The player's bare hands (64 + 0..10) can never beat a goblin's ordinary guard (96 + 0..10) -- but when the goblin's guard comes out 0, one blow kills it. The trolls and the dragon are out of reach of the player's ordinary blow, even with the sword, and fall to it only when their guard collapses the same way.

Wearing down

A wound takes something off the target's strength and defence. DO_ATTACK doubles the margin to index WOUNDS (RLCA), then halves it back and halves it again with RRCA -- a rotate, where a shift was surely meant, so the margin's lowest bit goes round into bit 7. That value plus one comes off the strength, and the next rotate plus one off the defence, each only if it does not take them below zero. So an even margin m takes m/2 + 1 off the strength, and an odd one tries to take 129 or more: a target of 128 or less is spared entirely, a stronger one loses nearly all of it. The defence loses a quarter of the margin plus one when the margin is a multiple of 4, about 65 when it is one more than that, and 129 or more otherwise -- again nothing for a weak target and most of it for a strong one. The table is the wound branch run from $91C1 with the blow and the guard set for each margin, against three targets as the tape has them; each result matched the value worked out from the instructions beforehand (all 48).

Marginthorin (104/120)hideous troll (160/160)nasty goblin (72/96)WOUNDS entry
1104/5531/9572/311, message $AF2B
2102/120158/3170/962, message $AF20
3104/12030/16072/963, message $AF15
4101/118157/15869/944, message $AF09
5104/5429/9472/305, message $AEF4
6100/120156/3068/966, message $AEE2
7104/12028/16072/967, message $AED1
899/117155/15767/938, message $AEBA
9104/5327/9372/299, message $AEAC
1098/120154/2966/9610, message $AE98
11104/12026/16072/9611, message $AE8B
1297/116153/15665/9212, message $AE7A
13104/5225/9272/2813, message $AE70
1496/120152/2864/9614, message $AE5A
15104/12024/16072/9615, message $AE49
1695/115151/15563/9116, message $2ADD

See Bugs. A troll, at 160/160, loses nearly all its strength to any odd margin and nearly all its defence to a margin of 2, 6, 10 or 14 -- which, with the dice above, makes a long fight with a troll a matter of luck rather than strength.

What a wound is called

The message comes from WOUNDS at twice the margin. The margins run from 1, so the table is read one entry late: its first message is never shown, and a margin of exactly 16 reads the word after the table, the first two bytes of ONE_PLACE's code -- $2ADD, an address in the ROM, whose bytes RUN_MESSAGE reads as a message. Each run through RUN_MESSAGE here, with the vicious warg as the actor and the wood elf as the target:

Word atEntryMessageMarginPrints
$92260$AF3Cnever“the vicious warg seems tired- the vicious warg staggers but valiantly attempts another blow.”
$92281$AF2B1“the vicious warg swings feebly at the elf but misses by a wide margin.”
$922A2$AF202“the vicious warg brandishes his, but the elf is on guard.”
$922C3$AF153“the vicious warg slashes at the elf but the blow is ineffective.”
$922E4$AF094“his sweeps past closes to his ear.”
$92305$AEF45“the vicious warg swings broadside at his body but at the last moment the elf jumps aside.”
$92326$AEE26“the vicious warg thrusts the elf back- the elf loses his footing but recovers quickly.”
$92347$AED17“the vicious warg hits the elf with a glancing blow and leaves the elf momentarily stunned.”
$92368$AEBA8“a fast stroke sweeps the elf off his feet, but the elf is on guard in a moment.”
$92389$AEAC9“a fast blow knocks the wind out of the elf.”
$923A10$AE9810“the vicious warg hits the elf hard on the shoulder- the elf staggers and almost falls.”
$923C11$AE8B11“the vicious warg gives the elf a nasty slash in the leg.”
$923E12$AE7A12“the vicious warg slices his- hand blood drips slowly to the ground.”
$924013$AE7013“a nasty slices misses his heart.”
$924214$AE5A14“the vicious warg gives the elf a vicious cut in the ribs- his strength is failing fast.”
$924415$AE4915“his violent attacks almost kills the vicious warg.”
$9246 (after the table: ONE_PLACE's first bytes)16$2ADD16“cut seclosedes.”

A fight nobody sees

From How the characters live: 10 turns of WAIT from the first prompt, nothing staged, and on the last the vicious warg meets the wood elf. Every real blow DO_ATTACK weighed, read at $91C1 (the blow and guard after the dice) and $91FB (the target after the wear):

TurnAttackerTargetTarget beforeBlowGuardOutcomeTarget after
10vicious wargwood elf64/486051wound, margin 964/48

A fight staged

The player given the short strong sword in Bag End (its holder and location poked), and ATTACK THORIN WITH SWORD typed every turn until one of them died (the player was killed on turn 1). The first blow takes Thorin off the player's side; his reaction script (ON_ATTACK_WITH) then attacks back every turn. Every blow:

TurnAttackerTargetTarget beforeBlowGuardOutcomeTarget after
1you with the short strong swordthorin104/120129122wound, margin 7104/120
1thorinyou64/6410664kill-

What the game printed:

you attack thorin with the short strong
sword.
you hit thorin with a glancing blow and
leave thorin momentarily stunned.
gandalf opens the round green door.
thorin attacks you.
with one well placed blow thorin cleaves
your skull.

A short fight, and a typical one. Thorin's strength, 104, against the player's defence of 64 leaves a margin of at least 30 -- far more than 16 -- so unless the dice give his blow a 0 his first reply kills, and the player's own first blow has to be the one that decides it.

Sides, and killing

The sides are the player's (the player, Gandalf, Thorin, Bard), the goblins' (the goblins, Gollum) and the elves' (the wood elf, the butler), with Elrond on both the player's and the elves'; the dragon, the warg and the trolls are on none, so anyone may fight them and they anyone (the table above, read from byte 4). KILL: the player's death is PLAYER_DIES; anyone else is marked dead (flag bit 3), drops what it holds (EMPTY_OUT), loses its slot in CHARACTERS, is renamed DEAD (BROKEN_OR_DEAD) and has its orders thrown away (CANCEL_ORDERS). A goblin comes straight back (GOBLIN_RETURNS), and Thorin's death shatters the small curious key (THORIN_KILLED). The other ways to kill -- DO_SHOOT, the dragon's BURN -- do not go through the blow at all.

What is confirmed, and what is not