input "maze width: ",mx
input "maze height: ",mz
 
sync on
sync rate 20
autocam off
randomize val(right$(get time$(),2))*val(left$(right$(get time$(),5),2))
 
dim temproutex(1)
dim temproutez(1)
routepos=0
dim maze(mx,mz)
objs=0
 
position camera mx/2.0,mx,mz/2.0
point camera mx/2.0,0,mz/2.0
objs=objs+4
 
objs=objs+1
make object sphere objs,0.5
 
exitposx=-1
exitposz=-1
select rnd(3)
  case 0
    currposx=0
    currposz=rnd(mz)
    exits=mz
    prev=8
    exitside=2
  endcase
  case 1
    currposx=rnd(mx)
    exits=mx
    currposz=0
    prev=1
    exitside=4
  endcase
  case 2
    currposx=mx
    currposz=rnd(mz)
    exits=mz
    prev=2
    exitside=8
  endcase
  case 3
    currposx=rnd(mx)
    exits=mx
    currposz=mz
    prev=4
    exitside=1
  endcase
endselect
dim mexits(exits)
for count=0 to exits
mexits(count)=count
next count
startposx=currposx
startposz=currposz
startdir=reverse(prev)
 
 
  border=0
  if currposx<1
    border=8
  endif
  if currposz>mz-1
    border=border+4
  endif
  if currposx>mx-1
    border=border+2
  endif
  if currposz<1
    border=border+1
  endif
border=border-prev
 
while reachedexit=0
  exclude=prev+border
  if debug=1
    objs=objs+1
    make object cube objs,0.7
    position object objs,currposx,0,currposz
    position object 5,currposx,1,currposz
    sync
  endif
  dim temproutex(routepos)
  dim temproutez(routepos)
  temproutex(routepos)=currposx
  temproutez(routepos)=currposz
  routepos=routepos+1
  exclude=check(exclude,currposx,currposz)
  direction=gen(exclude)
  maze(currposx,currposz)=setmaze((15-prev)-direction,currposx,currposz,border)
  if direction = 0
    counta=routepos-1
    while check(cborder(temproutex(counta),temproutez(counta),mx,mz),temproutex(counta),temproutez(counta))=15
      counta=counta-1
 
      if counta<0
        maze(exitposx,exitposz)=0
        counta=routepos-1
      endif
    endwhile
    currposx=temproutex(counta)
    currposz=temproutez(counta)
 
  endif
  prev=reverse(direction)
  currposx=currposx+dcx(direction)
  currposz=currposz+dcz(direction)
  border=0
  if currposx<1
      if exitside=8
        exits=exits-1
        for counte=0 to exits
          if mexits(counte)=currposz
            array delete element mexits(0),counte
            counte=exits
          endif
        next counte
      endif
      border=8
  endif
  if currposz>mz-1
      if exitside=4
        exits=exits-1
        for counte=0 to exits
          if mexits(counte)=currposx
            array delete element mexits(0),counte
            counte=exits
          endif
        next counte
      endif
      border=border+4
  endif
  if currposx>mx-1
      if exitside=2
        exits=exits-1
        for counte=0 to exits
          if mexits(counte)=currposz
            array delete element mexits(0),counte
            counte=exits
          endif
        next counte
      endif
      border=border+2
 
  endif
  if currposz<1
      if exitside=1
        exits=exits-1
        for counte=0 to exits
          if mexits(counte)=currposx
            array delete element mexits(0),counte
            counte=exits
          endif
        next counte
      endif
      border=border+1
  endif
  if exits=0
    select exitside
    case 8
      exitposx=0
      exitposz=mexits(0)
    endcase
    case 4
      exitposx=mexits(0)
      exitposz=mz
    endcase
    case 2
      exitposx=mx
      exitposz=mexits(0)
    endcase
    case 1
      exitposx=mexits(0)
      exitposz=0
    endcase
    endselect
    maze(exitposx,exitposz)=15
  endif
  if (currposx=exitposx) AND (currposz=exitposz)then reachedexit=1
endwhile
  direction=exitside
  maze(currposx,currposz)=(15-prev)-direction
 
