Deadly Towers 64 (beta for testing)
#1
My current official project!

a clone of Deadly Towers for the NES.

Arguably one of the more frustrating games ever released for the NES, I started this project to try and fix some of the issues I have with the game, mainly the collision detection. You get stuck in the game a lot.

I have done some testing on my own but would like to see if anybody else can break anything or if there are spots where you seem to get 'stuck' or have trouble with the character not moving.  Mainly to see if the collision detection can be broken anywhere. I have 1 dungeon loading the start location and exit location are the same as the NES version so you can use this map to navigate it.
https://gamefaqs.gamespot.com/nes/587219...aze-01-map

there are no shops yet or anything  its just map exploring.

keys are:
Arrow keys    move
Spacebar       brings up status screen
'a'                  uses item in status screen (lower case)
'b'                 drops item in status screen (lower case)
                       also exits game when out of status screen

Download the attached MFI file

Code: (Select All)
'Deadly Tower clone beta test release
'date code: 06252023
'Cobalt

TYPE Control_Keys
Up_Key AS LONG
Down_Key AS LONG
Left_Key AS LONG
Right_Key AS LONG
A_Button AS LONG
B_Button AS LONG
Select_Button AS LONG
Start_Button AS LONG
END TYPE

TYPE MapData
x AS INTEGER
y AS INTEGER
MaxScroll AS INTEGER
Scroll AS _BYTE
END TYPE

TYPE Corddata
X AS INTEGER
Y AS INTEGER
END TYPE

TYPE Gamedata
Map AS Corddata 'scroll value of map 0 to MaxScroll
Scroll_Direction AS _BYTE 'which direction does map scroll, vert or horiz
Passage AS _BYTE 'has player entered a doorway of somekind?
Dungeon AS _BYTE 'has player entered a dungeon?
Dungeon_Shop_Count AS _BYTE
Exit_Dungeon AS _BYTE ' works like passage, puts player on overworld at dungeon exit passage
Last_Dungeon AS _BYTE
Shop_Count AS _BYTE
Where AS _BYTE '  where the doorway leads
Door_Side AS _BYTE 'denote which door player went through in dungeon
Shop AS _BYTE 'which shop is player entering
FallDeath AS _BYTE
Scroll_Lock AS _BYTE 'turn scrolling on or off on level
On_Ladder AS _BYTE 'is player currently climbing a ladder
Duration AS _BYTE 'if player used blue or green necklace, how long it lasts
PauseEnemies AS _BYTE 'if player uses the figure pause all for
Duration
(affects all enemies not just humaniod ones as in original)
END TYPE

TYPE PlayerData
Health AS _UNSIGNED _BYTE
MaxHealth AS _UNSIGNED _BYTE
Ludder AS _UNSIGNED _BYTE
Bells AS _BYTE 'bells player has
Burned AS _BYTE 'bells burned
Helm AS _BYTE
Shield AS _BYTE
Armor AS _BYTE
Sword AS _BYTE
Enhance AS _BYTE
Glove AS _BYTE
Boots AS _BYTE
O_Necklace AS _BYTE
DefBonus AS _BYTE 'bonus to defence by blue or green necklaces
X AS INTEGER 'player screen location
Y AS INTEGER
DX AS _BYTE 'player location in Dungeon
DY AS _BYTE 'player location in dungeon
Level AS _BYTE
Direction AS _BYTE
Action AS _BYTE
END TYPE

TYPE Passage_Data
Level AS _BYTE
P AS Corddata
M AS Corddata
Scrolling AS _BYTE 'horizontal,vertical, locked
END TYPE

TYPE Item_Data
Name AS STRING * 14
x AS INTEGER
y AS INTEGER
power AS _BYTE
defen AS _BYTE
Heal AS _UNSIGNED _BYTE
effct AS _BYTE
END TYPE

TYPE Dungeon_Data
N AS _BYTE
E AS _BYTE
W AS _BYTE
S AS _BYTE
Doorways AS _BYTE
Layout AS _UNSIGNED INTEGER '4bit wall\door color, 3 bit floor color, 1 bit windows, 1 bit columns,3bit floor mural ,4bit is exit or shop,
Torch AS _BYTE
Monster_Group AS _BYTE
END TYPE

TYPE Dungeon_Extra
StartRoom AS _BYTE 'which room does player start in.
ExitRoom AS _BYTE 'Which room is exit.
Shop_Count AS _BYTE 'number of shops in dungeon
END TYPE

CONST TRUE = -1, FALSE = NOT TRUE, LOCKED = TRUE, Horizontal = 0, Vertical = 1
CONST UP = 0, DOWN = 4, LEFT = 6, RIGHT = 2
CONST UP_LEFT = 7, UP_RIGHT = 1, DOWN_LEFT = 5, DOWN_RIGHT = 3
CONST Moving = 1, Standing = 0, Climbing = 2
'map bounds collision and door way collision
CONST Collide_White = _RGB32(255), Collide_Blue = _RGB32(0, 0, 255)

SCREEN _NEWIMAGE(640, 480, 32): RANDOMIZE 79819.18: t! = TIMER: 'CLS

DIM SHARED Layer(16) AS LONG, Control AS Control_Keys
DIM SHARED P AS PlayerData, Pack(9) AS _BYTE, Map(33) AS MapData, G AS Gamedata
DIM SHARED D(84) AS Passage_Data, I(64) AS Item_Data
DIM SHARED Dungeon(10, 15, 15) AS Dungeon_Data, DE(10) AS Dungeon_Extra

Layer(0) = _DISPLAY
Layer(1) = _COPYIMAGE(_DISPLAY)
Layer(2) = _COPYIMAGE(_DISPLAY) 'collision mask layer
Layer(3) = _NEWIMAGE(8192, 7680, 32) 'dungeon map layer
Layer(4) = _NEWIMAGE(8192, 7680, 32) 'dungeon map mask layer

'Layer(13) = _LOADIMAGE("StatScreen.bmp", 32)
'Layer(14) = _LOADIMAGE("CastleMapsMask.bmp", 32)
'Layer(15) = _LOADIMAGE("Myer_Sheet_2.bmp", 32)
'Layer(16) = _LOADIMAGE("CastleMaps.bmp", 32)

MFI_Loader "DeadlyTowers_06252023.MFI"

_CLEARCOLOR _RGB32(64, 128, 128), Layer(15)
_CLEARCOLOR _RGB32(146, 144, 255), Layer(13)
_CLEARCOLOR _RGB32(255, 128, 255), Layer(16)
_CLEARCOLOR _RGB32(255, 128, 255), Layer(14)

_SOURCE Layer(2) 'Main collision detection layer

_PRINTSTRING (800, 100), "Dungeon 1", Layer(16)

'OPEN "DT_Data_V1_0.dat" FOR BINARY AS #1
'GET #1, , Map()
'GET #1, , D()
'GET #1, , I()
'GET #1, , Dungeon()
'GET #1, , DE()
'CLOSE

Control.Up_Key = 18432
Control.Down_Key = 20480
Control.Left_Key = 19200
Control.Right_Key = 19712
Control.Select_Button = 32 '  space
Control.Start_Button = 13 'enter
Control.A_Button = 97 '    a
Control.B_Button = 115 '  s



'player start status
P.Health = 100
P.MaxHealth = 100
P.Ludder = 50
P.Direction = DOWN
P.Helm = 0
P.Shield = 0
P.Armor = 0
P.Sword = 1
P.Enhance = 0
P.Glove = 0
P.Boots = 0

FOR i%% = 0 TO 8
Pack(i%%) = INT(RND * 54) + 1
NEXT i%%


