Prev: C892 Up: Map Next: CA11
C918: Character behaviour
This handles the various different pursuit modes that vischars can be in (pursuing the hero, a dog moving towards food, etc.) and drives character movement.
Used by the routines at spawn_character and automatics.
Input
IY Pointer to visible character.
Proceed into the character behaviour handling only when this delay field hits zero. This stops characters navigating around obstacles too quickly.
character_behaviour C918 LD A,(IY+$07) Fetch vischar.counter_and_flags
C91B LD B,A Copy it to B
If the counter field is set then decrement it and return.
C91C AND $0F Isolate the counter field in the bottom nibble
C91E JR Z,cb_proceed Decrement the counter if it's positive
C920 DEC B
C921 LD (IY+$07),B
C924 RET Return
We arrive here when the counter is zero.
cb_proceed C925 PUSH IY Copy the vischar pointer into HL
C927 POP HL
C928 INC L Advance HL to vischar.flags
C929 LD A,(HL) Fetch the flags so we can check the mode field
C92A AND A Are any flag bits set?
C92B JP Z,cb_check_halt Jump if not
Check for mode 1 ("pursue")
C92E CP $01 Is the mode vischar_PURSUIT_PURSUE?
C930 JR NZ,cb_hassle_check Jump if not
Mode 1: Hero is chased by hostiles and sent to solitary if caught.
cb_pursue_hero C932 PUSH HL Preserve vischar.flags pointer
C933 EXX Bank
C934 POP DE Restore vischar.flags pointer
C935 INC E Advance DE to vischar.position
C936 INC E
C937 INC E
C938 LD HL,$81B8 Point HL at the global map position (the hero's position)
C93B LDI Copy hero's (x,y) position to vischar.target
C93D LDI
C93F EXX Unbank
C940 JP cb_move Jump to 'move'
Check for mode 2 ("hassle")
cb_hassle_check C943 CP $02 Is the mode vischar_PURSUIT_HASSLE?
C945 JR NZ,cb_dog_food_check Jump if not
Mode 2: Hero is chased by hostiles if under player control.
C947 LD A,($A139) Is the automatic_player_counter non-zero?
C94A AND A
The hero is under player control: pursue.
C94B JR NZ,cb_pursue_hero Jump into mode 1's pursue handler
Otherwise the hero is under automatic control: hostiles lose interest and resume their original route.
C94D LD (HL),$00 Clear vischar.flags
C94F INC L
C950 JP get_target_assign_pos Exit via get_target_assign_pos
Check for mode 3 ("dog food")
cb_dog_food_check C953 CP $03 Is the mode vischar_PURSUIT_DOG_FOOD?
C955 JR NZ,cb_saw_bribe_check Jump if not
Mode 3: The food item is near a guard dog.
C957 PUSH HL Preserve vischar.flags pointer
C958 EX DE,HL (get it in DE)
C959 LD HL,$76FA Point HL at item_structs[item_FOOD].room
C95C BIT 7,(HL) Is itemstruct_ROOM_FLAG_NEARBY_7 set?
C95E JR Z,cb_dog_food_not_nearby Jump if not
Set the dog's target to the poisoned food location.
C960 INC HL Advance HL to item_structs[item_FOOD].pos.x
C961 LD A,E Point DE at vischar.target.x
C962 ADD A,$03
C964 LD E,A
C965 LDI Copy (x,y)
C967 LDI
C969 POP HL Restore vischar.flags pointer
C96A JR cb_move Jump to 'move'
Nearby flag wasn't set.
cb_dog_food_not_nearby C96C XOR A Clear vischar.flags
C96D LD (DE),A
C96E EX DE,HL (get vischar.flags pointer in HL)
C96F INC L Set vischar.route.index to routeindex_255_WANDER ($FF)
C970 LD (HL),$FF
C972 INC L Set vischar.route.step to zero -- wander from 0..7
C973 LD (HL),$00
C975 POP HL Restore vischar.flags pointer
C976 JP get_target_assign_pos Exit via get_target_assign_pos
Check for mode 4 ("saw bribe")
cb_saw_bribe_check C979 CP $04 Is the mode vischar_PURSUIT_SAW_BRIBE?
C97B JR NZ,cb_check_halt Jump if not
Mode 4: Hostile character witnessed a bribe being given (in accept_bribe).
C97D PUSH HL Preserve vischar.flags pointer
C97E LD A,($AF8E) Get the global bribed character
C981 CP $FF Is it character_NONE? ($FF)
C983 JR Z,cb_bribe_not_found Jump if so
C985 LD C,A Copy the bribed character to C
Iterate over non-player characters.
C986 LD B,$07 Set B for seven iterations
C988 LD HL,$8020 Point HL at the second visible character
Start loop
cb_bribe_loop C98B LD A,C Copy bribed character to A
C98C CP (HL) Is this vischar the bribed character?
C98D JR Z,cb_bribed_visible Jump if so
C98F LD A,$20 Step HL to the next vischar
C991 ADD A,L
C992 LD L,A
C993 DJNZ cb_bribe_loop ...loop
cb_bribe_not_found C995 POP HL Restore vischar.flags pointer
Bribed character was not visible: hostiles lose interest and resume following their original route.
C996 LD (HL),$00 Clear vischar.flags
C998 INC L
C999 JP get_target_assign_pos Exit via get_target_assign_pos
Found the bribed character in vischars: hostiles target him.
cb_bribed_visible C99C LD A,$0F Advance HL to vischar.mi.pos
C99E ADD A,L
C99F LD L,A
C9A0 POP DE Get the vischar pointer
C9A1 PUSH DE
C9A2 LD A,E Point DE at vischar.target
C9A3 ADD A,$03
C9A5 LD E,A
C9A6 LD A,($68A0) Get the global current room index
C9A9 AND A Is it zero?
C9AA JP NZ,cb_bribed_indoors Jump if not
Outdoors
C9AD CALL pos_to_tinypos Scale down the bribed character's position to this vischar's target field
C9B0 JR cb_bribed_done (else)
Indoors
cb_bribed_indoors C9B2 LDI Scale down the bribed character's position to this vischar's target field
C9B4 INC L
C9B5 LDI
cb_bribed_done C9B7 POP HL Restore the vischar pointer
C9B8 JR cb_move Jump to 'move'
cb_check_halt C9BA INC L Advance HL to vischar.route.index
C9BB LD A,(HL) Fetch it
C9BC DEC L Step back
C9BD AND A Is it routeindex_0_HALT? ($00)
C9BE JR Z,cb_set_input Jump if so (set input)
cb_move C9C0 LD A,(HL) Get vischar.flags
C9C1 EXX Bank
C9C2 LD C,A C = flags
Select a scaling routine.
C9C3 LD A,($68A0) Get the global current room index
C9C6 AND A Is it outdoors? (zero)
C9C7 JR Z,cb_scaling_door Jump if so
cb_scaling_indoors C9C9 LD HL,$CB75 Point HL at multiply_by_1
C9CC JR cb_self_modify (else)
cb_scaling_door C9CE BIT 6,C Is vischar.flags vischar_FLAGS_TARGET_IS_DOOR set?
C9D0 JR Z,cb_scaling_outdoors Jump if not
C9D2 LD HL,$B295 Point HL at multiply_by_4
C9D5 JR cb_self_modify (else)
cb_scaling_outdoors C9D7 LD HL,$B1C7 Point HL at multiply_by_8
Self modify vischar_move_x/y routines.
cb_self_modify C9DA LD ($CA13),HL Self-modify vischar_move_x
C9DD LD ($CA4B),HL Self-modify vischar_move_y
C9E0 EXX Unbank
If the vischar_BYTE7_Y_DOMINANT flag is set then cb_move_y_dominant is used instead of the code below, which is x dominant. i.e. It means "try moving y then x, rather than x then y". This is the code which makes characters alternate left/right when navigating.
C9E1 BIT 5,(IY+$07) Does the vischar's counter_and_flags field have flag vischar_BYTE7_Y_DOMINANT set? ($20)
C9E5 JR NZ,cb_move_y_dominant Jump if so
cb_move_x_dominant C9E7 INC L Advance HL to vischar.position.x
C9E8 INC L
C9E9 INC L
C9EA CALL vischar_move_x Call vischar_move_x
C9ED JR NZ,cb_set_input If it couldn't move call vischar_move_y
C9EF CALL vischar_move_y
C9F2 JP Z,target_reached If it still couldn't move exit via target_reached
This entry point is used by the routine at target_reached.
cb_set_input C9F5 CP (IY+$0D) Is our new input different from the vischar's existing input?
C9F8 RET Z Return if not
C9F9 OR $80 Otherwise set the input_KICK flag
C9FB LD (IY+$0D),A
C9FE RET Return
cb_move_y_dominant C9FF LD A,$04 Advance HL to vischar.position.y
CA01 ADD A,L
CA02 LD L,A
CA03 CALL vischar_move_y Call vischar_move_y
CA06 JR NZ,cb_set_input If it couldn't move call vischar_move_x
CA08 CALL vischar_move_x
CA0B JR NZ,cb_set_input If it could move, jump to cb_set_input
CA0D DEC L Rewind HL to vischar.position.x
CA0E JP target_reached Exit via target_reached
Prev: C892 Up: Map Next: CA11