Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- Tetris
- "Tetris" Copyright... somebody... probably nintendo, or one of their
- subsidiaries, I dunno. They took it from Tengen in court, in any case.
- This /particular/ version was written by Gopher, at the request of
- Dan200, for ComputerCraft v1.6. No particular rights are reserved,
- since in this case I probably don't, strictly speaking, possess any
- rights to be reserved in the first place. Don't sue me, or something.
- --]]
- local function colorass(c,bw)
- return term.isColor() and c or bw
- end
- local block_s1= {
- {
- { 1,0,0,0, },
- { 1,1,0,0, },
- { 0,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,0,0,0, },
- { 0,1,1,0, },
- { 1,1,0,0, },
- { 0,0,0,0, },
- },
- ch="{}",
- fg=colorass(colors.blue,colors.black),
- bg=colorass(colors.cyan,colors.white),
- }
- local block_s2= {
- {
- { 0,1,0,0, },
- { 1,1,0,0, },
- { 1,0,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,0,0,0, },
- { 1,1,0,0, },
- { 0,1,1,0, },
- { 0,0,0,0, },
- },
- ch="{}",
- fg=colorass(colors.green,colors.black),
- bg=colorass(colors.lime,colors.white),
- }
- local block_line = {
- {
- { 0,1,0,0, },
- { 0,1,0,0, },
- { 0,1,0,0, },
- { 0,1,0,0, },
- },
- {
- { 0,0,0,0, },
- { 1,1,1,1, },
- { 0,0,0,0, },
- { 0,0,0,0, },
- },
- ch="[]",
- fg=colorass(colors.pink,colors.black),
- bg=colorass(colors.red,colors.white),
- }
- local block_square = {
- {
- { 1,1,0,0, },
- { 1,1,0,0, },
- { 0,0,0,0, },
- { 0,0,0,0, },
- },
- ch="[]",
- fg=colorass(colors.lightBlue,colors.black),
- bg=colorass(colors.blue,colors.white),
- }
- local block_L1 = {
- {
- { 1,1,0,0, },
- { 0,1,0,0, },
- { 0,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,0,0,0, },
- { 1,1,1,0, },
- { 1,0,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,1,0,0, },
- { 0,1,0,0, },
- { 0,1,1,0, },
- { 0,0,0,0, },
- },
- {
- { 0,0,1,0, },
- { 1,1,1,0, },
- { 0,0,0,0, },
- { 0,0,0,0, },
- },
- ch="()",
- fg=colorass(colors.orange,colors.black),
- bg=colorass(colors.yellow,colors.white),
- }
- local block_L2 = {
- {
- { 0,1,0,0, },
- { 0,1,0,0, },
- { 1,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,0,0,0, },
- { 1,1,1,0, },
- { 0,0,1,0, },
- { 0,0,0,0, },
- },
- {
- { 0,1,1,0, },
- { 0,1,0,0, },
- { 0,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 1,0,0,0, },
- { 1,1,1,0, },
- { 0,0,0,0, },
- { 0,0,0,0, },
- },
- ch="()",
- fg=colorass(colors.brown,colors.black),
- bg=colorass(colors.orange,colors.white),
- }
- local block_T = {
- {
- { 0,1,0,0, },
- { 1,1,0,0, },
- { 0,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,0,0,0, },
- { 1,1,1,0, },
- { 0,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,1,0,0, },
- { 0,1,1,0, },
- { 0,1,0,0, },
- { 0,0,0,0, },
- },
- {
- { 0,1,0,0, },
- { 1,1,1,0, },
- { 0,0,0,0, },
- { 0,0,0,0, },
- },
- ch="<>",
- fg=colorass(colors.cyan,colors.black),
- bg=colorass(colors.purple,colors.white),
- }
- local blocks={ block_line, block_square, block_s1, block_s2, block_L1, block_L2, block_T}
- local points={4,10,30,120}
- local function lpad(text,amt)
- text=tostring(text)
- return string.rep(" ",amt-#text)..text
- end
- local width,height=term.getSize()
- if height<19 or width<26 then
- print("Your screen is too small to play tetris. :(")
- return
- end
- local speedsByLevel={
- 1.2,
- 1.0,
- .8,
- .65,
- .5,
- .4,
- .3,
- .25,
- .2,
- .15,
- .1,
- .05,}
- local level=1
- local function playGame()
- local score=0
- local lines=0
- local initialLevel=level
- local next=blocks[math.random(1,#blocks)]
- local pit={}
- local heightAdjust=0
- if height<=19 then
- heightAdjust=1
- end
- local function drawScreen()
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setTextColor(colors.black)
- term.setBackgroundColor(colors.white)
- term.setCursorPos(22,2)
- term.write("Score") --score
- term.setCursorPos(22,5)
- term.write("Level") --level
- term.setCursorPos(22,8)
- term.write("Lines") --lines
- term.setCursorPos(22,12)
- term.write("Next") --next
- term.setCursorPos(21,1)
- term.write(" ")
- term.setCursorPos(21,2)
- term.write(" ") --score
- term.setCursorPos(21,3)
- term.write(" ")
- term.setCursorPos(21,4)
- term.write(" ")
- term.setCursorPos(21,5)
- term.write(" ") --level
- term.setCursorPos(21,6)
- term.write(" ")
- term.setCursorPos(21,7)
- term.write(" ")
- term.setCursorPos(21,8)
- term.write(" ") --lines
- term.setCursorPos(21,9)
- term.write(" ")
- term.setCursorPos(21,10)
- term.write(" ")
- term.setCursorPos(21,11)
- term.write(" ")
- term.setCursorPos(21,12)
- term.write(" ") --next
- term.setCursorPos(26,12)
- term.write(" ") --next
- term.setCursorPos(21,13)
- term.write(" ")
- term.setCursorPos(21,14)
- term.write(" ")
- term.setCursorPos(21,15)
- term.write(" ")
- term.setCursorPos(21,16)
- term.write(" ")
- term.setCursorPos(21,17)
- term.write(" ")
- term.setCursorPos(21,18)
- term.write(" ")
- term.setCursorPos(21,19)
- term.write(" ")
- term.setCursorPos(21,20)
- term.write(" ")
- end
- local function updateNumbers()
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- term.setCursorPos(22,3)
- term.write(lpad(score,5)) --score
- term.setCursorPos(22,6)
- term.write(lpad(level,5)) --level
- term.setCursorPos(22,9)
- term.write(lpad(lines,5)) --lines
- end
- local function drawBlockAt(block,xp,yp,rot)
- term.setTextColor(block.fg)
- term.setBackgroundColor(block.bg)
- for y=1,4 do
- for x=1,4 do
- if block[rot][y][x]==1 then
- term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust)
- term.write(block.ch)
- end
- end
- end
- end
- local function eraseBlockAt(block,xp,yp,rot)
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- for y=1,4 do
- for x=1,4 do
- if block[rot][y][x]==1 then
- term.setCursorPos((xp+x)*2-3,yp+y-1-heightAdjust)
- term.write(" ")
- end
- end
- end
- end
- local function testBlockAt(block,xp,yp,rot)
- for y=1,4 do
- local ty=yp+y-1
- for x=1,4 do
- local tx=xp+x-1
- if block[rot][y][x]==1 then
- if tx>10 or tx<1 or ty>20 or pit[ty][tx]~=0 then
- return true
- end
- end
- end
- end
- end
- local function pitBlock(block,xp,yp,rot)
- for y=1,4 do
- for x=1,4 do
- if block[rot][y][x]==1 then
- pit[yp+y-1][xp+x-1]=block
- end
- end
- end
- end
- local function clearPit()
- for row=1,20 do
- pit[row]={}
- for col=1,10 do
- pit[row][col]=0
- end
- end
- end
- drawScreen()
- updateNumbers()
- --declare & init the pit
- clearPit()
- local halt=false
- local dropSpeed=speedsByLevel[math.min(level,12)]
- local curBlock=next
- next=blocks[math.random(1,7)]
- local curX, curY, curRot=4, 1, 1
- local dropTimer=os.startTimer(dropSpeed)
- drawBlockAt(next,11.5,15+heightAdjust,1)
- drawBlockAt(curBlock,curX,curY,curRot)
- local function redrawPit()
- for r=1+heightAdjust,20 do
- term.setCursorPos(1,r-heightAdjust)
- for c=1,10 do
- if pit[r][c]==0 then
- term.setTextColor(colors.black)
- term.setBackgroundColor(colors.black)
- term.write(" ")
- else
- term.setTextColor(pit[r][c].fg)
- term.setBackgroundColor(pit[r][c].bg)
- term.write(pit[r][c].ch)
- end
- end
- end
- end
- local function hidePit()
- for r=1+heightAdjust,20 do
- term.setCursorPos(1,r-heightAdjust)
- term.setTextColor(colors.black)
- term.setBackgroundColor(colors.black)
- term.write(" ")
- end
- end
- local function msgBox(message)
- local x=math.floor((17-#message)/2)
- term.setBackgroundColor(colors.white)
- term.setTextColor(colors.black)
- term.setCursorPos(x,9)
- term.write("+"..string.rep("-",#message+2).."+")
- term.setCursorPos(x,10)
- term.write("|")
- term.setCursorPos(x+#message+3,10)
- term.write("|")
- term.setCursorPos(x,11)
- term.write("+"..string.rep("-",#message+2).."+")
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- term.setCursorPos(x+1,10)
- term.write(" "..message.." ")
- end
- local function clearRows()
- local rows={}
- for r=1,20 do
- local count=0
- for c=1,10 do
- if pit[r][c]~=0 then
- count=count+1
- else
- break
- end
- end
- if count==10 then
- rows[#rows+1]=r
- end
- end
- if #rows>0 then
- for i=1,4 do
- sleep(.1)
- for r=1,#rows do
- r=rows[r]
- term.setCursorPos(1,r)
- for c=1,10 do
- term.setTextColor(pit[r][c].bg)
- term.setBackgroundColor(pit[r][c].fg)
- term.write(pit[r][c].ch)
- end
- end
- sleep(.1)
- for r=1,#rows do
- r=rows[r]
- term.setCursorPos(1,r)
- for c=1,10 do
- term.setTextColor(pit[r][c].fg)
- term.setBackgroundColor(pit[r][c].bg)
- term.write(pit[r][c].ch)
- end
- end
- end
- --now remove the rows and drop everythign else
- term.setBackgroundColor(colors.black)
- for r=1,#rows do
- r=rows[r]
- term.setCursorPos(1,r)
- term.write(" ")
- end
- sleep(.25)
- for r=1,#rows do
- table.remove(pit,rows[r])
- table.insert(pit,1,{0,0,0,0,0,0,0,0,0,0})
- end
- redrawPit()
- lines=lines+#rows
- score=score+points[#rows]*math.min(level,20)
- level=math.floor(lines/10)+initialLevel
- dropSpeed=speedsByLevel[math.min(level,12)]
- updateNumbers()
- end
- sleep(.25)
- end
- local function blockFall()
- if testBlockAt(curBlock,curX,curY+1,curRot) then
- pitBlock(curBlock,curX,curY,curRot)
- --detect rows that clear
- clearRows(rows)
- curBlock=next
- curX=4
- curY=1
- curRot=1
- if testBlockAt(curBlock,curX,curY,curRot) then
- halt=true
- end
- drawBlockAt(curBlock,curX,curY,curRot)
- eraseBlockAt(next,11.5,15+heightAdjust,1)
- next=blocks[math.random(1,7)]
- drawBlockAt(next,11.5,15+heightAdjust,1)
- else
- eraseBlockAt(curBlock,curX,curY,curRot)
- curY=curY+1
- drawBlockAt(curBlock,curX,curY,curRot)
- end
- dropTimer=os.startTimer(dropSpeed)
- end
- while not halt do
- local e={os.pullEvent()}
- if e[1]=="timer" then
- if e[2]==dropTimer then
- blockFall()
- end
- elseif e[1]=="key" then
- local key=e[2]
- local dx,dy,dr=0,0,0
- if key==keys.left or key==keys.a then
- dx=-1
- elseif key==keys.right or key==keys.d then
- dx=1
- elseif key==keys.up or key==keys.w then
- dr=1
- elseif key==keys.down or key==keys.s then
- blockFall()
- elseif key==keys.space then
- hidePit()
- msgBox("Paused")
- while ({os.pullEvent("key")})[2]~=keys.space do end
- redrawPit()
- drawBlockAt(curBlock,curX,curY,curRot)
- end
- if dx+dr~=0 then
- if not testBlockAt(curBlock,curX+dx,curY+dy,(dr>0 and curRot%#curBlock+dr or curRot)) then
- eraseBlockAt(curBlock,curX,curY,curRot)
- curX=curX+dx
- curY=curY+dy
- curRot=dr==0 and curRot or (curRot%#curBlock+dr)
- drawBlockAt(curBlock,curX,curY,curRot)
- end
- end
- elseif e[1]=="term_resize" then
- local w,h=term.getSize()
- if h==20 then
- heightAdjust=0
- else
- heightAdjust=1
- end
- redrawPit()
- drawBlockAt(curBlock,curX,curY,curRot)
- end
- end
- msgBox("Game Over!")
- while true do
- local _,k=os.pullEvent("key")
- if k==keys.space or k==keys.enter then
- break
- end
- end
- end
- local selected=1
- local playersDetected=false
- local function drawMenu()
- term.setBackgroundColor(colors.black)
- term.setTextColor(colorass(colors.red,colors.white))
- term.clear()
- local cx,cy=math.floor(width/2),math.floor(height/2)
- term.setCursorPos(cx-3,cy-3)
- term.write("Tetris")
- if playersDetected then
- if selected==0 then
- term.setTextColor(colorass(colors.blue,colors.black))
- term.setBackgroundColor(colors.white)
- else
- term.setTextColor(colorass(colors.lightBlue,colors.white))
- term.setBackgroundColor(colors.black)
- end
- term.setCursorPos(cx-11,cy+3)
- term.write("Play head-to-head game!")
- end
- term.setCursorPos(cx-10,cy+4)
- if selected==1 then
- term.setTextColor(colorass(colors.blue,colors.black))
- term.setBackgroundColor(colors.white)
- else
- term.setTextColor(colorass(colors.lightBlue,colors.white))
- term.setBackgroundColor(colors.black)
- end
- term.write("Play from level: "..(level==1 and " " or "<")..lpad(level,2)..(level<10 and ">" or " "))
- term.setCursorPos(cx-2,cy+5)
- if selected==2 then
- term.setTextColor(colorass(colors.blue,colors.black))
- term.setBackgroundColor(colors.white)
- else
- term.setTextColor(colorass(colors.lightBlue,colors.white))
- term.setBackgroundColor(colors.black)
- end
- term.write("Quit")
- end
- local function runMenu()
- drawMenu()
- while true do
- local event={os.pullEvent()}
- if event[1]=="key" then
- local key=event[2]
- if key==keys.right or key==keys.d and selected==1 then
- level=math.min(level+1,10)
- drawMenu()
- elseif key==keys.left or key==keys.a and selected==1 then
- level=math.max(level-1,1)
- drawMenu()
- elseif key>=keys.one and key<=keys.zero and selected==1 then
- level=key-1
- drawMenu()
- elseif key==keys.up or key==keys.w then
- selected=selected-1
- if selected==0 then
- selected=2
- end
- drawMenu()
- elseif key==keys.down or key==keys.s then
- selected=selected%2+1
- drawMenu()
- elseif key==keys.enter or key==keys.space then
- break --begin play!
- end
- end
- end
- end
- while true do
- runMenu()
- if selected==2 then
- break
- end
- playGame()
- end
- term.setTextColor(colors.white)
- term.setBackgroundColor(colors.black)
- term.clear()
- term.setCursorPos(1,1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement