Prev: C651 Up: Map Next: C79A
C6A0: Move a character
This moves one (off-screen) character around at a time.
Used by the routine at main_loop.
move_a_character C6A0 LD A,$FF Set the 'character index is valid' flag
C6A2 LD ($A13E),A
Move to the next character, wrapping around after character 26.
C6A5 LD A,($8217) Load and increment the current character index
C6A8 INC A
C6A9 CP $1A If the character index became character_26_STOVE_1 then wrap around to character_0_COMMANDANT
C6AB JR NZ,mc_didnt_wrap
C6AD XOR A
mc_didnt_wrap C6AE LD ($8217),A Store the character index
Get its chararacter struct and exit if the character is on-screen.
C6B1 CALL get_character_struct Get a pointer to the character struct for character index A, in HL
C6B4 BIT 6,(HL) Is the character on-screen? characterstruct_FLAG_ON_SCREEN
C6B6 RET NZ It is - return
C6B7 PUSH HL Preserve the character struct pointer
Are any items to be found in the same room as the character?
C6B8 INC HL Advance HL to charstr.room and fetch it
C6B9 LD A,(HL)
C6BA AND A Are we outdoors?
C6BB JR Z,mc_no_item Jump if so
Note: This discovers just one item at a time.
C6BD CALL is_item_discoverable_interior Is the item discoverable indoors?
C6C0 JR NZ,mc_no_item Jump if not found
C6C2 CALL item_discovered Otherwise cause item C to be discovered
mc_no_item C6C5 POP HL Restore the character struct pointer
C6C6 INC HL Advance HL to charstr.pos
C6C7 INC HL
C6C8 PUSH HL Preserve the charstr.pos pointer
C6C9 INC HL Advance HL to charstr.route
C6CA INC HL
C6CB INC HL
If the character is standing still, return now.
C6CC LD A,(HL) Fetch charstr.route.index
C6CD AND A Is it routeindex_0_HALT?
C6CE JR NZ,mc_not_halted Jump if not
mc_halted C6D0 POP HL Restore the charstr.pos pointer
C6D1 RET Return
mc_not_halted C6D2 CALL get_target Get our next target: a location, a door or 'route ends'. The result is returned in A, target pointer returned in HL
C6D5 CP $FF Did get_target return get_target_ROUTE_ENDS? ($FF)
C6D7 JP NZ,mc_door Jump if not
When the route ends, reverse the route.
C6DA LD A,($8217) Fetch the current character index
C6DD AND A Is it the commandant? (character_0_COMMANDANT)
C6DE JR Z,mc_commandant Jump if so
Not the commandant.
C6E0 CP $0C Is it character_12_GUARD_12 or higher?
C6E2 JR NC,mc_trigger_event Jump if so
Characters 1..11.
mc_reverse_route C6E4 LD A,(HL) Toggle charstr.route direction flag routeindexflag_REVERSED ($80)
C6E5 XOR $80
C6E7 LD (HL),A
C6E8 INC HL
Pattern: [-2]+1
C6E9 BIT 7,A If the route is reversed then step backwards, otherwise step forwards
C6EB JR Z,mc_route_fwd
C6ED DEC (HL)
C6EE DEC (HL)
mc_route_fwd C6EF INC (HL)
C6F0 POP HL Restore the charstr.pos pointer
C6F1 RET Return
Commandant only.
mc_commandant C6F2 LD A,(HL) Read the charstr.route index
C6F3 AND $7F
C6F5 CP $24 Jump if it's not routeindex_36_GO_TO_SOLITARY
C6F7 JR NZ,mc_reverse_route
We arrive here if the character index is character_12_GUARD_12, or higher, or if it's the commandant on route 36 ("go to solitary").
mc_trigger_event C6F9 POP DE Restore the charstr.pos pointer
C6FA JP character_event Exit via character_event
Two unused bytes.
C6FD DEFB $18,$6F
mc_door C6FF CP $80 Did get_target return get_target_DOOR? ($80)
C701 JP NZ,mc_regular_move Jump if not
Handle the target-is-a-door case.
C704 POP DE Restore the charstr.pos pointer (PUSH at C6C8)
C705 DEC DE Get room index
C706 LD A,(DE)
C707 INC DE
C708 PUSH HL Preserve the door.pos pointer
C709 AND A Are we outdoors?
C70A JP NZ,mc_door_choose_maxdist Jump if not
Outdoors
C70D PUSH DE Preserve the charstr.pos pointer
Divide the door.pos location at HL by two and store it to saved_pos.
C70E LD DE,$81A4 Point DE at saved_pos_x
C711 LD B,$02 Set B for two iterations
Start loop
mc_door_copypos_loop C713 LD A,(HL) Copy X,Y of door.pos, each axis divided by two
C714 AND A
C715 RRA
C716 LD (DE),A
C717 INC HL
C718 INC DE
C719 DJNZ mc_door_copypos_loop ...loop
C71B LD HL,$81A4 Point HL at saved_pos_x
C71E POP DE Restore the charstr.room pointer
Decide on a maximum movement distance for move_towards to use.
mc_door_choose_maxdist C71F DEC DE Rewind DE to point at charstr.room
C720 LD A,(DE) Fetch it
C721 INC DE Advance DE back
C722 AND A Was charstr.room room_0_OUTDOORS?
C723 LD A,$02 Set the maximum distance to two irrespectively
C725 JR Z,mc_door_maxdist_chosen Jump if it was
C727 LD A,$06 Otherwise set the maximum distance to six
mc_door_maxdist_chosen C729 EX AF,AF' Move maximum to A'
C72A LD B,$00 Initialise the "arrived" counter to zero
C72C CALL move_towards Move charstr.pos.x (pointed to by DE) towards tinypos.x (HL), with a maximum delta of A'. B is incremented if no movement was required
C72F INC DE Advance to Y axis
C730 INC HL
C731 CALL move_towards Move again, but on Y axis
C734 POP HL Restore the door.pos pointer
C735 LD A,B Did we move?
C736 CP $02
C738 RET NZ Return if so
If we reach here the character has arrived at their destination.
Our current target is a door, so change to the door's target room.
mc_door_reached C739 DEC DE Rewind DE to charstr.room
C73A DEC DE
C73B DEC HL Rewind HL to door.room_and_direction
C73C LD A,(HL) Fetch door.room_and_direction
C73D AND $FC Isolate the room number
C73F RRA
C740 RRA
C741 LD (DE),A Assign to charstr.room (i.e. change room)
Determine the destination door.
C742 LD A,(HL) Isolate the direction (door_FLAGS_MASK_DIRECTION)
C743 AND $03
C745 CP $02 Is the door facing top left or top right?
C747 JR NC,mc_door_prev Jump if neither
C749 INC HL Otherwise calculate the address of the next door half
C74A INC HL
C74B INC HL
C74C INC HL
C74D INC HL
C74E JR mc_door_copy_pos (else)
mc_door_prev C750 DEC HL Calculate the address of the previous door half
C751 DEC HL
C752 DEC HL
Copy the door's tinypos position into the charstr.
mc_door_copy_pos C753 LD A,(DE) Fetch charstr.room
C754 INC DE Advance to charstr.pos
C755 AND A Is it room_0_OUTDOORS?
C756 JR Z,mc_door_outdoors Jump if so
Indoors. Copy the door's tinypos into the charstr's tinypos.
C758 LDI Copy X
C75A LDI Copy Y
C75C LDI Copy height
C75E DEC DE Rewind DE to charstr.pos.height
C75F JR mc_regular_reached (else)
Outdoors. Copy the door's tinypos into the charstr's tinypos, dividing by two.
mc_door_outdoors C761 LD B,$03 Set B for three iterations
Start loop
mc_door_outdoors_loop C763 LD A,(HL) Copy X,Y of door.pos, each axis divided by two
C764 AND A
C765 RRA
C766 LD (DE),A
C767 INC HL
C768 INC DE
C769 DJNZ mc_door_outdoors_loop ...loop
C76B DEC DE Rewind DE to charstr.pos.height
C76C JR mc_regular_reached (else)
Normal move case.
mc_regular_move C76E POP DE Restore the charstr.pos pointer
Establish a maximum for passing into move_towards.
mc_regular_choose_maxdist C76F DEC DE Rewind DE to point at charstr.room
C770 LD A,(DE) Fetch it
C771 INC DE Advance DE back
C772 AND A Are we outdoors?
C773 LD A,$02 Set maximum to two irrespectively
C775 JR Z,mc_regular_maxdist_chosen Jump if we are
C777 LD A,$06 Otherwise set maximum to six
mc_regular_maxdist_chosen C779 EX AF,AF' Move maximum to A'
C77A LD B,$00 Initialise the "arrived" counter to zero
C77C CALL move_towards Move charstr.pos.x (pointed to by DE) towards tinypos.x (HL), with a maximum delta of A'. B is incremented if no movement was required
C77F INC HL Advance to Y axis
C780 INC DE
C781 CALL move_towards Move again, but on Y axis
C784 INC DE Advance DE to charstr.pos.height (possibly redundant)
C785 LD A,B Did we move?
C786 CP $02
C788 JR Z,mc_regular_reached Jump if not
C78A RET Otherwise return
If we reach here the character has arrived at their destination.
mc_regular_reached C78B INC DE Advance DE to charstr.route
C78C EX DE,HL Swap charstr into HL
C78D LD A,(HL) Read charstr.route.index
C78E CP $FF Is the route index routeindex_255_WANDER? ($FF)
C790 RET Z Return if so
C791 BIT 7,A If the route is reversed then step backwards, otherwise step forwards
C793 INC HL
C794 JR NZ,mc_route_down
mc_route_up C796 INC (HL) Increment route.step
C797 RET Return
mc_route_down C798 DEC (HL) Decrement route.step
C799 RET Return
Prev: C651 Up: Map Next: C79A