Advertisement
GopherAtl

Tetris

Mar 20th, 2014
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.88 KB | None | 0 0
  1. --[[
  2.   Tetris
  3. "Tetris" Copyright... somebody... probably nintendo, or one of their
  4. subsidiaries, I dunno. They took it from Tengen in court, in any case.
  5.  
  6. This /particular/ version was written by Gopher, at the request of
  7. Dan200, for ComputerCraft v1.6. No particular rights are reserved,
  8. since in this case I probably don't, strictly speaking, possess any
  9. rights to be reserved in the first place. Don't sue me, or something.
  10. --]]
  11.  
  12. local function colorass(c,bw)
  13.   return term.isColor() and c or bw
  14. end
  15.  
  16. local block_s1= {
  17.     {
  18.       { 1,0,0,0, },
  19.       { 1,1,0,0, },
  20.       { 0,1,0,0, },
  21.       { 0,0,0,0, },
  22.     },
  23.     {
  24.       { 0,0,0,0, },
  25.       { 0,1,1,0, },
  26.       { 1,1,0,0, },
  27.       { 0,0,0,0, },
  28.     },
  29.     ch="{}",
  30.     fg=colorass(colors.blue,colors.black),
  31.     bg=colorass(colors.cyan,colors.white),    
  32.   }
  33. local block_s2= {
  34.     {
  35.       { 0,1,0,0, },
  36.       { 1,1,0,0, },
  37.       { 1,0,0,0, },
  38.       { 0,0,0,0, },
  39.     },
  40.     {
  41.       { 0,0,0,0, },
  42.       { 1,1,0,0, },
  43.       { 0,1,1,0, },
  44.       { 0,0,0,0, },
  45.     },
  46.     ch="{}",
  47.     fg=colorass(colors.green,colors.black),
  48.     bg=colorass(colors.lime,colors.white),
  49.   }
  50. local block_line = {
  51.     {
  52.       { 0,1,0,0, },
  53.       { 0,1,0,0, },
  54.       { 0,1,0,0, },
  55.       { 0,1,0,0, },
  56.     },
  57.     {
  58.       { 0,0,0,0, },
  59.       { 1,1,1,1, },
  60.       { 0,0,0,0, },
  61.       { 0,0,0,0, },
  62.     },
  63.     ch="[]",
  64.     fg=colorass(colors.pink,colors.black),
  65.     bg=colorass(colors.red,colors.white),
  66.   }
  67. local block_square = {
  68.     {
  69.       { 1,1,0,0, },
  70.       { 1,1,0,0, },
  71.       { 0,0,0,0, },
  72.       { 0,0,0,0, },
  73.     },
  74.     ch="[]",
  75.     fg=colorass(colors.lightBlue,colors.black),
  76.     bg=colorass(colors.blue,colors.white),
  77.   }
  78. local block_L1 = {
  79.     {
  80.       { 1,1,0,0, },
  81.       { 0,1,0,0, },
  82.       { 0,1,0,0, },
  83.       { 0,0,0,0, },
  84.     },
  85.     {
  86.       { 0,0,0,0, },
  87.       { 1,1,1,0, },
  88.       { 1,0,0,0, },
  89.       { 0,0,0,0, },
  90.     },
  91.     {
  92.       { 0,1,0,0, },
  93.       { 0,1,0,0, },
  94.       { 0,1,1,0, },
  95.       { 0,0,0,0, },
  96.     },
  97.     {
  98.       { 0,0,1,0, },
  99.       { 1,1,1,0, },
  100.       { 0,0,0,0, },
  101.       { 0,0,0,0, },
  102.     },
  103.     ch="()",
  104.     fg=colorass(colors.orange,colors.black),
  105.     bg=colorass(colors.yellow,colors.white),
  106.   }
  107. local block_L2 = {
  108.     {
  109.       { 0,1,0,0, },
  110.       { 0,1,0,0, },
  111.       { 1,1,0,0, },
  112.       { 0,0,0,0, },
  113.     },
  114.     {
  115.       { 0,0,0,0, },
  116.       { 1,1,1,0, },
  117.       { 0,0,1,0, },
  118.       { 0,0,0,0, },
  119.     },
  120.     {
  121.       { 0,1,1,0, },
  122.       { 0,1,0,0, },
  123.       { 0,1,0,0, },
  124.       { 0,0,0,0, },
  125.     },
  126.     {
  127.       { 1,0,0,0, },
  128.       { 1,1,1,0, },
  129.       { 0,0,0,0, },
  130.       { 0,0,0,0, },
  131.     },
  132.     ch="()",
  133.     fg=colorass(colors.brown,colors.black),
  134.     bg=colorass(colors.orange,colors.white),
  135.   }
  136. local block_T = {
  137.     {
  138.       { 0,1,0,0, },
  139.       { 1,1,0,0, },
  140.       { 0,1,0,0, },
  141.       { 0,0,0,0, },
  142.     },
  143.     {
  144.       { 0,0,0,0, },
  145.       { 1,1,1,0, },
  146.       { 0,1,0,0, },
  147.       { 0,0,0,0, },
  148.     },
  149.     {
  150.       { 0,1,0,0, },
  151.       { 0,1,1,0, },
  152.       { 0,1,0,0, },
  153.       { 0,0,0,0, },
  154.     },
  155.     {
  156.       { 0,1,0,0, },
  157.       { 1,1,1,0, },
  158.       { 0,0,0,0, },
  159.       { 0,0,0,0, },
  160.     },
  161.     ch="<>",
  162.     fg=colorass(colors.cyan,colors.black),
  163.     bg=colorass(colors.purple,colors.white),
  164.   }
  165.  
  166. local blocks={ block_line, block_square, block_s1, block_s2, block_L1, block_L2, block_T}
  167.  
  168. local points={4,10,30,120}
  169.  
  170. local function lpad(text,amt)
  171.   text=tostring(text)
  172.   return string.rep(" ",amt-#text)..text
  173. end
  174.  
  175. local width,height=term.getSize()
  176.  
  177. if height<19 or width<26 then
  178.   print("Your screen is too small to play tetris. :(")
  179.   return
  180. end
  181.  
  182.  
  183. local speedsByLevel={
  184.   1.2,
  185.   1.0,
  186.    .8,
  187.    .65,
  188.    .5,
  189.    .4,
  190.    .3,
  191.    .25,
  192.    .2,
  193.    .15,
  194.    .1,
  195.    .05,}
  196.  
  197. local level=1
  198.    
  199. local function playGame()  
  200.   local score=0
  201.   local lines=0
  202.   local initialLevel=level
  203.   local next=blocks[math.random(1,#blocks)]
  204.  
  205.   local pit={}
  206.  
  207.  
  208.   local heightAdjust=0
  209.  
  210.   if height<=19 then
  211.     heightAdjust=1
  212.   end
  213.  
  214.  
  215.  
  216.   local function drawScreen()
  217.     term.setTextColor(colors.white)
  218.     term.setBackgroundColor(colors.black)
  219.     term.clear()
  220.  
  221.     term.setTextColor(colors.black)
  222.     term.setBackgroundColor(colors.white)
  223.     term.setCursorPos(22,2)
  224.     term.write("Score") --score
  225.     term.setCursorPos(22,5)
  226.     term.write("Level")  --level
  227.     term.setCursorPos(22,8)
  228.     term.write("Lines")  --lines
  229.     term.setCursorPos(22,12)
  230.     term.write("Next") --next
  231.  
  232.     term.setCursorPos(21,1)
  233.     term.write("      ")
  234.     term.setCursorPos(21,2)
  235.     term.write(" ") --score
  236.     term.setCursorPos(21,3)
  237.     term.write(" ")
  238.     term.setCursorPos(21,4)
  239.     term.write("      ")
  240.     term.setCursorPos(21,5)
  241.     term.write(" ")  --level
  242.     term.setCursorPos(21,6)
  243.     term.write(" ")
  244.     term.setCursorPos(21,7)
  245.     term.write("      ")
  246.     term.setCursorPos(21,8)
  247.     term.write(" ")  --lines
  248.     term.setCursorPos(21,9)
  249.     term.write(" ")
  250.     term.setCursorPos(21,10)
  251.     term.write("      ")
  252.     term.setCursorPos(21,11)
  253.     term.write("      ")
  254.     term.setCursorPos(21,12)
  255.     term.write(" ") --next
  256.     term.setCursorPos(26,12)
  257.     term.write(" ") --next  
  258.     term.setCursorPos(21,13)
  259.     term.write("      ")
  260.     term.setCursorPos(21,14)
  261.     term.write(" ")
  262.     term.setCursorPos(21,15)
  263.     term.write(" ")
  264.     term.setCursorPos(21,16)
  265.     term.write(" ")
  266.     term.setCursorPos(21,17)
  267.     term.write(" ")
  268.     term.setCursorPos(21,18)  
  269.     term.write(" ")
  270.     term.setCursorPos(21,19)  
  271.     term.write("      ")
  272.     term.setCursorPos(21,20)  
  273.     term.write("      ")
  274.   end
  275.  
  276.   local function updateNumbers()
  277.     term.setTextColor(colors.white)
  278.     term.setBackgroundColor(colors.black)
  279.  
  280.     term.setCursorPos(22,3)
  281.     term.write(lpad(score,5)) --score
  282.     term.setCursorPos(22,6)
  283.     term.write(lpad(level,5))  --level
  284.     term.setCursorPos(22,9)
  285.     term.write(lpad(lines,5))  --lines
  286.   end
  287.  
  288.   local function drawBlockAt(block,xp,yp,rot)
  289.     term.setTextColor(block.fg)
  290.     term.setBackgroundColor(block.bg)
  291.     for y=1,4 do
  292.       for x=1,4 do
  293.         if block[rot][y][x]==1 then
  294.           term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust)
  295.           term.write(block.ch)
  296.         end
  297.       end
  298.     end
  299.   end
  300.  
  301.   local function eraseBlockAt(block,xp,yp,rot)
  302.     term.setTextColor(colors.white)
  303.     term.setBackgroundColor(colors.black)
  304.     for y=1,4 do
  305.       for x=1,4 do
  306.         if block[rot][y][x]==1 then
  307.           term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust)
  308.           term.write("  ")
  309.         end
  310.       end
  311.     end
  312.   end
  313.  
  314.   local function testBlockAt(block,xp,yp,rot)
  315.     for y=1,4 do
  316.       local ty=yp+y-1
  317.       for x=1,4 do
  318.         local tx=xp+x-1
  319.         if block[rot][y][x]==1 then
  320.           if tx>10 or tx<1 or ty>20 or pit[ty][tx]~=0 then
  321.             return true
  322.           end
  323.         end
  324.       end
  325.     end
  326.   end
  327.  
  328.   local function pitBlock(block,xp,yp,rot)
  329.     for y=1,4 do
  330.       for x=1,4 do
  331.         if block[rot][y][x]==1 then
  332.           pit[yp+y-1][xp+x-1]=block
  333.         end
  334.       end
  335.     end
  336.   end
  337.  
  338.  
  339.   local function clearPit()
  340.     for row=1,20 do
  341.       pit[row]={}
  342.       for col=1,10 do
  343.         pit[row][col]=0
  344.       end
  345.     end
  346.   end
  347.  
  348.  
  349.  
  350.   drawScreen()
  351.   updateNumbers()
  352.  
  353.   --declare & init the pit
  354.   clearPit()
  355.  
  356.  
  357.  
  358.   local halt=false
  359.   local dropSpeed=speedsByLevel[math.min(level,12)]
  360.  
  361.  
  362.   local curBlock=next
  363.   next=blocks[math.random(1,7)]
  364.  
  365.   local curX, curY, curRot=4, 1, 1
  366.   local dropTimer=os.startTimer(dropSpeed)
  367.  
  368.   drawBlockAt(next,11.5,15+heightAdjust,1)
  369.   drawBlockAt(curBlock,curX,curY,curRot)
  370.  
  371.   local function redrawPit()
  372.     for r=1+heightAdjust,20 do
  373.       term.setCursorPos(1,r-heightAdjust)
  374.       for c=1,10 do
  375.         if pit[r][c]==0 then
  376.           term.setTextColor(colors.black)
  377.           term.setBackgroundColor(colors.black)
  378.           term.write("  ")
  379.         else
  380.           term.setTextColor(pit[r][c].fg)
  381.           term.setBackgroundColor(pit[r][c].bg)
  382.           term.write(pit[r][c].ch)
  383.         end
  384.       end
  385.     end
  386.   end
  387.  
  388.   local function hidePit()
  389.     for r=1+heightAdjust,20 do
  390.       term.setCursorPos(1,r-heightAdjust)
  391.       term.setTextColor(colors.black)
  392.       term.setBackgroundColor(colors.black)
  393.       term.write("                    ")
  394.     end
  395.   end
  396.  
  397.   local function msgBox(message)
  398.     local x=math.floor((17-#message)/2)
  399.     term.setBackgroundColor(colors.white)
  400.     term.setTextColor(colors.black)
  401.     term.setCursorPos(x,9)
  402.     term.write("+"..string.rep("-",#message+2).."+")
  403.     term.setCursorPos(x,10)
  404.     term.write("|")
  405.     term.setCursorPos(x+#message+3,10)
  406.     term.write("|")
  407.     term.setCursorPos(x,11)
  408.     term.write("+"..string.rep("-",#message+2).."+")
  409.     term.setTextColor(colors.white)
  410.     term.setBackgroundColor(colors.black)
  411.     term.setCursorPos(x+1,10)
  412.     term.write(" "..message.." ")
  413.   end
  414.  
  415.   local function clearRows()  
  416.     local rows={}
  417.     for r=1,20 do
  418.       local count=0
  419.       for c=1,10 do
  420.         if pit[r][c]~=0 then
  421.           count=count+1
  422.         else
  423.           break
  424.         end
  425.       end
  426.       if count==10 then
  427.         rows[#rows+1]=r
  428.       end
  429.     end
  430.  
  431.     if #rows>0 then
  432.       for i=1,4 do
  433.         sleep(.1)
  434.         for r=1,#rows do
  435.           r=rows[r]
  436.           term.setCursorPos(1,r)      
  437.           for c=1,10 do
  438.             term.setTextColor(pit[r][c].bg)
  439.             term.setBackgroundColor(pit[r][c].fg)
  440.             term.write(pit[r][c].ch)
  441.           end
  442.         end
  443.         sleep(.1)
  444.         for r=1,#rows do
  445.           r=rows[r]
  446.           term.setCursorPos(1,r)      
  447.           for c=1,10 do
  448.             term.setTextColor(pit[r][c].fg)
  449.             term.setBackgroundColor(pit[r][c].bg)
  450.             term.write(pit[r][c].ch)
  451.           end
  452.         end
  453.       end
  454.       --now remove the rows and drop everythign else
  455.       term.setBackgroundColor(colors.black)
  456.       for r=1,#rows do
  457.         r=rows[r]
  458.         term.setCursorPos(1,r)      
  459.         term.write("                    ")
  460.       end
  461.       sleep(.25)
  462.       for r=1,#rows do
  463.         table.remove(pit,rows[r])
  464.         table.insert(pit,1,{0,0,0,0,0,0,0,0,0,0})
  465.       end      
  466.       redrawPit()
  467.       lines=lines+#rows
  468.       score=score+points[#rows]*math.min(level,20)
  469.       level=math.floor(lines/10)+initialLevel
  470.       dropSpeed=speedsByLevel[math.min(level,12)]
  471.       updateNumbers()
  472.     end
  473.     sleep(.25)
  474.   end
  475.  
  476.   local function blockFall()
  477.     if testBlockAt(curBlock,curX,curY+1,curRot) then
  478.       pitBlock(curBlock,curX,curY,curRot)
  479.       --detect rows that clear
  480.       clearRows(rows)
  481.  
  482.       curBlock=next
  483.       curX=4
  484.       curY=1
  485.       curRot=1
  486.       if testBlockAt(curBlock,curX,curY,curRot) then
  487.         halt=true      
  488.       end
  489.       drawBlockAt(curBlock,curX,curY,curRot)
  490.       eraseBlockAt(next,11.5,15+heightAdjust,1)
  491.       next=blocks[math.random(1,7)]
  492.       drawBlockAt(next,11.5,15+heightAdjust,1)
  493.     else
  494.       eraseBlockAt(curBlock,curX,curY,curRot)
  495.       curY=curY+1
  496.       drawBlockAt(curBlock,curX,curY,curRot)
  497.     end
  498.     dropTimer=os.startTimer(dropSpeed)
  499.   end
  500.  
  501.  
  502.   while not halt do  
  503.     local e={os.pullEvent()}
  504.     if e[1]=="timer" then
  505.       if e[2]==dropTimer then
  506.         blockFall()
  507.       end
  508.     elseif e[1]=="key" then
  509.       local key=e[2]
  510.       local dx,dy,dr=0,0,0
  511.       if key==keys.left or key==keys.a then
  512.         dx=-1
  513.       elseif key==keys.right or key==keys.d then
  514.         dx=1
  515.       elseif key==keys.up or key==keys.w then
  516.         dr=1
  517.       elseif key==keys.down or key==keys.s then
  518.         blockFall()      
  519.       elseif key==keys.space then
  520.         hidePit()
  521.         msgBox("Paused")
  522.         while ({os.pullEvent("key")})[2]~=keys.space do end
  523.         redrawPit()
  524.         drawBlockAt(curBlock,curX,curY,curRot)        
  525.       end
  526.       if dx+dr~=0 then
  527.         if not testBlockAt(curBlock,curX+dx,curY+dy,(dr>0 and curRot%#curBlock+dr or curRot)) then
  528.           eraseBlockAt(curBlock,curX,curY,curRot)
  529.           curX=curX+dx
  530.           curY=curY+dy
  531.           curRot=dr==0 and curRot or (curRot%#curBlock+dr)
  532.           drawBlockAt(curBlock,curX,curY,curRot)
  533.         end
  534.       end
  535.     elseif e[1]=="term_resize" then
  536.       local w,h=term.getSize()
  537.       if h==20 then
  538.         heightAdjust=0
  539.       else
  540.         heightAdjust=1
  541.       end
  542.       redrawPit()
  543.       drawBlockAt(curBlock,curX,curY,curRot)
  544.     end
  545.   end
  546.  
  547.   msgBox("Game Over!")
  548.   while true do
  549.     local _,k=os.pullEvent("key")
  550.     if k==keys.space or k==keys.enter then
  551.       break
  552.     end
  553.   end
  554.  
  555. end
  556.  
  557.  
  558. local selected=1
  559. local playersDetected=false
  560.  
  561. local function drawMenu()
  562.   term.setBackgroundColor(colors.black)
  563.   term.setTextColor(colorass(colors.red,colors.white))
  564.   term.clear()
  565.  
  566.   local cx,cy=math.floor(width/2),math.floor(height/2)
  567.  
  568.   term.setCursorPos(cx-3,cy-3)
  569.   term.write("Tetris")
  570.  
  571.   if playersDetected then
  572.     if selected==0 then
  573.       term.setTextColor(colorass(colors.blue,colors.black))
  574.       term.setBackgroundColor(colors.white)
  575.     else
  576.       term.setTextColor(colorass(colors.lightBlue,colors.white))
  577.       term.setBackgroundColor(colors.black)
  578.     end
  579.     term.setCursorPos(cx-11,cy+3)
  580.     term.write("Play head-to-head game!")
  581.   end
  582.  
  583.   term.setCursorPos(cx-10,cy+4)
  584.   if selected==1 then
  585.     term.setTextColor(colorass(colors.blue,colors.black))
  586.     term.setBackgroundColor(colors.white)
  587.   else
  588.     term.setTextColor(colorass(colors.lightBlue,colors.white))
  589.     term.setBackgroundColor(colors.black)
  590.   end
  591.   term.write("Play from level: "..(level==1 and " " or "<")..lpad(level,2)..(level<10 and ">" or " "))
  592.  
  593.   term.setCursorPos(cx-2,cy+5)
  594.   if selected==2 then
  595.     term.setTextColor(colorass(colors.blue,colors.black))
  596.     term.setBackgroundColor(colors.white)
  597.   else
  598.     term.setTextColor(colorass(colors.lightBlue,colors.white))
  599.     term.setBackgroundColor(colors.black)
  600.   end
  601.   term.write("Quit")
  602. end
  603.  
  604.  
  605. local function runMenu()
  606.   drawMenu()
  607.  
  608.   while true do
  609.     local event={os.pullEvent()}
  610.     if event[1]=="key" then
  611.       local key=event[2]
  612.       if key==keys.right or key==keys.d and selected==1 then
  613.         level=math.min(level+1,10)
  614.         drawMenu()
  615.       elseif key==keys.left or key==keys.a and selected==1 then
  616.         level=math.max(level-1,1)
  617.         drawMenu()
  618.       elseif key>=keys.one and key<=keys.zero and selected==1 then
  619.         level=key-1
  620.         drawMenu()
  621.       elseif key==keys.up or key==keys.w then
  622.         selected=selected-1
  623.         if selected==0 then
  624.           selected=2
  625.         end
  626.         drawMenu()
  627.       elseif key==keys.down or key==keys.s then
  628.         selected=selected%2+1
  629.         drawMenu()
  630.       elseif key==keys.enter or key==keys.space then
  631.         break --begin play!
  632.       end
  633.     end
  634.   end  
  635. end
  636.  
  637. while true do
  638.   runMenu()
  639.   if selected==2 then
  640.     break
  641.   end
  642.  
  643.   playGame()
  644. end
  645.  
  646.  
  647. term.setTextColor(colors.white)
  648. term.setBackgroundColor(colors.black)
  649. term.clear()
  650. term.setCursorPos(1,1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement