option explicit

' Deep Deadly Dungeons
' (C)2006 by Richard Clark rickclark58@yahoo.com
' Compiled using FB version .15b
'
' This program is free software; you can redistribute it and/or modify it
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
'
'This is the main program file.
'
'To compile with no sound, uncomment #Define cnosound
'To compile ascii version, uncomment #Define isascii
'To see combat return values, uncomment #Define tweak

'#Define cnosound
'#Define tweak
'#Define isascii

#Include "colors.bi"
#Include "types.bi"
#Include "decs.bi"
#IfNDef cnosound
#Include Once "fmod.bi"
#Include "sounds.bi"
#endif
#Include "utilities.bi"
#Include "maps.bi"
#Include "inv.bi"
#Include "stats.bi"
#Include "monster.bi"


Dim npcoord As mcoord
Dim skey As String
Dim mmenu As Integer

WindowTitle "Deep Deadly Dungeons 1.0"
randomize timer
Screen 18, 32, 2
'ScreenSet 0
width 80, 60

'init the fmod dll
#IfNDef cnosound
InitFMod
#endif
Title
LoadGraphics
tryagain:
mmenu = MainMenu
If mmenu = mquit Then
    #IfNDef cnosound
    FSOUND_Close
    #endif
    End
elseif mmenu = mloadgame then
    If LoadGame Then
        UpdateMap
        #IfNDef cnosound
        PlaySoundTrack
        #endif
    Else
        Color fbWhite, fbBlack
        Cls
        Print "Could not load game. Press any key."
        Sleep
        Do:Loop While Inkey$ <> ""
        Goto tryagain
    End If
Else
    levels.showhealth = True
    GenCharacter
    levels.currlevel = 1
    NewLevel
