Prev: 83EA Up: Map Next: 8566
845F: Drive the pumpkin and the spider: move, bounce off the walls, animate
The per-actor update. Actors drift in a direction until they hit the edge of the room, then reverse; the direction is re-rolled at intervals from the refresh register, which is the game's random number source.
Velocity lives in +$08 (x) and +$09 (y) and is nudged one step per call toward +2 or -2 rather than being set outright, so things accelerate and turn smoothly instead of snapping.
Input
IX The actor to move
MOVE_ACTOR 845F CALL ACTOR_TO_WORKSPACE An actor in another room is not drawn or moved...
8462 LD A,($EA91)
8465 CP (IX+$01)
8468 JP NZ,ACTOR_TICK_TIMER ...it only gets its timer ticked.
846B LD HL,$5E25 Count of actors present in this room.
846E INC (HL)
846F CALL CHECK_SHOT_HIT Two proximity tests: has the player shot this monster, and has this monster caught the player.
8472 DEC E
8473 JP Z,KILL_MONSTER
8476 CALL CHECK_HIT
8479 DEC E
847A JP Z,MONSTER_CAUGHT_PLAYER
847D LD DE,($5E1D) The room's half-width and half-height -- how far from the centre an actor may stray.
8481 LD (IX+$0F),$00
8485 LD (IX+$05),$46
8489 LD A,(IX+$07)
848C AND $0F
848E JR NZ,MOVE_ACTOR_0
8490 LD A,R The refresh register as a source of randomness: whatever R happens to hold, masked to two direction bits.
8492 AND $03
8494 LD (IX+$06),A
MOVE_ACTOR_0 8497 BIT 0,(IX+$07)
849B JR NZ,MOVE_ACTOR_2
849D BIT 0,(IX+$06)
84A1 JP Z,MOVE_ACTOR_8
84A4 LD A,(IX+$08)
84A7 CP $02
84A9 JR Z,MOVE_ACTOR_1
84AB INC (IX+$08)
MOVE_ACTOR_1 84AE BIT 1,(IX+$06)
84B2 JP Z,MOVE_ACTOR_9
84B5 LD A,(IX+$09)
84B8 CP $02
84BA JR Z,MOVE_ACTOR_2
84BC INC (IX+$09)
MOVE_ACTOR_2 84BF INC (IX+$07)
84C2 LD A,(IX+$07) Flip the bottom bit of the sprite index every other tick, which is the walk animation.
84C5 AND $01
84C7 XOR (IX+$00)
84CA LD (IX+$00),A
This entry point is used by the routines at MOVE_BAT, MOVE_HOPPER, MOVE_FACE, MOVE_GHOST, MOVE_FRANKENSTEIN, MOVE_WITCH, MOVE_FACING_FLYER and MOVE_HUMPBACK.
STEP_ACTOR 84CD LD A,(IX+$03) Provisional new x = x + x-velocity.
84D0 ADD A,(IX+$08)
84D3 LD C,A
84D4 SUB $58 Distance from the room's centre column ($58)...
84D6 JR C,MOVE_ACTOR_3
84D8 CP E
84D9 JR C,MOVE_ACTOR_4
84DB RES 0,(IX+$06) ...and if that is outside the half-width, stay put and reverse.
84DF LD (IX+$08),$FE
84E3 LD C,(IX+$03)
84E6 JR MOVE_ACTOR_4
MOVE_ACTOR_3 84E8 NEG
84EA CP E
84EB JR C,MOVE_ACTOR_4
84ED SET 0,(IX+$06)
84F1 LD C,(IX+$03)
84F4 LD (IX+$08),$02
MOVE_ACTOR_4 84F8 LD A,(IX+$04) The same again for y, about centre row $68.
84FB ADD A,(IX+$09)
84FE LD B,A
84FF SUB $68
8501 JR C,MOVE_ACTOR_5
8503 CP D
8504 JR C,MOVE_ACTOR_6
8506 RES 1,(IX+$06)
850A LD (IX+$09),$FE
850E LD B,(IX+$04)
8511 JR MOVE_ACTOR_6
MOVE_ACTOR_5 8513 NEG
8515 CP D
8516 JR C,MOVE_ACTOR_6
8518 SET 1,(IX+$06)
851C LD B,(IX+$04)
851F LD (IX+$09),$02
MOVE_ACTOR_6 8523 LD (IX+$03),C Commit the new position.
8526 LD (IX+$04),B
8529 LD A,($EA91)
852C CP (IX+$01)
852F RET NZ
8530 LD A,(IX+$00) Two kinds are exempt from the test below: the humpback, whose codes are $9C-$9F, and the four big monsters at $70-$7F -- the mummy, Frankenstein's monster, the devil and Dracula, which come through STEP_ACTOR too. Masking with $FC and $F0 tests a whole run of codes in one compare, without caring which frame is showing.
8533 AND $FC
8535 CP $9C
8537 JR Z,MOVE_ACTOR_7
8539 AND $F0
853B CP $70
853D JR Z,MOVE_ACTOR_7
853F LD A,($EA90) Everything else is destroyed, with the 155 points of KILL_MONSTER, whenever the player is not in play -- sinking or rising. So dying clears the room of small creatures (measured in the simulator, 2026-09-27).
8542 CP $31
8544 JP NC,KILL_MONSTER
MOVE_ACTOR_7 8547 JP REDRAW_ACTOR
MOVE_ACTOR_8 854A LD A,(IX+$08)
854D CP $FE
854F JP Z,MOVE_ACTOR_1
8552 DEC (IX+$08)
8555 JP MOVE_ACTOR_1
MOVE_ACTOR_9 8558 LD A,(IX+$09)
855B CP $FE
855D JP Z,MOVE_ACTOR_2
8560 DEC (IX+$09)
8563 JP MOVE_ACTOR_2
Nothing in the disassembly jumps here, which is not because the routine is dead: it is entry $5C/$5D of the table at ACTOR_HANDLERS, and DISPATCH_ACTOR reaches it through a JP (HL). Breaking here does catch it, 16 times in 20, always with IX = $EE80 -- the monster whose sprite byte is currently $5C. Two earlier rounds of sampling reported zero hits and concluded it was unused; both were taken before the player had finished spawning, when no monster was in the room yet.
STEP_ACTOR is also entered directly by eight other routines, which is why the position update is written as a separate stretch: they supply their own velocity in +$08/+$09 and reuse the bounce logic. Verified against the running game -- ($5E1D) reads 56 by 56, and sampled actor positions stay inside $58 +/- 56 by $68 +/- 56.
Prev: 83EA Up: Map Next: 8566