'EnterDungeon 1
'CLS
'_PUTIMAGE , Layer(4), Layer(0), (1536, 0)-STEP(2047, 1939) '(8192, 7680)
'PRINT _BIN$(Dungeon(P.Level, P.DX, P.DY).Layout)

'_PRINTSTRING (160, 0), "Timer Seed" + STR$(t!), Layer(0)
'END
Passage 0 'start game here


DO
KB~%% = Controls
IF _READBIT(KB~%%, 0) THEN P.Action = Moving: P.Direction = UP 'player pressed up arrow
IF _READBIT(KB~%%, 1) THEN P.Action = Moving: P.Direction = DOWN 'player pressed down arrow
IF _READBIT(KB~%%, 2) THEN P.Action = Moving: P.Direction = LEFT 'player pressed left arrow
IF _READBIT(KB~%%, 3) THEN P.Action = Moving: P.Direction = RIGHT 'player pressed right arrow

IF _READBIT(KB~%%, 0) AND _READBIT(KB~%%, 2) THEN P.Action = Moving: P.Direction = UP_LEFT 'player pressed up arrow
IF _READBIT(KB~%%, 0) AND _READBIT(KB~%%, 3) THEN P.Action = Moving: P.Direction = UP_RIGHT 'player pressed down arrow
IF _READBIT(KB~%%, 1) AND _READBIT(KB~%%, 2) THEN P.Action = Moving: P.Direction = DOWN_LEFT 'player pressed left arrow
IF _READBIT(KB~%%, 1) AND _READBIT(KB~%%, 3) THEN P.Action = Moving: P.Direction = DOWN_RIGHT 'player pressed right arrow
IF _READBIT(KB~%%, 4) THEN Status_screen
IF _READBIT(KB~%%, 5) THEN Pause_Game

IF _READBIT(KB~%%, 7) THEN ExitFlag%% = -1

IF _SHL(KB~%%, 4) = FALSE THEN P.Action = Standing 'if no direction key press then stop moving

IF P.Action <> Standing THEN Move_Player
IF G.Passage THEN Passage G.Where
IF G.FallDeath THEN Fall_Death
IF G.Dungeon THEN EnterDungeon G.Dungeon 'big deal code wise! whole seperate main loop


Draw_Map
Draw_Player
'--------------------debug data--------------------------
_PRINTSTRING (0, 0), STR$(P.X), Layer(1)
_PRINTSTRING (0, 16), STR$(P.Y), Layer(1)
_PRINTSTRING (0, 32), "    ", Layer(1)
_PRINTSTRING (0, 32), STR$(G.Map.X), Layer(1)
_PRINTSTRING (0, 48), STR$(P.Level), Layer(1)
_PRINTSTRING (0, 64), "    ", Layer(1)
_PRINTSTRING (0, 64), STR$(G.Map.Y), Layer(1)
' _PRINTSTRING (0, 80), STR$(P.X + 2 + 64), Layer(1)
' _PRINTSTRING (0, 96), STR$(P.Y + 62 + 16), Layer(1)
'--------------------------------------------------------
_PUTIMAGE , Layer(1), Layer(0)
_LIMIT 60

LOOP UNTIL ExitFlag%% = -1


_PUTIMAGE , Layer(2), Layer(1)
Draw_Player
_PUTIMAGE , Layer(1), Layer(0)
LINE (P.X + 2 + 64, P.Y + 62 + 16)-STEP(1, 1), _RGB32(255, 0, 0), BF
LINE (P.X + 30 + 64, P.Y + 62 + 16)-STEP(1, 1), _RGB32(255, 0, 0), BF

SUB EnterDungeon (ID%%)
OPEN "debug.txt" FOR OUTPUT AS #1 'save dungeon room layouts incase of issue
Fade_Out Layer(0)
P.X = 242
P.Y = 288
P.Level = ID%% 'level = the dungeon player is in
P.DX = VAL("&H" + LEFT$(HEX$(DE(P.Level).StartRoom), 1)) 'High 4 bits room X loc
P.DY = DE(ID%%).StartRoom AND 15 'Low 4 bits room Y loc

IF G.Dungeon <> G.Last_Dungeon THEN 'don't recreate dungeon if player just left it(save 3.5s)
  ClearLayer Layer(3)
  ClearLayer Layer(4)
  COLOR _RGB32(64)
  FOR y%% = 0 TO 15
  FOR x%% = 0 TO 15
    ClearLayer Layer(1)
    Draw_Dungeon x%%, y%%
    percent%% = INT(count% / 256 * 100)
    _PRINTSTRING (212, 232), "Loading Dungeon..." + LTRIM$(STR$(percent%%)) + "%", Layer(0)
    count% = count% + 1
  NEXT x%%, y%%
  G.Last_Dungeon = G.Dungeon
END IF

Draw_Dungeon P.DX, P.DY
Draw_Player
Fade_In Layer(1)
G.Passage = FALSE
G.Scroll_Lock = TRUE
G.Dungeon = FALSE

Dungeon_Main_Routine 'normal routine incompatable with dungeon mechanics so switch over
CLOSE #1
END SUB

SUB Dungeon_Main_Routine
'first collision mask
_PUTIMAGE (64, 16)-STEP(511, 447), Layer(4), Layer(2), (512 * P.DX, 448 * P.DY)-STEP(511, 447)

DO
  KB~%% = Controls
  IF _READBIT(KB~%%, 0) THEN P.Action = Moving: P.Direction = UP 'player pressed up arrow
  IF _READBIT(KB~%%, 1) THEN P.Action = Moving: P.Direction = DOWN 'player pressed down arrow
  IF _READBIT(KB~%%, 2) THEN P.Action = Moving: P.Direction = LEFT 'player pressed left arrow
  IF _READBIT(KB~%%, 3) THEN P.Action = Moving: P.Direction = RIGHT 'player pressed right arrow

  IF _READBIT(KB~%%, 0) AND _READBIT(KB~%%, 2) THEN P.Action = Moving: P.Direction = UP_LEFT 'player pressed up arrow
  IF _READBIT(KB~%%, 0) AND _READBIT(KB~%%, 3) THEN P.Action = Moving: P.Direction = UP_RIGHT 'player pressed down arrow
  IF _READBIT(KB~%%, 1) AND _READBIT(KB~%%, 2) THEN P.Action = Moving: P.Direction = DOWN_LEFT 'player pressed left arrow
  IF _READBIT(KB~%%, 1) AND _READBIT(KB~%%, 3) THEN P.Action = Moving: P.Direction = DOWN_RIGHT 'player pressed right arrow
  IF _READBIT(KB~%%, 4) THEN Status_screen
  IF _READBIT(KB~%%, 5) THEN Pause_Game

  IF _READBIT(KB~%%, 7) THEN ExitFlag%% = -1

  IF _SHL(KB~%%, 4) = FALSE THEN P.Action = Standing 'if no direction key press then stop moving

  IF P.Action <> Standing THEN Move_Player
  IF G.Passage THEN Dungeon_Passage G.Where
  '  IF G.Dungeon THEN Passage G.Dungeon 'exit back to overworld
  IF G.Exit_Dungeon THEN Passage G.Exit_Dungeon: ExitFlag%% = TRUE: G.Exit_Dungeon = FALSE
  '  IF G.Shop THEN Run_Shop G.Shop

  _PUTIMAGE (64, 16)-STEP(511, 447), Layer(3), Layer(1), (512 * P.DX, 448 * P.DY)-STEP(511, 447)
  Draw_Player
  '--------------------debug data--------------------------
  _PRINTSTRING (0, 0), STR$(P.X), Layer(1)
  _PRINTSTRING (0, 16), STR$(P.Y), Layer(1)
  _PRINTSTRING (0, 32), "    ", Layer(1)
  _PRINTSTRING (0, 32), STR$(P.DX), Layer(1)
  _PRINTSTRING (0, 48), "    ", Layer(1)
  _PRINTSTRING (0, 48), STR$(P.DY), Layer(1)
  _PRINTSTRING (0, 64), STR$(P.Level), Layer(1)
  _PRINTSTRING (0, 80), STR$(Layer(4)) + " " + STR$(_SOURCE), Layer(1)
  _PRINTSTRING (96, 0), SPACE$(24), Layer(1)
  _PRINTSTRING (96, 0), HEX$(Dungeon(P.Level, P.DX, P.DY).N) + " " + HEX$(Dungeon(P.Level, P.DX, P.DY).E) + " " + HEX$(Dungeon(P.Level, P.DX, P.DY).W) + " " + HEX$(Dungeon(P.Level, P.DX, P.DY).S), Layer(1)

  '--------------------------------------------------------
  _PUTIMAGE , Layer(1), Layer(0)
  _LIMIT 60

