sync on
hide mouse
autocam off
randomize timer()
randomize 100
fog on
fog distance 400
 
sync rate 0
 
gosub GetStoneTex
gosub GetHedgeTex
gosub GetWaterTex
 
gridwidth=25
griddepth=25
maxradar=25
maxenemies=50
maxmarkers=5
waterheight#=180
whdir=1
watershift#=180
 
restart:
 
dim radar(maxradar)
dim mazepoint(gridwidth,griddepth)
dim enemydir(maxenemies)
 
gosub GenerateMaze
gosub MakeArrow
gosub MakeMatrix
gosub MakeEnd
gosub MakeMarkers
 
Replay:
 
gosub FindStartandEnd
gosub MakeEnemies
 
gosub setup3D
 
starttime=timer()
finish=0
death=0
usedmarkers=0
 
sync rate 40
 
do
 
   set cursor 0,0
 
   print "fps ";screen fps()
 
   gosub HandleInput
   gosub HandleVariables
   gosub HandleEnemies
   gosub HandleDisplay
   gosub Handle3D
 
   if finish=1 then goto Finish
   if death=1 then goto Death
 
   sync
 
loop
 
rem ******************************
rem *********SUB-ROUTINES*********
rem ******************************
 
GetStoneTex:
 
   texturexsize=64
   textureysize=64
 
   ink rgb(150,150,150),0
   box 1,1,texturexsize,textureysize
 
   ink rgb(50,50,50),0
   for i=1 to 500
      dot rnd(texturexsize),rnd(textureysize)
   next i
 
   for i=1 to 1000
      x1=rnd(texturexsize)
      y1=rnd(textureysize)
      x2=(rnd(10)-5)+x1
      y2=y1-rnd(5)+5
      grey=rnd(100)+50
      ink rgb(grey,grey,grey),0
      line x1,y1,x2,y2
   next i
 
   get image 2,1,1,texturexsize,textureysize
 
return
 
GetHedgeTex:
 
   texturexsize=64
   textureysize=64
 
   ink rgb(0,128,0),0
   box 1,1,texturexsize,textureysize
 
   ink rgb(0,100,25),0
   for i=1 to 500
      dot rnd(texturexsize),rnd(textureysize)
   next i
 
   for i=1 to 1000
      x1=rnd(texturexsize)
      y1=rnd(textureysize)
      x2=(rnd(10)-5)+x1
      y2=y1-rnd(5)+5
      ink rgb(0,rnd(150)+100,0),0
      line x1,y1,x2,y2
   next i
 
   get image 1,1,1,texturexsize,textureysize
 
return
 
GetWaterTex:
 
   texturexsize=256
   textureysize=256
 
   ink rgb(100,100,0),0
   box 1,1,texturexsize,textureysize
 
   ink rgb(0,100,25),0
   for i=1 to 500
      dot rnd(texturexsize),rnd(textureysize)
   next i
 
   remend
   for i=1 to 64000
      x1=rnd(texturexsize)
      y1=rnd(textureysize)
      x2=(rnd(10)-5)+x1
      y2=y1-rnd(5)+5
      ink rgb(rnd(10)+80,rnd(15)+95,0),0
      line x1,y1,x2,y2
   next i
 
   get image 3,1,1,texturexsize,textureysize
 
return
 
GenerateMaze:
 
   cls
 
   ink rgb(255,255,255),0
   print "Generating Maze..";
 
   unreachables=-100
 
   dim mazefill(gridwidth,griddepth)
 
   while unreachables<0
 
      print ".";
 
      undim mazefill(gridwidth,griddepth)
 
      for x=1 to gridwidth-1
         for z=1 to griddepth-1
            rand=rnd(4)
            if rand=0 or rand=1 or rand=2
               mazepoint(x,z)=0
            else
               mazepoint(x,z)=1
            endif
         next z
      next x
 
      for x=0 to gridwidth
         mazepoint(x,0)=1
         mazepoint(x,griddepth)=1
      next x
 
      for z=0 to griddepth
         mazepoint(0,z)=1
         mazepoint(gridwidth,z)=1
      next z
 
      dim mazefill(gridwidth,griddepth)
 
      fillmaze(gridwidth,griddepth)
 
      unreachables=20
      for x=1 to gridwidth-1
         for z=1 to griddepth-1
            if mazepoint(x,z)=0 and mazefill(x,z)=0 then unreachables=unreachables-1
         next z
      next x
 
      sync
 
   endwhile
 
   for x=0 to gridwidth
      for z=0 to griddepth
         if mazepoint(x,z)=0 and mazefill(x,z)=0 then mazepoint(x,z)=1
      next z
   next x
 
