Infinite lives
NEW_LIFE takes a life with DEC (HL) at TAKE_LIFE ($CBDD), and goes to the game over when that leaves less than none. The usual poke, a NOP there, does not work: before each new life NEW_LIFE reads that very byte, and unless it is still DEC (HL) it jumps to address 0 and the Spectrum starts again (see the facts). So leave the DEC where it is and aim it elsewhere: the LD HL before it gets ROM address 2 instead of LIVES. DEC (HL) cannot change the ROM, and the byte there, $11 in the 48K ROM and in the 128's 48 BASIC ROM, less one is positive, so the JP M after it never goes to the game over.
Tested in the simulator: a villain put on the knight at the start of every life. Without the poke LIVES went 5, 4, 3, 2, 1, 0 and the sixth death was the game over. With it, twelve deaths the same way and LIVES stayed at 5, the panel showing five knights throughout. With the NOP instead, at the first death the Spectrum started again from its copyright message:
The Spectrum's copyright message: the machine reset by the game's check
POKE 52187,2: POKE 52188,0
Nothing can kill him
Two things end his lives. A monster or the creature that touches him takes one of his three hits at MONSTER_HITS_KNIGHT (in WANDERING_MONSTER), and the third ends the life; a villain's touch ends it at once (VILLAIN_WANDER, into KNIGHT_KILLED). Make the DEC (HL) that takes the hit a RET -- the monster has already been made to vanish -- and the RET NC with which a villain gives up when it is not touching him a plain RET, and neither can hurt him. The monsters still score when they meet him.
Tested in the simulator, in cell (16,16): a villain put on him at the start of every turn cost 13 lives in 300 turns without the pokes and none with them; a monster of graphic 112 put on him whenever its record was free cost 29 hits and 9 lives in 300 turns without, and nothing with, the hits staying at three.
POKE 52930,201: POKE 55668,201
The top speeds the numbers say
The knight never reaches TOP_SPEED (see the bugs): he stops two short. Give TOP_SPEED two more wherever it is set -- 12 at a new game (NEW_GAME) and when the faster walk ends (UPDATE_KNIGHT), 20 for the faster walk (SPEED_BONUS) -- and he walks at the 10 and 18 the code names.
Tested in the simulator, walk held along an open street: without the pokes his speed went 4, 6, 8 and stayed at 8, and after the bonus 8, 12, 14, 16 and stayed at 16; with them 6, 8, 10 and 10, and after the bonus 10, 14, 16, 18 and 18. He still came to rest on the eight-unit grid when the key was let go.
POKE 48716,12: POKE 55958,12: POKE 55105,20
No monsters and no creature
Monsters are brought in by SPAWN_MONSTER every fourth turn, and the creature by SPAWN_CREATURE every 256th. A RET as the first instruction of each and none ever comes; the villains still wander, and still kill at a touch, and the antibodies have nothing to strike.
Tested in the simulator, 1000 turns in cell (16,16): without the pokes the six monster records were busy 5833 record-turns in all -- nearly all six all the time -- and the creature was there for 52 turns; with them the records stayed empty.
POKE 52712,201: POKE 49045,201
A hundred per cent printed as 100
PRINT_PERCENTAGE prints a hundred in whatever font was used last (see the bugs). These pokes put eleven bytes into UNUSED_F195, which the game never touches -- PUSH HL, LD HL,$6CDE (the digits), LD ($BBAC),HL (FONT_BASE), POP HL, JP $C327 -- and point PRINT_PERCENTAGE's jump there instead of straight at PRINT_BCD_LOW. The routine is outside the tape's block, so the pokes go in after loading.
Tested in the simulator, the same finished game as the bug's: FONT_BASE held the digits' font when the percentage was printed, and the screen said 100:
The game-over screen at a hundred per cent with the poke: COMPLETED 100
POKE 61845,229: POKE 61846,33: POKE 61847,222: POKE 61848,108: POKE 61849,34: POKE 61850,172: POKE 61851,187: POKE 61852,225: POKE 61853,195: POKE 61854,39: POKE 61855,195: POKE 48961,149: POKE 48962,241
The villains hum their own tunes
Each villain was meant to hum from a table of its own, and hums from the ROM instead (see the bugs). These pokes rewrite the seven bytes of VILLAIN_WANDER from the AND onwards: AND $30, so the offset is the kind alone, 0 to 48; then ADD A,$5D : LD C,A : LD B,$C3 and a NOP, so that BC is the table itself, where LD C,A : LD B,0 and the unused LD HL,$C35D were. BLIP_FROM_TABLE adds the turn's four bits to BC as it always did.
Tested in the simulator (at every build), each villain put near the knight: the pitches were read from $C38D-$C39C for the villain of 108-111, $C37D-$C38C for the villain of 104-107, $C36D-$C37C for the villain of 100-103 and $C35D-$C36C for the villain of 96-99, one table each.
POKE 55637,48: POKE 55638,198: POKE 55639,93: POKE 55640,79: POKE 55641,6: POKE 55642,195: POKE 55643,0
Play on a 128K in 128 mode
READ_KEYS sends the half-rows it is about to read to port $FD before reading port $FE, an OUT that does nothing on a 48K and pages memory on a 128K (see the bugs). The IN after it selects the half-rows by itself, so the OUT can simply go: two NOPs.
Tested in the emulator's 128K, from the loaded game put into a 128K snapshot with the 48 BASIC ROM and bank 0 paged in and the paging unlocked: without the poke the game crashed at the end of its first turn of play; with it, 300 turns of play with the paging as it started ($10: bank 0, the 48 BASIC ROM, unlocked). On a 48K it changes nothing but the refresh register, which counts one fetch for the OUT where it counts two for the NOPs, and with it the random numbers.
POKE 57913,0: POKE 57914,0