`First, we are going to set up our player character (pc) variables.
`We will use a User Defined Type because it makes this code easy to read.
`I use floats for the stats, even though they will only be integers, because
`we may want to do some math with flaots later on. I don't want DB to convert
`the results to an integer unless we tell it to.
`I also expect to return to this and add more or make changes, but this is a good start.
Type Character
   Str as Float
   Dex as Float
   Con as Float
   Int as Float
   HP as Float
   Gold as Float
   Level as Float
   Name as String
EndType
`Notice that we CAN use INT, a reserved word, as a User Defined Type.
 
`Declare our player as a global variable.
Global Player as Character
 
` This is an array that will hold our map level.
Dim Dungeon(30,30)
Global Startx as Integer
Global Starty as Integer
Global Exitx as Integer
global Exity as Integer
Global PlayerX as Integer
Global PlayerY as Integer
Global LastTime as DWord
Global MonsterX as Integer
Global MonsterY as Integer
Global MonsterTimer as DWord
Global Monster as Character
Global Monster$ as String
Global Player$ as String
Global WallGray as DWord
 
WallGray=Rgb(100,100,100)
 
`Now, create our character.
CLS
Set Cursor 0,0
Input "Enter your character's name:",Player.Name
Print
Print "Welcome ";Player.Name
Wait 1000
 
`Generate some stats.
Do
   Cls
   Set Cursor 0,0
   Print Player.Name;", press [R] to re-roll stats, or [Y] to accept stats."
   Print
   `Randomize the stats. Picks a number from 2 to 10: rnd(4)=0-4. So 0-4 plus 0-4 equals 0-8.
   `Plus 2 = 2 to 10. There is also more of a chance of 5&6 results than there are of 2 or 10.
   Player.Str=rnd(4)+rnd(4)+2
   Player.Dex=rnd(4)+rnd(4)+2
   Player.Con=rnd(4)+rnd(4)+2
   Player.Int=rnd(4)+rnd(4)+2
   Player.HP=Player.str+player.con
   Player.Gold=(Player.Dex+Player.Con)*2
   `I based gold on Intelligence and dexterity since the smart and/or quick person (thief?)
   `should have more. And to balance that Hit Points is based on Str and Con.
   `Print the stats out.
   Print "Strength: ";Player.Str
   Print "Dexterity: ";Player.Dex
   Print "Constitution: ";Player.Con
   Print "Inteligence: ";Player.Int
   Print "Health: ";Player.HP
   Print "Gold: ";Player.Gold
   `Let the player choose to keep the stats or re-roll.
   Do
      a$=Lower$(Inkey$())
      If a$="r" or a$="y" Then Exit
   Loop
   if a$="y" Then Exit
Loop
Player.level=1
 
`This is added to create our player
Make_Player()
 
`We moved the Dungeon Construction code over to a function. This will make it easier to call from anywhere.
Randomize_Dungeon(Timer())
Draw_Dungeon()
 
playerx = startx
playery = starty
lastpx = playerx
lastpy = playery
 
Start_Monster()
LastTime=Timer()
 
Paste Image 1001,0,0
 
Do
   `Check for combat
   If PlayerX=MonsterX and PlayerY=MonsterY
      Player_Fight()
      Monster_Fight()
   Endif
 
   `Move the player
   playerx=playerx+rightkey()-leftkey(): `Left and right movement
   playery=playery+downkey()-upkey():  `Up and down movement
   `Check for a valid move and if enough time since last move has past.
   if Dungeon(playerx,playery)<1 or (Timer()-LastTime)<200
      playerx=lastpx
      playery=lastpy
   Endif
 
   `Reset timer if player was moved. This keeps us from zooming across the dungeon.
   IF lastpx<>playerx or lastpy<>playery
      LastTime=Timer()
      Player$=""
   Endif
 
   `And reposition the player.
   Clear_Light(PLayerX,PLayerY,2)
   Move_Monster()
   Paste Image 1,(playerx-1)*15,(playery-1)*15: `Player
 
   `Print out the player's stats and messages.
   Print_Stats()
 
   `Track our player's last position.
   lastpx=playerx
   lastpy=playery
Loop
 
 
 
 
 
 
 
Wait Key
End
 
`Draw Dungeon around the Player or monster
Function Clear_Light(dx,dy,r)
   For x=dx-r To dx+r
      For y=dy-r To dy+r
         If x<31 and y<31
            If Dungeon(x,y)=1
               Paste Image 1002,(x-1)*15,(y-1)*15
            Else
               Paste Image 1003,(x-1)*15,(y-1)*15
            Endif
            If x=Startx and y=Starty
               Ink Rgb(0,255,0),0
               Box (x-1)*15,(y-1)*15,x*15,y*15
            Endif
            If x=Exitx and y=Exity
               Ink Rgb(255,0,0),0
               Box (x-1)*15,(y-1)*15,x*15,y*15
            Endif
            If x=MonsterX and y=MonsterY
               Paste Image 2,(x-1)*15,(y-1)*15
            Endif
            If x=PlayerX and y=PLayerY
               Paste Image 1,(x-1)*15,(y-1)*15
            Endif
         Endif
      Next y
   Next x
