CCCPaste
-- 2048 Game for SimpleOS
-- CC: Tweaked compatible

local w, h = term.getSize()

-- Game settings
local gridSize = 4
local cellWidth = 6
local startX = math.floor((w - gridSize * cellWidth) / 2)
local startY = 4

-- Game state
local grid = {}
local score = 0
local bestScore = 0
local gameOver = false
local gameWon = false

-- Colors for tiles
local tileColors = {
    [2] = colors.white,
    [4] = colors.lightGray,
    [8] = colors.orange,
    [16] = colors.orange,
    [32] = colors.red,
    [64] = colors.red,
    [128] = colors.yellow,
    [256] = colors.yellow,
    [512] = colors.yellow,
    [1024] = colors.yellow,
    [2048] = colors.lime
}

local textColors = {
    [2] = colors.black,
    [4] = colors.black,
    [8] = colors.white,
    [16] = colors.white,
    [32] = colors.white,
    [64] = colors.white,
    [128] = colors.white,
    [256] = colors.white,
    [512] = colors.white,
    [1024] = colors.white,
    [2048] = colors.white
}

-- Initialize grid
local function initGrid()
    grid = {}
    for y = 1, gridSize do
        grid[y] = {}
        for x = 1, gridSize do
            grid[y][x] = 0
        end
    end
    score = 0
    gameOver = false
    gameWon = false
end

-- Add random tile
local function addRandomTile()
    local empty = {}
    for y = 1, gridSize do
        for x = 1, gridSize do
            if grid[y][x] == 0 then
                table.insert(empty, {x = x, y = y})
            end
        end
    end
    
    if #empty > 0 then
        local pos = empty[math.random(#empty)]
        grid[pos.y][pos.x] = math.random(10) == 1 and 4 or 2
    end
end

-- Check if moves available
local function movesAvailable()
    for y = 1, gridSize do
        for x = 1, gridSize do
            if grid[y][x] == 0 then return true end
            if x < gridSize and grid[y][x] == grid[y][x+1] then return true end
            if y < gridSize and grid[y][x] == grid[y+1][x] then return true end
        end
    end
    return false
end

-- Move tiles in direction
local function move(dx, dy)
    local moved = false
    local merged = {}
    for y = 1, gridSize do
        merged[y] = {}
        for x = 1, gridSize do
            merged[y][x] = false
        end
    end
    
    local startX, endX, stepX = 1, gridSize, 1
    local startY, endY, stepY = 1, gridSize, 1
    
    if dx > 0 then startX, endX, stepX = gridSize, 1, -1 end
    if dy > 0 then startY, endY, stepY = gridSize, 1, -1 end
    
    for y = startY, endY, stepY do
        for x = startX, endX, stepX do
            if grid[y][x] ~= 0 then
                local newX, newY = x, y
                while true do
                    local nextX = newX + dx
                    local nextY = newY + dy
                    if nextX < 1 or nextX > gridSize or nextY < 1 or nextY > gridSize then
                        break
                    end
                    if grid[nextY][nextX] == 0 then
                        newX, newY = nextX, nextY
                    elseif grid[nextY][nextX] == grid[y][x] and not merged[nextY][nextX] then
                        newX, newY = nextX, nextY
                        merged[newY][newX] = true
                        break
                    else
                        break
                    end
                end
                
                if newX ~= x or newY ~= y then
                    moved = true
                    if grid[newY][newX] == grid[y][x] then
                        grid[newY][newX] = grid[y][x] * 2
                        score = score + grid[newY][newX]
                        if score > bestScore then bestScore = score end
                        if grid[newY][newX] == 2048 then gameWon = true end
                    else
                        grid[newY][newX] = grid[y][x]
                    end
                    grid[y][x] = 0
                end
            end
        end
    end
    
    return moved
end

-- Draw a tile
local function drawTile(x, y, value)
    local screenX = startX + (x - 1) * cellWidth
    local screenY = startY + (y - 1) * 2
    
    local bgColor = tileColors[value] or colors.purple
    local fgColor = textColors[value] or colors.white
    if value == 0 then bgColor = colors.gray end
    
    term.setBackgroundColor(bgColor)
    term.setCursorPos(screenX, screenY)
    term.write(string.rep(" ", cellWidth))
    term.setCursorPos(screenX, screenY + 1)
    term.write(string.rep(" ", cellWidth))
    
    if value > 0 then
        term.setTextColor(fgColor)
        local str = tostring(value)
        local offset = math.floor((cellWidth - #str) / 2)
        term.setCursorPos(screenX + offset, screenY)
        term.write(str)
    end
end

-- Draw game
local function draw()
    term.setBackgroundColor(colors.black)
    term.clear()
    
    -- Title
    term.setTextColor(colors.yellow)
    term.setCursorPos(math.floor(w/2) - 2, 1)
    term.write("2048")
    
    -- Score
    term.setTextColor(colors.white)
    term.setCursorPos(2, 2)
    term.write("Score: " .. score)
    term.setCursorPos(w - 12, 2)
    term.write("Best: " .. bestScore)
    
    -- Draw grid
    for y = 1, gridSize do
        for x = 1, gridSize do
            drawTile(x, y, grid[y][x])
        end
    end
    
    -- Controls
    term.setBackgroundColor(colors.black)
    term.setTextColor(colors.gray)
    term.setCursorPos(2, startY + gridSize * 2 + 1)
    term.write("Arrow keys: Move  [Q] Quit  [R] Restart")
end

-- Game over screen
local function showGameOver()
    term.setBackgroundColor(colors.black)
    term.setTextColor(colors.red)
    term.setCursorPos(math.floor(w/2) - 4, startY + gridSize)
    term.write("GAME OVER!")
end

-- Win screen
local function showWin()
    term.setBackgroundColor(colors.black)
    term.setTextColor(colors.lime)
    term.setCursorPos(math.floor(w/2) - 4, startY + gridSize)
    term.write("YOU WIN!")
end

-- Main game loop
local function run()
    initGrid()
    addRandomTile()
    addRandomTile()
    
    while true do
        draw()
        
        if not movesAvailable() then
            gameOver = true
            showGameOver()
        elseif gameWon then
            showWin()
        end
        
        local event, key = os.pullEvent("key")
        
        local moved = false
        if key == keys.up then
            moved = move(0, -1)
        elseif key == keys.down then
            moved = move(0, 1)
        elseif key == keys.left then
            moved = move(-1, 0)
        elseif key == keys.right then
            moved = move(1, 0)
        elseif key == keys.r then
            initGrid()
            addRandomTile()
            addRandomTile()
        elseif key == keys.q then
            return
        end
        
        if moved then
            addRandomTile()
        end
    end
end

run()