`Random Maze Generator
`Created by Parrot
`January 19, 2007
 
autocam off
sync on
sync rate 0
hide mouse
 
type collision_segment
   x1 as float
   x2 as float
   z1 as float
   z2 as float
endtype
 
dim collisions(25) as collision_segment
 
`Let there be light!
`set ambient light 80
make light 1
set point light 1,0,0,0
color light 1,RGB(255,255,255)
 
`Set the map values
mapxsize = 40
mapzsize = 40
squaresize = 6
 
`Create the map values and fill it with walls
dim map$(mapxsize,mapzsize)
for zsquare = 1 to mapzsize
   for xsquare = 1 to mapxsize
      map$(xsquare,zsquare) = "#"
   next xsqare
next zsquare
 
`Dig out the starting room
for zsquare = 2 to 6
   for xsquare = 2 to 6
      map$(xsquare,zsquare) = " "
   next xsqare
next zsquare
map$(4,4) = "S"
map$(4,7) = " "
 
north = 0
east = 1
south = 2
west = 3
 
randomize timer()
 
` Set the values to start and dig a path
direction = south
permutations = 20
xpos = 4
zpos = 8
gosub digger
 
`Dig out the destination room
for zsquare = mapzsize-5 to mapzsize-1
   for xsquare = mapxsize-5 to mapxsize-1
      map$(xsquare,zsquare) = " "
   next xsqare
next zsquare
 
map$(mapxsize-3,mapzsize-3) = "Z"
map$(mapxsize-3,mapzsize-6) = " "
 
`Dig a path from the destination room
direction = north
permutations = 20
xpos = mapxsize-3
zpos = mapzsize-7
gosub digger
 
`Dig a couple of extra paths for good measure
direction = north
permutations = 15
xpos = 2
zpos = mapzsize-1
gosub digger
 
direction = south
permutations = 15
xpos = mapzsize-1
zpos = 2
gosub digger
 
cubeofvictory = 1
walls = 2
ground = 3
 
floorxsize = squaresize * mapxsize
floorzsize = squaresize * mapzsize
sizeoffset# = squaresize / 2
 
`Create the ground
make object plain ground,floorxsize,floorzsize
rotate object ground,90,0,0
position object ground,floorxsize/2,0,floorzsize/2
color object ground, rgb(255,0,0)
 
`Create the seed object for the maze
make object cube walls, squaresize
make mesh from object walls, walls
delete object walls
make object cube walls, 1
 
wallpart = 1
 