EndFunction
 
 
 
Function Randomize_Dungeon(seed)
   Randomize seed
   `Create a Dungeon Level
   `Codes:
   `-1 = Solid wall. These walls are permanent and should not get replaced.
   ` 0 = Wall. These walls are temporary and can be replaced with ether open area or solid walls.
   ` 1 = Open. These are open areas and also should not be replaced.
   `First, clear out the dungeon.
   For x = 0 to 30
      For y = 0 to 30
         Dungeon(x,y)=0
      Next y
   Next x
   `First define our outside walls as solid.
   For i = 1 to 30
      Dungeon(i,1)=-1
      Dungeon(i,30)=-1
      Dungeon(1,i)=-1
      Dungeon(30,i)=-1
   Next i
   `Select our starting point "our entrance"
   startx=rnd(20)+5
   starty=rnd(20)+5
   Dungeon(startx,starty)=1
   `Now do our random map from that point.
   lastx=startx
   lasty=starty
   Set Cursor 0,0
   Do
      do
         `the random statements pick a number from -1 to 1 (or 0 to 2 minus 1).
         r=(rnd(1)*2)-1
         c=0
         if rnd(2)=1 then s=rnd(1) `this is used to keep a path going in the same direction.
         if s=1
            t=r:r=c:c=t `swap column and row
         Endif
         newx=lastx + r
         newy=lasty + c
         if Dungeon(newx,newy)=0 Then Exit
         if rnd(40)=3 `This keeps us from trying new directions forever.
            n=-1
            Do
               newx=rnd(28)+2
               newy=rnd(28)+2
               if Dungeon(newx,newy)=0 or (Dungeon(newx,newy)=1 and rnd(20)=1)
                  Dungeon(newx,newy)=0
                  exit
               Endif
               if rnd(100)<n `Again, when we run out of places, don't want to keep trying forever.
                  newx=0:newy=0 `setting these to 0 will tell us we're done.
                  Exit
               Endif
               inc n
            Loop
         Endif
         if newx=0 and newy=0 then exit
         if Dungeon(newx,newy)=0 Then exit
      Loop
      if newx=0 and newy=0 then exit
      Dungeon(newx,newy)=1 ` set our new open space.
      `this next part puts up some random solid walls around the last position.
      For i =-1 to 1
         If Dungeon(lastx+i,lasty)=0 and rnd(2)=0
            Dungeon(lastx+i,lasty)=-1
         Endif
      Next i
      For i =-1 to 1
         If Dungeon(lastx,lasty+i)=0 and rnd(2)=0
            Dungeon(lastx,lasty+i)=-1
         Endif
      Next i
      `Draw_Dungeon()
      lastx=newx
      lasty=newy
   Loop
Endfunction
 
Function Draw_Dungeon()
   cls
   Get Image 1002,0,0,15,15,1: ` A blank image for drawing clear space
   Ink WallGray,0
   Box 0,0,15,15
   Get Image 1003,0,0,15,15,1: ` A blank image for drawing wall space
   Ink Rgb(50,50,50),0
   Box 0,0,30*15,30*15
   Get Image 1001,0,0,30*15,30*15,1: ` A big blank square to cover our area.
   Ink WallGray,0
   For x= 1 to 30
      For y = 1 to 30
         If Dungeon(x,y)<1
            Box (x-1)*15,(y-1)*15,x*15,y*15
         Endif
      Next y
   Next x
   `Draw our Entrance
   Ink Rgb(0,255,0),0
   Box (startx-1)*15,(starty-1)*15,startx*15,starty*15
   `And last, make and draw our exit.
   Do
      exitx=Rnd(27)+2
      exity=rnd(27)+2
      If Dungeon(exitx,exity)=1
         d=(exitx-startx)*(exitx-startx)+(exity-starty)*(exity-starty)
         if d>8 Then exit
      Endif
   Loop
   Ink Rgb(255,0,0),0
   Box (exitx-1)*15,(exity-1)*15,exitx*15,exity*15
   Get Image 1000,0,0,30*15,30*15,1:` A picture of our map (a treasure for later on).