return
 
MakeArrow:
 
   make object cone 1,5
   scale object 1,100,30,200
   color object 1,rgb(255,255,0)
   disable object zdepth 1
   xrotate object 1,90
   fix object pivot 1
   hide object 1
 
return
 
MakeMatrix:
 
   make matrix 3,5000,5000,gridwidth,griddepth
   prepare matrix texture 3,3,1,1
   set matrix 3,1,1,0,1,1,1,1
   position matrix 3,0,15,0
 
   make matrix 4,5000,5000,gridwidth,griddepth
   prepare matrix texture 4,3,1,1
   set matrix 4,1,1,0,1,1,1,1
   position matrix 4,0,12,0
   ghost matrix on 4
 
   make matrix 1,5000,5000,gridwidth,griddepth
   prepare matrix texture 1,1,1,1
 
   make matrix 2,5000,5000,gridwidth,griddepth
   prepare matrix texture 2,2,1,1
   position matrix 2,0,200,0
 
   for x=0 to gridwidth-0
      for z=0 to griddepth-0
         if mazepoint(x,z)=1
            set matrix height 1,x,z,100
            set matrix height 2,x,z,-200
         endif
      next z
   next x
 
   update matrix 1
   update matrix 2
 
return
 
MakeEnd:
 
   make object sphere 2,40
   color object 2,rgb(255,255,0)
 
   make mesh from object 1,2
   add limb 2,1,1
   hide limb 2,1
 
   make object sphere 3,45
   color object 3,rgb(255,255,0)
   ghost object on 3
   glue object to limb 3,2,1
 
   make object sphere 4,50
   color object 4,rgb(255,0,0)
   ghost object on 4
   glue object to limb 4,2,1
 
return
 
MakeMarkers:
 
   for i=1 to maxmarkers
      make object cone i+10,25
      scale object i+10,100,10,100
      color object i+10,rgb(0,255,255)
      position object i+10,0,1000,0
   next i
 
return
 
