-- Tetris Game for SimpleOS -- CC: Tweaked compatible local w, h = term.getSize() -- Game board dimensions local boardWidth = 10 local boardHeight = 18 local boardX = math.floor((w - boardWidth * 2) / 2) local boardY = 2 -- Tetromino shapes local shapes = { { -- I {{1,1,1,1}}, {{1},{1},{1},{1}} }, { -- O {{1,1},{1,1}} }, { -- T {{0,1,0},{1,1,1}}, {{1,0},{1,1},{1,0}}, {{1,1,1},{0,1,0}}, {{0,1},{1,1},{0,1}} }, { -- S {{0,1,1},{1,1,0}}, {{1,0},{1,1},{0,1}} }, { -- Z {{1,1,0},{0,1,1}}, {{0,1},{1,1},{1,0}} }, { -- J {{1,0,0},{1,1,1}}, {{1,1},{1,0},{1,0}}, {{1,1,1},{0,0,1}}, {{0,1},{0,1},{1,1}} }, { -- L {{0,0,1},{1,1,1}}, {{1,0},{1,0},{1,1}}, {{1,1,1},{1,0,0}}, {{1,1},{0,1},{0,1}} } } local shapeColors = { colors.cyan, colors.yellow, colors.purple, colors.green, colors.red, colors.blue, colors.orange } -- Game state local board = {} local currentShape = nil local currentRotation = 1 local currentX, currentY = 1, 1 local currentType = 1 local score = 0 local level = 1 local lines = 0 local gameOver = false local speed = 0.5 -- Initialize board local function initBoard() board = {} for y = 1, boardHeight do board[y] = {} for x = 1, boardWidth do board[y][x] = 0 end end end -- Get current shape data local function getShape() local rotations = shapes[currentType] return rotations[((currentRotation - 1) % #rotations) + 1] end -- Check collision local function checkCollision(shape, px, py) for y, row in ipairs(shape) do for x, cell in ipairs(row) do if cell == 1 then local bx = px + x - 1 local by = py + y - 1 if bx < 1 or bx > boardWidth or by > boardHeight then return true end if by >= 1 and board[by][bx] ~= 0 then return true end end end end return false end -- Spawn new piece local function spawnPiece() currentType = math.random(1, #shapes) currentRotation = 1 currentX = math.floor(boardWidth / 2) - 1 currentY = 1 if checkCollision(getShape(), currentX, currentY) then gameOver = true end end -- Lock piece to board local function lockPiece() local shape = getShape() for y, row in ipairs(shape) do for x, cell in ipairs(row) do if cell == 1 then local by = currentY + y - 1 local bx = currentX + x - 1 if by >= 1 and by <= boardHeight and bx >= 1 and bx <= boardWidth then board[by][bx] = currentType end end end end end -- Clear completed lines local function clearLines() local cleared = 0 local y = boardHeight while y >= 1 do local full = true for x = 1, boardWidth do if board[y][x] == 0 then full = false break end end if full then table.remove(board, y) local newRow = {} for x = 1, boardWidth do newRow[x] = 0 end table.insert(board, 1, newRow) cleared = cleared + 1 else y = y - 1 end end if cleared > 0 then local points = {40, 100, 300, 1200} score = score + (points[cleared] or 1200) * level lines = lines + cleared level = math.floor(lines / 10) + 1 speed = math.max(0.05, 0.5 - (level - 1) * 0.05) end end -- Draw game local function draw() term.setBackgroundColor(colors.black) term.clear() -- Draw border term.setBackgroundColor(colors.gray) for y = 0, boardHeight + 1 do term.setCursorPos(boardX - 1, boardY + y) term.write(" ") term.setCursorPos(boardX + boardWidth * 2, boardY + y) term.write(" ") end for x = -1, boardWidth * 2 do term.setCursorPos(boardX + x, boardY + boardHeight + 1) term.write(" ") end -- Draw board for y = 1, boardHeight do for x = 1, boardWidth do term.setCursorPos(boardX + (x - 1) * 2, boardY + y - 1) if board[y][x] ~= 0 then term.setBackgroundColor(shapeColors[board[y][x]]) term.write(" ") else term.setBackgroundColor(colors.black) term.write(" ") end end end -- Draw current piece if not gameOver then local shape = getShape() term.setBackgroundColor(shapeColors[currentType]) for y, row in ipairs(shape) do for x, cell in ipairs(row) do if cell == 1 then local dy = currentY + y - 1 local dx = currentX + x - 1 if dy >= 1 then term.setCursorPos(boardX + (dx - 1) * 2, boardY + dy - 1) term.write(" ") end end end end end -- Draw info term.setBackgroundColor(colors.black) term.setTextColor(colors.white) term.setCursorPos(2, 2) term.write("TETRIS") term.setCursorPos(2, 4) term.write("Score:") term.setCursorPos(2, 5) term.write(tostring(score)) term.setCursorPos(2, 7) term.write("Level:") term.setCursorPos(2, 8) term.write(tostring(level)) term.setCursorPos(2, 10) term.write("Lines:") term.setCursorPos(2, 11) term.write(tostring(lines)) term.setCursorPos(2, h - 1) term.write("[Q] Quit") end -- Game over screen local function showGameOver() term.setBackgroundColor(colors.black) term.setTextColor(colors.red) term.setCursorPos(boardX + 2, boardY + 7) term.write("GAME OVER") term.setTextColor(colors.white) term.setCursorPos(boardX, boardY + 9) term.write("ENTER=Restart") end -- Move piece local function movePiece(dx, dy) local shape = getShape() if not checkCollision(shape, currentX + dx, currentY + dy) then currentX = currentX + dx currentY = currentY + dy return true end return false end -- Rotate piece local function rotatePiece() local oldRotation = currentRotation currentRotation = currentRotation + 1 local shape = getShape() if checkCollision(shape, currentX, currentY) then currentRotation = oldRotation end end -- Drop piece local function dropPiece() while movePiece(0, 1) do end lockPiece() clearLines() spawnPiece() end -- Main game loop local function run() initBoard() spawnPiece() score = 0 level = 1 lines = 0 gameOver = false speed = 0.5 while true do draw() if gameOver then showGameOver() while true do local event, key = os.pullEvent("key") if key == keys.enter then initBoard() spawnPiece() score = 0 level = 1 lines = 0 gameOver = false speed = 0.5 break elseif key == keys.q then return end end end local timer = os.startTimer(speed) while true do local event, p1 = os.pullEvent() if event == "key" then if p1 == keys.left then movePiece(-1, 0) draw() elseif p1 == keys.right then movePiece(1, 0) draw() elseif p1 == keys.down then movePiece(0, 1) draw() elseif p1 == keys.up then rotatePiece() draw() elseif p1 == keys.space then dropPiece() break elseif p1 == keys.q then return end elseif event == "timer" and p1 == timer then break end end if not gameOver then if not movePiece(0, 1) then lockPiece() clearLines() spawnPiece() end end end end run()