LOOP UNTIL ExitFlag%% = TRUE
ExitFlag%% = FALSE
END SUB


SUB Draw_Dungeon (X%%, Y%%)
IF Dungeon(P.Level, X%%, Y%%).Layout = 0 THEN Create_Dungeon_Layout X%%, Y%%
Tmp& = _COPYIMAGE(Layer(0)) 'create a temp creation layer for the mask screen
temp$ = HEX$(Dungeon(P.Level, X%%, Y%%).Layout)
binn$ = _BIN$(Dungeon(P.Level, X%%, Y%%).Layout)
B$ = LEFT$("0000000000000000", 16 - LEN(binn$)) + binn$

W%% = VAL("&H" + LEFT$(temp$, 1)) 'wall color
S%% = VAL("&H" + RIGHT$(temp$, 1)) 'shop or exit
F%% = VAL("&B" + MID$(B$, 5, 3))

' PRINT _BIN$(F%%), B$
' IF F%% = 0 OR F%% > 6 THEN BEEP: END

_PUTIMAGE (192, 16)-STEP(255, 255), Layer(16), Layer(1), (3335, 1 + 129 * (W%% - 1))-STEP(127, 127)
_PUTIMAGE (64, 16)-STEP(127, 383), Layer(16), Layer(1), (3464, 1 + 193 * ((W%% - 1) MOD 5))-STEP(63, 191)
_PUTIMAGE (64 + 256 + 128, 16)-STEP(127, 383), Layer(16), Layer(1), (3528, 1 + 193 * ((W%% - 1) MOD 5))-STEP(63, 191)
'---------------------------mask---------------------------------
_PUTIMAGE (192, 16)-STEP(255, 255), Layer(14), Tmp&, (3334, 1 + 129 * (W%% - 1))-STEP(127, 127)
_PUTIMAGE (64, 16)-STEP(127, 383), Layer(14), Tmp&, (3464, 1 + 193 * ((W%% - 1) MOD 5))-STEP(63, 191)
_PUTIMAGE (64 + 256 + 128, 16)-STEP(127, 383), Layer(14), Tmp&, (3528, 1 + 193 * ((W%% - 1) MOD 5))-STEP(63, 191)

SELECT CASE (W%% - 1) MOD 5 'bottom wall
  CASE 0
  _PUTIMAGE (64, 400)-STEP(511, 63), Layer(16), Layer(1), (1277, 1912)-STEP(255, 31)
  _PUTIMAGE (64, 400)-STEP(511, 79), Layer(14), Tmp&, (1277, 1912)-STEP(255, 39) 'mask
  CASE 1
  _PUTIMAGE (64, 400)-STEP(511, 63), Layer(16), Layer(1), (1020, 1912)-STEP(255, 31)
  _PUTIMAGE (64, 400)-STEP(511, 79), Layer(14), Tmp&, (1020, 1912)-STEP(255, 39) 'mask
  CASE 2
  _PUTIMAGE (64, 400)-STEP(511, 63), Layer(16), Layer(1), (1020, 1912)-STEP(255, 31)
  _PUTIMAGE (64, 400)-STEP(511, 79), Layer(14), Tmp&, (1020, 1912)-STEP(255, 39) 'mask
  CASE 3
  _PUTIMAGE (64, 400)-STEP(511, 63), Layer(16), Layer(1), (1020, 1912)-STEP(255, 31)
  _PUTIMAGE (64, 400)-STEP(511, 79), Layer(14), Tmp&, (1020, 1912)-STEP(255, 39) 'mask
  CASE 4
  _PUTIMAGE (64, 400)-STEP(511, 63), Layer(16), Layer(1), (1020, 1912)-STEP(255, 31)
  _PUTIMAGE (64, 400)-STEP(511, 79), Layer(14), Tmp&, (1020, 1912)-STEP(255, 39) 'mask
END SELECT

SELECT CASE F%% 'floor
  CASE 1
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(16), Layer(1), (1535, 1911)-STEP(255, 63)
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(14), Tmp&, (1535, 1911)-STEP(255, 63) 'mask
  CASE 2
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(16), Layer(1), (1535, 1976)-STEP(255, 63)
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(14), Tmp&, (1535, 1976)-STEP(255, 63) 'mask
  CASE 3
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(16), Layer(1), (1792, 1911)-STEP(255, 63)
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(14), Tmp&, (1792, 1911)-STEP(255, 63) 'mask
  CASE 4
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(16), Layer(1), (1792, 1976)-STEP(255, 63)
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(14), Tmp&, (1792, 1976)-STEP(255, 63) 'mask
  CASE 5
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(16), Layer(1), (2049, 1911)-STEP(255, 63)
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(14), Tmp&, (2049, 1911)-STEP(255, 63) 'mask
  CASE 6
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(16), Layer(1), (2049, 1976)-STEP(255, 63)
  _PUTIMAGE (64, 272)-STEP(511, 127), Layer(14), Tmp&, (2049, 1976)-STEP(255, 63) 'mask
END SELECT

