+ psh hl
+ xor a
+ ld (0),a ;remove bullet
+temp1 =$-2
+ pop hl
+
+ cal enemy_hit
+nohit:
+ pop hl
+ ld bc,enemysize
+ add hl,bc
+ pop bc
+ dnz hit_enemies ;check next enemy
+ ret
+
+enemy_hit:
+ dec hl
+ dec hl
+ dec hl
+
+ ld a,1 ;damage to inflict
+curweapdamage =$-1
+ rla
+ rla ;*4
+ ld b,a
+ ld a,(hl) ;load occ
+ sub b ;decrease HP (if <0 then c is set)
+ ld (hl),a ;save (no flag-changes)
+ dec hl ;goto hp64; no change in c
+ ld a,(hl) ;load; no c-change
+ sbc a,0 ;if c then decrease a
+ ld (hl),a ;save back the new value
+ ret nc ;if a>=0 then return, otherwise explode
+
+ inc hl ;goto occ again
+ ld (hl),%01 ;set to explode
+ ld a,(pickuptimer) ;counts enemies destroyed
+ dec a ;enough destroyed for a pickup?
+ jr nz,pickupdone ;otherwise just explode
+ ld (hl),%110 ;change it into a pickup (with 2 HP)
+ ld a,18 ;reset enemies counter (18 hits = next)
+pickupdone:
+ ld (pickuptimer),a ;save new enemiescounter value
+ inc hl
+ ld (hl),$00 ;explosionFrame 0
+
+ ld hl,1 ;increase score by one
+ jp scoreInc ;+ret
+
+;--------------------------- handle torpedo ----------------------------------
+
+Handle_torp:
+ ld a,(torp_occ)
+ sub 2
+ ret m ;return if occ=0/1
+
+ ld hl,torp_pos ;x-position
+ ld a,(hl) ;load in a
+ inc a ;move right
+ cp 125 ;right edge reached
+ jr nc,remove_torp ;remove if x>125
+ ld (hl),a ;save new x
+ ld d,a
+
+ inc hl ;y-position
+ ld a,(hl)
+ inc a ;move down
+ cp 56 ;bottom reached
+ jr nc,remove_torp ;remove if y>40
+ ld (hl),a ;save new y
+ ld e,a
+
+ ld ix,spr_bullett1
+ psh de
+ cal putsprite ;display torpedo
+ pop de
+ jp check_bullethits ;check for hits with enemies
+
+remove_torp:
+ ld a,1
+ ld (torp_occ),a
+ ret
+
+;--------------------------- level events -------------------------------------
+
+Level_event:
+ ld hl,nextevent ;time to next event <ld a,(nextevent)
+ dec (hl) ;decrease counter <dec a
+ ld a,(hl) ;look at counter <ld (nextevent),a
+ or a ;has it reached zero?
+ ret nz ;nope: get outta here!
+
+ ld a,(eventtime) ;enemy frequency (lvl)
+ ld (nextevent),a ;set time to next event
+ ld hl,eventleft
+ dec (hl) ;update enemy-counter
+
+ ld a,(hl) ;look at counter
+ or a ;has it reached 0?
+ jp z,Next_level ;yes: level finished
+ dec a ;has it reached 1?
+ jr z,standby_event ;yes: wait until no enemies present/left
+ dec a ;has it reached 2?
+ jr z,place_boss ;yep: place the BigBossTM!
+ dec a ;has it reached 3?
+ jr nz,do_event ;nope: >3 = place an enemy
+ inc hl ;nextevent located behind eventleft
+ ld (hl),123 ;set delay
+ ret ;don't place any more enemies
+
+place_boss:
+ ld hl,(levelp) ;the leveldata (including the boss)
+ dec hl ;points to leveldata\boss\enemynr
+ ld a,(hl) ;load it
+ ld (level_enemy),a ;set new enemy (boss)
+ dec hl ;points to level\boss\movement
+ ld a,(hl) ;load
+ ld (level_move),a ;set boss movement
+ dec hl ;@level\boss\firefreq
+ ld a,(hl) ;load in a
+ ld (level_fire),a ;set firefrequency
+ jp do_event ;+ret
+
+standby_event:
+ ld b,nrenemies
+ ld hl,enemies+1-enemysize
+ ld de,enemysize
+chk_enemyleft:
+ add hl,de
+ ld a,(hl)
+ or a ;0 = no enemy present
+ jr nz,enemyleft
+ dnz chk_enemyleft
+ ret
+enemyleft:
+ ld hl,eventleft
+ inc (hl)
+ ret
+
+
+do_event:
+ ld hl,enemies+1-enemysize
+ ld bc,enemysize
+ xor a ;a=0
+chk_noenemy:
+ add hl,bc
+ cp (hl) ;(hl) = 0 ??
+ jr nz,chk_noenemy ;jump if enemy present (non-0)
+ ex de,hl ;de=hl=usable enemy
+
+place_enemy:
+ ld a,(level_enemy) ;enemy type to place (lvl)
+ ld hl,XLenemyinfos-4 ;enemy "0" specs (1 before enemy #1)
+ add a,a ;a=type*2
+ add a,a ;a=type*4
+ ld c,a ;c=type
+ ld b,0 ;bc = enemy nr.&&&XX
+ add hl,bc ;hl = enemy specs
+ ld a,(hl) ;load hitpoints+occ of this enemy class
+ ld (de),a ;save occ
+
+ inc hl ;next enemyInfo byte
+ dec de ;goto hp
+ ld a,(hl) ;load hp64
+ ld (de),a ;save hp64
+ inc de ;next byte (or previous): occ again
+
+ inc hl ;next enemyInfo byte
+ inc de ;next byte of current enemy
+ ld a,(hl) ;load enemy class (nr)
+ ld (de),a ;save enemy type
+
+ inc de ;set x-pos
+ psh de
+ cal find_sprite
+ pop de
+ ld a,128 ;appear at right edge of screen
+ sub (ix) ;minus the width of this enemy (not offscreen)
+ ld (de),a ;= x-position (save)
+
+ inc de ;set y-pos
+ inc hl ;where to place??
+ ld a,(hl) ;load placeInfo
+ dec a ;is it 1?
+ jr z,random_enemy ;yes: create random value <51 in a
+ dec a ;is it 2?
+ jr z,lure_enemy ;yes: create a 100% luring enemy
+ ;otherwise?
+halflure_enemy: ;yes (of course it is): pick one (50% lure)
+ ld a,(timer) ;look at frame-number
+ and %00000001 ;make random if odd frame nr.
+ jr nz,random_enemy ;1st possibility: random enemy
+lure_enemy: ;2nd possibility: luring enemy
+ ld a,(y) ;place at same y-pos as YOUR ship
+ jr ypos_OK
+
+random_enemy:
+ ld b,e ;b will be added to random-value
+ cal Random50 ;make a (in a) random value 0-51
+
+ypos_OK: ;random value successfully created
+ ld (de),a ;save y-position
+
+ inc de ;set move
+ ld a,1 ;movecounter = 1
+ ld (de),a ;&&&(hl),1 better?
+
+ inc de ;set fire
+ ld a,(level_info)
+ and %00000001 ;bit meaning directfire
+ jr nz,ffireOK ;(a=time-to-fire) = 1 frame (fires directly)
+ ld a,(level_fire) ;set ttf to normal nr of frames
+ffireOK:ld (de),a ;save fire
+ ret ;return
+
+;--------------------------- enemy fires --------------------------------------
+
+Enemy_fires: ;de = x,y
+ dec d
+ dec d ;d = x-2
+ inc e ;e = y+1
+
+ ld b,nrebuls
+ ld hl,ebullets
+find_ebullet:
+ ld a,(hl)
+ or a
+ jr z,found_ebullet ;0 = not used
+ inc hl \ inc hl \ inc hl
+ dnz find_ebullet ;look next bullet
+ ret
+
+found_ebullet:
+ ld b,%1100
+ ld a,(level_info)
+ and %00001000
+ jr z,bulletok
+
+ ld a,(y)
+ sub e
+ add a,10
+ jp p,bulletnotup
+ ld b,%1011 ;yourY-bulY = negative (=bullet below you)
+ add a,10
+ jp p,bulletnotup
+ ld b,%1001 ;yourY-bulY = even more negative (going up)
+
+bulletnotup:
+ sub 20
+ jp m,bulletok
+ ld b,%1010 ;bullet going down
+ sub 10
+ jp m,bulletok ;even more going down
+ ld b,%1000
+
+bulletok:
+ ld a,(level_info)
+ and %11110000
+ or b
+ ld (hl),a ;set bullet direction
+ inc hl
+ ld (hl),d ;set x-pos
+ inc hl
+ ld (hl),e ;set y-pos
+ ret
+
+;----------------------------- enemy bullets ----------------------------------
+
+Enemy_bullets:
+ ld hl,ebullets
+ ld b,nrebuls
+handle_bullet:
+ psh bc
+ psh hl
+ ld a,(hl) ;load bulletType in a
+ and %1111 ;select direction-bits
+ jr nz,enemy_bullet ;non-0: handle bullet
+next_bullet:
+ pop hl ;do not move the <pop hl>
+ pop bc
+ inc hl \ inc hl \ inc hl
+ dnz handle_bullet
+ ret
+
+enemy_bullet:
+ ld b,a ;save type&%1111
+ inc hl ;bullet x
+ ld a,(hl) ;check if it has reached the left side of scrn
+ and %11111110 ;it is <2 (0 or 1)?
+ jr z,remove_ebullet ;yes, remove bullet
+ dec (hl) ;move one left
+ dec (hl) ;and another one
+ ld d,(hl) ;d=x
+ inc hl ;@y
+
+ ld a,b ;restore type
+ cp %1100 ;is it a normal bullet? (cp = faster than bit)
+ jr z,ebullet_common ;type %1100: normal bullet
+ and %111 ;isolate important bits
+ jr z,ebullet_down ;type %1000: moving down
+ dec a
+ jr z,ebullet_up ;type %1001: moving up
+ ld b,a
+
+ ld a,(timer)
+ rra
+ jr c,ebullet_common
+
+ ld a,b
+ dec a
+ jr z,ebullet_down ;type %1010: moving down 50%
+ ;type %1011: moving up 50%
+ebullet_up:
+ ld a,(hl)
+ dec a
+ jp m,ebullet_common
+ ld (hl),a
+ jr ebullet_common
+
+ebullet_down:
+ ld a,(hl)
+ inc a
+ cp 55
+ jr z,ebullet_common
+ ld (hl),a
+
+ebullet_common:
+ ld e,(hl) ;e=y
+ ld ix,spr_bullete1 ;display enemy bullet
+ cal putsprite
+
+ebullet_hits:
+ ld a,(your_occ)
+ or a
+ jr nz,next_bullet ;0 = you're normal
+
+ pop hl
+ psh hl
+ inc hl ;check x
+ ld a,(x)
+ sub (hl)
+ add a,6
+ jp m,next_bullet
+ cp 9
+ jr nc,next_bullet
+
+ inc hl ;check y
+ ld a,(y)
+ sub (hl)
+ add a,6
+ jp m,next_bullet
+ cp 9
+ jr nc,next_bullet
+
+ pop hl ;points to bullettype again
+ psh hl ;and save it again (ivm call to damage_you)
+ ld a,(hl) ;load bullettype
+ cal _shracc ;isolate damage-bits (%1111???? -> %00001111)
+ ld b,a ;set damage-amount
+ cal damage_you ;HIT!!
+remove_ebullet:
+ pop hl ;hl could be destroyed by damage_you
+ ld (hl),0 ;bullet > unused
+ jr next_bullet+1 ;next bullet (SKIP THE <POP HL> = one byte)
+
+;--------------------------- handle enemies -----------------------------------
+
+Handle_enemies:
+ ld hl,enemies+1
+ ld b,nrenemies ;handle all enemies
+
+handle_enemy:
+ psh bc
+ psh hl
+
+ ld a,(hl)
+ and %00000011
+ jr z,next_enemy ;occ "no enemy" 0
+ dec a
+ jr z,exploding_enemy ;occ "exploding" 1
+ ld b,a ;b=2 if moving, otherwise b=1
+
+normal_enemy: ;occ "normal" 2 or "moving" 3
+ inc hl
+ ld c,(hl) ;c = enemy type = de
+ cal find_sprite
+
+ inc hl
+ ld a,(hl) ;x
+ dec a ;move left
+ jr c,remove_enemy ;off screen
+ jr z,remove_enemy ;"
+ ld d,a
+
+ inc hl
+ ld e,(hl) ;y
+ ld a,b ;moving state was stored in b earlier
+ dec a ;is it 1?
+ cal nz,moving_enemy ;2 = moving enemy
+
+ ld (hl),e
+ dec hl ;@x
+ ld (hl),d ;store new x
+ ld a,c ;a = enemy type
+ or a ;type 0? (pickup)
+ jr nz,check_enemyfire ;no, a normal enemy; let em fire
+ ld a,(timer) ;load time
+ and %1 ;move left once every 2 turns
+ jr z,firing_done ;don't move now
+ inc d ;increase x-position (don't move this turn)
+ inc (hl) ;and save it
+ jr firing_done ;continue
+
+check_enemyfire:
+ inc hl ;go to <y>
+ inc hl ;go to <move>
+ inc hl ;go to <fire>
+ dec (hl) ;decrease counter till next blast
+ ld a,(hl) ;&&&doesn't seem efficient to me
+ or a ;has it reached zero?
+ jr nz,firing_done ;finished if not
+
+ ld a,(level_fire) ;re-set counter for next blast
+ ld (hl),a ;save time to fire
+ inc hl ;next byte = bullettype &&&
+ psh de ;save registers for firing-use
+ cal Enemy_fires ;fires bullet
+ pop de ;restore (destroyed by Enemy_fires)
+firing_done:
+ cal putwidesprite ;display sprite @ix
+
+next_enemy:
+ pop hl
+ ld bc,enemysize
+ add hl,bc
+ pop bc
+ dnz handle_enemy
+ ret
+
+remove_enemy:
+ pop hl
+ ld (hl),$0000 ;bye bye enemy
+ jr next_enemy+1 ;continue AFTER pop hl (already done)
+
+exploding_enemy:
+ inc hl
+ psh hl
+ ld a,(hl)
+ cal explosion_stuff ;display explosion
+ pop hl
+
+ ld a,(hl)
+ cp 15
+ jr z,remove_enemy ;remove when at last frame
+ inc a
+ ld (hl),a ;next frame
+ jr next_enemy
+
+;--------------------------- moving enemies -----------------------------------
+
+moving_enemy:
+ ld a,(level_move)
+ and a
+ jr z,movetype_updown ;type 0
+ dec a
+ jr z,movetype_vslow ;1
+ dec a
+ jr z,movetype_fast ;2
+ dec a
+ jr z,movetype_vfast ;3
+ dec a
+ jr z,movetype_smart ;4
+ dec a
+ jr z,movetype_lure ;5
+ dec a
+ jr z,movetype_slowlure ;6
+ dec a
+ jr z,movetype_stoplure ;7
+; dec a
+; jr z,movetype_fulllure ;8
+
+movetype_fulllure:
+ inc d
+ ld a,(timer)
+ and 1
+ ret z
+ cal movetype_lure
+ ld a,(x)
+ cp d
+ jr c,lure_left
+lure_right:
+ inc d
+ ret
+lure_left:
+ dec d
+ ret
+
+movetype_stoplure:
+ inc d
+ jr movetype_slowlure
+
+movetype_slowlure:
+ ld a,(timer)
+ and 1
+ ret z
+
+movetype_lure:
+ ld a,(y)
+ cp e
+ jr c,lure_up
+lure_down:
+ inc e
+ ret
+lure_up:
+ dec e
+ ret
+
+movetype_smart:
+ inc hl ;hl =@ <move>
+ ld a,(timer)
+ and %1111 ; |
+ ld a,(hl) ;&&& \|/
+ jr nz,smartupdate
+ inc a
+smartupdate:
+ ld (hl),a
+
+ or a ;reset carry flag
+ dec hl ;reset hl to <y>
+ and %11111100
+ jr z,movetype_fast
+
+movetype_vslow:
+ ld a,(timer)
+ and %11
+ ret z
+ inc d
+ ret
+
+movetype_fast:
+ ld a,(timer)
+ and %1
+ ret z
+movetype_vfast:
+ dec d ;move left
+ ret nz ;finished
+ pop hl ;restore stack (no ret used)
+ jp remove_enemy ;remove this enemy (off screen)
+
+movetype_updown:
+ inc hl ;@ <move>
+ ld a,(hl)
+ dec a
+ jr nz,move_updated
+ add a,128
+move_updated:
+ ld (hl),a
+
+ or a ;reset carry flag
+ dec hl ;@ <y>
+ and %00100000
+ ld a,(hl);&&&ld a,e ;load current y-position
+ jr z,movedown
+
+moveup: dec a ;decrease y-pos (=move up)
+ ret m ;don't move off the screen (y<0)
+ dec e ;save new y-pos
+ ret ;finish
+movedown:
+ inc a ;increase y-pos
+ cp 55 ;compare with bottom
+ ret nc ;return if it has passed that line (>40)
+ inc e ;otherwise save new position
+ ret ;and return
+
+;--------------------------- check collision ----------------------------------
+
+Enemies_hit:
+ ld hl,(x) ;e = X, d = Y
+ ld de,$0707 ;add 7 to both d and e
+ add hl,de
+ ld d,h
+ ld e,l ;e = X+7, d = Y+7
+
+ ld hl,enemies+1
+ ld b,nrenemies ;check all 20 enemies
+check_collision:
+ psh hl
+ ld a,(hl)
+ and %00000010
+ jr z,check_next ;2 or 3 = ok
+ inc hl
+
+collide_enemy: ;&&& include in Handle_enemy proc
+ psh de
+ cal find_sprite
+ pop de
+
+ inc hl
+ ld a,(hl) ;check x match
+ sub e ;enemy position minus yours minus 7
+ jp p,check_next
+ add a,6
+ add a,(ix)
+ jp m,check_next
+
+ inc hl
+ ld a,(hl) ;check y match
+ sub d ;same as with x-check
+ jp p,check_next
+ add a,6
+ add a,(ix+1)
+ jp m,check_next
+ dec hl
+ dec hl
+
+take_pickup:
+ psh hl ;we need hl
+ ld hl,2 ;increase score by 2
+ cal scoreInc
+ pop hl ;we're done
+
+ ld a,(hl) ;load enemy type
+ or a
+ jr nz,collide ;enemy when <>0
+
+ psh hl
+ ld hl,your_pickup ;your pickups
+ ld a,(hl) ;current
+ inc a ;go to next
+ cp 6 ;pickups >=6
+ jr c,not_maxpickup
+ ld a,1 ;yes: reset to pickup 1
+not_maxpickup:
+ ld (hl),a ;save new
+ cal disp_icons ;display altered pickupicons