for count= 5 to objs
delete object count
next count
objs=4
for countx = 0 to mx
  for countz = 0 to mz
  currsquare=maze(countx,countz)
  if int(currsquare/8)=1
    objs=objs+1
    make object box objs,0.1,1,1
    position object objs,countx-0.5,0,countz
    currsquare=currsquare-8
  endif
  if int(currsquare/4)=1
    objs=objs+1
    make object box objs,1,1,0.1
    position object objs,countx,0,countz+0.5
    currsquare=currsquare-4
  endif
  if int(currsquare/2)=1
    objs=objs+1
    make object box objs,0.1,1,1
    position object objs,countx+0.5,0,countz
    currsquare=currsquare-2
  endif
  if currsquare=1
    objs=objs+1
    make object box objs,1,1,0.1
    position object objs,countx,0,countz-0.5
  endif
  next countz
next countx
 
objs=objs+1
make object sphere objs,0.6
position object objs,exitposx,1,exitposz
sync
sync
while spacekey()<>1
endwhile
cmax=camera angle x()
cmay=camera angle y()
cmaz=camera angle z()
cmx=camera position x()
cmy=camera position y()
cmz=camera position z()
for count=1 to 20
  rotate camera cmax-((cmax/20.0)*count),cmay-(((cmay-angle(exitside))/20.0)*count),cmaz-((cmaz/20.0)*count)
  position camera cmx-(((cmx-exitposx)/20.0)*count),cmy-((cmy/20.0)*count),cmz-(((cmz-exitposz)/20.0)*count)
  sync
next count
set camera range 0.1,3000
position camera exitposx,0,exitposz
rotate camera 0,angle(exitside),0
cp=0
ct=angle(exitside)
tar=0
currposx=exitposx
currposz=exitposz
objs=objs+1
make object cube objs,0.6
position object objs, startposx,0,startposz
endobj=objs
objs=objs+1
make object cube objs,0.5
playerobj=objs
gradx=0
gradz=0
targetposx=currposx
targetposz=currposz
 
do
 
 
cp=cp+mousemovey()
if cp>40 then cp=40
if cp<-40 then cp=-40
xrotate camera wrapvalue(cp)
ct=wrapvalue(ct+mousemovex())
yrotate camera ct
 
if (spacekey()) AND (tar=0)
  tar=1
  if controlkey()
    direction=cv(int(wrapvalue(camera angle y()+225)/90))
  else
    direction=cv(int(wrapvalue(camera angle y()+45)/90))
  endif
  if contains(direction,cborder(currposx,currposz,mx,mz))=1 then direction=direction-cborder(currposx,currposz,mx,mz)
  if contains(maze(currposx+dcx(direction),currposz+dcz(direction)),reverse(direction))=0
    `currposx=currposx+dcx(direction)
    `currposz=currposz+dcz(direction)
    targetposx=currposx+dcx(direction)
    targetposz=currposz+dcz(direction)
  endif
endif
if targetposx>currposx then gradx=gradx+1
if targetposx<currposx then gradx=gradx-1
if targetposz>currposz then gradz=gradz+1
if targetposz<currposz then gradz=gradz-1
if (currposx+(gradx/10.0)=targetposx) OR (currposx=targetposx)
  currposx=targetposx
  gradx=0
  tar=0
endif
if (currposz+(gradz/10.0)=targetposz) OR (currposz=targetposz)
  currposz=targetposz
  gradz=0
  tar=0
endif
if shiftkey()
  set camera range 1,3000
  position camera mx/2.0,mx,mz/2.0
  point camera mx/2.0,0,mz/2.0
else
  set camera range 0.1,3000
  position camera currposx+(gradx/10.0),0,currposz+(gradz/10.0)
  yrotate object playerobj,camera angle y()
endif
endscreenx=object screen x(endobj)
if endscreenx>screen width() then endscreenx=screen width()
if endscreenx<0 then endscreenx=0
if object in screen(endobj)=0
  if endscreenx>(screen width()/2) then endscreenx=screen width()
  if endscreenx<(screen width()/2) then endscreenx=0
