![]() |
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 |