SELECT CASE (W%% - 1) MOD 5 'door
  CASE 0
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 0) THEN
    _PUTIMAGE (288, 176)-STEP(63, 95), Layer(16), Layer(1), (2508 + 34, 1911)-STEP(31, 47)
    _PUTIMAGE (288, 176)-STEP(63, 97), Layer(14), Tmp&, (2508 + 34, 1911)-STEP(31, 48) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 1) THEN
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(16), Layer(1), (2508 + 67, 1911)-STEP(31, 71)
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(14), Tmp&, (2508 + 67, 1911)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 2) THEN
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(16), Layer(1), (2508 + 0, 1911)-STEP(31, 71)
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(14), Tmp&, (2508 + 0, 1911)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 3) THEN
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(16), Layer(1), (2609, 2048)-STEP(48, 8)
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(14), Tmp&, (2609, 2048)-STEP(48, 8) 'mask
  END IF
  CASE 1
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 0) THEN
    _PUTIMAGE (288, 176)-STEP(63, 95), Layer(16), Layer(1), (2407 + 34, 1984)-STEP(31, 47)
    _PUTIMAGE (288, 176)-STEP(63, 97), Layer(14), Tmp&, (2407 + 34, 1984)-STEP(31, 48) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 1) THEN
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(16), Layer(1), (2407 + 67, 1984)-STEP(31, 71)
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(14), Tmp&, (2407 + 67, 1984)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 2) THEN
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(16), Layer(1), (2407 + 0, 1984)-STEP(31, 71)
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(14), Tmp&, (2407 + 0, 1984)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 3) THEN
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(16), Layer(1), (2609, 2048)-STEP(48, 8)
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(14), Tmp&, (2609, 2048)-STEP(48, 8) 'mask
  END IF
  CASE 2
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 0) THEN
    _PUTIMAGE (288, 176)-STEP(63, 95), Layer(16), Layer(1), (2306 + 34, 1984)-STEP(31, 47)
    _PUTIMAGE (288, 176)-STEP(63, 97), Layer(14), Tmp&, (2306 + 34, 1984)-STEP(31, 48) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 1) THEN
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(16), Layer(1), (2306 + 67, 1984)-STEP(31, 71)
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(14), Tmp&, (2306 + 67, 1984)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 2) THEN
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(16), Layer(1), (2306 + 0, 1984)-STEP(31, 71)
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(14), Tmp&, (2306 + 0, 1984)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 3) THEN
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(16), Layer(1), (2609, 2048)-STEP(40, 8)
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(14), Tmp&, (2609, 2048)-STEP(40, 8) 'mask
  END IF
  CASE 3
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 0) THEN
    _PUTIMAGE (288, 176)-STEP(63, 95), Layer(16), Layer(1), (2407 + 34, 1911)-STEP(31, 47)
    _PUTIMAGE (288, 176)-STEP(63, 97), Layer(14), Tmp&, (2407 + 34, 1911)-STEP(31, 48) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 1) THEN
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(16), Layer(1), (2407 + 67, 1911)-STEP(31, 71)
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(14), Tmp&, (2407 + 67, 1911)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 2) THEN
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(16), Layer(1), (2407 + 0, 1911)-STEP(31, 71)
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(14), Tmp&, (2407 + 0, 1911)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 3) THEN
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(16), Layer(1), (2609, 2048)-STEP(48, 8)
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(14), Tmp&, (2609, 2048)-STEP(48, 8) 'mask
  END IF
  CASE 4
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 0) THEN
    _PUTIMAGE (288, 176)-STEP(63, 95), Layer(16), Layer(1), (2306 + 34, 1911)-STEP(31, 47)
    _PUTIMAGE (288, 176)-STEP(63, 97), Layer(14), Tmp&, (2306 + 34, 1911)-STEP(31, 48) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 1) THEN
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(16), Layer(1), (2306 + 67, 1911)-STEP(31, 71)
    _PUTIMAGE (480, 224)-STEP(63, 143), Layer(14), Tmp&, (2306 + 67, 1911)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 2) THEN
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(16), Layer(1), (2306 + 0, 1911)-STEP(31, 71)
    _PUTIMAGE (94, 224)-STEP(63, 143), Layer(14), Tmp&, (2306 + 0, 1911)-STEP(31, 71) 'mask
  END IF
  IF _READBIT(Dungeon(P.Level, X%%, Y%%).Doorways, 3) THEN
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(16), Layer(1), (2609, 2048)-STEP(48, 8)
    _PUTIMAGE (272, 400)-STEP(95, 15), Layer(14), Tmp&, (2609, 2048)-STEP(48, 8) 'mask
  END IF
END SELECT
'murals
M%% = VAL("&B" + MID$(B$, 10, 3))
IF M%% THEN _PUTIMAGE (272, 304)-STEP(99, 35), Layer(16), Layer(1), (2563, 2057 + 19 * (M%% - 1))-STEP(49, 17)
'exit and shop

IF VAL("&B" + MID$(B$, 13, 4)) = 15 THEN 'exit
  _DEST Tmp&
  LINE (306, 310)-STEP(27, 15), _RGB32(255, 1, 74 + P.Level), BF
  _DEST Layer(0)
ELSEIF VAL("&B" + MID$(B$, 13, 4)) > 0 THEN 'shop
  _DEST Tmp&
  LINE (306, 310)-STEP(27, 15), _RGB32(255, 0, VAL("&B" + MID$(_BIN$(Dungeon(P.Level, X%%, Y%%).Layout), 13, 4))), BF
  _DEST Layer(0)
END IF

_PUTIMAGE (X%% * 512, Y%% * 448)-STEP(511, 447), Layer(1), Layer(3), (64, 16)-STEP(511, 447)
_PUTIMAGE (X%% * 512, Y%% * 448)-STEP(511, 447), Tmp&, Layer(4), (64, 16)-STEP(511, 447)

END SUB

SUB Create_Dungeon_Layout (X%%, Y%%)
'setup a layout for this room if not set
colors%% = INT(RND * 15) + 1 'wall and door colors
floor%% = INT(RND * 6) + 1 'floor color
windows%% = INT(RND * 1) 'window flag
columns%% = INT(RND * 1) 'column flag
IF INT(RND * 255) > 245 THEN Murals%% = INT(RND * 5) + 1 'is there a mural?
IF G.Shop_Count < DE(P.Level).Shop_Count THEN 'if more shops available and not the exit room
  IF X%% <> VAL("&H" + LEFT$(HEX$(DE(P.Level).ExitRoom), 1)) AND Y%% <> DE(P.Level).ExitRoom AND 15 THEN
  'IF INT(RND * 255) > 230 THEN shops%% = INT(RND * 8) + 1
  'Murals%% = INT(RND * 5) + 1 'shops auto get a mural
  END IF
END IF
temp%% = VAL("&H" + HEX$(X%%) + HEX$(Y%%))
IF temp%% = DE(P.Level).ExitRoom THEN
  FlagForExit%% = TRUE
  Murals%% = INT(RND * 5) + 1 'exits auto get a mural
END IF
A$ = LEFT$("0000", 4 - LEN(_BIN$(colors%% AND 15))) + _BIN$(colors%% AND 15) + LEFT$("000", 3 - LEN(_BIN$(floor%% AND 7))) + _BIN$(floor%% AND 7)

IF windows%% THEN 'windows and columns are mutually exclusive, windows take precidence.
  A$ = A$ + "10"
ELSEIF columns%% THEN
  A$ = A$ + "01"
ELSE
  A$ = A$ + "00"
END IF

A$ = A$ + LEFT$("000", 3 - LEN(_BIN$(Murals%% AND 7))) + _BIN$(Murals%% AND 7)
IF FlagForExit%% THEN A$ = A$ + "1111" ELSE A$ = A$ + LEFT$("0000", 4 - LEN(_BIN$(shops%% AND 15))) + _BIN$(shops%% AND 15): FlagForExit%% = FALSE

PRINT #1, HEX$(X%%) + HEX$(Y%%) + "-" + A$ + "||" + STR$(DE(P.Level).ExitRoom)
' PRINT "&B" + A$
' PRINT VAL("&B" + A$)
Dungeon(P.Level, X%%, Y%%).Layout = VAL("&B" + A$)
' PRINT Dungeon(P.Level, X%%, Y%%).Layout
END SUB

SUB Draw_Health
END SUB

SUB Draw_Map
'screen map
_PUTIMAGE (64, 16)-STEP(511, 447), Layer(16), Layer(1), (Map(P.Level).x + G.Map.X, Map(P.Level).y + G.Map.Y)-STEP(255, 223)
'collision mask
_PUTIMAGE (64, 16)-STEP(511, 447), Layer(14), Layer(2), (Map(P.Level).x + G.Map.X, Map(P.Level).y + G.Map.Y)-STEP(255, 223)

END SUB

SUB Draw_Player
STATIC Frame%%, Count%%
IF P.Action = Standing THEN
ELSE 'if player is not standing then animate
  Count%% = Count%% + 1
  IF Count%% = 8 THEN Frame%% = NOT Frame%%: Count%% = 0
END IF

IF P.Action = Climbing THEN
  _PUTIMAGE (64 + P.X, 16 + P.Y)-STEP(31, 63), Layer(15), Layer(1), (3 + (19 * ABS(Frame%%)), 37)-STEP(15, 31)
