← back to Model Arena

data/artifacts/04692f72ef1d/kimi.html

495 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tetris</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background: #111;
            color: #fff;
            font-family: 'Courier New', Courier, monospace;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            overflow: hidden;
        }
        #gameContainer {
            display: flex;
            gap: 20px;
            background: #222;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 20px rgba(0,0,0,0.8);
        }
        #board {
            border: 3px solid #444;
            background: #000;
        }
        #sidePanel {
            display: flex;
            flex-direction: column;
            gap: 20px;
            width: 120px;
        }
        #nextCanvas {
            border: 2px solid #444;
            background: #000;
        }
        .infoBox {
            background: #333;
            padding: 10px;
            border-radius: 4px;
            text-align: center;
            border: 1px solid #555;
        }
        .label {
            font-size: 12px;
            color: #888;
            text-transform: uppercase;
            margin-bottom: 5px;
        }
        .value {
            font-size: 20px;
            font-weight: bold;
            color: #fff;
        }
        #controls {
            font-size: 11px;
            color: #666;
            line-height: 1.5;
            margin-top: auto;
        }
        #gameOver, #paused {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: rgba(0,0,0,0.9);
            padding: 30px;
            border-radius: 8px;
            text-align: center;
            border: 2px solid #fff;
            display: none;
        }
        button {
            background: #4a4;
            color: white;
            border: none;
            padding: 10px 20px;
            font-family: inherit;
            font-size: 16px;
            cursor: pointer;
            margin-top: 10px;
            border-radius: 4px;
        }
        button:hover {
            background: #5c5;
        }
        h1 {
            margin: 0 0 10px 0;
            font-size: 24px;
            text-shadow: 2px 2px 0 #f00;
        }
    </style>