End If
Do  
    skey = Inkey$
    'PrintMessage "Key: " + skey
    If skey = key_up Then 'north
        npcoord = GetCoord(north, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_dn Then 'south
        npcoord = GetCoord(south, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_rt  Then 'east
        npcoord = GetCoord(east, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_lt Then 'west
        npcoord = GetCoord(west, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_home Then 'nw
        npcoord = GetCoord(nwest, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_pgup Then 'ne
        npcoord = GetCoord(neast, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_end Then 'sw
        npcoord = GetCoord(swest, player.pcoord)
        MovePlayer npcoord
    ElseIf skey = key_pgdn Then 'se
        npcoord = GetCoord(seast, player.pcoord)
        MovePlayer npcoord
    elseif skey = "<" then 'go up 1 level
        If player.pcoord.x = levels.startx And player.pcoord.y = levels.starty Then
            CheckForWin
            If levels.currlevel > 1 Then
                levels.lcount(levels.currlevel) += 1
                levels.currlevel -= 1
                NewLevel
            End If
        end if
    elseif skey = ">" then 'go down 1 level
        if player.pcoord.x = levels.endx and player.pcoord.y = levels.endy and levels.currlevel < maxlevels then
            levels.lcount(levels.currlevel) += 1
            levels.currlevel += 1
            NewLevel
        End If
    elseif skey = "?" then 'show command list
        ShowCommands
        UpdateMap
    ElseIf skey = "c" Then 'perform scan
        DoScan
    ElseIf skey = "d" Then 'perform dodge
        If player.isdodging Then
            player.isdodging = False
        Else  
            player.isdodging = True
        End If
        DrawMap
    ElseIf skey = "o"  Or skey = "b" Then 'open or bash a door
        DoOpenDoor skey
        UpdateMap
    elseif skey = "g" then 'get item
        GetInvItem
        UpdateMap
    elseif skey = "i" then 'show inventory
        ShowInventory
        UpdateMap
    ElseIf skey = "p" Then 'print attributes/skills
        cls
        CenterText 2, "Character Stats"
        PrintAttributes
        CenterText 55, "Press any key to continue."
        sleep
        Do While Inkey$<>"":Loop
        Cls
        UpdateMap
    ElseIf skey = "s" Then 'search
        DoSearch
        UpdateMap
    ElseIf skey = "t" Then 'target
        DoTarget
    ElseIf skey = "v" Then 'improve character
        DoImproveCharacter
        UpdateMap
    ElseIf skey = "x" Then 'show expanded minimap
        ExpandMiniMap
    ElseIf skey = "z" Then 'zap a wand'
        DoWand
    ElseIf skey = "D" Then 'disarm trap
        DoDisarmTrap
    ElseIf skey = "H" Then 'toggle health bars
        If levels.showhealth Then
            levels.showhealth = False
        Else
            levels.showhealth = True
        End If
        DrawMap
    ElseIf skey = "S" Then 'toggle sounds
        If soundon = True Then
            soundon = False
            PrintMessage "Sound off."
        Else
            soundon = True
            PrintMessage "Sound on."
        End If
    ElseIf skey = "R" Then 'load game
        If LoadGame Then
            UpdateMap
        Else
            PrintMessage "Could not load save game."
        End If
    ElseIf skey = "W" Then 'save game
        SaveGame
    ElseIf skey = "+" Then 'increase music vol
        sndvol += 2
        If sndvol > 256 Then sndvol = 256
        #IfNDef cnosound
        If finit And soundon Then
            FMUSIC_SetMasterVolume sndtrack, sndvol
        End If
        #endif
    ElseIf skey = "-" Then 'decrease music vol
        sndvol -= 2
        If sndvol < 0 Then sndvol = 0
        #IfNDef cnosound
        If finit And soundon Then
            FMUSIC_SetMasterVolume sndtrack, sndvol
        End If
        #endif
    'cheats
    ElseIf skey = "1" Then 'goto next level
        If cheater Then
            If levels.currlevel < maxlevels Then
                PrintMessage "Next level."
                levels.lcount(levels.currlevel) += 1
                levels.currlevel += 1
                NewLevel
            End If
        End If
    ElseIf skey = "2" Then 'goto previous level
        If cheater Then
            If levels.currlevel > 1 Then
                PrintMessage "Previous level."
                levels.lcount(levels.currlevel) += 1
                levels.currlevel -= 1
                NewLevel
            End If
        End If
    ElseIf skey = "3" Then 'kill all monsters
        If cheater Then
            PrintMessage "Monsters killed."
            KillAllMonsters
            UpdateMap
        End If
    ElseIf skey = "4" Then 'full health
        If cheater Then
            PrintMessage "Full health."
            player.attr.currhp = player.attr.maxhp
            UpDateMap
        End If
    ElseIf skey = "5" Then 'restock dungeon
        If cheater Then
            PrintMessage "Restocking dungeon."
            AddItems
            UpDateMap
        End If
    ElseIf skey = "6" Then 'increase strength
        If cheater Then
            PrintMessage "Increasing strength."
            player.attr.strg += 10
            player.attr.maxhp = player.attr.strg + player.attr.endu
            UpdateMap
        End If
    End If
    Sleep 10
Loop Until skey = "Q" Or skey = key_close
CleanUp
End

Sub CleanUp
    Dim i As Integer
    
    #IfNDef cnosound
    'stop the sound track
    StopSoundTrack
    'clear sounds
    ClearSounds
    'Close fmod
    FSOUND_Close
    #endif
    #IfNDef isascii
    'clean up the graphics
    ImageDestroy titem
    ImageDestroy tmap
    ImageDestroy tmonster
    ImageDestroy tweapon
    ImageDestroy tp
    #endif
End Sub

Sub LoadGraphics
    #IfNDef isascii
    titem = ImageCreate(480, 16)
    Bload "gfx\item.bmp", titem
    tmap = ImageCreate(320, 16)
    Bload "gfx\map.bmp", tmap
    tmonster = ImageCreate(832, 16)
    Bload "gfx\monster.bmp", tmonster
    tweapon = ImageCreate(784, 16)
    Bload "gfx\weapon.bmp", tweapon
    tp = ImageCreate(16, 16)
    #endif
End Sub

Sub DoDisarmTrap
    Dim As Integer istrap, i, tdr, stat
    Dim As mcoord tcoord
    
    istrap = False
    For i = north To seast
        tcoord = GetCoord(i, player.pcoord)
        If levels.traps(tcoord.x, tcoord.y).istrap = True Then
            tdr = levels.traps(tcoord.x, tcoord.y).dr 
            istrap = True
            Exit For
        End If
    Next
    If istrap Then
        stat = (player.skill.disarmtrap /10) + player.skill.moddisarmtrap
        If GetRoll(stat, tdr) Then
            PrintMessage "Disarmed trap."
            #IfNDef cnosound
                PlayWavSound sndplck
            #endif
            player.attr.expr += levels.traps(tcoord.x, tcoord.y).dr 
            player.attr.totexp += levels.traps(tcoord.x, tcoord.y).dr 
            levels.traps(tcoord.x, tcoord.y).ttype = 0
            levels.traps(tcoord.x, tcoord.y).istrap = False
            levels.traps(tcoord.x, tcoord.y).isseen = False
            levels.traps(tcoord.x, tcoord.y).damage = 0
            levels.traps(tcoord.x, tcoord.y).dr = 0
            UpdateMap 
        Else
            PrintMessage "Failed to disarm trap."
        End If
    Else
        PrintMessage "No traps found."
    End If
End Sub

Sub DoAddMonster
    Dim idx As Integer
    
    If GetPercentage(levels.currlevel * 4) Then
        idx = GetFreeMonsterIndex
        If idx > -1 Then
            AddAMonster idx
        End If
    End If
End Sub


Sub DoScan
    Dim i As Integer
    Dim stat As Integer
    
    For i = 1 To monarray
        With levels.monster(i)
            If PlayerCanSee(.mmcoord.x, .mmcoord.y) Then
                stat = (player.skill.scan \ 10) + player.skill.modscan + player.attr.modintl
                If GetRoll(stat, .stealth) Then
                    .isscanned = True
                    PrintMessage "Successfully scanned " + GetMonsterName(.id) + "."
                Else
                    PrintMessage "Failed to scan " + GetMonsterName(.id) + "."
                End If
            Else
                .isscanned = False
            End If
        End With
    Next i
End Sub

Sub ShowAsciiDead
    Dim As Integer row, col, i
    Dim As String pic, ch

    pic =       "XXXXXXXXXXXXXXXXXXXXXXX...'''.73JJJ3JJJJCJC!!.''.'..XXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXX.....'.''.!JJJJ3JJJJJJJ!!'..'....XXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXX............'.''',(CJJ33JJJJJJJ(=(*'.......XXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXX...'''''....'''''',=33JCJJJJCJJJJJ3%A%C,.......XXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'*7J333JCCC7==((??J33JJJJJJC7CCCJJ3$%A%3*.........XXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'CCC3$$$%AAAAAAAAJJ33JJJJJJ3$CJCCJJ333$%3*,,''............XXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'7(7CJCJJ$$$333$37JJ3JC3J=JC3C=3CCJJJJJ=$$$3JCC7==(?!!*,'.......XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'=C7CJJJ3$$$3J3$3JJJJ333=?7J7?CJJCCJJC(=7333$$%%%%%$%AAAAA%C''..XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'CCCCJJJ3$$$3J3$3JJJC3(?!(=C7?=(%C37C7C=C7CCCCCCCCJJJ3333$3!'...XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'CCCCJJJJ3$$3JJ$3JJJ3CJJ77C7CJ7C((J=7CC7C7CCCJJJJJCCJJJ3J3C,'...XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXX.777CCJJJJ3$3JJ$3JJJJJJ7=C7C7J3JJJ7C=CC777CCJJJJJJJJJJ33J3C*'''.XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXX.(7CCCJJJ3333JJ$3JJJCJ*(!?7C7=?7(CJ==7777CCJJJJJJJJJJ33333C*.'..XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXX.'**!(==CJ333JC33JJJJJCJ==(7=*(=77C?77=7CCCJJ3JJJJJ333$$$$C*''..XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXX.........',**!((CJJJJ==7(===(=JC7?=7777CCJJJ333JJJ333$$$$7*'''.XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXX.....'',CJJ3J7=7==(CJC((=777=7CCJJ33333J3333%$%$=*.''.XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXX....,7333J7((==!=((CCC77(,!!?(==7CCCJ333%%%%?''''.XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXX...'(J3JJJJC7CJCCCCC7('.......'''',,*!?(==,'....XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXX....,=3JJJ3JJJJ=(=(*..........................XXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXX....?33333JJJJJ(,*....XXXXXXXX...........XXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXX...?JJ333JJJJJ=**...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXX...=JJJJ3JJJJJ7!*'.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX..CJJJJJJJJCCC(!'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXX...$JJJJJJJJC77=*,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXX..,3JJCJJJJC7777!,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXX...?JJCCJJJCC777J?*.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXX...7JJCJJJCCC777J(*.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXX....3JJCCCJCC7=7CJ7*'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXX.....3JJCCJJCCC77CJC!,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXX....,3JJCCJJCCC7CJJJ?!.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXX.....!3JCCCJJCCC7CJ3J(!,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXX......(3JJCCJJJCC7CJ3J7!!.XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXX.......CJCCJCJJJCC7J33JC?!'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXX.......'CJCCJCJJJCC7CJ3J=?!*XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXX........?CCCCCCJJJCC7CJ3JC(!*.XXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXX........'CCC7CCCJJJCC7CJ3JC7??,XXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXX..........!CCCCCCCCJJCC77J3JCC((?.XXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXX.''''''''''7CCC7CCCCCCCCC7C33CC7==,XXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXX..',???*,,''?CCCCCCCCCCCCCC7C33JCCC(!.XXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXX.''!3%%$3JC7(CCCCCCCCCCCCCCC7CJJJCCC(('.XXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXX.'',(%A%%%%$$CCCC77CC7CCCCCCCCCCJJCCC7?(*..XXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXX..',*(%AA%%%%%377CCC77C7CC7CC77CCCCJCCC7*?=*..XXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'''*J%A3%%AAAA$CCC777777C777777CCCCCC7C7??=(!'.....XXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXX.'''*J$J$33$AA%%%33JJCCC777C77C7777CCC77C7=(!=C(*,,,''.......XXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXX.'',=7(=C7C$%%%%AA%%%%$3JJCCCCCC77CCCC7C7=(?==(?7CC7=(!!*,'.......XXXXX" + Chr$(1)
    pic = pic + "XXXXXXX.',7A7===(((((=7C3$$%%A%%%%$$$3JCCCCCCC77====7?!?JJJCJJJJC777(,''.XXXXX" + Chr$(1)
    pic = pic + "XXXXXXX.'C$%3JC7==((??!((((=7CJ3$%%%%$$$$$$$33JC77777(*73JJJJJ3JCCJJJ*'''XXXXX" + Chr$(1)
    pic = pic + "XXXXXXX.'777CJJ333JC7=(=(????(((((=7CJ3$%%%%%%%%$$3JJ7C33JJJ33JJCJJJ=,!''XXXXX" + Chr$(1)
    pic = pic + "XXXXXXX..7CCC77CCCJJJJJJCC7=((?(((((((=7CCJ3$%%%%%%%%$$333J333JCJJ3J!*C,'XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.'*?((=7C7CC7==77CCJJJJC777===(=======7CJ3$$$$$333J33JJJJ3J(*(C.'XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX.',,,,,*!?(77777===(==7CJ33JJJCC77========7777CJJJJJJCCJJC7!!C?.'XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXX.'',,,,',,,*?((==(=((==7CJJ333333JCCC77=7=====777==777C=(*(J,.'XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXX..''''',',,,,,,*!?(==7CCCCC7CJJ333333JJCC7777====777C(!!C7.''XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXX......'''''',,,,**!?==7C77CCCCCCCCJJ3$$333JCCC777C7?(J!.''XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXX....'''',,,,**!?(777CJCC7==777CJ333$$33JJJ7$C'.,'XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX....''',,'',,*!(==77777====77CJ33$$$$J?.'''XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.....''''',,,,*??((==777CCCJJJJ=,.','XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX....'''''',,**!?=7CCCJCC?.',,'XXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..'''''''''',*?(=77?.,,,'XXXXX" + Chr$(1)
    
    Color  fbWarmGrey, fbIvoryBlack
    Cls
    row = 2: col = 1
    For i = 1 To Len(pic)
        ch = Mid(pic, i, 1)
        If ch = Chr$(1) Then
            row += 1
            col = 1
        ElseIf ch = "X" Then
            col += 1
        ElseIf ch = "C" Then
            Color  fbSlateGreyDark, fbIvoryBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "J" Then
            Color  fbWarmGrey, fbIvoryBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "." Or ch = "'" Then
            Color  fbColdGrey, fbIvoryBlack
            col += 1
            Locate row, col
            Print ch
        Else
            Color  fbDimGrey, fbIvoryBlack
            col += 1
            Locate row, col
            Print ch
        End If
    Next
    Color fbWhite, fbIvoryBlack
    CenterText 57, "  " + Trim$(player.pname) + " perished on level " + Str$(levels.currlevel) + " with " + Str$(player.attr.totexp) + " total XP.  "     
End Sub

Sub CheckForDead
    Dim skey As String
    Dim stext As String
    
    If player.attr.currhp <= 0 Then
        #IfNDef cnosound
        StopSoundTrack
        PlayWavSound sndpded
        #endif
        Cls
        #IfNDef isascii
        Bload "gfx\dead.bmp"
        Color fbwhite, fbBlack
        stext = Trim$(player.pname) 
        stext += " has perished on Level " 
        stext += Str$(levels.currlevel)
        stext += " with " + Str$(player.attr.totexp) + " total experience."
        CenterText 59, stext
        #Else
        ShowAsciiDead
        #endif
        #IfNDef cnosound
        PlayDeadTitle
        #Else
        Sleep
        #endif
        CleanUp
        End
    End If
End Sub

Sub ShowAsciiWin
    Dim As String pic, ch
    Dim As Integer row, col, i
    
    pic =        "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'7|C7|7.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'!A#C7JA@C!.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+=Ð##+=!¦$55@(XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX33(C7+=C$J7J3XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX$A¦(7¦(3CC3$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX!A$%A¦+=53$+=,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.,7@%C73#7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX*A55%J%Ð@(,XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX(@$AAA+=$#A@¦.XXXXXXXX..XXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXX.**,..XXXX'CWÐ3@$J7$#7#W3*X.***+=7+=C+=¦,**.XXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXX,'(+=¦¦$AJJ$%7+=C¦JA#5$$C+=((J3%5J7C$A$35@5%A5AJCJ(XXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXX.'!7%%A5Ð#Ð5$AA%3A#5$#A7+=$A%J3C$%$A5@%#$333CCCJ+=7#@%$A.XXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXJ$A##5#5#5%JCJJCCCJ3$53JJ%A%$C73$%%+=CCJ777CC777J%5@###J.XXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXX.*A#5%%JJCCJCCC77+=+=+=+=+=77CJ3$$JCJJJC7J$%5A$%$$$$%%%$$A5XXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX($A##J33$$$%3J7777CJCJJCCJ3$%$CJJ$3JC7+=(¦¦*!!*,,¦(73A5%$A5AXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX!5##53%AJ7+=*''....',',,,*(3%A#JJ3$3,'..X..XXXXXXX.,(!$#%%Ð@XXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX'@@#A55(¦¦XXXXXXXXXXXX.''¦@#%5%J$5C,'XXXXXXXXXXXXXX+=!(##ÐW#7XXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX7#W@#5%¦C!XXXXXXXXX..¦((¦+=(A55J77%%¦¦¦((*XXXXXXXXX.A+=C#@ÐWA,XXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX(@WÐ#537+=CXXXXX'*!+=37(¦¦!,,CÐ@5A%##C*!!(J7!*'XXXX¦%$JA5@WÐ3XXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX.%MW##3J73'X..(+=(+=C7(!!*,',7Ð@A3C%@%,**!+=C7((¦*.J5J+=A%@ÐWXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXX.%ÐWÐ##377C¦77(!!J77+=+=¦!*,,(%AA77$##¦((+=+=7C!!(C3AJC%%#ÐWWXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXX,%ÐW@#5CJ7(7+=!**C77777(¦!,!($@%3A5#7CC7+=(¦¦¦(77(3%3A#ÐW5WWXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXX%WÐ@@5$C!!+=!!¦!¦(+=77CC+=¦!%@5C(C#A+=¦¦¦!!*¦(((¦+=$7%A@@$.XXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXX'C#@#553+=!+=(((!!¦¦¦¦((+=7¦#$5+=!(#$(,,,**'!+=+=+=((CJ$5%XXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXX!5@#A%J*(((¦¦**¦!¦+=(+=+=+=@¦@%+=3577*,''',*+=7+=(7J(%Ð*XXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXX!W@%C$¦¦(((**,,,*¦¦¦¦!@Ð@A3%A#J,..'',¦(¦!¦J+=JA,(7J(%XXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXX.%@3J7+=!!!!!!*,,*!¦(+=(###%+=+=5@7'..'*!¦***!¦+=(7%XXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXX,553+=(!***!¦!!!!*,*!¦%@53(+=5@!.'****,,*¦C(7$@'(%XXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXX+=@%+=¦*77',****!!***¦$@5#J$5@,''''''...(%$7AA'BXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXA5$C$5A+=*7+=¦*(J+=!7C%#5C(C55!..***,.',*%@A@QXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXCA%@#Ð3**¦+=+=!*,,*!C3#5(*75%C..,,'''!JC#@%A+=XXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXX.($$3#ÐA777**,,,,,*+=C%53C%J3*...'''!J5A@$$JJXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXX+=3(AC(5@5%%(*,*,,**!7$37(J3!'**.','!((JA%A+=3XXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXJ77+=5C$#57((¦**,*3C((7%5A$(!¦3J',,,,'(A5%+=C5XXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXX¦CC7C55A5C**!***,CA%$%$3JJJJJ%!..'''*J5%(C3Ð3XXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXX.3(777%@#3+=!,*,*,¦JJJJ+=**77(!,',*(+=J5$7¦+3XXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXX'$J¦¦JC7$A55%J7¦¦¦¦(¦7J3C$+=!,!+=77337(¦((7%ÐÐXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXX3ÐC¦!CJ$J3J3$A##5AAAA57*$A3J77+=(!!(+=¦!7%@Ð#XXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXX!M@%7+=!J3$%JC(¦¦(¦¦((¦*C*,*,,*¦¦+=(¦!(J$#ÐÐCXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXMM@537+=J$$3C7¦¦7(*!((A%3(,',!(C7¦+=C3%5Ð@@.XXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXX3W@#%%A$J3$377+=((*,.+=+=+=A3,,¦+=777$55A%#@XXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXX.JWÐA@55##AC(C3+=(3!!7'+=C!*(JC+=¦(A5$555@(XXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXX*5@Ð#$J#57+=¦CAJJ*7+=*(,($*+=37J%@@55AA'XXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXX*!J@#%$#5##A%%$7(,!(7+=7%3%J+=##A#C!,XXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXX,+=3$#@5@#5@5J!'.!,!C#AA#A5J!¦XXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXX''+=(J5A$$AA$+=*(7JJ%AAC,*'XXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX,,',(+=¦(77$C+=7('X.XXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic +  "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX..'.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)

    Color  fbGold, fbBlack
    Cls
    row = 2: col = 1
    For i = 1 To Len(pic)
        ch = Mid(pic, i, 1)
        If ch = Chr$(1) Then
            row += 1
            col = 1
        ElseIf ch = "X" Then
            col += 1
        ElseIf ch = "," Or ch = ";" Then
            Color  fbPurple, fbBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "*" Then
            Color  fbDarkOrange, fbBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "7" Then
            Color  fbPeachPuff, fbBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "J" Then
            Color  fbGoldOchre, fbBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "W" Then
            Color  fbRosyBrown, fbBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "5" Then
            Color  fbTan, fbBlack
            col += 1
            Locate row, col
            Print ch
        ElseIf ch = "#" Then
            Color  fbSnow, fbBlack
            col += 1
            Locate row, col
            Print ch
        Else
            Color  fbGold, fbBlack
            col += 1
            Locate row, col
            Print ch
        End If
    Next
    Color fbWhite, fbBlack
    CenterText 55, "All Hail King " + Trim(player.pname) + "!"
    CenterText 57, "Long Live the King!"

End Sub

Sub CheckForWin
    Dim skey As String
    Dim stext As String
    
    With player.hasorbs
        If .hascrown = True And _
           .hasredorb  = True And _
           .hasblueorb  = True And _
           .hasgreenorb  = True And _
           .hasyelloworb  = True And _
           .haswhiteorb  = True Then
            Cls
            #IfNDef isascii
            Bload "gfx\win.bmp"
            #Else
            ShowAsciiWin
            #endif
            #IfNDef cnosound
            StopSoundTrack
            PlayWavSound sndtrum
            PlayWinTitle
            #Else
            Sleep
            #endif
            CleanUp
            End
        Else
            PrintMessage "The way is magically barred."
        End If
    End With
End Sub

sub UpdateMap
    CalcLOS
    DrawMap
end sub

sub NewLevel
    Cls
    ClearMap
    If levels.currlevel = 1 Then
        levels.tmaptype = dungeon
        BuildDungeon
    ElseIf levels.currlevel = maxlevels Then
        levels.tmaptype = cavern
        BuildCavern
    Else    
        If GetPercentage(25) Then
            levels.tmaptype = cavern
            BuildCavern
        Else
            levels.tmaptype = dungeon
            BuildDungeon
        End If
    End If
    levels.mapscheme = GetPercentage(49)
    UpdateMap
    #IfNDef cnosound
    PlaySoundTrack
    #endif
end sub

Function GetTile(x, y As Integer) As Integer
    Return levels.map(x, y)
End Function

Function GetSoundValue(initval As Integer = 0) As Integer
    Dim As Integer sndval = 8 + initval
    Dim As Integer i
    
    'get the armor soundamount
    If player.parmor.typeid = armors Then
        sndval += player.parmor.armor.noise
    End If
    'get shield sound amount
    If player.righthand.typeid = shields Then
        sndval += player.righthand.shield.noise
    End If
    If player.lefthand.typeid = shields Then
        sndval += player.lefthand.shield.noise
    End If
    'check for lantern being carried
    If player.righthand.typeid = lights Then
        sndval += player.righthand.light.noise    
    End If
    If player.lefthand.typeid = lights Then
        sndval += player.lefthand.light.noise    
    End If
    'check inventory
    For i = 0 To 25
        With player.inventory(i)
            If .typeid > 0 Then
                Select Case .typeid
                    Case supplies
                        sndval += .supply.noise
                    Case necklaces
                        sndval += .necklace.noise
                    Case potions
                        sndval += .potion.noise
                    Case rings
                        sndval += .ring.noise
                    Case wands
                        sndval += .wand.noise
                    Case weapons
                        sndval += .weapon.noise
                    Case armors
                        sndval += .armor.noise
                    Case lights
                        sndval += .light.noise
                    Case ammos
                        sndval += .ammo.noise
                    Case shields
                        sndval += .shield.noise
                    Case scrolls
                        sndval += .scroll.noise
                End Select
            End If
        End With
    Next
    'if player is sneaking reduce sound amount
    If player.issneaking Then
        sndval = sndval / 2
    End If
    
    Return sndval
End Function

Sub MovePlayer(ncoord As mcoord)
    dim tile as integer
    Dim idx As Integer
    Dim sndval As Integer
    Dim heal As Integer
        
    If IsMonsterLoc(ncoord.x, ncoord.y) Then
        idx = GetMonsterIndex(ncoord.x, ncoord.y)
        If player.righthand.typeid = weapons  Then
            If IsProjectile(player.righthand.weapon) = False Then
                DoCombat idx
            Else
                If HasAmmo(player.righthand.weapon) Then
                    DoCombat idx, wpRight
                Else
                    PrintMessage "No ammo for weapon."
                End If
            End If
        ElseIf player.lefthand.typeid = weapons Then
            If IsProjectile(player.lefthand.weapon) = False Then
                DoCombat idx
            Else
                If HasAmmo(player.lefthand.weapon) Then
                    DoCombat idx, wpLeft
                Else
                    PrintMessage "No ammo for weapon."
                End If
            End If
        Else
            DoCombat idx
        End If
    Else
        tile = GetTile(ncoord.x, ncoord.y)
        if tile = doorns or tile = doorew then
            If levels.isdoor(ncoord.x, ncoord.y).islocked Then
                PrintMessage "Door is locked."
                #IfNDef cnosound
                PlayWavSound sndthud
                #endif
            Else
                ClearMonsterScan
                levels.map(ncoord.x, ncoord.y) = IIf(levels.map(ncoord.x, ncoord.y) = doorew, dooropew, dooropns)
                player.pcoord.x = ncoord.x
                player.pcoord.y = ncoord.y
                sndval = GetSoundValue(4)
                GenSoundMap ncoord.x, ncoord.y, sndval
                CheckLight
                UpdateMap
                DoAddMonster
                RoamMonsters
            End If
        elseif tile <> wall and tile <> secretwall then
            ClearMonsterScan
            player.pcoord.x = ncoord.x
            player.pcoord.y = ncoord.y
            If levels.map(player.pcoord.x, player.pcoord.y) = water Then
                sndval = GetSoundValue(4)
            Else
                sndval = GetSoundValue
            End If
            GenSoundMap ncoord.x, ncoord.y, sndval
            CheckLight
            UpdateMap
            #IfNDef cnosound
            If levels.map(player.pcoord.x, player.pcoord.y) = water Then
                PlayWavSound sndspls
            End If
            #endif
            CheckTrap
            DoAddMonster
            RoamMonsters
        End If
        If GetPercentage(player.attr.recovery) Then
            heal = GetRandom(1, 10)
            player.attr.currhp += heal
            If player.attr.currhp > player.attr.maxhp Then
                player.attr.currhp = player.attr.maxhp
            End If
        End If
    End If
end sub

Sub ShowAsciiTitle
    Dim As String pic, ch
    Dim As Integer row, col, i
    
    pic =       "XXXXXXXXXXXXXXXXXXXXXXXXXXXX..XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXXX7A!XXXXXXX.*.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXX..'.XXXXXXXXXXXXXXC©#(*¦(!=7C=*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXX.=3$%5@@7*.X*777JJJ7CC5@@@5%A(¦*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXX7#A#%JAAA5AJAÐWÐMÐA5#5#AQQ%$#%JCC7(*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXX'7J5=(335$%$$$$$$$$AA%$3$$%A%$%5%(*,.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXX,¦7CA$=(3(****!¦(7CCJJ35%3A55A%%3=,XXX'*7C33$%J$C=¦,.XXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXX!**(%#@@@###AJÐ@5%J$('X'J3W@WÐÐÐÐÐÐ@@#5A37'XXXX''!%!,¦=XXXX" + Chr$(1)
    pic = pic + "XXXX.7WWÐÐ%3==C%7J$A#@Ð@@@#AA5AA%%%J=!!*3W©WWM©©©©©M©MWMWÐ#5$=.X.3@ÐMÐÐ$,XXXX" + Chr$(1)
    pic = pic + "XXX'7C3#@MW5%%3%A55AA5AAAA5%5%A%37=,XX'#MMWM©®©©MMWÐÐÐÐWWWW@#%CC#©MÐ5##%!XXXX" + Chr$(1)
    pic = pic + "XXX','!¦((==¦((!*****!',%W©®®©W5$3!!X,Ð©MM©®®©©MWÐ533$$5ÐMMW@53ÐM®W5#%=¦.XXXX" + Chr$(1)
    pic = pic + "XXXXXX.'.XXXXXXXXXXXXX!5W©®®©W@A3¦*'.W©WM©®®©©MÐ#J!*¦JAÐW©©WÐ#%5Ð©M$,.XXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXX*$ÐM©©©MW#%3¦!*X3®MM®®®®©MÐ#C'XX!A@W©®©M©@$5MÐ©©@7'XXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXX,$ÐM©®©MWÐ#%C*!*X7©©M©®®®®MW#3,XX'%@M©®®©Ð©©5@ÐM#W©©@C'XXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXX.CÐM©®®©©W@@AC,!.XXW®WM©®®®©MÐA=XX,%Ð©®®®©M5@ÐWÐC$W5ÐM©M#¦XXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXX'$W©®®®©©W@@5A*¦,XXC©MW©®®®©MÐ#%,X!5W©®®®®M#%CA®©WÐ%55@M©MÐ(XX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXX.%W©®®®©©MMÐ#5$,(''$MM@M©®®®©W@57.*5M©®®®®©W53@AWW@©Ð$A5Ð©©M5*X" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXCÐM©®®®©©©WWÐ#%=!=J%AA@WM©MMM55%!X7W©®®®©MÐ#5#WM@ÐM©Ð$A#W©®M@3X" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXX.#W©®®®®©©©©©©W@5$CCC$5@ÐÐMÐMMA$7.*JÐ©M@#@ÐWM®®©W#M@Ð%%@W©®®ÐW3X" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXX,@W©®®®®©©©©®®®®©MW@53JJ%@@@©©W3*X*7#W55ÐW©®©MWÐAW©ÐAW©©®®©MÐ#*X" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXX.#W©®®®©©©M©©©©©©MWMWWÐ#%C35ÐM©W=XXX(%#%#ÐWÐ@55AWW#@®®®®©MÐ#$*XX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXX7@WM©©©©©©MWWMMMÐ#A%%3%A#5$3AMM#7'XX*A55A5%$$5©©@ÐMMWW@5$=,.XXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXX,Ð##ÐW©©©©MM©MW@#A%$%#3C%$$$$$5Ð##CXX!#Ð#@MA%$5@ÐÐÐ5=(¦*'.XXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXX,AW#$%#ÐWMMMWW#@5AJ$JJ5ÐJ$A#@@#5@@57XXX!'$$7!...XXXX'XXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXX.,.X.*=J%555%ÐM@5C%#$C@#=,¦J%#@@#7'XXXXX.XXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXX..',*#Ð#@WÐ#$7#Ð$XXXX...XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    pic = pic + "XXXXXXXXXXXXXXXXXXXXXXXXXX*$%3J=¦,,*'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" + Chr$(1)
    Color  fbEmeraldGreen, fbLampBlack
    Cls
    row = 12: col = 1
    For i = 1 To Len(pic)
        ch$ = Mid(pic, i, 1)
        If ch$ = Chr$(1) Then
            row += 1
            col = 1
        ElseIf ch$ = "X" Then
            col += 1
        ElseIf ch$ = "®" Then
            Color  fbGold, fbLampBlack
            col += 1
            Locate row, col
            Print ch$
        ElseIf ch$ = "©" Then
            Color  fbYellowLight, fbLampBlack
            col += 1
            Locate row, col
            Print ch$
        ElseIf ch$ = "Q" Then
            Color  fbTomato, fbLampBlack
            col += 1
            Locate row, col
            Print ch$
        Else
            Color  fbEmeraldGreen, fbLampBlack
            col += 1
            Locate row, col
            Print ch$
        End If
    Next
    Color fbRed, fbLampBlack
    CenterText 5, "Deep Deady Dungeons"
    Color fbGold, fbLampBlack
    CenterText 52, "The Search for the Crown of Alegare"
End Sub

Sub Title
    
    #IfNDef isascii
    If Len(Dir$("gfx\title.bmp")) > 0 Then
        Bload "gfx\title.bmp"
    End If
    #Else
    ShowAsciiTitle
    #endif
    #IfNDef cnosound
    PlayTitle
    #Else
    Sleep
    Do:Loop While Inkey$=""
    #endif
end sub

'draws the current status
sub DrawStats
    dim s as string
    Dim i As Integer
    
    'Line (0, 340) - (639, 344), fbMarsOrange, BF
    Color fbWhite, fbBlack
    Locate 57, 1
    Print Space$(55);
    Locate 57, 2
    if player.righthand.typeid <> 0 then
        print GetInventoryItemDesc(player.righthand); " ";
    end if
    if player.lefthand.typeid <> 0 then
        print GetInventoryItemDesc(player.lefthand); " ";
    end if
    if player.parmor.typeid <> 0 then
        Print GetInventoryItemDesc(player.parmor);
    end if
    Color fbWhite, fbBlack
    Locate 58, 1
    Print Space$(80);
    s = "Dungeon Level: "+ Str$(levels.currlevel)
    locate 58, 79 - len(s)
    print s;
    Color fbWhite, fbBlack
    Locate 59, 1
    Print Space$(80);
    Locate 59, 2
    print trim$(player.pname);" ";
    print " HP:";player.attr.currhp;"/";
    print trim$(str$(player.attr.maxhp));
    print " Exp:";player.attr.expr;
    s = ""
    if levels.isdark then
        s += " (Dark)"
    End If
    If levels.map(player.pcoord.x, player.pcoord.y) = water Then
        s += " (Water)"
    End If
    If player.isdodging Then
        s += " (Dodging) "
    End If
    If cheater Then
        s += " (Cheat) "
    End If
    If easteregg Then
        s += " (Egg) "
    End If
    Locate 59, 79 - Len(s)
    Print s;
    PrintMessage
End Sub

function MainMenu() as integer
    dim mchoice as integer
    dim ky as string
    dim row as integer
    dim done as integer = False
    dim oldrow as integer
    dim menu1 as integer = 10
    dim menu2 as integer 
    dim menu3 as integer 
    dim smenu1 as string = " (N)ew Game  "
    dim smenu2 as string = " (L)oad Game "
    dim smenu3 as string = " (Q)uit Game "
    
    menu2 = menu1 + 2
    menu3 = menu2 + 2
    
    Color fbWhite, fbBlack    
    cls
    color fbAlizarinCrimson, fbBlack
    CenterText 2, "Deep Deadly Dungeons"
    color fbCadmiumLemon, fbBlack
    CenterText 4, "The Search for the Crown of Alegare"
    color fbWhite, fbBlack
    CenterText menu1, smenu1
    CenterText menu2, smenu2
    CenterText menu3, smenu3
    row = menu1
    oldrow = 0    
    do
        if oldrow <> row then
            color fbWhite, fbBlack
            CenterText menu1, smenu1
            CenterText menu2, smenu2
            CenterText menu3, smenu3
            if row = menu1 then
                color fbBlack, fbWhite
                CenterText menu1,  smenu1
            elseif row = menu2 then
                color fbBlack, fbWhite
                CenterText menu2, smenu2
            elseif row = menu3 then
                color fbBlack, fbWhite
                CenterText menu3, smenu3
            end if
            oldrow = row
        end if
        ky = inkey$
        if ky = key_up then 'up
            if row = menu1 then 
                row = menu3
            else
                row = row - 2
            end if
        elseif ky = key_dn then 'down
            if row = menu3 then 
                row = menu1
            else
                row = row + 2
            end if
        ElseIf ky = key_esc Or ky = key_close Then
            mchoice = mquit
            done = True
        elseif ky = key_enter then
            if row = menu1 then
                mchoice = mnewgame
                done = True
            elseif row = menu2 then
                mchoice = mloadgame
                done = True
            elseif row = menu3 then
                mchoice = mquit
                done = True
            end if
        elseif ky = "N" or ky = "n" then
            mchoice = mnewgame
            done = True
        elseif ky = "L" or ky = "l" then
            mchoice = mloadgame
            done = True
        elseif ky = "Q" or ky = "q" then
            mchoice = mquit
            done = True
        end if
    loop until done
    return mchoice
end function

sub ShowCommands
    Dim As Integer col, row
    
    color fbAlizarinCrimson, fbBlack
    cls
    CenterText 2, "Deep Deadly Dungeons Commands"
    color fbWhite, fbBlack
    col = 2
    row = 4
    Locate row, col
    Print "Esc : Exit program"
    row += 2
    Locate row, col
    Print "Arrows/Numpad: Move character"
    row += 2
    Locate row, col
    Print "+ : Increase music volume"
    row += 2
    Locate row, col
    Print "- : Decrease music volume"
    row += 2
    Locate row, col
    Print "< : Ascend staircase"
    row += 2
    Locate row, col
    print "> : Descend staircase"
    row += 2
    Locate row, col
    print "? : Show commands"
    row += 2
    Locate row, col
    print "b : Bash door"
    row += 2
    Locate row, col
    Print "c : Scan"
    row += 2
    Locate row, col
    Print "d : Dodge"
    row += 2
    Locate row, col
    print "g : Get item"
    row += 2
    Locate row, col
    print "i : Inventory"
    row += 2
    Locate row, col
    print "o : Open door"
    row += 2
    Locate row, col
    print "p : Print character stats"
    row += 2
    Locate row, col
    print "s : Search for traps & secrets"
    row += 2
    Locate row, col
    Print "t : Target projectile weapon"
    row += 2
    Locate row, col
    Print "v : Improve chracter"
    row += 2
    Locate row, col
    Print "z : Zap a wand"
    row += 2
    Locate row, col
    Print "x : Expnad mini-map"
    col = 36
    row = 4
    Locate row, col
    print "D : Disarm trap"
    row += 2
    Locate row, col
    Print "H : Toggle health bars"
    row += 2
    Locate row, col
    Print "Q : Quit Game"
    row += 2
    Locate row, col
    Print "R : Load Game"
    row += 2
    Locate row, col
    Print "S : Toggle sound effects"
    row += 2
    Locate row, col
    Print "W : Save game"
    CenterText 59, "Press any key to continue."
    sleep
    do while inkey$<>"":loop
end sub

sub DoSearch
    dim as integer i, j
    dim as integer px, py
    dim as integer dist
    Dim As Integer stat, sndval
    
    'current player position
    px = player.pcoord.x
    py = player.pcoord.y
    #IfNDef cnosound
    PlayWavSound sndsrch
    #endif
    'iterate through the map
    for i = 0 to dunw - 1
        for j = 0 to dunh - 1
            'calc the distance from player to point
            dist = CalcDist(px, i, py, j)
            if dist <= 1 and levels.isseen(i,j) = True then
                If levels.map(i, j) = secretwall Then
                    stat = (player.skill.search / 10) + player.skill.modsearch + player.attr.modintl
                    If GetRoll(stat) Then
                        levels.map(i, j) = mfloor
                        sndval = GetSoundValue(8)
                        GenSoundMap px, py, sndval
                        PrintMessage "You found a secret wall."
                        #IfNDef cnosound
                        PlayWavSound sndscrp
                        #endif
                    End If
                ElseIf levels.traps(i, j).istrap = True Then
                    stat = (player.skill.search / 10) + player.skill.modsearch +  player.attr.modintl
                    If GetRoll(stat, levels.traps(i, j).dr) Then
                        levels.traps(i, j).isseen = True
                        sndval = GetSoundValue(4)
                        PrintMessage "You found a trap."
                        GenSoundMap px, py, sndval
                        #IfNDef cnosound
                        PlayWavSound sndscrp
                        #endif
                    End If
                end if
            end if
        next j
    next i
end sub

sub CheckTrap
    dim dam as integer
    dim def as integer
    Dim stat As Integer
    
    If levels.traps(player.pcoord.x, player.pcoord.y).istrap Then
        #IfNDef cnosound
        PlayWavSound sndtrap
        #endif
        'get the armor protection
        If player.parmor.typeid > 0 Then
            def = player.parmor.armor.ac \ 10
        else
            def = 0
        end if
        dam = levels.traps(player.pcoord.x, player.pcoord.y).damage - def
        'does the player dodge the trap
        stat = (player.skill.dodge / 10) + player.skill.moddodge + player.attr.modagl
        If GetRoll(stat, levels.traps(player.pcoord.x, player.pcoord.y).dr) Then
            PrintMessage "You dodged a trap!"
            levels.traps(player.pcoord.x, player.pcoord.y).isseen = True
            player.attr.expr += levels.traps(player.pcoord.x, player.pcoord.y).dr
            player.attr.totexp += levels.traps(player.pcoord.x, player.pcoord.y).dr
        Else
            if dam < 1 then
                PrintMessage "You triggered a trap but your armor saved you!"
                levels.traps(player.pcoord.x, player.pcoord.y).isseen = True
            else
                player.attr.currhp -= dam
                levels.traps(player.pcoord.x, player.pcoord.y).isseen = True
                PrintMessage "You triggered a trap for " + str$(dam) + "damage!"
                levels.traps(player.pcoord.x, player.pcoord.y).isseen = True
                CheckForDead
            end if
        end if
    end if
end sub

sub CheckLight
    with player.haslight
        if .typeid = lights then
            if .light.count > 0 then
                .light.count -= 1
                if .light.count = 0 then
                    .light.range = 0
                end if
            end if
        end if
    end with
end sub

sub DoOpenDoor(tp as string)
    dim ky as string
    dim as integer x, y
    dim as integer dr, dstr
    Dim As Integer stat, roll, sndval
    
    PrintMessage "Which direction? (Arrow keys)"
    do
        ky = inkey$
        if ky <> "" then
            if ky <> key_up and ky <> key_dn and ky <> key_rt and ky <> key_lt then
                PrintMessage "Which direction? (Arrow keys)"
            end if
        end if
    loop until ky = key_up or ky = key_dn or ky = key_rt or ky = key_lt 
    x = player.pcoord.x
    y = player.pcoord.y
    if ky = key_up then
        y = y - 1
    elseif ky = key_dn then
        y = y + 1
    elseif ky = key_rt then
        x = x + 1
    elseif ky = key_lt then
        x = x - 1
    end if
    if levels.map(x, y) = doorew or levels.map(x, y) = doorns then
        If tp = "o" Then
            #IfNDef cnosound
            PlayWavSound sndplck
            #endif
            dr = GetDR
            stat = (player.skill.picklock / 10) + player.skill.modpicklock + player.attr.moddext
            If GetRoll(stat, dr) Then
                levels.map(x, y) = IIf(levels.map(x, y) = doorew, dooropew, dooropns)
                player.attr.expr += dr
                player.attr.totexp += dr
                PrintMessage "You picked the lock."
                #IfNDef cnosound
                PlayWavSound snddoor
                #endif
            Else
                PrintMessage "You failed to pick the lock."
            end if
            sndval = GetSoundValue(4)
            GenSoundMap player.pcoord.x, player.pcoord.y, sndval
        Else
            #IfNDef cnosound
            PlayWavSound sndbash
            #endif
            dstr = levels.isdoor(x, y).dstr
            roll = (player.attr.strg / 10) + player.attr.modstrg
            dstr = dstr - roll
            if dstr <= 0 then
                levels.map(x, y) = IIf(levels.map(x, y) = doorew, dooropew, dooropns)
                player.attr.expr += GetDR
                player.attr.totexp += GetDR
                PrintMessage "You bash the door open."
                #IfNDef cnosound
                PlayWavSound snddoor
                #endif
            Else
                player.attr.currhp = player.attr.currhp - 1
                levels.isdoor(x, y).dstr = dstr
                PrintMessage "The door remains stubborn."
            end if
            sndval = GetSoundValue(8)
            GenSoundMap player.pcoord.x, player.pcoord.y, sndval
        End If
    else
        PrintMessage "There is no door in that location."
    End If
    RoamMonsters
end sub

Function GetWSkillAmount(skilltype As Integer)
    Select Case skilltype
        Case wmelee: Return (player.skill.melee / 10)  + player.skill.modmelee + player.attr.modagl
        Case wsword: Return (player.skill.sword / 10) + player.skill.modsword + player.attr.moddext
        Case waxe: Return (player.skill.axe / 10) + player.skill.modaxe + player.attr.moddext
        Case wspear: Return (player.skill.spear / 10) + player.skill.modspear + player.attr.moddext
        Case wmace: Return (player.skill.mace / 10) + player.skill.modmace + player.attr.moddext
        Case wflail: Return (player.skill.flail / 10) + player.skill.modflail + player.attr.moddext
        Case wbow: Return (player.skill.bow / 10) + player.skill.modbow + player.attr.moddext
        Case wcrossbow: Return (player.skill.crossbow / 10) + player.skill.modcrossbow + player.attr.moddext
    End Select

End Function

'return the tohit amount for roll
Function GetWeaponToHitAmount(weap As weapontype) As Integer
    Dim As Integer wskill, ret
    
    With weap
        'get the skill amount
        ret = GetWSkillAmount(.skill) + player.modtohit
        If .eval = True Then
            ret += .tohitmod
        End If
        If player.isdodging Then
            ret -= 10
        End If
        'is player standing in water
        If levels.map(player.pcoord.x, player.pcoord.y) = water Then
            ret -= 10
        End If
    End With
    If ret < 1 Then ret = 1
    Return ret
End Function

'calc weapon damage
Function GetWeaponDamage(weap As weapontype) As Integer
    Dim As Integer damage
    
    With weap
        damage = .damage
        If .eval = True Then
            damage += .dammod
        End If
        damage += player.moddamage
    End With
    If damage < 1 Then damage = 1
    
    Return damage
End Function

Function UseWeapon(idx As Integer, tohit As Integer, damage As Integer, isshield = False) As Integer
    Dim As Integer didhit, mdef, roll, dam
    Dim mult As Single
    
    'get the monster defense factor
    mdef = GetMonsterDefense(idx)
    'see if player hits
    roll = GetRandom(1, mdef)
    #IfDef tweak
    PrintMessage "Player tohit: " + Str$(tohit)
    PrintMessage "Player roll: " + Str$(roll)
    PrintMessage "M def: " + Str$(mdef)
    #endif
    If tohit >= roll Then
        mult = (tohit - roll) / 50
        'dam = damage + Int(damage * mult)
        'report successful hit
        If isshield Then
            PrintMessage "You bash the " + GetMonsterName(levels.monster(idx).id) + " for " + Str$(damage) + " pts damage."
        Else
            PrintMessage "You hit the " + GetMonsterName(levels.monster(idx).id) + " for " + Str$(damage) + " pts damage."
        End If
        'reduce monster damage
        levels.monster(idx).attr.currhp -= damage
        If levels.monster(idx).attr.currhp <= 0 Then
            player.attr.expr += levels.monster(idx).attr.maxhp
            player.attr.totexp += levels.monster(idx).attr.maxhp
        End If
        didhit = True
    Else
        PrintMessage "You missed the " + GetMonsterName(levels.monster(idx).id) + "."
        didhit = False
    End If
    Return didhit
End Function

Function IsProjectile(weap As weapontype) As Integer
    Dim ret As Integer = False
    
    With weap
        If .id = sling Then
            ret = True
        ElseIf .id = shortbow Then
            ret = True
        ElseIf .id = longbow Then
            ret = True
        ElseIf .id = bonebow Then
            ret = True
        ElseIf .id = adaminebow Then
            ret = True
        ElseIf .id = lightcrossbow Then
            ret = True
        ElseIf .id = heavycrossbow Then
            ret = True
        ElseIf .id = barrelcrossbow Then
            ret = True
        End If
    End With
    Return ret
End Function

Sub DoShieldBash(idx As Integer)
    Dim As Integer tohit, damage, didhit, shld
    
    'get the shield skill mods
    tohit = player.skill.shield / 10
    tohit += player.skill.modshield
    tohit += player.modtohit
    If levels.monster(idx).id > 0 Then
        'check righthand for shield
        If player.righthand.typeid = shields Then
            damage = player.righthand.shield.ac + ((player.attr.strg + player.attr.modstrg) / 10)
            If damage <= 0 Then damage = 1
            didhit = UseWeapon(idx, tohit, damage, True)
            If didhit Then
                
                #IfNDef cnosound
                PlayWavSound sndpunc
                #endif
                If levels.monster(idx).attr.currhp <= 0 Then
                    PrintMessage "You killed the " + GetMonsterName(levels.monster(idx).id) + "."
                    #IfNDef cnosound
                    PlayWavSound sndmond
                    #endif
                    MonsterDropItem idx
                    ClearMonster levels.monster(idx)
                End If
                GenSoundMap player.pcoord.x, player.pcoord.y, 12
            Else
                #IfNDef cnosound
                PlayWavSound sndmiss
                #endif
                GenSoundMap player.pcoord.x, player.pcoord.y, 8
            End If
        End If
        'check the left hand
        If levels.monster(idx).id > 0 Then
            If player.lefthand.typeid = shields Then
                damage = player.lefthand.shield.ac + (player.attr.strg / 10) + player.attr.modstrg
                If damage <= 0 Then damage = 1
                didhit = UseWeapon(idx, tohit, damage, True)
                If didhit Then
                    
                    #IfNDef cnosound
                    PlayWavSound sndpunc
                    #endif
                    If levels.monster(idx).attr.currhp <= 0 Then
                        PrintMessage "You killed the " + GetMonsterName(levels.monster(idx).id) + "."
                        #IfNDef cnosound
                        PlayWavSound sndmond
                        #endif
                        MonsterDropItem idx
                        ClearMonster levels.monster(idx)
                    End If
                    GenSoundMap player.pcoord.x, player.pcoord.y, 12
                Else
                    #IfNDef cnosound
                    PlayWavSound sndmiss
                    #endif
                    GenSoundMap player.pcoord.x, player.pcoord.y, 8
                End If
            End If
        End If
    End If
    
End Sub

Sub DoCombat(idx As Integer, weaphand As Integer = 0)
    Dim As Integer tohit, damage, didhit
    Dim isflail As Integer = False
    
    'is monster scanned
    If levels.monster(idx).isscanned = True Then
        tohit = 10
    End If
    'This is a projectile weapon, get the weapon skill
    If weaphand > 0 Then
        If weaphand = wpRight Then
            tohit += GetWeaponToHitAmount(player.righthand.weapon)
            damage = GetWeaponDamage(player.righthand.weapon)
            DecAmmo player.righthand.weapon
        Else
            tohit += GetWeaponToHitAmount(player.lefthand.weapon)
            damage = GetWeaponDamage(player.lefthand.weapon)
            DecAmmo player.righthand.weapon
        End If
        didhit = UseWeapon(idx, tohit, damage)
        AnimateProjectile player.pcoord.x, player.pcoord.y, levels.monster(idx).mmcoord.x, levels.monster(idx).mmcoord.y
        If Not didhit Then
            #IfNDef cnosound
            PlayWavSound sndarms
            #endif
            GenSoundMap player.pcoord.x, player.pcoord.y, 8
        Else
            'show the hit amount
            
            #IfNDef cnosound
            PlayWavSound sndarht
            #endif
            If levels.monster(idx).attr.currhp <= 0 Then
                PrintMessage "You killed the " + GetMonsterName(levels.monster(idx).id) + "."
                #IfNDef cnosound
                PlayWavSound sndmond
                #endif
                MonsterDropItem idx
                ClearMonster levels.monster(idx)
            End If
            GenSoundMap player.pcoord.x, player.pcoord.y, 12
        End If
    Else
        'This is a melee weapon; check each hand and calc hit
        If player.righthand.typeid = weapons Then
            If player.righthand.weapon.skill = wflail Then
                isflail = True
            End If    
            tohit += GetWeaponToHitAmount(player.righthand.weapon)
            damage = GetWeaponDamage(player.righthand.weapon) + ((player.attr.strg + player.attr.modstrg) / 10)
            didhit = UseWeapon(idx, tohit, damage)
            If didhit Then
                
                #IfNDef cnosound
                If isflail Then
                    PlayWavSound sndwhit
                Else
                    
                    PlayWavSound sndshit
                End If
                #endif
                If levels.monster(idx).attr.currhp <= 0 Then
                    PrintMessage "You killed the " + GetMonsterName(levels.monster(idx).id) + "."
                    #IfNDef cnosound
                    PlayWavSound sndmond
                    #endif
                    MonsterDropItem idx
                    ClearMonster levels.monster(idx)
                End If
                GenSoundMap player.pcoord.x, player.pcoord.y, 12
            Else
                #IfNDef cnosound
                PlayWavSound sndmiss
                #endif
                GenSoundMap player.pcoord.x, player.pcoord.y, 8
            End If
        End If
        'check the left hand
        If levels.monster(idx).id > 0 Then
            If player.lefthand.typeid = weapons Then
                If player.lefthand.weapon.skill = wflail Then
                    isflail = True
                End If    
                tohit += GetWeaponToHitAmount(player.lefthand.weapon)
                damage = GetWeaponDamage(player.lefthand.weapon) + ((player.attr.strg + player.attr.modstrg) / 10)
                didhit = UseWeapon(idx, tohit, damage)
                If didhit Then
                    
                    #IfNDef cnosound
                    If isflail Then
                        PlayWavSound sndwhit
                    Else
                        PlayWavSound sndshit
                    End If
                    #endif
                    If levels.monster(idx).attr.currhp <= 0 Then
                        PrintMessage "You killed the " + GetMonsterName(levels.monster(idx).id) + "."
                        #IfNDef cnosound
                        PlayWavSound sndmond
                        #endif
                        MonsterDropItem idx
                        ClearMonster levels.monster(idx)
                    End If
                    GenSoundMap player.pcoord.x, player.pcoord.y, 12
                Else
                    #IfNDef cnosound
                    PlayWavSound sndmiss
                    #endif
                    GenSoundMap player.pcoord.x, player.pcoord.y, 8
                End If
            End If
        End If
        'unarmed combat
        If player.righthand.typeid <> weapons And player.lefthand.typeid <> weapons Then
            tohit = (player.skill.melee / 10) + player.skill.modmelee + player.modtohit
            damage =  ((player.attr.strg + player.attr.modstrg) / 10) + player.moddamage 
            didhit = UseWeapon(idx, tohit, damage)
            If didhit Then
                
                #IfNDef cnosound
                PlayWavSound sndpunc
                #endif
                If levels.monster(idx).attr.currhp <= 0 Then
                    PrintMessage "You killed the " + GetMonsterName(levels.monster(idx).id) + "."
                    #IfNDef cnosound
                    PlayWavSound sndmond
                    #endif
                    MonsterDropItem idx
                    ClearMonster levels.monster(idx)
                End If
                GenSoundMap player.pcoord.x, player.pcoord.y, 12
            Else
                #IfNDef cnosound
                PlayWavSound sndmiss
                #endif
                GenSoundMap player.pcoord.x, player.pcoord.y, 8
            End If
        End If
    End If
    DoShieldBash idx
    UpdateMap
    'monster turn
    RoamMonsters
End Sub

#IfNDef isascii
Function GetTargetCoord() As mcoord
    Dim As mcoord ncoord, rcoord
    Dim skey As String
    Dim As Integer i, j
    Dim w As Integer = vw
    Dim h As Integer = vh
    Dim tt As Any Ptr
    
    tt = ImageCreate(16, 16)    
    Get tmap,(208, 0) - (223, 15), tt
    rcoord = player.pcoord
    i = player.pcoord.x - (w / 2)
    j = player.pcoord.y - (h / 2)
    If i < 0 Then i = 0
    If j < 0 Then j = 0
    If i + w > dunw - 1 Then i = dunw - w - 1
    If j + h > dunh - 1 Then j = dunh - h - 1
    'get offset
    ncoord.x = (player.pcoord.x - i) * 16
    ncoord.y = (player.pcoord.y - j) * 16
    Put (ncoord.x, ncoord.y), tt, Trans
    Do
        skey = Inkey$
        If skey = key_up Then 'north
            rcoord = GetCoord(north, rcoord)
            DrawMap
            ncoord.y -= 16
            If ncoord.y < 0 Then ncoord.y = 0
            Put (ncoord.x, ncoord.y), tt, Trans
        ElseIf skey = key_dn Then 'south
            rcoord = GetCoord(south, rcoord)        
            DrawMap
            ncoord.y += 16
            If ncoord.y > (vh * 16) Then ncoord.y = vh * 16
            Put (ncoord.x, ncoord.y), tt, Trans
        ElseIf skey = key_rt  Then 'east
            rcoord = GetCoord(east, rcoord)
            DrawMap
            ncoord.x += 16
            If ncoord.x > (vw * 16) Then ncoord.x = vw * 16
            Put (ncoord.x, ncoord.y), tt, Trans
        ElseIf skey = key_lt Then 'west
            rcoord = GetCoord(west, rcoord)
            DrawMap
            ncoord.x -= 16
            If ncoord.x < 0 Then ncoord.x = 0
            Put (ncoord.x, ncoord.y), tt, Trans
        ElseIf skey = key_home Then 'nw
            rcoord = GetCoord(nwest, rcoord)
            DrawMap
            ncoord.x -= 16
            ncoord.y -= 16
            If ncoord.y < 0 Then ncoord.y = 0
            If ncoord.x < 0 Then ncoord.x = 0
            Put (ncoord.x, ncoord.y), tt, Trans
        ElseIf skey = key_pgup Then 'ne
            rcoord = GetCoord(neast, rcoord)
            DrawMap
            ncoord.x += 16
            ncoord.y -= 16
            If ncoord.y < 0 Then ncoord.y = 0
            If ncoord.x > (vw * 16) Then ncoord.x = vw * 16
            Put (ncoord.x, ncoord.y), tt, Trans
             
        ElseIf skey = key_end Then 'sw
            rcoord = GetCoord(swest, rcoord)
            DrawMap
            ncoord.x -= 16
            ncoord.y += 16
            If ncoord.x < 0 Then ncoord.x = 0
            If ncoord.y > (vh * 16) Then ncoord.y = vh * 16
            Put (ncoord.x, ncoord.y), tt, Trans
             
        ElseIf skey = key_pgdn Then 'se
            rcoord = GetCoord(seast, rcoord)
            DrawMap
            ncoord.x += 16
            ncoord.y += 16
            If ncoord.x > (vw * 16) Then ncoord.x = vw * 16
            If ncoord.y > (vh * 16) Then ncoord.y = vh * 16
            Put (ncoord.x, ncoord.y), tt, Trans
             
        End If
    Loop While skey <> key_esc And skey <> key_enter
    If skey = key_esc Then
        PrintMessage "Target cancelled."
        rcoord.x = -1
        rcoord.y = -1
    End If
    DrawMap
    ImageDestroy tt
    Return rcoord
End Function
#Else
Sub PrintReticle(tcoord As mcoord)
    Dim As Integer row, col
    
    Color fbRed, fbBlack
    row = tcoord.y
    col = tcoord.x - 1
    If col > 0 Then
        Locate row, col
        Print "[";
    End If
    col = tcoord.x + 1
    If col < 81 Then
        Locate row, col
        Print "]";
    End If
End Sub

Function GetTargetCoord() As mcoord
    Dim As mcoord ncoord, rcoord
    Dim skey As String
    Dim As Integer i, j
    Dim w As Integer = vw
    Dim h As Integer = vh
    
    rcoord = player.pcoord
    i = player.pcoord.x - (w / 2)
    j = player.pcoord.y - (h / 2)
    If i < 0 Then i = 0
    If j < 0 Then j = 0
    If i + w > dunw - 1 Then i = dunw - w - 1
    If j + h > dunh - 1 Then j = dunh - h - 1
    'get offset
    ncoord.x = (player.pcoord.x - i) + 1
    ncoord.y = (player.pcoord.y - j) + 1
    PrintReticle ncoord
    Do
        skey = Inkey$
        If skey = key_up Then 'north
            rcoord = GetCoord(north, rcoord)
            DrawMap
            ncoord.y -= 1
            If ncoord.y < 1 Then ncoord.y = 1
            PrintReticle ncoord
        ElseIf skey = key_dn Then 'south
            rcoord = GetCoord(south, rcoord)        
            DrawMap
            ncoord.y += 1
            If ncoord.y > vh + 1 Then ncoord.y = vh + 1
            PrintReticle ncoord
        ElseIf skey = key_rt  Then 'east
            rcoord = GetCoord(east, rcoord)
            DrawMap
            ncoord.x += 1
            If ncoord.x > vw + 1 Then ncoord.x = vw + 1
            PrintReticle ncoord
        ElseIf skey = key_lt Then 'west
            rcoord = GetCoord(west, rcoord)
            DrawMap
            ncoord.x -= 1
            If ncoord.x < 1 Then ncoord.x = 1
            PrintReticle ncoord
        ElseIf skey = key_home Then 'nw
            rcoord = GetCoord(nwest, rcoord)
            DrawMap
            ncoord.x -= 1
            ncoord.y -= 1
            If ncoord.y < 1 Then ncoord.y = 1
            If ncoord.x < 1 Then ncoord.x = 1
            PrintReticle ncoord
        ElseIf skey = key_pgup Then 'ne
            rcoord = GetCoord(neast, rcoord)
            DrawMap
            ncoord.x += 1
            ncoord.y -= 1
            If ncoord.y < 1 Then ncoord.y = 1
            If ncoord.x > vw + 1 Then ncoord.x = vw + 1
            PrintReticle ncoord
        ElseIf skey = key_end Then 'sw
            rcoord = GetCoord(swest, rcoord)
            DrawMap
            ncoord.x -= 1
            ncoord.y += 1
            If ncoord.x < 1 Then ncoord.x = 1
            If ncoord.y > vh + 1 Then ncoord.y = vh + 1
            PrintReticle ncoord
        ElseIf skey = key_pgdn Then 'se
            rcoord = GetCoord(seast, rcoord)
            DrawMap
            ncoord.x += 1
            ncoord.y += 1
            If ncoord.x > vw + 1 Then ncoord.x = vw + 1
            If ncoord.y > vh + 1 Then ncoord.y = vh + 1
            PrintReticle ncoord
        End If
    Loop While skey <> key_esc And skey <> key_enter
    If skey = key_esc Then
        PrintMessage "Target cancelled."
        rcoord.x = -1
        rcoord.y = -1
    End If
    DrawMap
    Return rcoord
End Function
#endif

Sub AnimateProjectile(x1 As Integer, y1 As Integer, x2 As Integer, y2 As Integer)
    Dim As Integer i, j, k, deltax, deltay, numtiles
    Dim As Integer d, dinc1, dinc2
    Dim As Integer x, xinc1, xinc2
    Dim As Integer y, yinc1, yinc2
    Dim As Integer px, py
    Dim w As Integer = vw
    Dim h As Integer = vh

    'get the view coords
    i = player.pcoord.x - (w / 2)
    j = player.pcoord.y - (h / 2)
    If i < 0 Then i = 0
    If j < 0 Then j = 0
    If i + w > dunw - 1 Then i = dunw - w - 1
    If j + h > dunh - 1 Then j = dunh - h - 1

    deltax = Abs(x2 - x1)
    deltay = Abs(y2 - y1)

    If deltax >= deltay Then
        numtiles = deltax + 1
        d = (2 * deltay) - deltax
        dinc1 = deltay Shl 1
        dinc2 = (deltay - deltax) Shl 1
        xinc1 = 1
        xinc2 = 1
        yinc1 = 0
        yinc2 = 1
    Else
        numtiles = deltay + 1
        d = (2 * deltax) - deltay
        dinc1 = deltax Shl 1
        dinc2 = (deltax - deltay) Shl 1
        xinc1 = 0
        xinc2 = 1
        yinc1 = 1
        yinc2 = 1
    End If

    If x1 > x2 Then
        xinc1 = - xinc1
        xinc2 = - xinc2
    End If
    
    If y1 > y2 Then
        yinc1 = - yinc1
        yinc2 = - yinc2
    End If

    x = x1
    y = y1

    For k = 2 To numtiles
      If BlockingTile(x, y) Then
        Exit For
      Else
        #IfNDef isascii
        px = (x - i) * 16
        py = (y - j) * 16
        Circle (px + 8, py + 8), 1, fbYellow, , , ,F
        #Else 
        px = (x - i)
        py = (y - j)
        Color fbYellow, fbBlack
        Locate py + 1, px + 1
        Print "*";
        #endif
      End If
      If d < 0 Then
          d = d + dinc1
          x = x + xinc1
          y = y + yinc1
      Else
          d = d + dinc2
          x = x + xinc2
          y = y + yinc2
       End If
       Sleep 10
       Do: Loop While Inkey$ <> ""
       DrawMap
    Next
    DrawMap
End Sub


Sub DoTarget
    Dim weap As Integer = False
    Dim wholding As weapontype
    Dim midx As Integer
    Dim ncoord As mcoord
    Dim skey As String
    Dim weaphand As Integer
    
    'make sure player has projectile weapon
    If player.righthand.typeid = weapons Then
        If IsProjectile(player.righthand.weapon) Then
            If HasAmmo(player.righthand.weapon) Then
                weap = True
                wholding = player.righthand.weapon
                weaphand = wpRight
            End If
        End If
    End If
    'check the left hand if right hand fails.
    If Not weap Then
        If player.lefthand.typeid = weapons Then
            If IsProjectile(player.lefthand.weapon) Then
                If HasAmmo(player.lefthand.weapon) Then
                    weap = True
                    wholding = player.lefthand.weapon
                    weaphand = wpLeft
                End If
            End If
        End If
    End If
    If weap Then
        'get target
        PrintMessage "Move cursor to target, press enter or esc."
        'get the target coord
        ncoord = GetTargetCoord()
        If ncoord.x > -1 And ncoord.y > -1 Then
            If PlayerCanSee(ncoord.x, ncoord.y) Then
                midx = GetMonsterIndex(ncoord.x, ncoord.y)
                If midx > 0 Then
                    DoCombat midx, weaphand
                End If
            End If
        End If
    Else
        PrintMessage "Not holding a projectile weapon or no ammo."
    End If
End Sub

Function GetPlayerDefense(mattack As Integer = False) As Integer
    Dim As Integer def, shld, cw
   
    With player
        def = (.attr.agl / 10) + .attr.modagl + .moddefense
        If mattack Then
            def += .modmagicdef
        End If
        shld = (.skill.shield / 10) + .skill.modshield
        cw = (.skill.caware / 10) + .skill.modcaware
        If GetPercentage(cw) Then
            def += (.skill.caware / 10) + .skill.modcaware
        End If
        If .parmor.typeid = armors Then
            def += .parmor.armor.ac + .modarmor
            If .parmor.armor.eval = true Then
                def += .parmor.armor.defmod
            End If
            If mattack Then
                If .parmor.armor.eval = True Then
                    def += .parmor.armor.defmagic + .parmor.armor.defmagicmod 
                End If
            End If
        End If
        If .isdodging Then
            def += 10
        End If
        If .righthand.typeid = shields Then
            def += .righthand.shield.ac + .modarmor
            If .righthand.shield.eval = True Then 
                def += .righthand.shield.defmod
            End If
            If mattack Then
                If .righthand.shield.eval = True Then
                    def += .righthand.shield.defmagic + .righthand.shield.defmagicmod + player.modmagicdef
                End If
            End If
        End If
        If .lefthand.typeid = shields Then
            def += .lefthand.shield.ac  + .modarmor 
            If .lefthand.shield.eval = True Then
                def += .lefthand.shield.defmod 
            End If
            If mattack Then
                If .lefthand.shield.eval = True Then
                    def += .lefthand.shield.defmagic + .lefthand.shield.defmagicmod + player.modmagicdef
                End If
            End If
        End If
    End With
    If def < 1 Then def = 1
    Return def
End Function

Sub DoWand
    Dim midx As Integer
    Dim ncoord As mcoord
    Dim usemagic As Integer
    Dim As Integer nowand1, nowand2
    Dim didhit As Integer
    Dim tohit As Integer
    Dim damage As Integer
            
    'make sure player has a wand
    If player.righthand.typeid = wands Then
        If player.righthand.wand.count > 0 Then
            If player.righthand.wand.eval = True Then    
                nowand1 = False
                'get target
                PrintMessage "Move cursor to target, press enter or esc."
                'get the target coord
                ncoord = GetTargetCoord()
                If ncoord.x > -1 And ncoord.y > -1 Then
                    If PlayerCanSee(ncoord.x, ncoord.y) Then
                        midx = GetMonsterIndex(ncoord.x, ncoord.y)
                        If midx > 0 Then
                            usemagic = (player.skill.usemagicitem / 10) + player.skill.modusemagicitem + player.attr.modintl
                            'does wand hit
                            If GetRoll(usemagic, player.righthand.wand.dr) Then
                                player.righthand.wand.count -= 1
                                AnimateProjectile player.pcoord.x, player.pcoord.y, levels.monster(midx).mmcoord.x, levels.monster(midx).mmcoord.y
                                tohit = player.skill.usemagicitem + player.modtohit + player.modmagicattack
                                damage = player.righthand.wand.damage  + player.moddamage
                                didhit = UseWeapon(midx, tohit, damage)
                                If didhit Then
                                    #IfNDef cnosound
                                    PlayWavSound sndfbll
                                    #endif
                                    If levels.monster(midx).attr.currhp <= 0 Then
                                        PrintMessage "You killed the " + GetMonsterName(levels.monster(midx).id) + "."
                                        #IfNDef cnosound
                                        PlayWavSound sndmond
                                        #endif
                                        MonsterDropItem midx
                                        ClearMonster levels.monster(midx)
                                    End If
                                Else
                                    #IfNDef cnosound
                                    PlayWavSound sndmiss
                                    #endif
                                End If
                            Else
                                PrintMessage "Nothing happens."
                            End If 
                        End If
                    End If
                    RoamMonsters
                End If
            Else
                PrintMessage "Wand not evaluated."
            End If
        Else
            PrintMessage "Wand out of charges."
        End If
    Else
        nowand1 = True
    End If
    'make sure player has a wand
    If player.lefthand.typeid = wands Then
        If player.lefthand.wand.count > 0 Then
            If player.lefthand.wand.eval = True Then    
                nowand2 = False
                'get target
                PrintMessage "Move cursor to target, press enter or esc."
                'get the target coord
                ncoord = GetTargetCoord()
                If ncoord.x > -1 And ncoord.y > -1 Then
                    If PlayerCanSee(ncoord.x, ncoord.y) Then
                        midx = GetMonsterIndex(ncoord.x, ncoord.y)
                        If midx > 0 Then
                            usemagic = (player.skill.usemagicitem / 10) + player.skill.modusemagicitem  + player.attr.modintl
                            'does wand hit
                            If GetRoll(usemagic, player.lefthand.wand.dr) Then
                                player.lefthand.wand.count -= 1
                                AnimateProjectile player.pcoord.x, player.pcoord.y, levels.monster(midx).mmcoord.x, levels.monster(midx).mmcoord.y
                                tohit = player.skill.usemagicitem + player.modtohit + player.modmagicattack
                                damage = player.lefthand.wand.damage + player.moddamage
                                didhit = UseWeapon(midx, tohit, damage)
                                If didhit Then
                                    #IfNDef cnosound
                                    PlayWavSound sndfbll
                                    #endif
                                    If levels.monster(midx).attr.currhp <= 0 Then
                                        PrintMessage "You killed the " + GetMonsterName(levels.monster(midx).id) + "."
                                        #IfNDef cnosound
                                        PlayWavSound sndmond
                                        #endif
                                        MonsterDropItem midx
                                        ClearMonster levels.monster(midx)
                                    End If
                                Else
                                    #IfNDef cnosound
                                    PlayWavSound sndmiss
                                    #endif
                                End If
                            Else
                                PrintMessage "Nothing happens."
                            End If 
                        End If
                    End If
                    RoamMonsters
                End If
            Else
                PrintMessage "Wand not evaluated."
            End If
        Else
            PrintMessage "Wand out of charges."
        End If
    Else
        nowand2 = True
    End If

    If nowand1 And nowand2 Then
        PrintMessage "Not holding a wand."
    End If

End Sub

Sub SaveGame
    Dim fh As Integer
    
    fh = FreeFile
    Open "dddlvl.dat" For Binary As #fh
    Put #fh,,levels
    Close #fh
    fh = FreeFile
    Open "dddply.dat" For Binary As #fh
    Put #fh,,player
    Close #fh
    PrintMessage "Game saved."
End Sub

Function LoadGame As Integer
    Dim As Integer fh, ret
    
    ret = False
    If Len(Dir$("dddlvl.dat")) > 0 Then
        If Len(Dir$("dddply.dat")) > 0 Then
            ClearMap 
            ret = True
            fh = FreeFile
            Open "dddlvl.dat" For Binary As #fh
            Get #fh,,levels
            Close #fh
            fh = FreeFile
            Open "dddply.dat" For Binary As #fh
            Get #fh,,player
            Close #fh
        End If
    End If
    Return ret        
End Function