ELSEIF G.On_Ladder THEN 'player is not climbing then use main sprite array
  IF P.Direction = UP OR P.Direction = DOWN THEN 'us climbing pose for up or down
  _PUTIMAGE (64 + P.X, 16 + P.Y)-STEP(31, 63), Layer(15), Layer(1), (3 + (19 * ABS(Frame%%)), 37)-STEP(15, 31)
  ELSE
  _PUTIMAGE (64 + P.X, 16 + P.Y)-STEP(31, 63), Layer(15), Layer(1), (3 + (38 * P.Direction) + (19 * ABS(Frame%%)), 4)-STEP(15, 31)
  END IF
ELSE
  _PUTIMAGE (64 + P.X, 16 + P.Y)-STEP(31, 63), Layer(15), Layer(1), (3 + (38 * P.Direction) + (19 * ABS(Frame%%)), 4)-STEP(15, 31)
END IF
END SUB

SUB Fall_Death
'player fell off of ledge
P.Health = 0
DO
  frame%% = frame%% + 1
  IF frame%% = 1 THEN
  P.Direction = P.Direction + 1
  IF P.Direction = 8 THEN P.Direction = 0
  P.Y = P.Y + 2
  IF P.Y >= 484 THEN ExitFlag%% = TRUE
  frame%% = 0
  END IF
  Draw_Map
  Draw_Player
  _PUTIMAGE , Layer(1), Layer(0)
  ClearLayer Layer(1)
  _LIMIT 60
LOOP UNTIL ExitFlag%%
Passage 0
G.FallDeath = FALSE
END SUB

SUB Move_Player
SELECT CASE P.Direction
  CASE UP
  P.Y = P.Y - 2 'movement
  'Basic Wall collision
  'check collision based on center point of player sprite, if true move P.Y back
  IF Player_Collision(P.X, P.Y) THEN P.Y = P.Y + 2
  CASE DOWN
  P.Y = P.Y + 2 'movement
  'Basic Wall collision
  'check collision based on center point of player sprite, if true move P.Y back
  IF Player_Collision(P.X, P.Y) THEN P.Y = P.Y - 2
  'Item collision (only chest right now)
  'Monster collision
  CASE LEFT
  P.X = P.X - 2 'movement
  'Basic Wall collision
  'check collision based on center point of player sprite, if true move P.Y back
  IF Player_Collision(P.X, P.Y) THEN P.X = P.X + 2
  CASE RIGHT
  P.X = P.X + 2 'movement
  'Basic Wall collision
  'check collision based on center point of player sprite, if true move P.Y back
  IF Player_Collision(P.X, P.Y) THEN P.X = P.X - 2
  CASE UP_LEFT
  'check each movement seperatly so player can 'slide' along walls
  P.Y = P.Y - 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.Y = P.Y + 2
  P.X = P.X - 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.X = P.X + 2
  CASE UP_RIGHT
  'check each movement seperatly so player can 'slide' along walls
  P.Y = P.Y - 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.Y = P.Y + 2
  P.X = P.X + 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.X = P.X - 2
  CASE DOWN_LEFT
  'check each movement seperatly so player can 'slide' along walls
  P.Y = P.Y + 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.Y = P.Y - 2
  P.X = P.X - 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.X = P.X + 2
  CASE DOWN_RIGHT
  'check each movement seperatly so player can 'slide' along walls
  P.Y = P.Y + 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.Y = P.Y - 2
  P.X = P.X + 2 'movement
  IF Player_Collision(P.X, P.Y) THEN P.X = P.X - 2
END SELECT

IF NOT G.Scroll_Lock THEN 'only run if scrolling allowed
  'scroll map if player reaches X max
  IF G.Scroll_Direction = Horizontal THEN 'only scroll this way if flagged to do so
  IF P.X > 354 THEN P.X = 354: G.Map.X = G.Map.X + 1
  IF G.Map.X > Map(P.Level).MaxScroll THEN G.Map.X = Map(P.Level).MaxScroll 'stop scroll at edge
  END IF
  'scroll map if player reaches X min
  IF G.Scroll_Direction = Horizontal THEN 'only scroll this way if flagged to do so
  IF P.X < 118 THEN P.X = 118: G.Map.X = G.Map.X - 1
  IF G.Map.X = -1 THEN G.Map.X = 0 'stop scroll at edge
  END IF

  IF G.Scroll_Direction = Vertical THEN 'only scroll this way if flagged to do so
  IF P.Y > 300 THEN P.Y = 300: G.Map.Y = G.Map.Y + 1
  IF G.Map.Y > Map(P.Level).MaxScroll THEN G.Map.Y = Map(P.Level).MaxScroll 'stop scroll at edge
  END IF

  IF G.Scroll_Direction = Vertical THEN 'only scroll this way if flagged to do so
  IF P.Y < 100 THEN P.Y = 100: G.Map.Y = G.Map.Y - 1
  IF G.Map.Y = -1 THEN G.Map.Y = 0 'stop scroll at edge
  END IF

END IF

IF P.Level = 10 THEN
  IF G.Map.X = 0 THEN G.Map.X = 2046
  IF G.Map.X = 2048 THEN G.Map.X = 2
END IF

END SUB

SUB Passage (ID%%)
IF ID%% = 73 AND P.Burned = 7 THEN
  'only allow player to take this passage if all bells are burned
  Fade_Out Layer(0)
  P.X = D(ID%%).P.X
  P.Y = D(ID%%).P.Y
  P.Level = D(ID%%).Level
  G.Map.X = D(ID%%).M.X
  G.Map.Y = D(ID%%).M.Y
  G.Scroll_Direction = Map(P.Level).Scroll
  G.Passage = FALSE
  G.Scroll_Lock = D(ID%%).Scrolling
  _DELAY .15
  Draw_Map
  Draw_Player
  Fade_In Layer(1)
ELSEIF ID%% <> 73 THEN
  Fade_Out Layer(0)
  P.X = D(ID%%).P.X
  P.Y = D(ID%%).P.Y
  P.Level = D(ID%%).Level
  G.Map.X = D(ID%%).M.X
  G.Map.Y = D(ID%%).M.Y
  G.Scroll_Direction = Map(P.Level).Scroll
  G.Passage = FALSE
  G.Scroll_Lock = D(ID%%).Scrolling
  _DELAY .15
  Draw_Map
  Draw_Player
  Fade_In Layer(1)
END IF
END SUB

SUB Dungeon_Passage (ID%%)
Fade_Out Layer(0)
P.DX = VAL("&H" + LEFT$(HEX$(G.Where), 1))
P.DY = VAL("&H" + RIGHT$(HEX$(G.Where), 1))

SELECT CASE G.Door_Side
  CASE 0 'up
  P.Y = 316
  CASE 1 'east
  P.X = 70
  CASE 2 'west
  P.X = 408
  CASE 3 'down
  P.Y = 208
END SELECT

G.Passage = FALSE
G.Scroll_Lock = TRUE
'change collision mask
_PUTIMAGE (64, 16)-STEP(511, 447), Layer(4), Layer(2), (512 * P.DX, 448 * P.DY)-STEP(511, 447)
'new screen
_PUTIMAGE (64, 16)-STEP(511, 447), Layer(3), Layer(1), (512 * P.DX, 448 * P.DY)-STEP(511, 447)
Draw_Player
Fade_In Layer(1)
END SUB


SUB Pause_Game
Control_lock
Tmp& = _COPYIMAGE(Layer(0))
DO
  KB~%% = Controls
  _LIMIT 60
LOOP UNTIL _READBIT(KB~%%, 5)
_FREEIMAGE Tmp&
Control_lock
END SUB

