C64_Superchase/inc_monster.bas

182 lines
6.2 KiB
QBasic

Const MASK_SUBGROUP = 8 '0000 1000
Const MASK_WALK_LOWHALF = 24 '0001 1000
Dim SHARED bMonster_Col as BYTE
Dim SHARED bMonster_Row as BYTE
Dim bMonster_Direction as BYTE
Dim bMonster_Lag as BYTE
Dim bMonster_PreviousTile as BYTE
Dim SHARED bMonster_SpeedUpMode as BYTE
Dim bMonster_MarkingMode as BYTE
Dim bMonster_DelayFrame as BYTE
Dim bMonster_Distance_TurnONSpeedUp as BYTE
Dim bMonster_Distance_TurnOFFSpeedUp as BYTE
Dim bManhattanDistance as BYTE
declare sub monsterMovement() STATIC
sub initMonster() SHARED STATIC
bMonsterIsOn = FALSE
if bSkillLevel < 8 then
bTreasuresToActivateMonster = 8 - bSkillLevel
end if
bMonster_Col = 1
bMonster_Row = 1
bMonster_Direction = EAST
bMonster_Lag = 10
bMonster_PreviousTile = SPACE
bMonster_SpeedUpMode = FALSE
bMonster_MarkingMode = FALSE
if bSkillLevel < 16 then
bMonster_Distance_TurnONSpeedUp = 21 - bSkillLevel 'minimum: 6
bMonster_Distance_TurnOFFSpeedUp = 12 - shr(bSkillLevel, 1) 'minimum: 5
end if
bMonster_DelayFrame = 9 '= Lag - 1
VOICE 2 OFF TONE 256 WAVE NOISE ADSR 0, 0, VOI2_S, VOI2_R 'monster sound
end sub
sub handleMonster() SHARED STATIC
Dim bMoveFrame as BYTE
bManhattanDistance = myByteABS(bPlayer_Row - bMonster_Row) + myByteABS(bPlayer_Col - bMonster_Col)
if bManhattanDistance > bMonster_Distance_TurnONSpeedUp then
bMonster_SpeedUpMode = TRUE
else
if bManhattanDistance < bMonster_Distance_TurnOFFSpeedUp then
if bMonster_SpeedUpMode then
if bMonster_Lag > 1 then
bMonster_Lag = bMonster_Lag - 1
textat 33, 20, 11 - bMonster_Lag, 2 'red
end if
bMonster_SpeedUpMode = FALSE
VOICE 2 TONE 256 ADSR 0, 0, VOI2_S, VOI2_R
end if
end if
end if
if bMonster_SpeedUpMode then
VOICE 2 TONE shl(cword(bManhattanDistance), 8) ADSR 0, 0, 2, VOI2_R
call monsterMovement()
exit sub
end if
if bMonster_DelayFrame then
bMonster_DelayFrame = bMonster_DelayFrame - 1
if bMonster_DelayFrame = 0 then bMoveFrame = bSkillLevel
else
call monsterMovement()
if bMoveFrame then bMoveFrame = bMoveFrame - 1
if bMoveFrame = 0 then bMonster_DelayFrame = bMonster_Lag - 1
end if
end sub
sub monsterMovement() STATIC
Const MINUS_ONE = 255
Dim wPeekingLocation as WORD
Dim bMonster_PreviousColour as BYTE
Dim bTravelingDirection as BYTE
Dim bThisTileDistance as BYTE
Dim bClosestDistance as BYTE
Dim bThisTileRow as BYTE
Dim bThisTileCol as BYTE
Dim bClosestTileDirection as BYTE
Dim bPeekedDirection as BYTE FAST
Dim bWalkableDirections(4) as BYTE '0...3
Dim bWalkableDirections_Count as BYTE FAST
Dim bTrailDirections(4) as BYTE '0...3
Dim bTrailDirections_Count as BYTE FAST
'------------------------------------------------
wPeekingLocation = scrAddrCache(bMonster_Row) + bMonster_Col
bTravelingDirection = bMonster_Direction
bWalkableDirections_Count = MINUS_ONE
bTrailDirections_Count = MINUS_ONE
bClosestDistance = 255
bMonster_Direction = (bMonster_Direction - 1) AND 3 'starting from the Monster's right (going clockwise)
For bPeekedDirection = 1 to 4
bPeekedTileContent = peek(wPeekingLocation + iDirections(bMonster_Direction))
if (bPeekedTileContent AND MASK_ALL) = GROUP_CREATURES then bExitEvent = EVENT_PLAYER_CAUGHT : exit for 'Gotcha, Player!!
if (bPeekedTileContent AND MASK_WALK_LOWHALF) = GROUP_WALKABLE then
if bPeekedTileContent = TRAIL then
bWalkableDirections_Count = bWalkableDirections_Count + 1
bTrailDirections_Count = bTrailDirections_Count + 1
bTrailDirections(bTrailDirections_Count) = bMonster_Direction
else
if bPeekedDirection < 4 then 'ignoring the opposite travelled direction!
bWalkableDirections_Count = bWalkableDirections_Count + 1
bWalkableDirections(bWalkableDirections_Count) = bMonster_Direction
'ALSO, find the closest tile to the player...
bThisTileRow = bMonster_Row : bThisTileCol = bMonster_Col
if (bMonster_Direction AND 1) then 'odd number, vertical direction
bThisTileRow = bMonster_Row + cbyte(SGN(iDirections(bMonster_Direction)))
else 'even number, horizontal direction
bThisTileCol = bMonster_Col + cbyte(iDirections(bMonster_Direction))
end if
bThisTileDistance = myByteABS(bPlayer_Row - bThisTileRow) + myByteABS(bPlayer_Col - bThisTileCol)
if bThisTileDistance < bClosestDistance then
bClosestDistance = bThisTileDistance
bClosestTileDirection = bMonster_Direction
end if
end if
end if
end if
bMonster_Direction = (bMonster_Direction + 1) AND 3 'now going counter-clockwise
next bPeekedDirection
if bExitEvent = EVENT_NONE then
if bTrailDirections_Count <> MINUS_ONE then
bMonster_Direction = bTrailDirections(myRandom(bTrailDirections_Count, 3))
else
if bWalkableDirections_Count = MINUS_ONE then
bMonster_Direction = (bTravelingDirection + 2) AND 3 'go to the opposite direction and start marking tiles
bMonster_MarkingMode = TRUE
else
if bWalkableDirections_Count = 2 then 'if there are *three* walkable tiles...
bWalkableDirections_Count = bWalkableDirections_Count + 1
bWalkableDirections(bWalkableDirections_Count) = bClosestTileDirection
end if
bMonster_Direction = bWalkableDirections(myRandom(bWalkableDirections_Count, 3))
end if
end if
if bWalkableDirections_Count AND (bWalkableDirections_Count <> MINUS_ONE) then bMonster_MarkingMode = FALSE 'if there are at least *two* walkable tiles...
end if
'------------------------DRAW-------------------------------------------
if (bMonster_PreviousTile AND MASK_ALL) <> GROUP_TREASURE then
bMonster_PreviousTile = SPACE
end if
if bMonster_MarkingMode then
bMonster_PreviousTile = bMonster_PreviousTile OR MASK_SUBGROUP
end if
charat bMonster_Col, bMonster_Row, bMonster_PreviousTile, bMonster_PreviousColour
bMonster_PreviousTile = peek(wPeekingLocation + iDirections(bMonster_Direction))
bMonster_PreviousColour = peek(VIC_COLOR_OFFSET + wPeekingLocation + iDirections(bMonster_Direction))
if (bMonster_Direction AND 1) then 'odd number, vertical direction
bMonster_Row = bMonster_Row + cbyte(SGN(iDirections(bMonster_Direction)))
else 'even number, horizontal direction
bMonster_Col = bMonster_Col + cbyte(iDirections(bMonster_Direction))
end if
charat bMonster_Col, bMonster_Row, MONSTER, 2 'red
VOICE 2 ON
end sub