Initialize_Entities: LD A, $mem_bunny_mana LD C, A LD A, $mem_bunny_health LD B, A LD HL, $mem_entities_list Clear_Entities.loop: XOR A LD (HL+), A CP L JR NZ, =Clear_Entities.loop LD A, B LD $mem_bunny_health, A LD A, C LD $mem_bunny_mana, A LD HL, $mem_entities_list LD A, $01 LD (HL+), A LD A, $mem_number_of_rooms CALL =RNG_Bound SLA A SLA A ADD low($mem_room_list) LD C, A LD B, high($mem_room_list) LD A, (BC) LD D, A INC BC LD A, (BC) INC A CALL =RNG_Bound ADD D LD (HL+), A INC BC LD A, (BC) LD D, A INC BC LD A, (BC) INC A CALL =RNG_Bound ADD D LD (HL), A PUSH BC LD C, (HL) DEC HL LD B, (HL) INC HL CALL =Carve_Entity_Collision_Map POP BC INC HL LD A, $enum_direction_down LD (HL+), A ; Turn LD A, $01 LD (HL+), A ; Action LD A, $00 LD (HL+), A INC HL ; skip health LD A, $00 ; Flags LD (HL+), A ; Status LD (HL+), A LD A, L AND $f0 ADD $10 LD L, A LD A, $00 LD $mem_enemies_alive_count, A LD A, $ff LD $mem_bunny_current_room_idx, A LD A, $00 LD $tmp_var_3, A CALL =Initialize_Enemy CALL =Initialize_Enemy CALL =Initialize_Enemy CALL =Initialize_Enemy CALL =Initialize_Enemy CALL =Reset_Entities_Collision_Map Fix_Bunny_screen: LD A, $mem_bunny_x SUB $05 LD $mem_viewport_x, A LD A, $mem_bunny_y SUB $04 LD $mem_viewport_y, A LD A, $mem_viewport_x SWAP A AND $f0 OR $08 LD $mem_prepared_viewport_x, A LD A, $mem_viewport_y SWAP A AND $f0 OR $08 LD $mem_prepared_viewport_y, A RET Initialize_Enemy: ; HL => pointer to entity struct CALL =Enemy_idx_to_spawn CP $ff RET Z ADD $03 Initialize_Entity: ; HL => pointer to entity struct, A => entity loaded index, 1 in $tmp_var_3 if should retry if collsion (could potentially fail multiple time/infinite loop) LD E, A SLA A SLA A LD B, A SLA A ADD B INC A LD (HL+), A LD A, $mem_bunny_current_room_idx LD $tmp_var_6, A CP $FF JR Z, =Initialize_Enemy.All_rooms_allowed LD B, A Initialize_Enemy.Skip_bunny_room: LD A, $mem_number_of_rooms CP $01 JR Z, =Initialize_Enemy.All_rooms_allowed DEC A CALL =RNG_Bound LD $tmp_var_5, A INC A LD C, A LD A, B CP C LD A, C JR C, =Initialize_Enemy.Room_restriction.end DEC A JR =Initialize_Enemy.Room_restriction.end Initialize_Enemy.All_rooms_allowed: LD A, $mem_number_of_rooms CALL =RNG_Bound Initialize_Enemy.Room_restriction.end: LD $tmp_var_4, A SLA A SLA A ADD low($mem_room_list) LD C, A LD B, high($mem_room_list) ; X LD A, (BC) LD D, A INC BC LD A, (BC) INC A CALL =RNG_Bound ADD D LD (HL+), A INC BC ; Y LD A, (BC) LD D, A INC BC LD A, (BC) INC A CALL =RNG_Bound ADD D LD (HL), A ; Check if spawning on collisionable tile PUSH BC LD C, (HL) DEC HL LD B, (HL) INC HL CALL =Is_Collisionable CP $00 JR Z, =.no_collision XOR A LD (HL-), A LD (HL-), A LD (HL), A POP BC LD A, $tmp_var_3 CP $01 RET NZ LD A, E JP =Initialize_Entity .no_collision: CALL =Carve_Entity_Collision_Map POP BC INC HL ; Direction LD A, $03 LD (HL+), A LD A, E CALL =Entity_idx_to_entity_list_ptr INC BC INC BC ; Turn LD A, (BC) LD (HL+), A INC BC ; Action LD A, (BC) LD (HL+), A INC BC ; Health LD A, (BC) LD (HL+), A INC BC XOR A ; flags & status LD (HL+), A LD A, (BC) LD (HL+), A INC BC ; Mana LD A, (BC) LD (HL+), A LD A, L ADD $06 LD L, A LD A, E CP $03 RET C CP $07 RET NC LD A, $mem_enemies_alive_count INC A LD $mem_enemies_alive_count, A RET FindFreeEntity: LD HL, $mem_entities_list FindFreeEntity.loop: ; This loop supposes that there is indeed enough space for a new entity ; to be spawn (thus the previous mem_enemies_alive_count). ; If entities are changed at some point to contain things that are not ; counted in mem_enemies_alive_count, this could result in an infinite loop. ; (Technically the quest goals can spawn other entities. We assume that the enemies alive count and the quest goal entities spawned will never exceed 15 together) LD A, L AND $f0 ADD $10 LD L, A LD A, $00 CP (HL) JR NZ, =FindFreeEntity.loop RET Respawn_Entities: LD A, $mem_moving_animation_step CP $04 RET NZ LD A, $mem_enemies_alive_count CP $05 RET NC LD A, $00 LD $tmp_var_3, A CALL =RNG_Step AND $07 CP $00 RET NZ CALL =FindFreeEntity CALL =Initialize_Enemy RET Enemy_spawn_pattern_to_probability: ; (1/(x + 1)) .DB 0b11111111 .DB 0b00000111 .DB 0b00000001 .DB 0b00000000 Enemy_idx_to_spawn: ; Return in A, ff if no entity to be spawned PUSH BC LD A, $mem_entity_spawning_pattern LD B, A CALL =RNG_Step AND $03 LD C, A SLA A CALL =RRx LD A, B AND $03 PUSH DE LD DE, =Enemy_spawn_pattern_to_probability ADD E LD E, A LD A, D ADC $00 LD D, A LD A, (DE) POP DE LD B, A CALL =RNG_Step AND B CP $00 LD A, $ff JR NZ, =.skip_set_enemy_idx LD A, C .skip_set_enemy_idx: POP BC RET .MACRODEF GET_ENTITY_IDX_SPAWN_RATE idx ; breaks BC & A LD A, low($idx) CALL =Entity_idx_to_entity_list_ptr LD A, C ADD $07 LD C, A LD A, B ADC $00 LD B, A LD A, (BC) AND $03 .END