SUB DT_Print (X%, Y%, Txt$)
L%% = LEN(Txt$)
FOR i%% = 1 TO L%%
  C%% = ASC(MID$(Txt$, i%%, 1))
  SELECT CASE C%%
  CASE 65 TO 90 'A-Z
    _PUTIMAGE (X% + 16 * i%%, Y%)-STEP(15, 15), Layer(13), Layer(1), (0 + 9 * (C%% - 65), 269)-STEP(7, 7)
  CASE 48 TO 57 '0-9
    _PUTIMAGE (X% + 16 * i%%, Y%)-STEP(15, 15), Layer(13), Layer(1), (0 + 9 * (C%% - 48), 278)-STEP(7, 7)
  CASE 46 '.
    _PUTIMAGE (X% + 16 * i%%, Y%)-STEP(15, 15), Layer(13), Layer(1), (0 + 9 * 13, 278)-STEP(7, 7)
  END SELECT
NEXT i%%
END SUB

SUB Status_screen
Control_lock
DO
  KB~%% = Controls
  Control_lock
  IF _READBIT(KB~%%, 2) THEN selection%% = selection%% - 1 'player pressed left arrow
  IF _READBIT(KB~%%, 3) THEN selection%% = selection%% + 1 'player pressed right arrow
  IF _READBIT(KB~%%, 6) THEN useitem%% = TRUE
  IF _READBIT(KB~%%, 7) THEN dropitem%% = TRUE

  IF selection%% = -1 THEN selection%% = 8
  IF selection%% = 9 THEN selection%% = 0

  'background
  _PUTIMAGE (64, 16)-STEP(512, 447), Layer(13), Layer(1), (0, 0)-STEP(255, 223)
  'status and items
  DT_Print 240, 128, LEFT$("000", 3 - LEN(LTRIM$(STR$(P.Health)))) + LTRIM$(STR$(P.Health))
  DT_Print 304, 128, LEFT$("000", 3 - LEN(LTRIM$(STR$(P.MaxHealth)))) + LTRIM$(STR$(P.MaxHealth))
  DT_Print 256, 160, LEFT$("000", 3 - LEN(LTRIM$(STR$(P.Ludder)))) + LTRIM$(STR$(P.Ludder))
  _PUTIMAGE (288, 288)-STEP(31, 31), Layer(13), Layer(1), (I(P.Sword).x, I(P.Sword).y)-STEP(15, 15) 'sword
  _PUTIMAGE (336, 288)-STEP(31, 31), Layer(13), Layer(1), (I(P.Enhance).x, I(P.Enhance).y)-STEP(15, 15) 'enhancement
  _PUTIMAGE (384, 288)-STEP(31, 31), Layer(13), Layer(1), (I(P.Glove).x, I(P.Glove).y)-STEP(15, 15) 'Cauntlets
  _PUTIMAGE (384, 176)-STEP(31, 31), Layer(13), Layer(1), (I(P.Boots).x, I(P.Boots).y)-STEP(15, 15) 'hyperboots
  _PUTIMAGE (112, 288)-STEP(31, 31), Layer(13), Layer(1), (I(P.Helm).x, I(P.Helm).y)-STEP(15, 15) 'helmet
  _PUTIMAGE (160, 288)-STEP(31, 31), Layer(13), Layer(1), (I(P.Shield).x, I(P.Shield).y)-STEP(15, 15) 'shield
  _PUTIMAGE (208, 288)-STEP(31, 31), Layer(13), Layer(1), (I(P.Armor).x, I(P.Armor).y)-STEP(15, 15) 'armor

  FOR J%% = 1 TO P.Bells 'bells player has
  _PUTIMAGE (480, 64 + 32 * J%%)-STEP(31, 31), Layer(13), Layer(1), (17 * 13, 303)-STEP(15, 15) 'bells
  NEXT J%%
  FOR J%% = 1 TO P.Burned 'bells player has bunred
  _PUTIMAGE (480, 64 + 32 * J%%)-STEP(31, 31), Layer(13), Layer(1), (I(57).x, I(57).y)-STEP(15, 15) 'bells
  NEXT J%%

  FOR J%% = 0 TO 8 'items player has
  _PUTIMAGE (112 + 48 * J%%, 400)-STEP(31, 31), Layer(13), Layer(1), (I(Pack(J%%)).x, I(Pack(J%%)).y)-STEP(15, 15)
  NEXT J%%

  DT_Print 96, 368, RTRIM$(I(Pack(selection%%)).Name)
  _PUTIMAGE (120 + 48 * selection%%, 384)-STEP(15, 15), Layer(13), Layer(1), (0 + 9 * 15, 278)-STEP(7, 7) 'arrow

  IF useitem%% THEN Item_Use selection%%: useitem%% = FALSE
  IF dropitem%% THEN Item_Drop selection%%: dropitem%% = FALSE

  _PUTIMAGE , Layer(1), Layer(0)
  _LIMIT 60
LOOP UNTIL _READBIT(KB~%%, 4)
Control_lock
END SUB

SUB Item_Use (ID%%)
'-----------equip-ables---------
SELECT CASE Pack(ID%%)
  CASE 1 TO 4 'swords
  P.Sword = Pack(ID%%)
  CASE 5 TO 7 'helms
  P.Helm = Pack(ID%%)
  CASE 8 TO 10 'shields
  P.Shield = Pack(ID%%)
  CASE 11 TO 13 'armor
  P.Armor = Pack(ID%%)
  CASE 14, 15 'boots
  P.Boots = Pack(ID%%)
  CASE 16, 17 'enhancements
  P.Enhance = Pack(ID%%)
  CASE 18 TO 20 'gloves
  P.Glove = Pack(ID%%)
  CASE 36 'agate (orange) necklace
  P.O_Necklace = TRUE 'adds a negligable amount of defence perminatly
END SELECT
'----------consume-ables----------
SELECT CASE Pack(ID%%)
  CASE 25 'key
  CASE 26 'torch
  CASE 27 ' grail
  P.Ludder = 255 'player gets full cash +5!(for that special item!)
  CASE 28 'figure
  G.Duration = 96
  G.PauseEnemies = TRUE
  CASE 31 TO 34 'potions
  IF P.Health + I(Pack(ID%%)).Heal > P.MaxHealth THEN P.Health = P.MaxHealth ELSE P.Health = P.Health + I(Pack(ID%%)).Heal
  CASE 35, 37, 38 'necklaces(minus agate(orange))
  IF Pack(ID%%) = 35 THEN a = FALSE 'do something unknown
  IF Pack(ID%%) = 37 THEN P.DefBonus = 8: G.Duration = 96
  IF Pack(ID%%) = 38 THEN P.DefBonus = 127: G.Duration = 32 'invincable!
  CASE 39 TO 42 'crystals
  CASE 46 TO 49 'scrolls
  IF Pack(ID%%) = 47 THEN Passage 29 'return to holy flame
  IF Pack(ID%%) = 48 THEN Passage 0 'return to start point
  CASE 59 'cursed shield
  P.Shield = FALSE ' player looses shield!
  P.Armor = FALSE 'player looses armor TOO!
  CASE 60 'False grail
  P.Ludder = 0 'player looses all cash
END SELECT

Pack(ID%%) = 0
Reduce_Pack ID%% 'remove empty item
END SUB

SUB Item_Drop (ID%%)
tmp& = _COPYIMAGE(Layer(1))
DO
  _PUTIMAGE , tmp&, Layer(1)
  KB~%% = Controls
  Control_lock

  FOR i%% = 0 TO 6 'anykey but 'b' exits routine
  IF _READBIT(KB~%%, i%%) THEN ExitFlag%% = TRUE
  NEXT i%%

  IF _READBIT(KB~%%, 7) THEN 'press 'B' again to confirm
  DT_Print 96, 368, RTRIM$(I(Pack(ID%%)).Name) + " DROPPED ! "
  Pack(ID%%) = 0
  ExitFlag%% = TRUE
  Reduce_Pack ID%%
  _PUTIMAGE , Layer(1), Layer(0)
  _DELAY .75
  END IF

  IF NOT ExitFlag%% THEN DT_Print 96, 368, RTRIM$(I(Pack(ID%%)).Name) + " THROW AWAY?"
  _PUTIMAGE , Layer(1), Layer(0)
  _LIMIT 60