FindStartandEnd:
 
   startsection=rnd(3)+1
   select startsection
      case 1
         repeat
            startx#=rnd(gridwidth*200/2)
            startz#=rnd(griddepth*200/2)
         until get ground height(1,startx#,startz#)<=20
         repeat
            endx#=rnd(gridwidth*200/2)+gridwidth*200/2
            endz#=rnd(griddepth*200/2)+griddepth*200/2
         until get ground height(1,endx#,endz#)<=20
      endcase
      case 2
         repeat
            startx#=rnd(gridwidth*200/2)+gridwidth*200/2
            startz#=rnd(gridwidth*200/2)
         until get ground height(1,startx#,startz#)<=20
         repeat
            endx#=rnd(gridwidth*200/2)
            endz#=rnd(griddepth*200/2)+griddepth*200/2
         until get ground height(1,endx#,endz#)<=20
      endcase
      case 3
         repeat
            startx#=rnd(gridwidth*200/2)
            startz#=rnd(griddepth*200/2)
         until get ground height(1,startx#,startz#)<=20
         repeat
            endx#=rnd(gridwidth*200/2)+gridwidth*200/2
            endz#=rnd(griddepth*200/2)+griddepth*200/2
         until get ground height(1,endx#,endz#)<=20
      endcase
      case 4
         repeat
            startx#=rnd(gridwidth*200/2)
            startz#=rnd(griddepth*200/2)+griddepth*200/2
         until get ground height(1,startx#,startz#)<=20
         repeat
            endx#=rnd(gridwidth*200/2)+gridwidth*200/2
            endz#=rnd(griddepth*200/2)
         until get ground height(1,endx#,endz#)<=20
      endcase
   endselect
 
return
 
MakeEnemies:
 
   for i=1 to maxenemies
      repeat
         enemyx#=rnd(gridwidth*200)
         enemyz#=rnd(griddepth*200)
      until get ground height(1,enemyx#,enemyz#)+40<get ground height(2,enemyx#,enemyz#)+180 and sqrt((enemyx#-startx#)^2+(enemyz#-startz#)^2)>600
      make object cube i+100,30
      color object i+100,255
      position object i+100,enemyx#,40,enemyz#
      enemydir(i)=rnd(360)
   next i
 
return
 
Setup3D:
 
   position camera startx#,get ground height(1,startx#,startz#)+20,startz#
   rotate camera 0,0,0
 
   position object 2,endx#,50,endz#
 
   if light exist(1)=0
      make light 1
      set point light 1,camera position x(),camera position y(),camera position z()
      set light to object position 1,2
      show light 1
   endif
 
   backdrop on
   color backdrop 0
 
return
 
HandleInput:
 
   if upkey()=1 then move camera 3.5
   if downkey()=1 then move camera -3.5
   if leftkey()=1 then yrotate camera wrapvalue(camera angle y()-2)
   if rightkey()=1 then yrotate camera wrapvalue(camera angle y()+2)
 
   if spacekey()=1
      if oldspacekey=0
         x#=camera position x()
         z#=camera position z()
         if get ground height(1,x#,z#)=0 and usedmarkers<maxmarkers
            position object usedmarkers+1+10,x#,15,z#
            usedmarkers=usedmarkers+1
         endif
      endif
      oldspacekey=1
   else
      oldspacekey=0
   endif
 
return
 
HandleVariables:
 
   distancetoend=enddistance()
 
   x#=camera position x()
   z#=camera position z()
   y#=get ground height(1,x#,z#)+20
 
   if sqrt((x#-endx#)^2+(z#-endz#)^2)<100
      finish=1
   endif
 
   if y#>get ground height(2,x#,z#)+180 then x#=oldx# : z#=oldz#
 
   oldx#=x#
   oldz#=z#
 
   for i=maxradar to 1 step -1
      radar(i)=radar(i-1)
   next i
 
   if timer()>=radartime
      radar(1)=1
      if distancetoend<300 then radartime=timer()+300 else radartime=timer()+distancetoend
   endif
 
   if whdir2=1
      waterheight#=waterheight#+1
      if waterheight#>360 then waterheight#=359 : whdir2=2
   else
      waterheight#=waterheight#-1
      if waterheight#<1 then waterheight#=1 : whdir2=1
   endif
   actualwh#=cos(waterheight#)*2
   watershift#=watershift#+1
 
return
 
HandleEnemies:
 
   for i=1 to maxenemies
      object=100+i
      oldenemyx#=object position x(object)
      oldenemyz#=object position z(object)
      if sqrt((x#-oldenemyx#)^2+(z#-oldenemyz#)^2)<500
         point object object,x#,object position y(object),z#
         move object object,1.5
         newenemyx#=object position x(object)
         newenemyz#=object position z(object)
         if get ground height(1,newenemyx#,newenemyz#)+40>get ground height(2,newenemyx#,newenemyz#)+180
            position object object,oldenemyx#,get ground height(1,oldenemyx#,oldenemyz#)+40,oldenemyz#
         else
            position object object,newenemyx#,get ground height(1,newenemyx#,newenemyz#)+40,newenemyz#
         endif
         enemyx#=object position x(object)
         enemyz#=object position z(object)
         if sqrt((enemyx#-x#)^2+(enemyz#-z#)^2)<40
            death=1
         endif
      else
         yrotate object object,enemydir(i)
         move object object,1.5
         newenemyx#=object position x(object)
         newenemyz#=object position z(object)
         if get ground height(1,newenemyx#,newenemyz#)+40>get ground height(2,newenemyx#,newenemyz#)+180
            position object object,oldenemyx#,get ground height(1,oldenemyx#,oldenemyz#)+40,oldenemyz#
            enemydir(i)=rnd(360)
         else
            position object object,newenemyx#,get ground height(1,newenemyx#,newenemyz#)+40,newenemyz#
         endif
      endif
   next i
 
return
 
HandleDisplay:
 
   markersleft$=""
   for i=1 to maxmarkers-usedmarkers
      markersleft$=markersleft$+"*"
   next i
   ink 0,0
   box 5,260,128,280
   ink rgb(0,200,0),0
   linebox(5,260,128,280)
   ink rgb(0,255,0),0
   text 9,262,"Markers left: "+markersleft$
 
   timenow=timer()
   timediff$=converttimer$(timenow-starttime)
   ink 0,0
   box 5,290,48,310
   ink rgb(0,200,0),0
   linebox(5,290,48,310)
   ink rgb(0,255,0),0
   text 9,292,timediff$
 
   ink 0,0
   SBFillCircle(30,350,maxradar+1)
   ink rgb(0,200,0),0
   circle 30,350,maxradar+1
   for i=1 to maxradar
      if radar(i)=1
         green=(250-i*10)
         ink rgb(0,green,0),0
         circle 30,350,i
      endif
   next i
 
   ink 0,0
   SBFillCircle(50,430,40)
 
   cameraangle#=wrapvalue(360-wrapvalue(camera angle y()-270))
 
   ink rgb(255,0,0),0
   for i=1 to maxenemies
      enemyx#=object position x(i+100)
      enemyz#=object position z(i+100)
      if sqrt((x#-enemyx#)^2+(z#-enemyz#)^2)<1000
         enemyx2#=((enemyx#-x#)/25)+50
         enemyz2#=((100-(enemyz#/25))-(100-(z#/25)))+430
         distance#=sqrt((50-enemyx2#)^2+(430-enemyz2#)^2)
         angle#=wrapvalue(wrapvalue(360-atanfull(enemyx2#-50,enemyz2#-430))-270)
         newangle#=wrapvalue(angle#+cameraangle#+90)
         expos#=(cos(newangle#)*distance#)+50
         eypos#=(sin(newangle#)*distance#)+430
         dot expos#,eypos#
      endif
   next i
 
   if usedmarkers>0
      for i=1 to usedmarkers
         markerx#=object position x(i+10)
         markerz#=object position z(i+10)
         if sqrt((x#-markerx#)^2+(z#-markerz#)^2)<1000
            markerx2#=((markerx#-x#)/25)+50
            markerz2#=((100-(markerz#/25))-(100-(z#/25)))+430
            distance#=sqrt((50-markerx2#)^2+(430-markerz2#)^2)
            angle#=wrapvalue(wrapvalue(360-atanfull(markerx2#-50,markerz2#-430))-270)
            newangle#=wrapvalue(angle#+cameraangle#+90)
            mxpos#=(cos(newangle#)*distance#)+50
            mypos#=(sin(newangle#)*distance#)+430
            ink rgb(0,255,255),0
            circle mxpos#,mypos#,1
            ink rgb(0,155,155),0
            circle mxpos#,mypos#,2
         endif
      next i
   endif
 
   Northx#=50.0+cos(cameraangle#)*47
   Northy#=430.0+sin(cameraangle#)*47
   ink rgb(0,220,0),0
   center text northx#,northy#-text height("N")/2,"N"
 
   startc=wrapvalue(cameraangle#+8)
   endc=wrapvalue(cameraangle#-11)
   partcircle(50,430,45,startc,endc)
 
   ink rgb(0,200,0),0
   circle 50,430,1
 
   ink rgb(0,200,0),0
   circle 50,430,40
 
return
 
Handle3D:
 
   position camera x#,y#,z#
 
   move camera 15
   point object 1,endx#,camera position y()-5,endz#
   position object 1,camera position x(),camera position y()+5,camera position z()
 
   move camera -15
 
   point light 1,x#,y#,z#
 
   position matrix 3,cos(watershift#)*2,actualwh#+10,sin(watershift#)*2
 
   if usedmarkers>0
      for i=1 to usedmarkers
         yrotate object i+10,wrapvalue(object angle y(i+10)+1)
      next i
   endif
 
return
 
Finish:
 
   if object visible(1)=1 then hide object 1
 
   sync
 
   timenow=timer()
   timediff$=converttimer$(timenow-starttime)
 
   for i=100 to 0 step -5
      fog distance i
      sync
   next i
 
   ink rgb(0,255,0),0
   set text size 100
   center text 320,100,"WINNER!"
   ink rgb(0,200,0),0
   set text size 20
   center text 320,200,"Congratulations! You finished in "+left$(timediff$,2)+" minutes and "+right$(timediff$,2)+" seconds!"
   center text 320,230,"Play another random maze?"
   center text 320,255,"[Y]es / [N]o"
 
   rem delete all data
 
   undim radar(maxradar)
   undim mazepoint(gridwidth,griddepth)
   undim mazefill(gridwidth,griddepth)
   undim enemydir(maxenemies)
 
   delete matrix 1
   delete matrix 2
   delete matrix 3
   delete matrix 4
 
   delete object 1
   delete object 2
   delete object 3
   delete object 4
 
   for i=1 to maxenemies
      delete object 100+i
   next i
 
   delete light 1
 
   backdrop off
 
   repeat : sync : until inkey$()="y" or inkey$()="n"
 
   fog distance 400
 
   if inkey$()="y" then goto restart
 
end
 
Death:
 
   for i=1 to maxenemies
      delete object 100+i
   next i
 
   fog distance 200
   fog color rgb(200,0,0)
   for i=100 to 0 step -2
      fog distance i
      sync
   next i
   for i=200 to 0 step -2
      fog color rgb(i,0,0)
      sync
   next i
 
   sync
 
   repeat
 
      ink rgb(255,0,0),0
      set text size 100
      center text 320,100,"You Lose!"
      ink rgb(200,0,0),0
      set text size 20
      center text 320,200,"They got you!"
      center text 320,230,"Play again?"
      center text 320,255,"[Y]es / [N]o"
 
      sync
 
   until inkey$()="y" or inkey$()="n"
 
   fog distance 400
   undim enemydir(maxenemies)
 
   if inkey$()="y" then goto Replay
 
end
 
rem ******************************
rem **********FUNCTIONS***********
rem ******************************
 
function linebox(x1,y1,x2,y2)
 
   line x1,y1,x1,y2
   line x1,y2,x2,y2
   line x2,y2,x2,y1
   line x2,y1,x1,y1
 
endfunction
 
function SBFillCircle( CX, CY, R )
   sR = R*R
   for i = 1 to R
      h = sqrt( sR - i*i )
      box CX - i, CY - h, CX + i, CY + h
   next i
endfunction
 
function partcircle(x,y,radius,startc,endc)
 
   endc=wrapvalue(endc)
   startc=wrapvalue(startc)
   crcmfrnc=wrapvalue(endc-startc)
   if endc=startc then crcmfrnc=360
 
   do#=wrapvalue(startc)
   sofar#=0
 
   repeat
 
      sofar#=sofar#+1
 
      do#=wrapvalue(do#+1)
      dx#=cos(do#)*radius
      dy#=sin(do#)*radius
      bx=x+dx#
      by=y+dy#
 
      dot bx,by
 
   until sofar#>=crcmfrnc
 
endfunction
 
function enddistance()
 
   x#=object position x(2)-camera position x()
   z#=object position z(2)-camera position z()
 
   distance#=sqrt(x#^2+z#^2)
 
endfunction distance#
 
function converttimer$(timer)
 
   timer=timer/1000
   timer2#=timer
   endloop=0
   seconds=0
   check#=0
   if timer>=60
      repeat
         check#=timer2#/60
         check$=str$(check#)
         dpoint=0
         for i=1 to len(check$)
            if mid$(check$,i)="." then dpoint=1
         next i
         if dpoint=0
            endloop=1
         else
            timer2#=timer2#-1
            seconds=seconds+1
         endif
      until endloop=1
      minutes=timer2#/60
   else
      minutes=0
      seconds=timer2#
   endif
   if seconds<10 then seconds$="0"+str$(seconds) else seconds$=str$(seconds)
   if minutes<10 then minutes$="0"+str$(minutes) else minutes$=str$(minutes)
   time$=minutes$+":"+seconds$
 
endfunction time$
 
function fillmaze(gridwidth,griddepth)
 
   for x=1 to gridwidth-1
      for z=1 to griddepth-1
         if mazepoint(x,z)=0 then mazefill(x,z)=1 : goto Ihategotos
      next z
   next x
 
   Ihategotos:
 
   repeat
 
      endfill=1
 
      for x=1 to gridwidth-1
         for z=1 to griddepth-1
            if mazefill(x,z)=1
 
               if mazepoint(x,z-1)=0 and mazefill(x,z-1)=0
                  mazefill(x,z-1)=1
               endif
               if mazepoint(x+1,z)=0 and mazefill(x+1,z)=0
                  mazefill(x+1,z)=1
               endif
               if mazepoint(x,z+1)=0 and mazefill(x,z+1)=0
                  mazefill(x,z+1)=1
               endif
               if mazepoint(x-1,z)=0 and mazefill(x-1,z)=0
                  mazefill(x-1,z)=1
               endif
 
               mazefill(x,z)=2
               endfill=0
 
            endif
         next z
      next x
 
   until endfill=1
 
endfunction