Routines |
Prev: C651 | Up: Map | Next: C79A |
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 |