LOOP UNTIL ExitFlag%%
Layer(1) = _COPYIMAGE(tmp&)
_FREEIMAGE tmp&
END SUB

SUB Reduce_Pack (Start%%)
FOR i%% = Start%% TO 8
  SWAP Pack(i%%), Pack(i%% + 1) 'move current `0'ed item to end
NEXT i%%
END SUB

SUB Run_Shop (ID%%)

END SUB

FUNCTION Controls~%%
IF _KEYDOWN(Control.Up_Key) THEN Result~%% = _SETBIT(Result~%%, 0) '1
IF _KEYDOWN(Control.Down_Key) THEN Result~%% = _SETBIT(Result~%%, 1) '2
IF _KEYDOWN(Control.Left_Key) THEN Result~%% = _SETBIT(Result~%%, 2) '4
IF _KEYDOWN(Control.Right_Key) THEN Result~%% = _SETBIT(Result~%%, 3) '8
IF _KEYDOWN(Control.Select_Button) THEN Result~%% = _SETBIT(Result~%%, 4) '16
IF _KEYDOWN(Control.Start_Button) THEN Result~%% = _SETBIT(Result~%%, 5) '32
IF _KEYDOWN(Control.A_Button) THEN Result~%% = _SETBIT(Result~%%, 6) '64
IF _KEYDOWN(Control.B_Button) THEN Result~%% = _SETBIT(Result~%%, 7) '128
Controls = Result~%%
END FUNCTION

FUNCTION Player_Collision%% (Xpos%, Ypos%)
Result%% = FALSE 'start with no collision

Point1~& = POINT(Xpos% + 2 + 64, Ypos% + 62 + 16) 'bottom lt collision point
Point2~& = POINT(Xpos% + 30 + 64, Ypos% + 62 + 16) 'bottom rt collision point
Rp1~%% = _RED32(Point1~&)
Rp2~%% = _RED32(Point2~&)
Gp1~%% = _GREEN32(Point1~&)
Gp2~%% = _GREEN32(Point2~&)
Bp1~%% = _BLUE32(Point1~&)
Bp2~%% = _BLUE32(Point2~&)
'Point3~& = POINT(Xpos% + 16, Ypos% + 20) 'bottom
'Point4~& = POINT(Xpos% - 16, Ypos% + 20) 'bottom

'passages
IF Bp1~%% = 255 AND Rp1~%% < 75 THEN Point1~& = Collide_White: G.Passage = TRUE: G.Where = Rp1~%% 'passage check
IF Bp2~%% = 255 AND Rp2~%% < 75 THEN Point2~& = Collide_White: G.Passage = TRUE: G.Where = Rp2~%% 'passage check

'dungeon passages
IF Bp1~%% = 255 AND Rp1~%% = 90 THEN Point1~& = Collide_White: G.Passage = TRUE: G.Door_Side = 0: G.Where = Dungeon(P.Level, P.DX, P.DY).N 'north door
IF Bp2~%% = 255 AND Rp2~%% = 90 THEN Point2~& = Collide_White: G.Passage = TRUE: G.Door_Side = 0: G.Where = Dungeon(P.Level, P.DX, P.DY).N '
IF Bp1~%% = 255 AND Rp1~%% = 91 THEN Point1~& = Collide_White: G.Passage = TRUE: G.Door_Side = 1: G.Where = Dungeon(P.Level, P.DX, P.DY).E 'east door
IF Bp2~%% = 255 AND Rp2~%% = 91 THEN Point2~& = Collide_White: G.Passage = TRUE: G.Door_Side = 1: G.Where = Dungeon(P.Level, P.DX, P.DY).E '
IF Bp1~%% = 255 AND Rp1~%% = 92 THEN Point1~& = Collide_White: G.Passage = TRUE: G.Door_Side = 2: G.Where = Dungeon(P.Level, P.DX, P.DY).W 'west door
IF Bp2~%% = 255 AND Rp2~%% = 92 THEN Point2~& = Collide_White: G.Passage = TRUE: G.Door_Side = 2: G.Where = Dungeon(P.Level, P.DX, P.DY).W '
IF Bp1~%% = 255 AND Rp1~%% = 93 THEN Point1~& = Collide_White: G.Passage = TRUE: G.Door_Side = 3: G.Where = Dungeon(P.Level, P.DX, P.DY).S 'south door
IF Bp2~%% = 255 AND Rp2~%% = 93 THEN Point2~& = Collide_White: G.Passage = TRUE: G.Door_Side = 3: G.Where = Dungeon(P.Level, P.DX, P.DY).S '

'ladder
IF Bp1~%% = 255 AND Rp1~%% = 255 AND Gp1~%% = 0 THEN P.Action = Climbing: G.On_Ladder = TRUE ELSE G.On_Ladder = FALSE
IF Bp2~%% = 255 AND Rp2~%% = 255 AND Gp2~%% = 0 THEN P.Action = Climbing

'fall off edge
IF Gp1~%% = 255 AND Bp1~%% = 0 AND Rp1~%% = 0 THEN Point1~& = Collide_White: G.FallDeath = TRUE 'cliff edge check
IF Gp2~%% = 255 AND Bp2~%% = 0 AND Rp2~%% = 0 THEN Point2~& = Collide_White: G.FallDeath = TRUE 'cliff edge check

'dungeons
IF Gp1~%% = 255 AND Bp1~%% < 11 AND Rp1~%% = 255 THEN Point1~& = Collide_White: G.Dungeon = Bp1~%% 'dungeon check
IF Gp2~%% = 255 AND Bp2~%% < 11 AND Rp2~%% = 255 THEN Point2~& = Collide_White: G.Dungeon = Bp2~%% 'dungeon check

'Dungeon Exit
IF Rp1~%% = 255 AND Gp1~%% = 1 AND Bp1~%% >= 75 THEN Point1~& = Collide_White: G.Exit_Dungeon = Bp1~%% 'dungeon check
IF Rp2~%% = 255 AND Gp2~%% = 1 AND Bp2~%% >= 75 THEN Point2~& = Collide_White: G.Exit_Dungeon = Bp2~%% 'dungeon check

'dungeon shop
IF Rp1~%% = 255 AND Gp1~%% = 0 AND Bp1~%% < 10 THEN Point1~& = Collide_White: G.Shop = Bp1~%% 'dungeon check
IF Rp2~%% = 255 AND Gp2~%% = 0 AND Bp2~%% < 10 THEN Point2~& = Collide_White: G.Shop = Bp2~%% 'dungeon check

'chests
'IF Point1~& = _RGB32(255, 0, 0) THEN Game.Chest = TRUE
'IF Point2~& = _RGB32(255, 0, 0) THEN Game.Chest = TRUE
' IF Point3~& = _RGB32(255, 0, 0) THEN Game.Chest = TRUE
' IF Point4~& = _RGB32(255, 0, 0) THEN Game.Chest = TRUE
'normal
IF Point1~& = Collide_White THEN Point1~& = FALSE ELSE Point1~& = TRUE
IF Point2~& = Collide_White THEN Point2~& = FALSE ELSE Point2~& = TRUE
' IF Point3~& = _RGB32(255) THEN Point3~& = TRUE ELSE Point3~& = FALSE
' IF Point4~& = _RGB32(255) THEN Point4~& = TRUE ELSE Point4~& = FALSE

IF Point1~& = FALSE OR Point2~& = FALSE THEN Result%% = TRUE
Player_Collision = Result%%
END FUNCTION