</head>
<body>
    <div id="gameContainer">
        <canvas id="board" width="300" height="600"></canvas>
        <div id="sidePanel">
            <div class="infoBox">
                <div class="label">Next</div>
                <canvas id="nextCanvas" width="120" height="120"></canvas>
            </div>
            <div class="infoBox">
                <div class="label">Score</div>
                <div class="value" id="score">0</div>
            </div>
            <div class="infoBox">
                <div class="label">Lines</div>
                <div class="value" id="lines">0</div>
            </div>
            <div class="infoBox">
                <div class="label">Level</div>
                <div class="value" id="level">1</div>
            </div>
            <div id="controls">
                <strong>Controls:</strong><br>
                ← → : Move<br>
                ↑ / X : Rotate<br>
                Z : Rotate CCW<br>
                ↓ : Soft Drop<br>
                Space : Hard Drop<br>
                P : Pause<br>
                R : Restart
            </div>
        </div>
    </div>
    
    <div id="gameOver">
        <h1>GAME OVER</h1>
        <div>Score: <span id="finalScore">0</span></div>
        <button onclick="resetGame()">Restart</button>
    </div>
    
    <div id="paused">
        <h1>PAUSED</h1>
        <div>Press P to resume</div>
    </div>

    <script>
        const canvas = document.getElementById('board');
        const ctx = canvas.getContext('2d');
        const nextCanvas = document.getElementById('nextCanvas');
        const nextCtx = nextCanvas.getContext('2d');
        
        const COLS = 10;
        const ROWS = 20;
        const BLOCK_SIZE = 30;
        const PREVIEW_BLOCK_SIZE = 25;
        
        let board = [];
        let score = 0;
        let lines = 0;
        let level = 1;
        let gameOver = false;
        let paused = false;
        let dropCounter = 0;
        let lastTime = 0;
        let dropInterval = 1000;
        
        const PIECES = [
            { shape: [[1,1,1,1]], color: '#00f0f0' }, // I
            { shape: [[1,1],[1,1]], color: '#f0f000' }, // O
            { shape: [[0,1,0],[1,1,1]], color: '#a000f0' }, // T
            { shape: [[0,1,1],[1,1,0]], color: '#00f000' }, // S
            { shape: [[1,1,0],[0,1,1]], color: '#f00000' }, // Z
            { shape: [[1,0,0],[1,1,1]], color: '#0000f0' }, // J
            { shape: [[0,0,1],[1,1,1]], color: '#f0a000' }  // L
        ];
        
        let currentPiece = null;
        let nextPiece = null;
        
        function createBoard() {
            board = Array(ROWS).fill().map(() => Array(COLS).fill(0));
        }
        
        function rotateMatrix(matrix, times) {
            times = ((times % 4) + 4) % 4;
            let result = matrix;
            for (let i = 0; i < times; i++) {
                result = rotate90(result);
            }
            return result;
        }
        
        function rotate90(matrix) {
            const rows = matrix.length;
            const cols = matrix[0].length;
            const rotated = [];
            for (let i = 0; i < cols; i++) {
                rotated[i] = [];
                for (let j = 0; j < rows; j++) {
                    rotated[i][j] = matrix[rows - 1 - j][i];
                }
            }
            return rotated;
        }
        
        function getRandomPiece() {
            const piece = PIECES[Math.floor(Math.random() * PIECES.length)];
            return {
                shape: piece.shape,
                color: piece.color,
                x: 0,
                y: 0,
                rotation: 0
            };
        }
        
        function spawnPiece() {
            currentPiece = nextPiece || getRandomPiece();
            nextPiece = getRandomPiece();
            
            const shape = rotateMatrix(currentPiece.shape, currentPiece.rotation);
            currentPiece.x = Math.floor(COLS / 2) - Math.floor(shape[0].length / 2);
            currentPiece.y = 0;
            
            if (!isValidPosition(currentPiece, currentPiece.x, currentPiece.y, currentPiece.rotation)) {
                endGame();
            }
        }
        
        function isValidPosition(piece, x, y, rotation) {
            const shape = rotateMatrix(piece.shape, rotation);
            for (let r = 0; r < shape.length; r++) {
                for (let c = 0; c < shape[r].length; c++) {
                    if (shape[r][c]) {
                        const newX = x + c;
                        const newY = y + r;
                        if (newX < 0 || newX >= COLS || newY >= ROWS) return false;
                        if (newY >= 0 && board[newY][newX]) return false;
                    }
                }
            }
            return true;
        }
        
        function rotatePiece(clockwise = true) {
            const newRotation = clockwise ? (currentPiece.rotation + 1) % 4 : (currentPiece.rotation + 3) % 4;
            const kicks = [0, -1, 1, -2, 2];
            
            for (let kick of kicks) {
                if (isValidPosition(currentPiece, currentPiece.x + kick, currentPiece.y, newRotation)) {
                    currentPiece.x += kick;
                    currentPiece.rotation = newRotation;
                    break;
                }
            }
        }
        
        function movePiece(dx, dy) {
            if (isValidPosition(currentPiece, currentPiece.x + dx, currentPiece.y + dy, currentPiece.rotation)) {
                currentPiece.x += dx;
                currentPiece.y += dy;
                return true;
            }
            return false;
        }
        
        function dropPiece() {
            if (!movePiece(0, 1)) {
                lockPiece();
            }
            dropCounter = 0;
        }
        
        function hardDrop() {
            while (movePiece(0, 1)) {
                score += 2;
            }
            lockPiece();
            dropCounter = 0;
        }
        
        function lockPiece() {
            const shape = rotateMatrix(currentPiece.shape, currentPiece.rotation);
            for (let r = 0; r < shape.length; r++) {
                for (let c = 0; c < shape[r].length; c++) {
                    if (shape[r][c]) {
                        const y = currentPiece.y + r;
                        const x = currentPiece.x + c;
                        if (y >= 0) {
                            board[y][x] = currentPiece.color;
                        }
                    }
                }
            }
            clearLines();
            spawnPiece();
            updateStats();
        }
        
        function clearLines() {
            let linesCleared = 0;
            for (let r = ROWS - 1; r >= 0; r--) {
                if (board[r].every(cell => cell !== 0)) {
                    board.splice(r, 1);
                    board.unshift(Array(COLS).fill(0));
                    linesCleared++;
                    r++;
                }
            }
            
            if (linesCleared > 0) {
                lines += linesCleared;
                const points = [0, 100, 300, 500, 800];
                score += points[linesCleared] * level;
                level = Math.floor(lines / 10) + 1;
                dropInterval = Math.max(100, 1000 - (level - 1) * 80);
            }
        }
        
        function drawBlock(context, x, y, color, size = BLOCK_SIZE) {
            context.fillStyle = color;
            context.fillRect(x * size, y * size, size, size);
            
            context.strokeStyle = 'rgba(255,255,255,0.4)';
            context.lineWidth = 2;
            context.strokeRect(x * size, y * size, size, size);
            
            context.fillStyle = 'rgba(255,255,255,0.3)';
            context.fillRect(x * size + 2, y * size + 2, size - 4, 3);
            context.fillStyle = 'rgba(0,0,0,0.2)';
            context.fillRect(x * size + 2, y * size + size - 5, size - 4, 3);
        }
        
        function draw() {
            ctx.fillStyle = '#000';
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            
            ctx.strokeStyle = '#222';
            ctx.lineWidth = 1;
            for (let i = 0; i <= COLS; i++) {
                ctx.beginPath();
                ctx.moveTo(i * BLOCK_SIZE, 0);
                ctx.lineTo(i * BLOCK_SIZE, canvas.height);
                ctx.stroke();
            }
            for (let i = 0; i <= ROWS; i++) {
                ctx.beginPath();
                ctx.moveTo(0, i * BLOCK_SIZE);
                ctx.lineTo(canvas.width, i * BLOCK_SIZE);
                ctx.stroke();
            }
            
            for (let r = 0; r < ROWS; r++) {
                for (let c = 0; c < COLS; c++) {
                    if (board[r][c]) {
                        drawBlock(ctx, c, r, board[r][c]);
                    }
                }
            }
            
            if (currentPiece) {
                const shape = rotateMatrix(currentPiece.shape, currentPiece.rotation);
                for (let r = 0; r < shape.length; r++) {
                    for (let c = 0; c < shape[r].length; c++) {
                        if (shape[r][c]) {
                            drawBlock(ctx, currentPiece.x + c, currentPiece.y + r, currentPiece.color);
                        }
                    }
                }
            }
            
            if (nextPiece) {
                nextCtx.fillStyle = '#000';
                nextCtx.fillRect(0, 0, nextCanvas.width, nextCanvas.height);
                const shape = nextPiece.shape;
                const offsetX = Math.floor((4 - shape[0].length) / 2);
                const offsetY = Math.floor((4 - shape.length) / 2);
                for (let r = 0; r < shape.length; r++) {
                    for (let c = 0; c < shape[r].length; c++) {
                        if (shape[r][c]) {
                            drawBlock(nextCtx, offsetX + c, offsetY + r, nextPiece.color, PREVIEW_BLOCK_SIZE);
                        }
                    }
                }
            }
        }
        
        function update(time = 0) {
            if (gameOver || paused) return;
            
            const deltaTime = time - lastTime;
            lastTime = time;
            dropCounter += deltaTime;
            
            if (dropCounter > dropInterval) {
                dropPiece();
            }
            
            draw();
            requestAnimationFrame(update);
        }
        
        function updateStats() {
            document.getElementById('score').textContent = score;
            document.getElementById('lines').textContent = lines;
            document.getElementById('level').textContent = level;
        }
        
        function endGame() {
            gameOver = true;
            document.getElementById('finalScore').textContent = score;
            document.getElementById('gameOver').style.display = 'block';
        }
        
        function resetGame() {
            createBoard();
            score = 0;
            lines = 0;
            level = 1;
            dropInterval = 1000;
            gameOver = false;
            paused = false;
            currentPiece = null;
            nextPiece = null;
            document.getElementById('gameOver').style.display = 'none';
            document.getElementById('paused').style.display = 'none';
            updateStats();
            spawnPiece();
            lastTime = 0;
            dropCounter = 0;
            update();
        }
        
        function togglePause() {
            if (gameOver) return;
            paused = !paused;
            document.getElementById('paused').style.display = paused ? 'block' : 'none';
            if (!paused) {
                lastTime = performance.now();
                update();
            }
        }
        
        document.addEventListener('keydown', (e) => {
            if (e.key === 'r' || e.key === 'R') {
                if (gameOver) resetGame();
                return;
            }
            
            if (gameOver) return;
            
            if (e.key === 'p' || e.key === 'P') {
                togglePause();
                return;
            }
            
            if (paused) return;
            
            switch(e.key) {
                case 'ArrowLeft':
                    if (movePiece(-1, 0)) draw();
                    break;
                case 'ArrowRight':
                    if (movePiece(1, 0)) draw();
                    break;
                case 'ArrowDown':
                    if (movePiece(0, 1)) {
                        score += 1;
                        updateStats();
                        draw();
                    }
                    break;
                case 'ArrowUp':
                case 'x':
                case 'X':
                    rotatePiece(true);
                    draw();
                    break;
                case 'z':
                case 'Z':
                    rotatePiece(false);
                    draw();
                    break;
                case ' ':
                    hardDrop();
                    updateStats();
                    draw();
                    break;
            }
        });
        
        createBoard();
        spawnPiece();
        updateStats();
        update();
    </script>
</body>
</html>