Endfunction
 
Function Make_Player()
   `What we do here is simply read in the data statements for each pixel, then capture the image.
   `c is our color. If we read c, and it's 0, then c= 0. Otherwise, if c=1, it will convert to white: rgb(255,255,255)
   Ink 0,0
   Box 0,0,25,25
   Local c as Dword
   Restore Character_Pic
   For y=0 to 14
      for x=0 to 14
         read c
         c=c*Rgb(255,255,255) `"c" is either 0 or 1. Multiply by White: RGB(255,255,255) and either get 0, or white.
         Dot x,y,c
      Next x
   Next y
   Get Image 1,0,0,15,15,1
Endfunction
 
Function Make_Monster()
   Ink 0,0
   Box 0,0,25,25
   Local c as Dword
   `We will be making changes to this later on to select more than one monster type
   Restore Spider_Pic
   For y=0 to 14
      for x=0 to 14
         read c
         c=c*Rgb(255,50,50): `"c" is either 0 or 1. Multiply by White RGB(255,255,255) and either get 0, or white.
         Dot x,y,c
      Next x
   Next y
   Get Image 2,0,0,15,15,1
   `We will be adding in moster stats in the next update.
Endfunction
 
Function Start_Monster()
   Make_Monster()
   Do
      x=rnd(27)+2
      y=rnd(27)+2
      if Dungeon(x,y)=1 Then Exit: `Looking for an open space
   Loop
   MonsterX=x
   MonsterY=y
   MonsterTimer=Timer()
   Monster.name="Spider"
   Monster.str=Rnd(5)+2
   Monster.dex=Rnd(5)+2
   Monster.con=Rnd(5)+2
   Monster.int=Rnd(5)+2
   Monster.hp=monster.str+monster.con
   Monster.gold=(Monster.dex+monster.int)*.5
Endfunction
 
Function Move_Monster()
   If Timer()-MonsterTimer<1000 Then ExitFunction: `We only want the monster to move once a second (for now).
   MonsterTimer=Timer(): `Reset our MonsterTimer
   Monster$=""
   IF rnd(20)=1
      Restore Spider_Talk
      Read m
      For i = 0 to Rnd(m-1)
         Read Monster$
      Next i
   Endif
   xdir=(PlayerX>MonsterX)-(PlayerX<MonsterX): `Add 1 if player is to the right, subtract 1 if the player it to the left.
   ydir=(PlayerY>MonsterY)-(PlayerY<MonsterY): `Same as the x, but verticle.
   `Now check for valid moves.. and move the monster
   nx=MonsterX+xdir
   ny=MonsterY+ydir
   If Dungeon(nx,ny)=1
      `Erase the previous monster position if the monster was not hidden.
      If Point((MonsterX-1)*15+7,(MonsterY-1)*15+7)<>WallGray Then Paste Image 1002,(MonsterX-1)*15,(MonsterY-1)*15
      MonsterX=nx
      MonsterY=ny
      `Draw the monster if the monster is not hidden.
      If Point((nx-1)*15+7,(ny-1)*15+7)<>WallGray Then Paste Image 2,(nx-1)*15,(ny-1)*15
      ExitFunction
   Endif
   nx=MonsterX+xdir
   ny=MonsterY
   If Dungeon(nx,ny)=1
      If Point((MonsterX-1)*15+7,(MonsterY-1)*15+7)<>WallGray Then Paste Image 1002,(MonsterX-1)*15,(MonsterY-1)*15
      MonsterX=nx
      MonsterY=ny
      If Point((nx-1)*15+7,(ny-1)*15+7)<>WallGray Then Paste Image 2,(nx-1)*15,(ny-1)*15
      ExitFunction
   Endif
   nx=MonsterX
   ny=MonsterY+ydir
   If Dungeon(nx,ny)=1
      If Point((MonsterX-1)*15+7,(MonsterY-1)*15+7)<>WallGray Then Paste Image 1002,(MonsterX-1)*15,(MonsterY-1)*15
      MonsterX=nx
      MonsterY=ny
      If Point((nx-1)*15+7,(ny-1)*15+7)<>WallGray Then Paste Image 2,(nx-1)*15,(ny-1)*15
      ExitFunction
   Endif
   If Point(( MonsterX - 1)*15+7,( MonsterY - 1)*15+7)<>WallGray Then Paste Image 2,( MonsterX - 1)*15,(MonsterY - 1)*15
   `If we get to here, there are no valid moves and the monster stays put.
Endfunction
 
Function Print_Stats()
   Ink 0,0
   Box 450,0,800,200
   Ink rgb(150,150,255),0
   Set Cursor 450,0
   Print "Name: ";Player.name
   Set Cursor 450,15
   Print "Str: ";str$(Player.str)
   Set Cursor 450,30
   Print "Dex: ";str$(Player.dex)
   Set Cursor 450,45
   Print "Con: ";str$(Player.con)
   Set Cursor 450,60
   Print "Int: ";str$(Player.int)
   Set Cursor 450,80
   Ink Rgb(255,0,0),0
   Print "Health: ";str$(Player.HP)
   Set Cursor 450,100
   Ink Rgb(255,255,0),0
   Print "Gold: ";str$(Player.gold)
   Set Cursor 450,150
   Ink Rgb(0,255,0),0
   Print Player$
   Set Cursor 450,165
   Ink Rgb(255,100,0),0
   Print Monster$
Endfunction
 
Function Monster_Fight()
   If Timer()-MonsterTimer<500 Then ExitFunction: `We only want the monster to attack once a second (for now).
   MonsterTimer=Timer(): `Reset our MonsterTimer
   ToHit=Monster.Dex+Rnd(10)
   Defense=Player.Dex+Rnd(10)
   Damage=Monster.Str+Rnd(10)
   Armor=Player.Con+Rnd(1)
   If ToHit>Defense and Damage>Armor
      Player.HP=Player.HP-(Damage-Armor)
      Monster$=Monster.Name+" hit "+Player.name+" for "+Str$(Damage-Armor)+"."
   Else
      Monster$=Monster.Name+" misses "+Player.name+"."
   Endif
Endfunction
 
Function Player_Fight()
   If Timer()-LastTime<500 Then ExitFunction
   LastTime=Timer(): `Reset our PlayerTimer
   ToHit=Player.Dex+Rnd(10)
   Defense=Monster.Dex+Rnd(10)
   Damage=Player.Str+Rnd(10)
   Armor=Monster.Con+Rnd(1)
   If ToHit>Defense and Damage>Armor
      Monster.HP=Monster.HP-(Damage-Armor)
      Player$=Player.Name+" hit "+Monster.name+" for "+Str$(Damage-Armor)+"."
   Else
      Player$=Player.Name+" misses "+Monster.name+"."
   Endif