SUB ClearLayer (L&)
Old& = _DEST: _DEST L&: CLS: _DEST Old&
END SUB

SUB Control_lock
DO
LOOP WHILE Controls
END SUB

SUB DarkenImage (Image AS LONG, Value_From_0_To_1 AS SINGLE)
IF Value_From_0_To_1 <= 0 OR Value_From_0_To_1 >= 1 OR _PIXELSIZE(Image) <> 4 THEN EXIT SUB
DIM Buffer AS _MEM: Buffer = _MEMIMAGE(Image) 'Get a memory reference to our image
DIM Frac_Value AS LONG: Frac_Value = Value_From_0_To_1 * 65536 'Used to avoid slow floating point calculations
DIM O AS _OFFSET, O_Last AS _OFFSET
O = Buffer.OFFSET 'We start at this offset
O_Last = Buffer.OFFSET + _WIDTH(Image) * _HEIGHT(Image) * 4 'We stop when we get to this offset
'use on error free code ONLY!
$CHECKING:OFF
DO
  _MEMPUT Buffer, O, _MEMGET(Buffer, O, _UNSIGNED _BYTE) * Frac_Value \ 65536 AS _UNSIGNED _BYTE
  _MEMPUT Buffer, O + 1, _MEMGET(Buffer, O + 1, _UNSIGNED _BYTE) * Frac_Value \ 65536 AS _UNSIGNED _BYTE
  _MEMPUT Buffer, O + 2, _MEMGET(Buffer, O + 2, _UNSIGNED _BYTE) * Frac_Value \ 65536 AS _UNSIGNED _BYTE
  O = O + 4
LOOP UNTIL O = O_Last
'turn checking back on when done!
$CHECKING:ON
_MEMFREE Buffer
END SUB

SUB Fade_Out (L&)
FOR n! = 1 TO 0.00 STEP -0.05
  i2& = _COPYIMAGE(L&)
  DarkenImage i2&, n!
  _PUTIMAGE (0, 0), i2&
  _FREEIMAGE i2&
  _DELAY .03
NEXT
END SUB

SUB Fade_In (L&)
FOR n! = 0.01 TO 1 STEP 0.05
  i2& = _COPYIMAGE(L&)
  DarkenImage i2&, n!
  _PUTIMAGE (0, 0), i2&
  _FREEIMAGE i2&
  _DELAY .03
NEXT
END SUB


SUB MFI_Loader (FN$)
DIM Size(128) AS LONG, FOffset(128) AS LONG
OPEN FN$ FOR BINARY AS #1
GET #1, , c~%% 'retrieve number of files
FOR I~%% = 1 TO c~%%
  GET #1, , FOffset(I~%%)
  GET #1, , Size(I~%%)
  FOffset&(I~%%) = FOffset&(I~%%) + 1
NEXT I~%%
_KEYCLEAR
Layer(13) = LoadGFX(FOffset(2), Size(2))
Layer(14) = LoadGFX(FOffset(4), Size(4))
Layer(15) = LoadGFX(FOffset(1), Size(1))
Layer(16) = LoadGFX(FOffset(3), Size(3))
LoadData FOffset(5), Size(5)
CLOSE #1
IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
END SUB

SUB LoadData (Foff&, Size&)
IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
OPEN "temp.dat" FOR BINARY AS #3
dat$ = SPACE$(Size&)
GET #1, Foff&, dat$
PUT #3, , dat$
CLOSE #3

F1 = FREEFILE
OPEN "temp.dat" FOR BINARY AS #F1
GET #F1, , Map()
GET #F1, , D()
GET #F1, , I()
GET #F1, , Dungeon()
GET #F1, , DE()
CLOSE #F1
END SUB

FUNCTION LoadGFX& (Foff&, Size&)
IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
OPEN "temp.dat" FOR BINARY AS #3
dat$ = SPACE$(Size&)
GET #1, Foff&, dat$
PUT #3, , dat$
CLOSE #3
LoadGFX& = _LOADIMAGE("temp.dat", 32)
END FUNCTION

FUNCTION LoadFFX& (Foff&, Size&, Fize%%)
IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
OPEN "temp.dat" FOR BINARY AS #3
dat$ = SPACE$(Size&)
GET #1, Foff&, dat$
PUT #3, , dat$
CLOSE #3
LoadFFX& = _LOADFONT("temp.dat", Fize%%, "monospace")
END FUNCTION

FUNCTION LoadSFX& (Foff&, Size&)
IF _FILEEXISTS("temp.dat") THEN KILL "temp.dat"
OPEN "temp.dat" FOR BINARY AS #3
dat$ = SPACE$(Size&)
GET #1, Foff&, dat$
PUT #3, , dat$
CLOSE #3
LoadSFX& = _SNDOPEN("temp.dat")
END FUNCTION


SUB maptest
FOR y%% = 0 TO 15
  FOR x%% = 0 TO 15
  IF Dungeon(1, x%%, y%%).Doorways > 0 THEN LINE (x%% * 7, y%% * 7)-STEP(4, 4), _RGB32(255, 255, 0), BF
  IF _READBIT(Dungeon(1, x%%, y%%).Doorways, 0) THEN PSET (x%% * 7 + 2, y%% * 7), _RGB32(255, 0, 0)
  IF _READBIT(Dungeon(1, x%%, y%%).Doorways, 1) THEN PSET (x%% * 7 + 4, y%% * 7 + 2), _RGB32(255, 0, 0)
  IF _READBIT(Dungeon(1, x%%, y%%).Doorways, 2) THEN PSET (x%% * 7, y%% * 7 + 2), _RGB32(255, 0, 0)
  IF _READBIT(Dungeon(1, x%%, y%%).Doorways, 3) THEN PSET (x%% * 7 + 2, y%% * 7 + 4), _RGB32(255, 0, 0)
  NEXT x%%
NEXT y%%
_PUTIMAGE (0, 0)-STEP(299, 299), Layer(0), Layer(1), (0, 0)-STEP(149, 149)
CLS
_PUTIMAGE , Layer(1), Layer(0)
END
END SUB


Attached Files
.mfi   DeadlyTowers_06252023.MFI (Size: 1.88 MB / Downloads: 36)
Reply
#2
Wow Cobalt! long time, you came to see b+ Summer Banner didn't you? ;-))

OK tried the game and get's around fine! by me. You make it hard to walk off a ledge, but you do give a clue which ledges are dangerous.
b = b + ...
Reply
#3
(06-25-2023, 10:44 PM)bplus Wrote: Wow Cobalt! long time, you came to see b+ Summer Banner didn't you? ;-))

OK tried the game and get's around fine! by me. You make it hard to walk off a ledge, but you do give a clue which ledges are dangerous.
The banner is pretty cool, just lacking the Bikini clad hotties!


opps, yeah I did not think to mention that there are crumbled edges that you can fall from.

Thank you for the feed back!
Reply
#4
Oh man you have been looking at stone towers too long ;-))
b = b + ...
Reply
#5
@Cobalt Whoa dude! This is so cool.

That .MFI file... seems to be some kind resource data file like a doom .WAD file? Are you using any public tool to generate that or is it something custom that you made? Just curious.  Smile

I noticed that LoadGFX(), LoadFFX() and LoadSFX() are writing to temp files then _LOADIMAGE(), _LOADFONT() and _SNDOPEN() are used to load the resource. You can use the load-from-memory extensions of _LOADIMAGE(), _LOADFONT() and _SNDOPEN() to load the data directly from memory and avoid any file writes. That way your code can run in environments where there are no write-permissions.
Reply
#6
Great work! I'm looking forward to playing more of it when you have it further along.

I'll be keeping an eye on this.
Reply




Users browsing this thread: 1 Guest(s)