Prev: B4B8 Up: Map Next: B53E
B4D0: Get nearest door
This returns the nearest door to the hero.
Used by the routines at action_lockpick and action_key.
Output
HL Pointer to door in locked_doors.
F Returns Z set if a door was found, clear otherwise.
get_nearest_door B4D0 LD A,($68A0) Get the global current room index
B4D3 AND A Is it room_0_OUTDOORS?
B4D4 JR Z,gnd_outdoors Jump forward to handle outdoors if so
Bug: Could avoid this jump instruction by using fallthrough instead.
B4D6 JP gnd_indoors Otherwise jump forward to handle indoors
Outdoors.
Locked doors 0..4 include exterior doors.
gnd_outdoors B4D9 LD B,$05 Set B for five iterations
B4DB LD HL,$F05D Point HL at the locked door indices
Start loop
gnd_outdoors_loop B4DE LD A,(HL) Fetch the door index and door_LOCKED flag
B4DF AND $7F Mask off door_LOCKED flag to get the door index alone
B4E1 EXX Switch register banks for this iteration
B4E2 CALL get_door Turn a door index into a door_t pointer in HL
B4E5 PUSH HL Preserve the door_t pointer
B4E6 CALL door_in_range Call door_in_range. C is clear if it's in range
B4E9 POP HL Restore door_t pointer
B4EA JR NC,gnd_in_range Jump forward if in range
B4EC INC HL Advance HL to the next door_t
B4ED INC HL
B4EE INC HL
B4EF INC HL
B4F0 CALL door_in_range Call door_in_range. C is clear if it's in range
B4F3 JR NC,gnd_in_range Jump forward if in range
B4F5 EXX Unbank
B4F6 INC HL Advance to the next door index and flag in locked_doors
B4F7 DJNZ gnd_outdoors_loop ...loop
B4F9 RET Return with Z clear (from the INC HL above) (not found)
gnd_in_range B4FA EXX Unbank
B4FB XOR A Set Z flag (found)
B4FC RET Return
Indoors.
Locked doors 2..8 include interior doors.
gnd_indoors B4FD LD HL,$F05F Point HL at the third locked door index
Bug: Ought to be 7 iterations.
B500 LD B,$08 Set B for eight iterations
Start loop
gnd_indoors_loop B502 LD A,(HL) Fetch the door index and door_LOCKED flag
B503 AND $7F Mask off door_LOCKED flag to get the door index alone
B505 LD C,A Keep in C for use during the loop
Search interior doors for the door index in C.
B506 LD DE,$81D6 Point DE at interior_doors
Start loop (inner)
gnd_indoors_loop_2 B509 LD A,(DE) Fetch an interior door index
B50A CP $FF Is it door_NONE? (end of list)
B50C JR Z,gnd_next Jump if so
B50E AND $7F Mask off door_REVERSE flag to get the door index alone
B510 CP C Is it a locked door index?
B511 JR Z,gnd_found Jump if so
B513 INC DE Otherwise advance to the next interior door index
There's no termination condition here where you might expect a test to see if we've run out of doors, but since every room has at least one door it *must* find one.
B514 JR gnd_indoors_loop_2 ...loop
Start loop
gnd_next B516 INC HL Advance to the next door index and flag in locked_doors
B517 DJNZ gnd_indoors_loop ...loop
B519 OR $01 Clear the Z flag (not found)
B51B RET Return
gnd_found B51C LD A,(DE) Fetch an interior door index
B51D EXX Switch register banks until we return
B51E CALL get_door Turn a door index into a door_t pointer in HL
B521 INC HL Advance door pointer to door.pos.x
B522 EX DE,HL Move the door pointer into DE
B523 LD HL,$81A4 Point HL at saved_pos_x
B526 LD B,$02 Set B for two iterations (two axis)
Note: This treats saved_pos as an 8-bit quantity in a 16-bit container.
Start loop -- once for each axis
On each axis if ((door - 2) <= pos and (door + 3) >= pos) then we're good.
get_nearest_door_0 B528 LD A,(DE) Fetch door.pos.x/y
B529 SUB $03 Compute the lower bound by subtracting 3
B52B CP (HL) Is lower bound >= saved_pos_x/y?
B52C JR NC,gnd_exx_next Jump if so (out of bounds - try the next door)
B52E ADD A,$06 Compute the upper bound by adding 6
B530 CP (HL) Is upper bound < saved_pos_x/y?
B531 JR C,gnd_exx_next Jump if so (out of bounds - try the next door)
B533 INC HL Advance to the next saved_pos axis
B534 INC HL
B535 INC DE Advance to the next door.pos axis
B536 DJNZ get_nearest_door_0 ...loop
If we arrive here then we're within the bounds
B538 EXX Switch back
B539 XOR A Set Z flag (found)
B53A RET Return
gnd_exx_next B53B EXX Switch back
B53C JR gnd_next ...loop
Prev: B4B8 Up: Map Next: B53E