Nothing really new this time, just constant use of existing parts. A new enemy, some sort of mummy, which slowly walks back and forth. And takes a few more hits than the bats.
It's a new behaviour added to the table and some extra code that checks for gaps before walking.
Adding the enemy itself is nothing more than adding new entries to the existing tables
;object type constants
TYPE_PLAYER = 1
TYPE_BAT_LR = 2
TYPE_BAT_UD = 3
TYPE_BAT_8 = 4
TYPE_MUMMY = 5
ENEMY_BEHAVIOUR_TABLE_LO
!byte <PlayerControl
!byte <BehaviourBatLR
!byte <BehaviourBatUD
!byte <BehaviourBat8
!byte <BehaviourMummy
ENEMY_BEHAVIOUR_TABLE_HI
!byte >PlayerControl
!byte >BehaviourBatLR
!byte >BehaviourBatUD
!byte >BehaviourBat8
!byte >BehaviourMummy
IS_TYPE_ENEMY
!byte 0 ;dummy entry for inactive object
!byte 0 ;player
!byte 1 ;bat_lr
!byte 1 ;bat_ud
!byte 1 ;bat 8
!byte 1 ;mummy
TYPE_START_SPRITE
!byte 0 ;dummy entry for inactive object
!byte SPRITE_PLAYER_STAND_R
!byte SPRITE_BAT_1
!byte SPRITE_BAT_1
!byte SPRITE_BAT_2
!byte SPRITE_MUMMY_R_1
TYPE_START_COLOR
!byte 0
!byte 10
!byte 3
!byte 3
!byte 8
!byte 1
TYPE_START_MULTICOLOR
!byte 0
!byte 1
!byte 0
!byte 0
!byte 0
!byte 0
TYPE_START_HP
!byte 0
!byte 1
!byte 5
!byte 5
!byte 5
!byte 10
The behaviour code looks quite simple, as most of the new code is inside subroutines ObjectWalkLeft/ObjectWalkRight.
;------------------------------------------------------------
;simply walk left/right, do not fall off
;------------------------------------------------------------
!zone BehaviourMummy
BehaviourMummy
lda DELAYED_GENERIC_COUNTER
and #$3beq .MovementUpdate
rts
.MovementUpdate
inc SPRITE_MOVE_POS,x
lda SPRITE_MOVE_POS,x
and #$7
sta SPRITE_MOVE_POS,x
cmp #4bpl .CanMove
rts
.CanMove
lda SPRITE_DIRECTION,x
beq .MoveRight
;move left
jsr ObjectWalkLeft
beq .ToggleDirection
rts
.MoveRight
jsr ObjectWalkRight
beq .ToggleDirection
rts
.ToggleDirection
lda SPRITE_DIRECTION,x
eor #1
sta SPRITE_DIRECTION,x
rts
The new subroutines are a more complex version of ObjectMoveLeft/ObjectMoveRight. They add a new check, so the enemy only walks forward, if it's not blocked and there is no gap in the floor in front:
;------------------------------------------------------------
;walk object right if not blocked, do not fall off
;x = object index
;------------------------------------------------------------
!zone ObjectWalkRight
ObjectWalkRight
lda SPRITE_CHAR_POS_X_DELTA,x
beq .CheckCanMoveRight
.CanMoveRight
inc SPRITE_CHAR_POS_X_DELTA,x
lda SPRITE_CHAR_POS_X_DELTA,x
cmp #8bne .NoCharStep
lda #0
sta SPRITE_CHAR_POS_X_DELTA,x
inc SPRITE_CHAR_POS_X,x
.NoCharStep
jsr MoveSpriteRight
lda #1
rts
.CheckCanMoveRight
ldy SPRITE_CHAR_POS_Y,x
iny
lda SCREEN_LINE_OFFSET_TABLE_LO,y
sta ZEROPAGE_POINTER_1
lda SCREEN_BACK_LINE_OFFSET_TABLE_HI,y
sta ZEROPAGE_POINTER_1 + 1
ldy SPRITE_CHAR_POS_X,x
iny
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlockingFall
beq .BlockedRight
ldy SPRITE_CHAR_POS_Y,x
dey
lda SCREEN_LINE_OFFSET_TABLE_LO,y
sta ZEROPAGE_POINTER_1
lda SCREEN_BACK_LINE_OFFSET_TABLE_HI,y
sta ZEROPAGE_POINTER_1 + 1
ldy SPRITE_CHAR_POS_X,x
iny
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedRight
tya
clc
adc #40
tay
lda (ZEROPAGE_POINTER_1),y
jsr IsCharBlocking
bne .BlockedRight
jmp .CanMoveRight
.BlockedRight
lda #0
rts