Endfunction
 
Character_Pic:
data  0,1,0,0,0,0,0,1,1,0,0,0,0,0,0
data  0,1,0,0,0,0,1,1,1,1,0,0,0,0,0
data  0,0,1,0,0,0,1,1,1,1,0,0,0,0,0
data  0,0,1,0,0,0,0,1,1,0,0,0,0,0,0
data  0,0,0,1,0,0,1,1,1,1,1,0,0,0,0
data  0,0,0,1,0,1,1,1,0,0,1,1,1,0,0
data  0,0,0,0,1,1,0,1,0,1,1,1,1,0,0
data  0,0,0,0,1,0,1,1,1,0,1,1,0,0,0
data  0,0,0,0,0,0,1,1,1,0,1,1,0,0,0
data  0,0,0,0,0,0,1,1,1,1,1,0,0,0,0
data  0,0,0,0,0,0,1,1,0,1,1,0,0,0,0
data  0,0,0,0,0,0,1,1,0,1,1,0,0,0,0
data  0,0,0,0,0,0,1,1,0,1,1,0,0,0,0
data  0,0,0,0,0,1,1,1,0,1,1,1,0,0,0
data  0,0,0,0,0,1,1,1,0,1,1,1,0,0,0
Spider_Pic:
data  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
data  0,0,1,0,0,1,0,0,0,1,0,0,1,0,0
data  0,1,0,1,0,1,0,0,0,1,0,1,0,1,0
data  0,1,0,1,0,0,1,1,1,0,0,1,0,1,0
data  0,1,0,0,1,1,1,1,1,1,1,0,0,1,0
data  1,0,0,0,1,1,0,1,0,1,1,0,0,0,1
data  1,0,1,0,1,1,1,1,1,1,1,0,1,0,1
data  1,0,1,0,0,1,1,1,1,1,0,0,1,0,1
data  1,0,1,0,1,0,1,0,1,0,1,0,1,0,1
data  1,0,1,0,1,0,1,0,1,0,1,0,1,0,1
data  1,0,1,0,1,0,1,0,1,0,1,0,1,0,1
 
Spider_Talk:
Data 5
Data "Itsy bitsy spider..."
Data "Clik-clik-clickity-clik."
Data "Come here little fly."
Data "Come for my dinnerss?"
Data "Ssstick around!"