sync on
sync rate 30
autocam off
color backdrop rgb(0,0,0)
 
wire=0 ` 0=ghosting, 1=wireframe
 
dim shapes(9,2,2)
for shp=0 to 7
  for cy=0 to 2
      for cx = 0 to 2
        read shapes(shp,cx,cy)
      next cx
  next cy
next shp
 
for c=1 to 17
  make object plain c,0.1,0.1
  hide object c
next c
 
position object 1,14.9,14.5,15.4
position object 2,14.1,14.5,15.4
position object 3,14.1,14.5,14.6
position object 4,14.9,14.5,14.6
 
position object 5,14.9,14.5,14.4
position object 6,14.1,14.5,14.4
position object 7,14.1,14.5,13.6
position object 8,14.9,14.5,13.6
 
position object 9,13.9,14.5,14.4
position object 10,13.1,14.5,14.4
position object 11,13.1,14.5,13.6
position object 12,13.9,14.5,13.6
 
position object 13,15.9,14.5,14.4
position object 14,15.1,14.5,14.4
position object 15,15.1,14.5,13.6
position object 16,15.9,14.5,13.6
 
position object 17,14.5,14.5,15.5
areasize=29
ghost=1
 
dim tempshape(2,2,2)
dim currshape(2,2,2)
dim tempblocks(areasize,areasize,areasize)
dim blockobj(areasize,areasize,areasize)
dim blockghost(areasize,areasize,areasize)
 
dim colour(10)
colour(1)=rgb(100,100,100)
colour(2)=rgb(255,0,0)
colour(3)=rgb(0,0,255)
colour(4)=rgb(0,255,0)
colour(5)=rgb(255,255,0)
colour(6)=rgb(0,255,255)
colour(7)=rgb(255,0,255)
 
start:
 
randomize val(right$(get time$(),2))*val(left$(right$(get time$(),5),2))
nextshape=rnd(6)
objs=0
 
dim blocks(areasize,areasize,areasize)
for cx=0 to areasize
  for cy=0 to areasize
    for cz=0 to areasize
    blocks(cx,cy,cz)=0
    blockghost(cx,cy,cz)=0
    next cz
  next cy
next cx
 
blocks(14,14,14)=1
blocks(14,14,15)=1
blocks(14,15,14)=1
blocks(14,15,15)=1
blocks(15,14,14)=1
blocks(15,14,15)=1
blocks(15,15,14)=1
blocks(15,15,15)=1
currframe=0
falling=1
newblock=1
fallfraction=0
camrot#=0
camxrot#=20
score=0
brlimit=0
lives=3
pause=0
fallspeed#=29
gameover=0
ghosty=-1
 
sw=screen width()
sh=screen height()
 
position camera 14.5,20,14.5
yrotate camera camrot#
xrotate camera camxrot#
move camera -15
 
 
do
 
  mx=mousemovex()
  my=mousemovey()
  if mx<>0
    camrot#=camrot#+(mx/4)
    camxrot#=camxrot#+(my/4)
    position camera 14.5,14.5,14.5
    yrotate camera camrot#
    xrotate camera camxrot#
    move camera -15
    position camera camera position x(), camera position y()+5, camera position z()
  endif
 
  ox=(sw-(sw/10))-object screen x(17)
  oy=(sh-(sh/10))-object screen y(17)
  for c=0 to 3
  mc=c*4
  line object screen x(mc+1)+ox,object screen y(mc+1)+oy,object screen x(mc+2)+ox,object screen y(mc+2)+oy
  line object screen x(mc+2)+ox,object screen y(mc+2)+oy,object screen x(mc+3)+ox,object screen y(mc+3)+oy
  line object screen x(mc+3)+ox,object screen y(mc+3)+oy,object screen x(mc+4)+ox,object screen y(mc+4)+oy
  line object screen x(mc+4)+ox,object screen y(mc+4)+oy,object screen x(mc+1)+ox,object screen y(mc+1)+oy
  next c
 
  keyspace=0
  keyreturn=0
  keybackspace=0
  if spacekey()=0
  space=0
  endif
  if (spacekey()=1) AND (space=0)
  space=1
  keyspace=1
  endif
  if returnkey()=0
  returnk=0
  endif
  if (returnkey()=1) AND (returnk=0)
  returnk=1
  keyreturn=1
  endif
  if keystate(14)=0
  backspace=0
  endif
  if (keystate(14)=1) AND (backspace=0)
  backspace=1
  keybackspace=1
  endif
 
 
if pause=0
  fallfraction=fallfraction+1;
 
  if ghosty>-1
    for cx=0 to 2
      for cy=0 to 2
        for cz=0 to 2
          if (cy-(shapey-ghosty)>-1) AND (cy-(shapey-ghosty)<3)
            if currshape(cx,cy-(shapey-ghosty),cz)=0
              if currshape(cx,cy,cz)<>0
                blocks(shapex+cx,ghosty+cy,shapez+cz)=0
                `blockghost(shapex+cx,ghosty+cy,shapez+cz)=0
              endif
            endif
          else
            if currshape(cx,cy,cz)<>0
              blocks(shapex+cx,ghosty+cy,shapez+cz)=0
              `blockghost(shapex+cx,ghosty+cy,shapez+cz)=0
            endif
          endif
        next cz
      next cy
    next cx
  endif
 
  if upkey()=0
  up=0
  endif
  if downkey()=0
  down=0
  endif
  if rightkey()=0
  right=0
  endif
  if leftkey()=0
  left=0
  endif
 
  moveshape=0
  rotateshape=0
  rotateblocks=0
  xrotate=0
  yrotate=0
  zrotate=0
  rmod=0
  oshapex=shapex
  oshapez=shapez
  mouseval=mouseclick()
  lmb=0
  mmb=0
  rmb=0
  if int(mouseval/8)=1
  mouseval=mouseval-8
  endif
  if int(mouseval/4)=1
  mouseval=mouseval-4
  mmb=1
  endif
  if int(mouseval/2)=1
  mouseval=mouseval-2
  rmb=1
  endif
  if mouseval=1
  lmb=1
  endif
 
  if (lmb=1) OR (shiftkey())
    if (rmb=1) OR (controlkey())
      if (rightkey()=1) AND (right=0)
        right=1
        rotateshape=1
        yrotate=1
        rmod=1
      endif
      if (leftkey()=1) AND (left=0)
        left=1
        rotateshape=1
        yrotate=1
        rmod=0
      endif
    else
      if (upkey()=1) AND (up=0)
        up=1
        rotateshape=1
        xrotate=1
        rmod=0
      endif
      if (downkey()=1) AND (down=0)
        down=1
        rotateshape=1
        xrotate=1
        rmod=1
      endif
      if (rightkey()=1) AND (right=0)
        right=1
        rotateshape=1
        zrotate=1
        rmod=1
      endif
      if (leftkey()=1) AND (left=0)
        left=1
        rotateshape=1
        zrotate=1
        rmod=0
      endif
    endif
  else
    if (rmb=1) OR (controlkey())
      if (upkey()=1) AND (up=0)
        up=1
        rotateblocks=1
        xrotate=1
        rmod=1
      endif
      if (downkey()=1) AND (down=0)
        down=1
        rotateblocks=1
        xrotate=1
        rmod=0
      endif
      if (rightkey()=1) AND (right=0)
        right=1
        rotateblocks=1
        zrotate=1
        rmod=0
      endif
      if (leftkey()=1) AND (left=0)
        left=1
        rotateblocks=1
        zrotate=1
        rmod=1
      endif
    endif
    if (upkey()=1) AND (up=0)
      up=1
      moveshape=1
      shapez=shapez+1
    endif
    if (downkey()=1) AND (down=0)
      down=1
      moveshape=1
      shapez=shapez-1
    endif
    if (rightkey()=1) AND (right=0)
      right=1
      moveshape=1
      shapex=shapex+1
    endif
    if (leftkey()=1) AND (left=0)
      left=1
      moveshape=1
      shapex=shapex-1
    endif
  endif
 
  if rotateblocks=1
      for cx = 0 to 2
        for cy = 0 to 2
          for cz = 0 to 2
            if (currshape(cx,cy,cz)<>0) then blocks(oshapex+cx,shapey+cy,oshapez+cz)=0
          next cz
        next cy
      next cx
 
    for cx= 0 to areasize
      for cy= 0 to areasize
        for cz= 0 to areasize
          if zrotate=1
            if rmod=0
              tempblocks(cx,cy,cz)= blocks(areasize-cy,cx,cz)
            else
              tempblocks(cx,cy,cz)= blocks(cy,areasize-cx,cz)
            endif
          endif
          if xrotate=1
            if rmod=0
              tempblocks(cx,cy,cz)= blocks(cx,areasize-cz,cy)
            else
              tempblocks(cx,cy,cz)= blocks(cx,cz,areasize-cy)
            endif
          endif
          if yrotate=1
            if rmod=0
              tempblocks(cx,cy,cz)= blocks(areasize-cz,cy,cx)
            else
              tempblocks(cx,cy,cz)= blocks(cz,cy,areasize-cx)
            endif
          endif
        next cz
      next cy
    next cx
    clear=1
      for cx = 0 to 2
        for cy = 0 to 2
          for cz = 0 to 2
            if (tempblocks(oshapex+cx,shapey+cy,oshapez+cz)<>0) AND (currshape(cx,cy,cz)<>0) then clear=0
          next cz
        next cy
      next cx
 
    if clear=1
      for cx= 0 to areasize
        for cy= 0 to areasize
          for cz= 0 to areasize
            blocks(cx,cy,cz)=tempblocks(cx,cy,cz)
          next cz
        next cy
      next cx
    endif
 
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          blocks(shapex+cx,shapey+cy,shapez+cz)=currshape(cx,cy,cz)
        next cz
      next cy
    next cx
 
  endif
 
  if rotateshape=1
    clear=1
 
    if zrotate=1
      for cx = 0 to 2
        for cy = 0 to 2
          for cz = 0 to 2
            if rmod=0
              tempshape(2-cy,cx,cz)=currshape(cx,cy,cz)
            else
              tempshape(cy,2-cx,cz)=currshape(cx,cy,cz)
            endif
            if currshape(cx,cy,cz)<>0
              blocks(cx+oshapex,cy+shapey,cz+oshapez)=0
            endif
          next cz
        next cy
      next cx
    endif
 
    if xrotate=1
      for cx = 0 to 2
        for cy = 0 to 2
          for cz = 0 to 2
            if rmod=0
              tempshape(cx,2-cz,cy)=currshape(cx,cy,cz)
            else
              tempshape(cx,cz,2-cy)=currshape(cx,cy,cz)
            endif
            if currshape(cx,cy,cz)<>0
              blocks(cx+oshapex,cy+shapey,cz+oshapez)=0
            endif
          next cz
        next cy
      next cx
    endif
 
    if yrotate=1
      for cx = 0 to 2
        for cy = 0 to 2
          for cz = 0 to 2
            if rmod=0
              tempshape(2-cz,cy,cx)=currshape(cx,cy,cz)
            else
              tempshape(cz,cy,2-cx)=currshape(cx,cy,cz)
            endif
            if currshape(cx,cy,cz)<>0
              blocks(cx+oshapex,cy+shapey,cz+oshapez)=0
            endif
          next cz
        next cy
      next cx
    endif
 
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if (blocks(cx+shapex,cy+shapey,cz+shapez)<>0) AND (tempshape(cx,cy,cz)<>0)
            clear=0
          endif
        next cz
      next cy
    next cx
 
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if clear=0
            if currshape(cx,cy,cz)<>0
              blocks(cx+shapex,cy+shapey,cz+shapez)=currshape(cx,cy,cz)
            endif
          else
            currshape(cx,cy,cz)=tempshape(cx,cy,cz)
            if tempshape(cx,cy,cz)<>0
              blocks(cx+shapex,cy+shapey,cz+shapez)=tempshape(cx,cy,cz)
            endif
          endif
        next cz
      next cy
    next cx
  endif
 
  if moveshape=1
 
    clear=1
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if currshape(cx,cy,cz)<>0
            blocks(cx+oshapex,cy+shapey,cz+oshapez)=0
          endif
        next cz
      next cy
    next cx
 
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if (blocks(cx+shapex,cy+shapey,cz+shapez)<>0) AND (currshape(cx,cy,cz)<>0)
            clear=0
          endif
        next cz
      next cy
    next cx
    if clear=0
    shapex=oshapex
    shapez=oshapez
    endif
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if currshape(cx,cy,cz)<>0
 
            blocks(cx+shapex,cy+shapey,cz+shapez)=currshape(cx,cy,cz)
          endif
 
        next cz
      next cy
    next cx
  endif
 
  tmpfallspeed=int(fallspeed#)
  if (returnkey()) OR (mmb=1)
  tmpfallspeed=1
  endif
 
  if fallfraction>tmpfallspeed
    clear=1
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if currshape(cx,cy,cz)<>0
            blocks(cx+shapex,cy+shapey,cz+shapez)=0
          endif
        next cz
      next cy
    next cx
    shapey=shapey-1;
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if (blocks(cx+shapex,cy+shapey,cz+shapez)<>0) AND (currshape(cx,cy,cz)<>0)
            clear=0
          endif
        next cz
      next cy
    next cx
    if clear=0
    shapey=shapey+1;
    newblock=1
    endif
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if currshape(cx,cy,cz)<>0
            blocks(cx+shapex,cy+shapey,cz+shapez)=currshape(cx,cy,cz)
          endif
        next cz
      next cy
    next cx
    fallfraction=0;
    if shapey<4
    newblock=1
    lives=lives-1
    for cx = 0 to 2
      for cy = 0 to 2
        for cz = 0 to 2
          if currshape(cx,cy,cz)<>0
            blocks(cx+shapex,cy+shapey,cz+shapez)=0
          endif
        next cz
      next cy
    next cx
    endif
  endif
 
  if newblock=1
     fallspeed#=fallspeed#-0.3
     if fallspeed#<6 then fallspeed#=6
    rectfound=1
    while rectfound=1
 
      rectfound=0
      for axis=1 to 3
      plane=0
     while (plane < (areasize+1))
          blocksinplane=0
          limita=-1
          limitb=areasize+1
          limitc=-1
          limitd=areasize+1
 
            for counta=0 to areasize
              for countb=0 to areasize
                occupied=0
                select axis
                  case 1
                    if (blocks(counta,plane,countb)<>0) then occupied=1
                  endcase
                  case 2
                    if (blocks(plane,counta,countb)<>0) then occupied=1
                  endcase
                  case 3
                    if (blocks(counta,countb,plane)<>0) then occupied=1
                  endcase
                endselect
 
                if occupied=1
                  blocksinplane=blocksinplane+1
                  if countb>limita then limita=countb
                  if countb<limitb then limitb=countb
                  if counta>limitc then limitc=counta
                  if counta<limitd then limitd=counta
                endif
              next countb
            next counta
 
          rx=(limitc-limitd+1)
          ry=(limita-limitb+1)
          rectarea=rx*ry
                if plane>14.5
                  pmod=1
                  ptarget= areasize-1
                  ppatch=areasize
                else
                  pmod=-1
                  ptarget=1
                  ppatch=0
                endif
          if ((rectarea>5) AND (rectarea=blocksinplane)) AND ((plane<14) OR (plane>15))
            score=score+(rectarea*1000)
            if rx=ry then score=(score+((rectarea*rectarea)*1000))-(rectarea*1000)
            for cplane=plane to ptarget step pmod
              for ca=0 to areasize
                for cb=0 to areasize
 
                select axis
                  case 1: blocks(ca,cplane,cb)=blocks(ca,cplane+pmod,cb) : endcase
                  case 2: blocks(cplane,ca,cb)=blocks(cplane+pmod,ca,cb) : endcase
                  case 3: blocks(ca,cb,cplane)=blocks(ca,cb,cplane+pmod) : endcase
                endselect
 
                next cb
              next ca
            next cplane
              for ca=0 to areasize
                for cb=0 to areasize
                select axis
                  case 1: blocks(ca,ppatch,cb)=0 : endcase
                  case 2: blocks(ppatch,ca,cb)=0 : endcase
                  case 3: blocks(ca,cb,ppatch)=0 : endcase
                endselect
 
                next cb
              next ca
              plane=areasize
              rectfound=1
          endif
          plane=plane+1
 
        endwhile
 
      next axis
    endwhile
 
    rand=nextshape
    nextshape=rnd(6)
    clear=1
    shapex=13
    shapey=areasize-4
    shapez=13
    for cx=0 to 2
      for cy=0 to 2
        if (shapes(rand,cx,cy)<>0) AND (blocks(shapex+cx,shapey+cy,shapez+1)<>0) then clear=0
      next cy
    next cx
    if clear=1
      for cx=0 to 2
        for cy=0 to 2
          currshape(cx,cy,0)=0
          currshape(cx,cy,2)=0
          currshape(cx,cy,1)=shapes(rand,cx,cy)
        next cy
      next cx
    else
      brlimit=1
    endif
    currframe=0
    newblock=0
    fallfraction=0
  endif
if ghost=1
  clear=1
  csy=shapey
  while (csy>-1) AND (clear=1)
    for cx=0 to 2
      for cy=0 to 2
        for cz=0 to 2
          if (cy-(shapey-csy)>-1) AND (cy-(shapey-csy)<3)
            if currshape(cx,cy-(shapey-csy),cz)=0
              if (blocks(shapex+cx,csy+cy,shapez+cz)<>0) AND (currshape(cx,cy,cz)<>0) then clear=0
            endif
          else
            if (blocks(shapex+cx,csy+cy,shapez+cz)<>0) AND (currshape(cx,cy,cz)<>0) then clear=0
          endif
        next cz
      next cx
    next cy
    if clear=1 then csy=csy-1
  endwhile
  csy=csy+1
  if csy>0
    for cx=0 to 2
      for cy=0 to 2
        for cz=0 to 2
          if (currshape(cx,cy,cz)<>0) AND (blocks(shapex+cx,csy+cy,shapez+cz)=0)
            blocks(shapex+cx,csy+cy,shapez+cz)=currshape(cx,cy,cz)+10
            blockghost(shapex+cx,ghosty+cy,shapez+cz)=0
          endif
        next cz
      next cy
    next cx
    ghosty=csy
  else
    ghosty=-1
  endif
endif
 
  for cx=0 to areasize
    for cy=0 to areasize
      for cz=0 to areasize
        if blocks(cx,cy,cz)<>0
          if blockobj(cx,cy,cz)=0
            obj=nextobj()
            make object cube obj,0.8
            position object obj,cx,cy,cz
            if blocks(cx,cy,cz)>9
              color object obj,colour(blocks(cx,cy,cz)-10)
              if wire=1
                set object wireframe obj,1
              else
                ghost object on obj
              endif
              blockghost(cx,cy,cz)=1
            else
              color object obj,colour(blocks(cx,cy,cz))
            endif
            blockobj(cx,cy,cz)=obj
          endif
          if (blocks(cx,cy,cz)>9) AND (blockghost(cx,cy,cz)=0)
            color object blockobj(cx,cy,cz),colour(blocks(cx,cy,cz)-10)
            if wire=1
              set object wireframe blockobj(cx,cy,cz),1
            else
              ghost object on blockobj(cx,cy,cz)
            endif
            blockghost(cx,cy,cz)=1
          endif
          if (blocks(cx,cy,cz)<10) AND (blockghost(cx,cy,cz)=1)
            if wire=1
              set object wireframe blockobj(cx,cy,cz),0
            else
              ghost object off blockobj(cx,cy,cz)
            endif
            blockghost(cx,cy,cz)=0
          endif
        else
          if blockobj(cx,cy,cz)<>0
            delete object blockobj(cx,cy,cz)
            blockobj(cx,cy,cz)=0
          endif
        endif
      next cz
    next cy
  next cx
endif
 
blocksize=sh/20
gap=blocksize/10
ox=sw-(blocksize*4)
oy=sh/2
 
text ox,(oy-text height("Next:"))-(blocksize/2),"Next:"
 
for cx=0 to 2
  for mcy=0 to 2
    if shapes(nextshape,cx,mcy)<>0
      cy=2-mcy
      ink colour(shapes(nextshape,cx,mcy)),rgb(0,0,0)
      line ox+(cx*blocksize)+gap,oy+(cy*blocksize)+gap,ox+(cx*blocksize)+gap,(oy+((cy+1)*blocksize))-gap
      line ox+(cx*blocksize)+gap,oy+(cy*blocksize)+gap,(ox+((cx+1)*blocksize))-gap,oy+(cy*blocksize)+gap
      line (ox+((cx+1)*blocksize))-gap,oy+(cy*blocksize)+gap,(ox+((cx+1)*blocksize))-gap,(oy+((cy+1)*blocksize))-gap
      line ox+(cx*blocksize)+gap,(oy+((cy+1)*blocksize))-gap,(ox+((cx+1)*blocksize))-gap,(oy+((cy+1)*blocksize))-gap
    endif
  next cy
next cx
ink rgb(255,255,255),rgb(0,0,0)
 
 
 
if (gameover=0) AND (keyspace=1)
if pause=0
pause=1
else
pause=0
endif
endif
if ((lives<0) AND (brlimit=1)) OR ((lives<0) OR (brlimit=1))
  gameover=1
  pause=1
  text (screen width()/2)-(text width("Game Over")/2),screen height()/2,"Game Over"
  if spacekey() then goto start
endif
if (pause=1) AND (gameover=0)
  if ghost=1
    text (screen width()/2)-(text width("Preview block: On  (Enter to change)")/2),10,"Preview block: On  (Enter to change)"
  else
    text (screen width()/2)-(text width("Preview block: Off  (Enter to change)")/2),10,"Preview block: Off  (Enter to change)"
  endif
  if wire=1
    text (screen width()/2)-(text width("Wireframe  (Backspace to change)")/2),25,"Wireframe  (Backspace to change)"
  else
    text (screen width()/2)-(text width("Ghosting  (Backspace to change)")/2),25,"Ghosting  (Backspace to change)"
  endif
  text (screen width()/2)-(text width("Paused")/2),screen height()/2,"Paused"
  if keyreturn=1
    if ghost=1
      ghost=0
    else
      ghost=1
    endif
  endif
  if keybackspace=1
    if wire=1
      wire=0
    else
      wire=1
    endif
  endif
endif
text (screen width()-blocksize)-text width("lives: "+str$(lives)),10,"lives: "+str$(lives)
text blocksize,10,"score: "+str$(score)
sync
 
loop
 
 
function ismiddle(x,y,z)
imc=0
res=0
if (x=14) OR (x=15) then imc=1
if (y=14) OR (y=15) then imc=imc+1
if (z=14) OR (z=15) then imc=imc+1
if imc=3 then res=1
endfunction res
 
function nextobj()
fcount=1
while object exist(fcount)=1
fcount=fcount+1
endwhile
res=fcount
endfunction res
 
data 0,2,0
data 0,2,0
data 2,2,0
 
data 0,2,0
data 0,2,0
data 0,2,2
 
data 0,3,0
data 3,3,3
data 0,0,0
 
data 0,4,4
data 4,4,0
data 0,0,0
 
data 4,4,0
data 0,4,4
data 0,0,0
 
data 5,5,0
data 5,5,0
data 0,0,0
 
data 0,6,0
data 0,6,0
data 0,6,0