| The Hobbit (v1.0) | Routines |
| Prev: 90B4 | Up: Map | Next: 917D |
|
The fight routine. It is used both when the player attacks someone and when another character attacks (for example Thorin retaliating, or the trolls and goblins attacking Bilbo). The attacker's object record is pointed to by $B5FC, the target's by B5F8, and the weapon's (if any) by $B5FA; B5DA holds the weapon's object number, or $FF when there is none.
It uses two bytes of the 8-byte object header (see C00B): byte 5 is STRENGTH and byte 6 is DEFENCE. Some starting values: Bilbo 64/64, Thorin 104/120, Gandalf 112/136, the trolls 160/160, the goblins 72/96, Bard 96/96, the dragon 192/192, and the short strong sword has strength 64 (255 in my modified tape).
Step 1: 'you attack thorin' is printed ($90FE onwards), naming the weapon if one was used.
Step 2: the attack value is the attacker's strength (90F9), plus the weapon's strength if one was used (9102-9116), capped at 255. A weapon is only accepted if byte 0 of its record is 1 (an ordinary one-place object); otherwise the message at AE52 is printed.
Step 3: the attack value is randomised by 917D (roughly -10 to +10) and so is the target's defence (9121-$912A).
Step 4: if the randomised defence is greater than or equal to the attack, the blow does nothing: 'but the effort is wasted. his defense is too strong' (AE43).
Step 5: if the attack exceeds the defence by more than 16, the blow is fatal. The message at AD2D ('with one well placed blow you cleave his skull') is printed and bit 3 of the target's flag byte (byte 7) is set, marking it dead (9168).
Step 6: otherwise the target is wounded. The difference d (1-16) selects a message from the table at 9190 - the larger the margin the nastier the description. The code then tries to reduce the target's strength by d/2+1 and its defence by d/4+1 (914E-$9164), skipping either reduction if it would go below 0. It computes d/2 and d/4 with RRCA (rotate right) rather than SRL (shift right), though.
BUG: RRCA moves the bit shifted out of the bottom back into the top, so the halving only works when the bit being shifted out is 0. With Thorin (strength 104, defence 120) the actual results are: margins 4, 8, 12 and 16 reduce both strength and defence as intended (for example margin 8 takes him to 99/117); margins 2, 6, 10 and 14 reduce strength only; margins 3, 7, 11 and 15 do nothing at all; and margins 1, 5, 9 and 13 leave strength alone but slash his defence by about 65, to 52-55, which makes the next blow very likely to kill him.
|
||||
| 90DB | CALL $90B4 | Check the target is something that can be attacked | ||
| 90DE | LD A,($B5DA) | Was a weapon named? | ||
| 90E1 | LD HL,$026F | HL = the word used when there is no weapon | ||
| 90E4 | CP $FF | |||
| 90E6 | JR Z,$90F2 | No weapon: skip | ||
| 90E8 | LD IX,($B5FA) | IX = the weapon's record | ||
| 90EC | LD L,(IX+$08) | HL = the weapon's noun (e.g. SWORD) | ||
| 90EF | LD H,(IX+$09) | |||
| 90F2 | LD ($B5ED),HL | Keep it for the report ("...with the sword") | ||
| 90F5 | LD IX,($B5FC) | IX = the attacker's record | ||
| 90F9 | LD B,(IX+$05) | B = the attacker's strength | ||
| 90FC | LD A,($B5DA) | Is there a weapon? | ||
| 90FF | INC A | ($FF + 1 = 0) | ||
| 9100 | JR Z,$9119 | No: attack with strength alone | ||
| 9102 | LD IY,($B5FA) | IY = the weapon's record | ||
| 9106 | LD A,(IY+$00) | Is it an ordinary object (one place)? | ||
| 9109 | DEC A | |||
| 910A | LD HL,$AE52 | "you cannot kill with the X" | ||
| 910D | JP NZ,$72D4 | No: say so and stop | ||
| 9110 | LD A,(IY+$05) | A = the weapon's strength | ||
| 9113 | ADD A,B | Add the attacker's strength | ||
| 9114 | JR NC,$9118 | No overflow: fine | ||
| 9116 | LD A,$FF | Overflow: cap it at 255 | ||
| 9118 | LD B,A | B = the attack value | ||
| 9119 | LD A,B | |||
| 911A | CALL $917D | Randomise the attack value by about +/-10 | ||
| 911D | LD B,A | |||
| 911E | CALL $9C99 | Dry run? Then stop here: the attack would happen | ||
| 9121 | LD IX,($B5F8) | IX = the target's record | ||
| 9125 | LD A,(IX+$06) | A = the target's defence | ||
| 9128 | CALL $917D | Randomise it too | ||
| 912B | CP B | Is the defence at least as big as the attack? | ||
| 912C | LD HL,$AE43 | "but the effort is wasted. his defense is too strong." | ||
| 912F | JP NC,$72D4 | Yes: the blow does nothing | ||
| 9132 | LD C,A | C = the defence | ||
| 9133 | ADD A,$10 | Defence + 16... | ||
| 9135 | JR NC,$9139 | |||
| 9137 | LD A,$FF | (capped at 255) | ||
| 9139 | CP B | ...less than the attack? | ||
| 913A | JR C,$9168 | Yes: a fatal blow | ||
| 913C | LD A,B | A wound. A = the margin (attack - defence, 1-16) | ||
| 913D | SUB C | |||
| 913E | RLCA | Double it to index the wound messages | ||
| 913F | LD E,A | |||
| 9140 | LD D,$00 | |||
| 9142 | LD IY,$9190 | IY = the wound message table | ||
| 9146 | ADD IY,DE | |||
| 9148 | LD L,(IY+$00) | HL = the message for this margin (a margin of 16 runs off the end of the table) | ||
| 914B | LD H,(IY+$01) | |||
| 914E | RRCA | Halve the doubled margin twice with RRCA: margin/2, but with bit 0 rotated into bit 7 (see the bug note) | ||
| 914F | RRCA | |||
| 9150 | LD B,A | B = the "half" margin | ||
| 9151 | CPL | A = 255 - B | ||
| 9152 | ADD A,(IX+$05) | Add the target's strength: carry only if strength > B | ||
| 9155 | JR NC,$915A | It would go negative: leave it alone | ||
| 9157 | LD (IX+$05),A | Otherwise strength = strength - B - 1 | ||
| 915A | LD A,B | A = the "half" margin again | ||
| 915B | RRCA | Halve it again (RRCA again) | ||
| 915C | CPL | A = 255 - that | ||
| 915D | ADD A,(IX+$06) | Add the target's defence | ||
| 9160 | JR NC,$9165 | It would go negative: leave it | ||
| 9162 | LD (IX+$06),A | Otherwise defence = defence - (margin/4) - 1 | ||
| 9165 | JP $72D4 | Print the wound message | ||
| 9168 | LD HL,$AD2D | "with one well placed blow <actor> cleaves <his/your> skull." | ||
| 916B | CALL $72D4 | |||
| 916E | SET 3,(IX+$07) | Mark the target dead | ||
| 9172 | LD A,($B5D9) | A = the target | ||
| 9175 | CALL $96DD | Kill it: drop its things, remove it from the character table | ||
| 9178 | LD A,$06 | Then report "<target> is dead." | ||
| 917A | JP $A09C | |||
| Prev: 90B4 | Up: Map | Next: 917D |