808 lines
27 KiB
QBasic
808 lines
27 KiB
QBasic
|
'***********************************************************************
|
||
|
'** SUPERCHASE **
|
||
|
'** REMIX! **
|
||
|
'** **
|
||
|
'** 3 different versions of the same game into one program! **
|
||
|
'** **
|
||
|
'** - Original VIC-20 version by Anthony Godshall - October 1982 **
|
||
|
'** - Atari version by someone @ Compute! Gazette **
|
||
|
'** - TI-99 4/A version by Cheryl Regena **
|
||
|
'** **
|
||
|
'** Written in XC-BASIC 3.0.8 by @JJFlash@mastodon.social - Sep 2022 **
|
||
|
'** XC-BASIC created by Csaba Fekete! - https://xc-basic.net/ **
|
||
|
'** **
|
||
|
'** WORK IN PROGRESS!! **
|
||
|
'***********************************************************************
|
||
|
|
||
|
|
||
|
'--------------INITIAL-SETUP--------------------------------------------
|
||
|
Dim scrAddrCache(25) as WORD @loc_scrAddrCache ' 0 -> 24
|
||
|
loc_scrAddrCache:
|
||
|
DATA AS WORD 1024, 1064, 1104, 1144, 1184, 1224, 1264, 1304, 1344, 1384
|
||
|
DATA AS WORD 1424, 1464, 1504, 1544, 1584, 1624, 1664, 1704, 1744, 1784
|
||
|
DATA AS WORD 1824, 1864, 1904, 1944, 1984
|
||
|
|
||
|
poke 53280, 0 : poke 53281, 0
|
||
|
|
||
|
memcpy @LOC_charset_addr, $3800, 1024
|
||
|
poke $D018, 31 'final character location: $3800
|
||
|
poke 657, 128 'disable upper-lower case change
|
||
|
Dim wStack(128) as WORD @LOC_charset_addr 'recycling the charset data already copied to the final location!
|
||
|
'-----------------------------------------------------------------------
|
||
|
|
||
|
'-------------CONSTANTS-------------------------------------------------
|
||
|
Const TRUE = 255
|
||
|
Const FALSE = 0
|
||
|
Const INIT = 255
|
||
|
Const GO_ON = 0
|
||
|
|
||
|
Const SPACE = 88
|
||
|
Const MARKED_SPACE = 89
|
||
|
Const WALL = 96
|
||
|
Const EX_WALL = 98
|
||
|
Const DOOR_CLOSED = 97
|
||
|
Const DOOR_CLOSED_REVERSED = 101
|
||
|
Const DOOR_OPEN = 99
|
||
|
Const DOOR_OPEN_REVERSED = 103
|
||
|
|
||
|
Const PLAYER = 64
|
||
|
Const PLAYER_LEFT = 66
|
||
|
Const MONSTER = 68
|
||
|
Const MONSTER_ALT = 69
|
||
|
Const TRAIL = 80
|
||
|
Const TREASURES = 112
|
||
|
Const TREASURE_GOLD = 116
|
||
|
|
||
|
Const EAST = 0
|
||
|
Const NORTH = 1
|
||
|
Const WEST = 2
|
||
|
Const SOUTH = 3
|
||
|
|
||
|
Const MASK_WALKABLE = 16 '0001 0000
|
||
|
Const MASK_ALL = 48 '0011 0000
|
||
|
Const MASK_SUBGROUP = 8 '0000 1000
|
||
|
Const MASK_ALL_SUBGROUP = 56 '0011 1000
|
||
|
Const MASK_TILE = 7 '0000 0111
|
||
|
|
||
|
Const GROUP_CREATURES = 0 '0000 0000
|
||
|
Const GROUP_WALKABLE = 16 '0001 0000
|
||
|
'~ Const GROUP_WALLS = 32 '0010 0000
|
||
|
Const GROUP_TREASURE = 48 '0011 0000
|
||
|
Const SUBGROUP_TREASURE = 56 '0011 1000
|
||
|
|
||
|
Const VIC_COLOR_OFFSET = $D400
|
||
|
'-----------------------------------------------------------------------
|
||
|
|
||
|
'--------------GAME-STATE-&-GLOBAL-STUFF--------------------------------
|
||
|
Dim bPeekedTileContent as BYTE
|
||
|
|
||
|
Dim bFrameCounter as BYTE
|
||
|
Dim bAnimFrameCounter as BYTE
|
||
|
|
||
|
Dim iDirections(4) as INT @loc_iDirections
|
||
|
loc_iDirections:
|
||
|
DATA as INT 1, -40, -1, 40 'east, north, west, south
|
||
|
|
||
|
Dim bPlayer_Col as BYTE
|
||
|
Dim bPlayer_Row as BYTE
|
||
|
Dim bPlayer_FacingCharacter as BYTE
|
||
|
|
||
|
Dim bMonsterIsOn as BYTE
|
||
|
Dim bMonster_Col as BYTE
|
||
|
Dim bMonster_Row as BYTE
|
||
|
Dim bMonster_Direction as BYTE
|
||
|
Dim bMonster_Lag as BYTE
|
||
|
Dim bMonster_PreviousTile as BYTE
|
||
|
Dim bMonster_SpeedUpMode as BYTE
|
||
|
Dim bMonster_DelayFrame as BYTE
|
||
|
Dim bMonster_Distance_TurnONSpeedUp as BYTE
|
||
|
Dim bMonster_Distance_TurnOFFSpeedUp as BYTE
|
||
|
|
||
|
Dim bTreasuresToActivateMonster as BYTE
|
||
|
|
||
|
Dim bManhattanDistance as BYTE
|
||
|
|
||
|
Dim wDoorAddress as WORD
|
||
|
Dim wGoldColorAddress as WORD
|
||
|
|
||
|
Dim bSkillLevel as BYTE : bSkillLevel = 1
|
||
|
Dim wScore as WORD
|
||
|
Dim wLastExitScore as WORD : wLastExitScore = 0
|
||
|
Dim bTreasures_Quantity as BYTE
|
||
|
Dim bTreasuresCollected as BYTE
|
||
|
Dim bTreasuresToOpenDoor as BYTE
|
||
|
Dim bGoldNotCollected as BYTE
|
||
|
Dim bPlayerExited as BYTE
|
||
|
Dim bPlayerCaught as BYTE
|
||
|
|
||
|
declare sub generateMaze () STATIC
|
||
|
declare sub placeDoor() STATIC
|
||
|
declare sub playerMovement() STATIC
|
||
|
declare sub initMonster() STATIC
|
||
|
declare sub handleMonster() STATIC
|
||
|
declare sub monsterMovement() STATIC
|
||
|
declare sub drawInfoBox() STATIC
|
||
|
declare sub shakeScreen() STATIC
|
||
|
declare sub mazeShiftAway() STATIC
|
||
|
declare sub openDoorAnimation() STATIC
|
||
|
declare sub goldFlashAnimation(bInitAnim as BYTE) STATIC
|
||
|
declare sub titleScreen() STATIC
|
||
|
'-----------------------------------------------------------------------
|
||
|
|
||
|
'------------------HELPER FUNCTIONS-------------------------------------
|
||
|
function myRandom as BYTE (bMax as BYTE, bMask as BYTE) STATIC
|
||
|
do
|
||
|
myRandom = RNDB() AND bMask
|
||
|
loop while myRandom > bMax
|
||
|
end function
|
||
|
|
||
|
function myByteABS as BYTE (bNumber as BYTE) STATIC
|
||
|
if (bNumber AND 128) = 128 then bNumber = (NOT bNumber) + 1
|
||
|
return bNumber
|
||
|
end function
|
||
|
|
||
|
|
||
|
'------------------TITLE SCREEN-----------------------------------------
|
||
|
sys $E544 FAST ' clear screen
|
||
|
call titleScreen()
|
||
|
|
||
|
'------------------LEVEL-START------------------------------------------
|
||
|
|
||
|
'~ Dim lRandomSeed as LONG : lRandomSeed = clong(248) ' <<<<<<<<<<<<<<<------------- RANDOM!!!
|
||
|
|
||
|
sys $E544 FAST ' clear screen
|
||
|
textat 32, 0, "super", 1 'white
|
||
|
textat 33, 1, "chase!", 1 'white
|
||
|
textat 32, 7, "skill", 5 'green
|
||
|
textat 33, 8, "level", 5 'green
|
||
|
textat 32, 13, "score", 3 'cyan
|
||
|
textat 32, 18, "speed", 7 'yellow
|
||
|
|
||
|
Randomize (TI() * (clong(peek( $D012)) + clong(1)))
|
||
|
|
||
|
redraw:
|
||
|
For N as BYTE = 0 to 24
|
||
|
memset scrAddrCache(N), 31, WALL
|
||
|
memset VIC_COLOR_OFFSET + scrAddrCache(N), 31, 6 'blue
|
||
|
Next N
|
||
|
|
||
|
'~ lRandomSeed = lRandomSeed + clong(1)
|
||
|
'~ textat 33, 23, str$(lRandomSeed), 14 'light blue
|
||
|
'~ Randomize (lRandomSeed)
|
||
|
|
||
|
For N as BYTE = 1 to 10 : bPeekedTileContent = RNDB() : Next N ' bPeekedTileContent used here as a dummy variable!
|
||
|
|
||
|
call generateMaze()
|
||
|
'~ textat 33, 24, str$(bTreasures_Quantity), 7 'yellow
|
||
|
call placeDoor()
|
||
|
|
||
|
bFrameCounter = 0
|
||
|
|
||
|
bPlayer_Col = 1
|
||
|
bPlayer_Row = 1
|
||
|
bPlayer_FacingCharacter = PLAYER
|
||
|
|
||
|
call initMonster()
|
||
|
|
||
|
wScore = wLastExitScore
|
||
|
bTreasuresCollected = 0
|
||
|
bPlayerExited = FALSE
|
||
|
bPlayerCaught = FALSE
|
||
|
|
||
|
textat 33, 10, str$(bSkillLevel), 1 'white
|
||
|
memset 1657, 5, 32 'erase previous printed score
|
||
|
textat 33, 15, str$(wScore), 10 'light red
|
||
|
textat 33, 20, "1 ", 2 'red
|
||
|
|
||
|
bTreasuresToOpenDoor = shr(bTreasures_Quantity, 1)
|
||
|
if bSkillLevel < bTreasuresToOpenDoor then
|
||
|
bTreasuresToOpenDoor = bTreasuresToOpenDoor + bSkillLevel
|
||
|
else
|
||
|
bTreasuresToOpenDoor = bTreasures_Quantity
|
||
|
end if
|
||
|
'~ textat 36, 24, str$(bTreasuresToOpenDoor), 12 'gray
|
||
|
|
||
|
'-------------------------MAIN LOOP!------------------------------------
|
||
|
do
|
||
|
on bFrameCounter goto actorMovement, endFrame, animation, endFrame
|
||
|
|
||
|
actorMovement:
|
||
|
'-------PLAYER MOVEMENT-----------------
|
||
|
call playerMovement()
|
||
|
if (bPlayerCaught OR bPlayerExited) then exit do
|
||
|
'~ textat 33, 22, str$(bTreasuresCollected) + " ", 15 ' light gray
|
||
|
|
||
|
'-------MONSTER MOVEMENT-----------------
|
||
|
if bMonsterIsOn then
|
||
|
call handleMonster()
|
||
|
if bPlayerCaught then exit do
|
||
|
else
|
||
|
if bTreasuresCollected = bTreasuresToActivateMonster then bMonsterIsOn = TRUE
|
||
|
end if
|
||
|
|
||
|
if NOT bGoldNotCollected then call goldFlashAnimation(GO_ON)
|
||
|
goto endFrame
|
||
|
'-------------------------------------------------------------------
|
||
|
|
||
|
animation:
|
||
|
if bGoldNotCollected then
|
||
|
poke wGoldColorAddress, peek(wGoldColorAddress) XOR 6 'alternates white, yellow, white, yellow, ...
|
||
|
else
|
||
|
call goldFlashAnimation(GO_ON)
|
||
|
end if
|
||
|
charat bPlayer_Col, bPlayer_Row, bPlayer_FacingCharacter XOR 1, 13 'light green
|
||
|
if bMonsterIsOn then
|
||
|
if bMonster_SpeedUpMode then
|
||
|
call handleMonster()
|
||
|
else
|
||
|
charat bMonster_Col, bMonster_Row, MONSTER_ALT, 2 'red
|
||
|
end if
|
||
|
end if
|
||
|
if bTreasuresCollected = bTreasuresToOpenDoor then call openDoorAnimation()
|
||
|
'-------------------------------------------------------------------
|
||
|
|
||
|
endFrame:
|
||
|
'~ if (peek ( $DC00) AND 16) = 0 then goto redraw
|
||
|
wait $d011, 128, 128 : wait $d011, 128 : wait $d011, 128, 128 : wait $d011, 128
|
||
|
bFrameCounter = (bFrameCounter + 1) AND 3
|
||
|
loop
|
||
|
|
||
|
if bPlayerCaught then
|
||
|
call shakeScreen()
|
||
|
call drawInfoBox()
|
||
|
textat 8, 12, "a tasty morsel", 8 'orange
|
||
|
textat 12, 13, "indeed!", 8 'orange
|
||
|
wScore = wLastExitScore
|
||
|
else
|
||
|
call drawInfoBox()
|
||
|
textat 8, 12, "congratulations!", 7 'yellow
|
||
|
textat 6, 13, "onto the next level!", 7 'yellow
|
||
|
wLastExitScore = wScore
|
||
|
if bSkillLevel < 255 then bSkillLevel = bSkillLevel + 1
|
||
|
end if
|
||
|
|
||
|
wait $DC00, 16, 16 'wait for fire to be pressed
|
||
|
if bPlayerExited then call mazeShiftAway()
|
||
|
goto redraw
|
||
|
|
||
|
'------------GAME-SUBROUTINES-------------------------------------------
|
||
|
sub generateMaze () STATIC
|
||
|
Dim bRow as BYTE
|
||
|
Dim bCol as BYTE
|
||
|
Dim bRowEnd as BYTE
|
||
|
Dim bColEnd as BYTE
|
||
|
|
||
|
memset 1065, 5, EX_WALL
|
||
|
poke 1105, EX_WALL
|
||
|
poke 1145, EX_WALL
|
||
|
poke 1185, EX_WALL
|
||
|
poke 1225, EX_WALL
|
||
|
|
||
|
For N as BYTE = 1 to 65
|
||
|
bCol = shl(myRandom(13, 15), 1) + 1
|
||
|
bRow = shl(myRandom(11, 15), 1) + 1
|
||
|
bColEnd = bCol + 6 : if bColEnd > 29 then bColEnd = 29
|
||
|
memset scrAddrCache(bRow) + bCol, bColEnd - bCol + 1, EX_WALL
|
||
|
Next N
|
||
|
|
||
|
For N as BYTE = 1 to 60
|
||
|
bCol = shl(myRandom(14, 15), 1) + 1
|
||
|
bRow = shl(myRandom(10, 15), 1) + 1
|
||
|
bRowEnd = bRow + 4 : if bRowEnd > 23 then bRowEnd = 23
|
||
|
For K AS BYTE = bRow to bRowEnd
|
||
|
poke scrAddrCache(K) + bCol, EX_WALL
|
||
|
Next K
|
||
|
Next N
|
||
|
|
||
|
Dim wCalcScreenAddress as WORD
|
||
|
Dim bStackPointer as BYTE
|
||
|
Dim wFilledCells as WORD
|
||
|
Dim wPatchScrAddress as WORD
|
||
|
|
||
|
bStackPointer = 1 : wFilledCells = 0
|
||
|
wStack(0) = 1065 'player starting position: Row 1, Column 1
|
||
|
wPatchScrAddress = 1226 'row 5, column 2
|
||
|
Const PATCHSCRADDRESS_END = 1253 'row 5, column 29
|
||
|
|
||
|
Dim bTreasures_Color(5) as BYTE @loc_bbTreasures_Color
|
||
|
loc_bbTreasures_Color:
|
||
|
DATA AS BYTE 12, 9, 10, 8, 7 'gray, brown, light red, orange, yellow
|
||
|
|
||
|
Dim bTreasures_Sequence(51) as BYTE @loc_bTreasures_Sequence
|
||
|
'26 treasure 0, 15 treasure 1, 12 treasure 2, 7 treasure 3, 1 treasure 4 (gold!)
|
||
|
loc_bTreasures_Sequence:
|
||
|
'0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||
|
'1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
|
||
|
'2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
|
||
|
'3, 3, 3, 3, 3, 3, 3
|
||
|
' 4
|
||
|
DATA AS BYTE 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 4
|
||
|
DATA AS BYTE 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 0, 1, 0, 1, 0
|
||
|
|
||
|
Dim bTreasures_Index as BYTE : bTreasures_Index = 0
|
||
|
Dim bTileType as BYTE
|
||
|
Dim bTileColor as BYTE
|
||
|
bTreasures_Quantity = 0
|
||
|
bGoldNotCollected = FALSE 'in the event the Gold treasure doesn't show up...
|
||
|
|
||
|
do
|
||
|
bStackPointer = bStackPointer - 1
|
||
|
wCalcScreenAddress = wStack(bStackPointer)
|
||
|
|
||
|
do while peek(wCalcScreenAddress) = EX_WALL
|
||
|
wCalcScreenAddress = wCalcScreenAddress - cword(1)
|
||
|
loop
|
||
|
wCalcScreenAddress = wCalcScreenAddress + cword(1)
|
||
|
|
||
|
do while peek(wCalcScreenAddress) = EX_WALL
|
||
|
bTileType = SPACE
|
||
|
if wFilledCells > 5 then
|
||
|
If myRandom(5, 7) = 5 then
|
||
|
bTileType = TREASURES + bTreasures_Sequence(bTreasures_Index)
|
||
|
bTileColor = bTreasures_Color(bTileType AND 7)
|
||
|
if bTreasures_Index < 50 then bTreasures_Index = bTreasures_Index + 1
|
||
|
bTreasures_Quantity = bTreasures_Quantity + 1
|
||
|
end if
|
||
|
end if
|
||
|
if bTileType = TREASURE_GOLD then wGoldColorAddress = VIC_COLOR_OFFSET + wCalcScreenAddress : bGoldNotCollected = TRUE
|
||
|
poke wCalcScreenAddress, bTileType : poke VIC_COLOR_OFFSET + wCalcScreenAddress, bTileColor
|
||
|
wFilledCells = wFilledCells + 1
|
||
|
|
||
|
wCalcScreenAddress = wCalcScreenAddress - cword(40) 'one row UP
|
||
|
if peek(wCalcScreenAddress) = EX_WALL then
|
||
|
wStack(bStackPointer) = wCalcScreenAddress
|
||
|
bStackPointer = bStackPointer + 1
|
||
|
end if
|
||
|
wCalcScreenAddress = wCalcScreenAddress + cword(80) 'back to the original row + one row DOWN
|
||
|
if peek(wCalcScreenAddress) = EX_WALL then
|
||
|
wStack(bStackPointer) = wCalcScreenAddress
|
||
|
bStackPointer = bStackPointer + 1
|
||
|
end if
|
||
|
|
||
|
wCalcScreenAddress = wCalcScreenAddress - cword(39) 'one row UP + one column RIGHT
|
||
|
loop
|
||
|
|
||
|
if bStackPointer = 0 then
|
||
|
if wFilledCells < 280 then
|
||
|
do until peek(wPatchScrAddress) = WALL
|
||
|
wPatchScrAddress = wPatchScrAddress + 1
|
||
|
if wPatchScrAddress > PATCHSCRADDRESS_END then exit sub
|
||
|
loop
|
||
|
poke wPatchScrAddress, EX_WALL
|
||
|
wStack(bStackPointer) = wPatchScrAddress
|
||
|
bStackPointer = 1
|
||
|
else
|
||
|
exit sub
|
||
|
end if
|
||
|
end if
|
||
|
loop
|
||
|
end sub
|
||
|
|
||
|
sub placeDoor() STATIC
|
||
|
wDoorAddress = $0586 'Col 30, Row 9
|
||
|
do
|
||
|
For bRowIncrement AS BYTE = 0 to 22 'row 9 -> 23 + 1 -> 8
|
||
|
if ((peek(wDoorAddress - cword(1)) AND MASK_WALKABLE) = GROUP_WALKABLE) then
|
||
|
poke wDoorAddress, DOOR_CLOSED
|
||
|
poke VIC_COLOR_OFFSET + wDoorAddress, 14 'light blue
|
||
|
exit sub
|
||
|
else
|
||
|
if bRowIncrement = 14 then
|
||
|
wDoorAddress = wDoorAddress - 880 'up 22 rows
|
||
|
else
|
||
|
wDoorAddress = wDoorAddress + cword(40) 'next row
|
||
|
end if
|
||
|
end if
|
||
|
Next bRowIncrement
|
||
|
|
||
|
'back to row 9? Try the previous column...
|
||
|
wDoorAddress = wDoorAddress - cword(1)
|
||
|
loop
|
||
|
end sub
|
||
|
|
||
|
sub playerMovement() STATIC
|
||
|
Dim wScoreTable(5) as WORD @loc_wScoreTable
|
||
|
loc_wScoreTable:
|
||
|
DATA AS WORD 10, 20, 30, 50, 500
|
||
|
|
||
|
Dim bJoystick2 as BYTE
|
||
|
bJoystick2 = peek ( $DC00) XOR 127
|
||
|
|
||
|
if (bJoystick2 AND 1) then
|
||
|
bJoystick2 = NORTH
|
||
|
else
|
||
|
if (bJoystick2 AND 2) then
|
||
|
bJoystick2 = SOUTH
|
||
|
else
|
||
|
if (bJoystick2 AND 4) then
|
||
|
bJoystick2 = WEST
|
||
|
bPlayer_FacingCharacter = PLAYER_LEFT
|
||
|
else
|
||
|
if (bJoystick2 AND 8) then
|
||
|
bJoystick2 = EAST
|
||
|
bPlayer_FacingCharacter = PLAYER
|
||
|
else
|
||
|
exit sub
|
||
|
end if
|
||
|
end if
|
||
|
end if
|
||
|
end if
|
||
|
|
||
|
bPeekedTileContent = peek(scrAddrCache(bPlayer_Row) + bPlayer_Col + iDirections(bJoystick2))
|
||
|
|
||
|
if (bPeekedTileContent AND MASK_ALL) = GROUP_CREATURES then 'Player bumped into Monster!
|
||
|
charat bPlayer_Col, bPlayer_Row, SPACE, 11 'dark grey
|
||
|
bPlayerCaught = TRUE : exit sub
|
||
|
end if
|
||
|
|
||
|
if ((bPeekedTileContent AND MASK_WALKABLE) = GROUP_WALKABLE) OR (bPeekedTileContent = DOOR_OPEN) then
|
||
|
charat bPlayer_Col, bPlayer_Row, TRAIL, 11 'dark grey
|
||
|
|
||
|
if (bJoystick2 AND 1) then 'odd number, vertical direction
|
||
|
bPlayer_Row = bPlayer_Row + cbyte(SGN(iDirections(bJoystick2)))
|
||
|
else 'even number, horizontal direction
|
||
|
bPlayer_Col = bPlayer_Col + cbyte(iDirections(bJoystick2))
|
||
|
end if
|
||
|
charat bPlayer_Col, bPlayer_Row, bPlayer_FacingCharacter, 13 'light green
|
||
|
|
||
|
if (bPeekedTileContent AND MASK_ALL) = GROUP_TREASURE Then
|
||
|
'~ poke 53280, (bPeekedTileContent AND MASK_TILE) + 1
|
||
|
'~ wait $d011, 128, 128 : wait $d011, 128 : wait $d011, 128, 128 : wait $d011, 128
|
||
|
'~ poke 53280, 0
|
||
|
bTreasuresCollected = bTreasuresCollected + 1
|
||
|
if (bPeekedTileContent AND 247) = TREASURE_GOLD then call goldFlashAnimation(INIT) 'both non-marked and marked!
|
||
|
wScore = wScore + wScoreTable ( (bPeekedTileContent AND MASK_TILE) )
|
||
|
textat 33, 15, str$(wScore), 10 'light red
|
||
|
else
|
||
|
if bPeekedTileContent = DOOR_OPEN then bPlayerExited = TRUE
|
||
|
end if
|
||
|
|
||
|
end if
|
||
|
end sub
|
||
|
|
||
|
sub initMonster() STATIC
|
||
|
bMonsterIsOn = FALSE
|
||
|
if bSkillLevel < 8 then
|
||
|
bTreasuresToActivateMonster = 8 - bSkillLevel
|
||
|
else
|
||
|
bTreasuresToActivateMonster = 1
|
||
|
end if
|
||
|
|
||
|
bMonster_Col = 1
|
||
|
bMonster_Row = 1
|
||
|
bMonster_Direction = EAST
|
||
|
bMonster_Lag = 10
|
||
|
bMonster_PreviousTile = SPACE
|
||
|
bMonster_SpeedUpMode = FALSE
|
||
|
if bSkillLevel < 14 then
|
||
|
bMonster_Distance_TurnONSpeedUp = 20 - bSkillLevel
|
||
|
bMonster_Distance_TurnOFFSpeedUp = 12 - shr(bSkillLevel, 1)
|
||
|
else
|
||
|
bMonster_Distance_TurnONSpeedUp = 7
|
||
|
bMonster_Distance_TurnOFFSpeedUp = 5
|
||
|
end if
|
||
|
|
||
|
bMonster_DelayFrame = 9 '= Lag - 1
|
||
|
|
||
|
'~ textat 33, 3, " "
|
||
|
'~ textat 33, 4, " "
|
||
|
'~ textat 33, 21, " "
|
||
|
end sub
|
||
|
|
||
|
sub handleMonster() STATIC
|
||
|
Dim bMoveFrame as BYTE
|
||
|
|
||
|
bManhattanDistance = myByteABS(bPlayer_Row - bMonster_Row) + myByteABS(bPlayer_Col - bMonster_Col)
|
||
|
'~ textat 33, 21, str$(bManhattanDistance) + " ", 11 'dark gray
|
||
|
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, str$(11 - bMonster_Lag), 2 'red
|
||
|
end if
|
||
|
bMonster_SpeedUpMode = FALSE
|
||
|
end if
|
||
|
end if
|
||
|
end if
|
||
|
if bMonster_SpeedUpMode then call monsterMovement() : exit sub
|
||
|
|
||
|
if bMonster_DelayFrame = 0 then
|
||
|
call monsterMovement()
|
||
|
if bMoveFrame > 0 then bMoveFrame = bMoveFrame - 1
|
||
|
if bMoveFrame = 0 then bMonster_DelayFrame = bMonster_Lag - 1
|
||
|
else
|
||
|
bMonster_DelayFrame = bMonster_DelayFrame - 1
|
||
|
if bMonster_DelayFrame = 0 then bMoveFrame = bSkillLevel
|
||
|
end if
|
||
|
|
||
|
'~ textat 33, 3, str$(bMonster_DelayFrame), 10 'light red
|
||
|
'~ textat 33, 4, str$(bMoveFrame) + " ", 13 'light green
|
||
|
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
|
||
|
|
||
|
Dim bWalkableDirections(4) as BYTE '0...3
|
||
|
Dim bWalkableDirections_Count as BYTE
|
||
|
Dim bTrailDirections(4) as BYTE '0...3
|
||
|
Dim bTrailDirections_Count as BYTE
|
||
|
'------------------------------------------------
|
||
|
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 bPlayerCaught = TRUE : exit for 'Gotcha, Player!!
|
||
|
|
||
|
if (bPeekedTileContent AND MASK_WALKABLE) = GROUP_WALKABLE then
|
||
|
'~ if (bPeekedTileContent AND MASK_ALL_SUBGROUP) = GROUP_TRAIL then
|
||
|
if bPeekedTileContent = TRAIL then
|
||
|
bWalkableDirections_Count = bWalkableDirections_Count + 1
|
||
|
'~ bWalkableDirections(bWalkableDirections_Count) = bMonster_Direction
|
||
|
bTrailDirections_Count = bTrailDirections_Count + 1
|
||
|
bTrailDirections(bTrailDirections_Count) = bMonster_Direction
|
||
|
else
|
||
|
if ((bPeekedTileContent AND MASK_ALL_SUBGROUP) <> SUBGROUP_TREASURE) AND (bPeekedTileContent <> MARKED_SPACE) and bPeekedDirection < 4 then 'ignoring the opposite direction travelled!
|
||
|
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 bPlayerCaught = FALSE 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 'opposite direction
|
||
|
else
|
||
|
bWalkableDirections_Count = bWalkableDirections_Count + 1
|
||
|
bWalkableDirections(bWalkableDirections_Count) = bClosestTileDirection
|
||
|
bMonster_Direction = bWalkableDirections(myRandom(bWalkableDirections_Count, 3))
|
||
|
end if
|
||
|
end if
|
||
|
end if
|
||
|
|
||
|
'------------------------DRAW-------------------------------------------
|
||
|
|
||
|
'~ for bMonsterDebug as BYTE = 0 to 3
|
||
|
'~ textat 33, 2 + bMonsterDebug, " "
|
||
|
'~ next bMonsterDebug
|
||
|
|
||
|
'~ if bWalkableDirections_Count <> MINUS_ONE then
|
||
|
'~ for bMonsterDebug as BYTE = 0 to bWalkableDirections_Count
|
||
|
'~ if bWalkableDirections(bMonsterDebug) = bMonster_Direction then
|
||
|
'~ textat 33, 2 + bMonsterDebug, str$(bWalkableDirections(bMonsterDebug)), 1 'white
|
||
|
'~ else
|
||
|
'~ textat 33, 2 + bMonsterDebug, str$(bWalkableDirections(bMonsterDebug)), 11 'gray
|
||
|
'~ end if
|
||
|
'~ next bMonsterDebug
|
||
|
'~ end if
|
||
|
|
||
|
if (bMonster_PreviousTile AND MASK_ALL) = GROUP_TREASURE then
|
||
|
if bWalkableDirections_Count = MINUS_ONE then
|
||
|
bMonster_PreviousTile = bMonster_PreviousTile OR MASK_SUBGROUP
|
||
|
end if
|
||
|
else
|
||
|
if bWalkableDirections_Count = MINUS_ONE then
|
||
|
bMonster_PreviousTile = MARKED_SPACE
|
||
|
else
|
||
|
bMonster_PreviousTile = SPACE
|
||
|
end if
|
||
|
end if
|
||
|
|
||
|
if (bMonster_PreviousColour AND 15) = 0 then bMonster_PreviousColour = 14
|
||
|
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) = 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
|
||
|
|
||
|
if bWalkableDirections_Count = MINUS_ONE then bMonster_Direction = bTravelingDirection
|
||
|
end sub
|
||
|
|
||
|
sub drawInfoBox() STATIC
|
||
|
'~ textat 4, 11, "{168}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{171}{173}", 6 'blu
|
||
|
'~ textat 4, 12, "{169} {174}", 6 'blu
|
||
|
'~ textat 4, 13, "{169} {174}", 6 'blu
|
||
|
'~ textat 4, 14, "{170}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{172}{175}", 6 'blu
|
||
|
poke 1468, 104 'col 4, row 11
|
||
|
memset 1469, 21, 107 'col 5-25, row 11
|
||
|
poke 1490, 109 'col 26, row 11
|
||
|
|
||
|
poke 1508, 105 'col 4, row 12
|
||
|
memset 1509, 21, 32 'col 5-25, row 12
|
||
|
poke 1530, 110 'col 26, row 12
|
||
|
|
||
|
poke 1548, 105 'col 4, row 13
|
||
|
memset 1549, 21, 32 'col 5-25, row 13
|
||
|
poke 1570, 110 'col 26, row 13
|
||
|
|
||
|
poke 1588, 106 'col 4, row 13
|
||
|
memset 1589, 21, 108 'col 5-25, row 13
|
||
|
poke 1610, 111 'col 26, row 13
|
||
|
|
||
|
memset VIC_COLOR_OFFSET + 1468, 23, 6 'blu
|
||
|
memset VIC_COLOR_OFFSET + 1508, 23, 6 'blu
|
||
|
memset VIC_COLOR_OFFSET + 1548, 23, 6 'blu
|
||
|
memset VIC_COLOR_OFFSET + 1588, 23, 6 'blu
|
||
|
|
||
|
end sub
|
||
|
|
||
|
sub shakeScreen() STATIC
|
||
|
Dim bVariance as BYTE : bVariance = 7
|
||
|
bAnimFrameCounter = 0
|
||
|
|
||
|
do
|
||
|
poke $D011, %10011000 OR ((3 + myRandom(bVariance, 7)) AND 7)
|
||
|
poke $D016, %00001000 OR myRandom(bVariance, 7)
|
||
|
wait $d011, 128, 128 : wait $d011, 128
|
||
|
|
||
|
bAnimFrameCounter = (bAnimFrameCounter + 1) AND 3
|
||
|
if bAnimFrameCounter = 0 then bVariance = bVariance - 1
|
||
|
loop until bVariance = 255
|
||
|
end sub
|
||
|
|
||
|
sub mazeShiftAway() STATIC
|
||
|
dim wLineAddress as WORD : dim wColorLineAddress as WORD
|
||
|
wait $d011, 128, 128 : wait $d011, 128
|
||
|
|
||
|
for nShiftColumn as BYTE = 0 to 30
|
||
|
for nShiftLine as BYTE = 0 to 24
|
||
|
wLineAddress = scrAddrCache(nShiftLine)
|
||
|
wColorLineAddress = VIC_COLOR_OFFSET + wLineAddress
|
||
|
memcpy wLineAddress + 1, wLineAddress, 31
|
||
|
memcpy wColorLineAddress + 1, wColorLineAddress, 31
|
||
|
next nShiftLine
|
||
|
wait $d011, 128, 128 : wait $d011, 128
|
||
|
next nShiftColumn
|
||
|
end sub
|
||
|
|
||
|
sub openDoorAnimation() STATIC
|
||
|
For bAnimFrameCounter = 1 to 5
|
||
|
poke wDoorAddress, DOOR_CLOSED_REVERSED
|
||
|
poke VIC_COLOR_OFFSET + wDoorAddress, 13 'light green
|
||
|
wait $d011, 128, 128 : wait $d011, 128 : wait $d011, 128, 128 : wait $d011, 128
|
||
|
poke wDoorAddress, DOOR_CLOSED
|
||
|
poke VIC_COLOR_OFFSET + wDoorAddress, 14 'light blue
|
||
|
wait $d011, 128, 128 : wait $d011, 128 : wait $d011, 128, 128 : wait $d011, 128
|
||
|
Next bAnimFrameCounter
|
||
|
For bAnimFrameCounter = 1 to 5
|
||
|
poke wDoorAddress, DOOR_OPEN_REVERSED
|
||
|
poke VIC_COLOR_OFFSET + wDoorAddress, 7 'yellow
|
||
|
wait $d011, 128, 128 : wait $d011, 128 : wait $d011, 128, 128 : wait $d011, 128
|
||
|
poke wDoorAddress, DOOR_OPEN
|
||
|
poke VIC_COLOR_OFFSET + wDoorAddress, 14 'light blue
|
||
|
wait $d011, 128, 128 : wait $d011, 128 : wait $d011, 128, 128 : wait $d011, 128
|
||
|
Next bAnimFrameCounter
|
||
|
|
||
|
bTreasuresToOpenDoor = 0
|
||
|
end sub
|
||
|
|
||
|
sub goldFlashAnimation (bInitAnim as BYTE) STATIC
|
||
|
Dim bFlashTimer as BYTE
|
||
|
|
||
|
if bInitAnim then
|
||
|
bGoldNotCollected = FALSE
|
||
|
bFlashTimer = 8
|
||
|
else
|
||
|
if bFlashTimer = 0 then exit sub
|
||
|
end if
|
||
|
|
||
|
bFlashTimer = bFlashTimer - 1
|
||
|
if (bFlashTimer AND 1) then
|
||
|
poke 53281, 8 'orange
|
||
|
else
|
||
|
poke 53281, 0 'black
|
||
|
end if
|
||
|
end sub
|
||
|
|
||
|
sub titleScreen() STATIC
|
||
|
Const PLAYER_LOCATION = 1354
|
||
|
Const MONSTER_LOCATION = 1434
|
||
|
|
||
|
Dim bJoystick2 as BYTE
|
||
|
|
||
|
'treasure frame for title
|
||
|
memset 1036, 16, TREASURE_GOLD
|
||
|
memset 1236, 16, TREASURE_GOLD
|
||
|
memset 55308, 216, 7 'yellow
|
||
|
poke 1076, TREASURE_GOLD
|
||
|
poke 1116, TREASURE_GOLD
|
||
|
poke 1156, TREASURE_GOLD
|
||
|
poke 1196, TREASURE_GOLD
|
||
|
poke 1091, TREASURE_GOLD
|
||
|
poke 1131, TREASURE_GOLD
|
||
|
poke 1171, TREASURE_GOLD
|
||
|
poke 1211, TREASURE_GOLD
|
||
|
|
||
|
textat 15, 2, "superchase", 1 'white
|
||
|
textat 17, 3, "remix!", 1 'white
|
||
|
textat 13, 8, "treasure hunter", 3 'cyan
|
||
|
textat 13, 10, "monster of dungeons!", 7 'yellow
|
||
|
|
||
|
textat 12, 15, "choose skill level", 5 'green
|
||
|
charat 18, 17, 60, 10 'left arrow, light red
|
||
|
charat 22, 17, 62, 10 'right arrow, light red
|
||
|
|
||
|
poke PLAYER_LOCATION, PLAYER : poke 55626, 13 'light green
|
||
|
poke MONSTER_LOCATION, MONSTER : poke 55706, 2 'red
|
||
|
|
||
|
do
|
||
|
charat 20, 17, 48 + bSkillLevel, 1 'white
|
||
|
|
||
|
poke 55994, 10 'color for left arrow, light red
|
||
|
poke 55998, 10 'color for right arrow, light red
|
||
|
|
||
|
bJoystick2 = peek( $DC00) XOR 127
|
||
|
|
||
|
if (bJoystick2 AND 4) then 'color for left arrow, left
|
||
|
poke 55994, 1 'white
|
||
|
if bSkillLevel > 1 then bSkillLevel = bSkillLevel - 1
|
||
|
else
|
||
|
if (bJoystick2 AND 8) then 'right
|
||
|
poke 55998, 1 'color for right arrow, white
|
||
|
if bSkillLevel < 9 then bSkillLevel = bSkillLevel + 1
|
||
|
else
|
||
|
if (bJoystick2 AND 16) then 'fire
|
||
|
exit do
|
||
|
end if
|
||
|
end if
|
||
|
end if
|
||
|
|
||
|
poke PLAYER_LOCATION, peek(PLAYER_LOCATION) XOR 1
|
||
|
poke MONSTER_LOCATION, peek(MONSTER_LOCATION) XOR 1
|
||
|
|
||
|
wait $D011, 128, 128 : wait $D011, 128 : wait $D011, 128, 128 : wait $D011, 128
|
||
|
wait $D011, 128, 128 : wait $D011, 128 : wait $D011, 128, 128 : wait $D011, 128
|
||
|
wait $D011, 128, 128 : wait $D011, 128 : wait $D011, 128, 128 : wait $D011, 128
|
||
|
loop
|
||
|
end sub
|
||
|
|
||
|
'-----------------------------------------------------------------------
|
||
|
LOC_charset_addr:
|
||
|
incbin "charset_superchase.chr"
|