`Set everything up according to the map
for zpos=1 to mapzsize
   for xpos=1 to mapxsize
      floorxpos = xpos * squaresize
      floorzpos = zpos * squaresize
      if map$(xpos,zpos)="S"
         position camera floorxpos-sizeoffset#,sizeoffset#,floorzpos-sizeoffset#
      endif
      if map$(xpos,zpos)="#"
         add limb walls, wallpart, walls
         offset limb walls, wallpart, floorxpos-sizeoffset#, sizeoffset#, floorzpos-sizeoffset#
         wallpart = wallpart + 1
      endif
      if map$(xpos,zpos)="Z"
         make object cube cubeofvictory, 2
         position object cubeofvictory, floorxpos-sizeoffset#, 3, floorzpos-sizeoffset#
      endif
   next xpos
next zpos
 
delete mesh walls
 
color object walls, rgb(0,255,0)
 
mapxpos = int(camera position x()/squaresize)
mapzpos = int(camera position z()/squaresize)
oldx# = camera position x()
oldz# = camera position z()
 
`Main Loop
DO
   nomove = 1
 
   `Detect keys and move the camera appropriately
   if upkey()
      move camera 0.1
      nomove = 0
   endif
   if downkey()
      move camera -0.1
      nomove = 0
   endif
   if leftkey()
      yrotate camera camera angle y()-0.5
      nomove = 0
   endif
   if rightkey()
      yrotate camera camera angle y()+0.5
      nomove = 0
   endif
 
   xdiff# = camera position x() - oldx#
   zdiff# = camera position z() - oldz#
 
   `Calculate the current position based on map co-ordinates
   mapxpos = int(camera position x()/squaresize)
   mapzpos = int(camera position z()/squaresize)
 
   if not nomove
      `Calculate a map-area perimiter around the player
      zpstart = mapzpos-2
      zpend = mapzpos+2
      xpstart = mapxpos-2
      xpend = mapxpos+2
      if zpstart < 1 then zpstart = 1
      if zpend > mapzsize then zpend = mapzsize
      if xpstart < 1 then xpstart = 1
      if xpend > mapxsize then xpend = mapxsize
 
      colcount = 0
      `Loop through all the co-ordinates in the map perimiter we just calculated
      for zperim = zpstart to zpend
         for xperim = xpstart to xpend
            if map$(xperim,zperim) = "#" `If there's a wall, calculate the collision values
               testx1# = (xperim * squaresize) - squaresize - sizeoffset#/2
               testz1# = (zperim * squaresize) - squaresize - sizeoffset#/2
               testx2# = (xperim * squaresize) + sizeoffset#/2
               testz2# = (zperim * squaresize) + sizeoffset#/2
 
               xcollision = 0
               zcollision = 0
               if camera position x() >= testx1# and camera position x() <= testx2# then xcollision = 1
               if camera position z() >= testz1# and camera position z() <= testz2# then zcollision = 1
 
               `If a collision occurs, record the collision values
               if xcollision and zcollision
                  colcount = colcount + 1
                  collisions(colcount).x1 = testx1#
                  collisions(colcount).x2 = testx2#
                  collisions(colcount).z1 = testz1#
                  collisions(colcount).z2 = testz2#
               endif
            endif
         next xperim
      next zperim
   endif
 
   `Handle the collisions based on all collision objects recorded
   if colcount
      xpointx# = oldx#+xdiff#
      xpointz# = oldz#
      zpointx# = oldx#
      zpointz# = oldz#+zdiff#
      for i=1 to colcount
         if xpointx# >= collisions(i).x1 and xpointx# <= collisions(i).x2 and xpointz# >= collisions(i).z1 and xpointz# <= collisions(i).z2
            xdiff# = 0
         endif
         if zpointx# >= collisions(i).x1 and zpointx# <= collisions(i).x2 and zpointz# >= collisions(i).z1 and zpointz# <= collisions(i).z2
            zdiff# = 0
         endif
      next i
      position camera oldx#+xdiff#,sizeoffset#,oldz#+zdiff#
   endif
 
   oldx# = camera position x()
   oldz# = camera position z()
 
   position light 1,camera position x(),camera position y(),camera position z()
   rotate light 1,camera angle x(),camera angle y(),camera angle z()
 
   `Draw a 2D Map on the screen
   for zpos=1 to mapzsize
      for xpos=1 to mapxsize
         floorxpos = xpos * squaresize
         floorzpos = zpos * squaresize
         if map$(xpos,zpos)="S"
            ink rgb(0,255,0),rgb(0,0,0)
            x1 = mapxsize*5 - 5*xpos
            x2 = x1+5
            box x1,5*zpos,x2,5*zpos+5
         endif
         if map$(xpos,zpos)="Z"
            ink rgb(255,0,0),rgb(0,0,0)
            x1 = mapxsize*5 - 5*xpos
            x2 = x1+5
            box x1,5*zpos,x2,5*zpos+5
         endif
         if map$(xpos,zpos)=" "
            ink rgb(255,255,255),rgb(0,0,0)
            x1 = mapxsize*5 - 5*xpos
            x2 = x1+5
            box x1,5*zpos,x2,5*zpos+5
         endif
      next xpos
   next zpos
 
   yrotate object cubeofvictory, object angle y(cubeofvictory) + 0.6
 
   sync
LOOP
 
digger:
   gosub excavate
 
   for pcount = 1 to permutations
      turnto = rnd(1)
      if direction = north or direction = south
         direction = west
         if turnto then direction = east
      else
         direction = south
         if turnto then direction = north
      endif
 
      gosub excavate
   next pcount
return
 
excavate:
   if direction = north then squaresleft = zpos - 2
   if direction = east then squaresleft = mapxsize - xpos - 2
   if direction = south then squaresleft = mapzsize - zpos - 2
   if direction = west then squaresleft = xpos - 2
 
   if squaresleft < 4
      olddir = direction
      oldsl = squaresleft
 
      if direction = north
         direction = south
      else
         if direction = south then direction = north
      endif
 
      if direction = east
         direction = west
      else
         if direction = west then direction = east
      endif
 
      if direction = north then squaresleft = zpos - 2
      if direction = east then squaresleft = mapxsize - xpos - 2
      if direction = south then squaresleft = mapzsize - zpos - 2
      if direction = west then squaresleft = xpos - 2
   endif
 
   distance = rnd(squaresleft-4) + 4
   if distance > 10 then distance = 10
 
   go = 1
   for i = 1 to distance
      if xpos <= 7 and zpos <= 7 then go = 0
      if xpos >= mapxsize-6 and zpos >= mapzsize-6 then go = 0
 
      if go
         map$(xpos,zpos) = " "
         if direction = north then zpos = zpos - 1
         if direction = east then xpos = xpos + 1
         if direction = south then zpos = zpos + 1
         if direction = west then xpos = xpos - 1
      endif
   next i
return