endif
line endscreenx-10,10,endscreenx+10,10
line endscreenx+10,10,endscreenx,40
line endscreenx,40,endscreenx-10,10
rotate object endobj,wrapvalue(object angle x(endobj)+5),wrapvalue(object angle y(endobj)+5),wrapvalue(object angle z(endobj)+5)
position object playerobj,currposx+(gradx/10.0),0,currposz+(gradz/10.0)
if (currposx=startposx) AND (currposz=startposz) then exit
sync
loop
 
 
function cv(a)
select a
  case 0:res=4:endcase
  case 1:res=2:endcase
  case 2:res=1:endcase
  case 3:res=8:endcase
endselect
endfunction res
 
 
function gen(a)
dim pr(3)
prs=0
  if int(a/8)=1
    a=a-8
  else
    pr(prs)=8
    prs=prs+1
  endif
  if int(a/4)=1
    a=a-4
  else
    pr(prs)=4
    prs=prs+1
  endif
  if int(a/2)=1
    a=a-2
  else
    pr(prs)=2
    prs=prs+1
  endif
  if a=0
    pr(prs)=1
    prs=prs+1
  endif
if prs>0
  res=pr(rnd(prs-1))
endif
endfunction res
 
function dcx(a)
res=0
  if int(a/8)=1
    a=a-8
    res=-1
  endif
  if int(a/4)=1
    a=a-4
  endif
  if int(a/2)=1
    a=a-2
    res=1
  endif
endfunction res
 
function dcz(a)
res=0
  if int(a/8)=1
    a=a-8
  endif
  if int(a/4)=1
    a=a-4
    res=1
  endif
  if int(a/2)=1
    a=a-2
  endif
  if a=1
    res=-1
  endif
endfunction res
 
function reverse(a)
select a
  case 1:res=4:endcase
  case 2:res=8:endcase
  case 4:res=1:endcase
  case 8:res=2:endcase
endselect
endfunction res
 
 
function check(a,x,z)
res=a
  if int(a/8)=1
    a=a-8
  else
    if maze(x-1,z)<>0 then res=res+8
  endif
  if int(a/4)=1
    a=a-4
  else
    if maze(x,z+1)<>0 then res=res+4
  endif
  if int(a/2)=1
    a=a-2
  else
    if maze(x+1,z)<>0 then res=res+2
  endif
  if a=0
    if maze(x,z-1)<>0 then res=res+1
  endif
endfunction res
 
function cborder(x,z,mx,mz)
  res=0
  if x<1
    res=res+8
  endif
  if z>(mz-1)
    res=res+4
  endif
  if x>(mx-1)
    res=res+2
  endif
  if z<1
    res=res+1
  endif
endfunction res
 
 
function contains(a,b)
ret=0
  if int(a/8)=1
    a=a-8
    if b=8 then ret=1
  endif
  if int(a/4)=1
    a=a-4
    if b=4 then ret=1
  endif
  if int(a/2)=1
    a=a-2
    if b=2 then ret=1
  endif
  if a=1
    if b=1 then ret=1
  endif
endfunction ret
 
function setmaze(a,x,z,b)
res=a
a=a-b
  if int(a/8)=1
    a=a-8
    if (maze(x-1,z)>0) AND (contains(maze(x-1,z),2)=0) then res=res-8
  endif
  if int(a/4)=1
    a=a-4
    if (maze(x,z+1)>0) AND (contains(maze(x,z+1),1)=0) then res=res-4
  endif
  if int(a/2)=1
    a=a-2
    if (maze(x+1,z)>0) AND (contains(maze(x+1,z),8)=0) then res=res-2
  endif
  if a=1
    if (maze(x,z-1)>0) AND (contains(maze(x,z-1),4)=0) then res=res-1
  endif
  if res=0 then res=-1
endfunction res
 
function angle(a)
  if int(a/8)=1
    a=a-8
    res=90
  endif
  if int(a/4)=1
    a=a-4
    res=180
  endif
  if int(a/2)=1
    a=a-2
    res=270
  endif
  if a=1
    res=0
  endif
endfunction res