← back to Model Arena

data/artifacts/04692f72ef1d/hermes3-8b.html

338 lines

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Playable Tetris</title>
  <style>
    body {
      font-family: monospace;
      background-color: #000;
      color: #0f0;
      padding: 10px;
    }
    
    canvas {
      background-color: #333;
    }
    
    .score {
      margin-top: 5px;
    }
    
    .controls {
      margin-top: 10px;
    }
    
    button {
      margin-right: 5px;
    }
  </style>
</head>
<body>
  <canvas id="game"></canvas>
  <div class="score">Score: <span id="score">0</span></div>
  <div class="controls">
    <button id="pause" disabled>Pause</button>
    <button id="restart">Restart</button>
  </div>

  <script>
    const canvas = document.getElementById('game');
    const ctx = canvas.getContext('2d');

    const tetrominoes = [
      [[1]], [[1], [1], [1]], [[1, 1], [1, 1]], [[1, 1, 1], [0, 1, 0]],
    ];

    let grid = Array(20).fill().map(() => Array(10).fill(0));
    let currentPiece = null;
    let currentX = 0;
    let currentY = 0;

    function getRandomInt(max) {
      return Math.floor(Math.random() * max);
    }

    function rotatePiece() {
      if (currentPiece === tetrominoes[3]) {
        return;
      }
      
      for (let i = 0; i < currentPiece.length; i++) {
        for (let j = 0; j < currentPiece[i].length; j++) {
          const temp = currentPiece[i][j];
          currentPiece[i][j] = currentPiece[j][i];
          currentPiece[j][i] = temp;
        }
      }

      if (!isCollision()) {
        return;
      }

      for (let i = 0; i < currentPiece.length; i++) {
        for (let j = 0; j < currentPiece[i].length; j++) {
          currentPiece[i][j] = 0;
        }
      }

      if (!isCollision()) {
        return;
      }

      for (let i = 0; i < currentPiece.length; i++) {
        for (let j = 0; j < currentPiece[i].length; j++) {
          currentPiece[i][j] = temp;
        }
      }
    }

    function movePieceDown() {
      currentY++;

      if (isCollision()) {
        setCurrentPiece(null);
        merge();
        return;
      }
      
      clearLines();
    }

    function movePieceLeft() {
      currentX--;

      if (isCollision()) {
        currentX++;
      }
    }

    function movePieceRight() {
      currentX++;

      if (isCollision()) {
        currentX--;
      }
    }

    function isCollision() {
      for (let i = 0; i < currentPiece.length; i++) {
        for (let j = 0; j < currentPiece[i].length; j++) {
          const value = currentPiece[i][j];

          if (value !== 0) {
            if (currentX + i >= 0 && currentX + i < grid.length &&
                currentY + j >= 0 && currentY + j < grid[0].length) {

              if (grid[currentX + i][currentY + j] !== 0) {
                return true;
              }
            } else {
              return true;
            }
          }
        }
      }

      return false;
    }

    function clearLines() {
      for (let i = grid.length - 1; i >= 0; i--) {
        let lineFull = true;

        for (let j = 0; j < grid[i].length; j++) {
          if (grid[i][j] === 0) {
            lineFull = false;
            break;
          }
        }

        if (lineFull) {
          grid.splice(i, 1);
          grid.unshift(Array(grid[0].length).fill(0));

          for (let k = i; k < grid.length; k++) {
            for (let j = 0; j < grid[k].length; j++) {
              grid[k][j]++;
            }
          }
        }
      }

      if (grid.length === 0) {
        grid.unshift(Array(grid[0].length).fill(0));
      }
    }

    function merge() {
      let score = 0;

      for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[i].length; j++) {
          if (grid[i][j] > 0) {
            const count = Math.floor(grid[i][j] / tetrominoes[3][0].length);

            for (let k = 0; k < count; k++) {
              score += count;
              grid[i][j] -= tetrominoes[3][0].length;
            }
          }
        }
      }

      document.getElementById('score').textContent = score;
    }

    function setCurrentPiece(piece) {
      currentX = Math.floor(grid.length / 2) - Math.floor(tetrominoes[piece][0].length / 2);
      currentY = Math.floor(grid[0].length / 2) - Math.floor(tetrominoes[piece][0][0] / 2);

      if (isCollision()) {
        setCurrentPiece(0);
      }

      currentPiece = tetrominoes[piece];
    }

    function getRandomTetromino() {
      const types = [1, 2, 3, 4];

      for (let i = 0; i < types.length; i++) {
        if (types[i] !== null) {
          return types.splice(getRandomInt(types.length), 1)[0];
        }
      }

      return 0;
    }

    function drawPiece(x, y) {
      for (let i = 0; i < currentPiece.length; i++) {
        for (let j = 0; j < currentPiece[i].length; j++) {
          if (currentPiece[i][j] > 0) {
            ctx.fillStyle = 'rgba(255, 255, 0, 1)';
            ctx.fillRect((x + j) * 20, (y + i) * 20, 20, 20);
            ctx.strokeStyle = '#000';
            ctx.strokeRect((x + j) * 20, (y + i) * 20, 20, 20);
          }
        }
      }
    }

    function drawGrid() {
      for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[i].length; j++) {
          if (grid[i][j] > 0) {
            ctx.fillStyle = 'rgba(255, 255, 0, 1)';
            ctx.fillRect(j * 20, i * 20, 20, 20);
            
            if (grid[i][j] > 9) {
              ctx.font = "12px monospace";
              ctx.fillStyle = "#fff";
              ctx.textAlign = "center";
              ctx.fillText(grid[i][j], j * 20 + 10, i * 20 + 20);
            }
          } else {
            ctx.strokeStyle = '#fff';
            ctx.strokeRect(j * 20, i * 20, 20, 20);
          }
        }
      }
    }

    function drawNextPiece() {
      const nextX = Math.floor(grid.length / 2) - Math.floor(tetrominoes[getRandomTetromino()][0].length / 2);

      for (let i = 0; i < tetrominoes[getRandomTetromino()].length; i++) {
        for (let j = 0; j < tetrominoes[getRandomTetromino()][i].length; j++) {
          if (tetrominoes[getRandomTetromino()][i][j] > 0) {
            ctx.fillStyle = 'rgba(255, 255, 255, 1)';
            ctx.fillRect((nextX + j) * 20, (i) * 20, 20, 20);
          }
        }
      }
    }

    function draw() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      drawGrid();
      drawPiece(currentX, currentY);

      if (!isGameOver()) {
        setTimeout(() => {
          movePieceDown();
          draw();
        }, 500 - document.getElementById('score').textContent * 5);
      } else {
        ctx.fillStyle = 'rgba(255, 0, 0, 1)';
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        ctx.font = "24px monospace";
        ctx.fillStyle = "#fff";
        ctx.textAlign = "center";
        ctx.fillText('Game Over!', canvas.width / 2, canvas.height / 2);
      }

      drawNextPiece();
    }

    function isGameOver() {
      return currentPiece === null && !isCollision();
    }

    document.getElementById('pause').addEventListener('click', () => {
      const pause = document.getElementById('pause');
      
      if (pause.innerText === 'Pause') {
        pause.innerText = 'Resume';
        pause.disabled = true;
      } else {
        pause.innerText = 'Pause';
        pause.disabled = false;

        draw();
      }
    });

    document.getElementById('restart').addEventListener('click', () => {
      grid = Array(20).fill().map(() => Array(10).fill(0));
      currentPiece = null;
      currentX = 0;
      currentY = 0;

      document.getElementById('score').textContent = 0;
      document.getElementById('pause').disabled = true;
      document.getElementById('pause').innerText = 'Pause';

      draw();
    });

    setCurrentPiece(getRandomTetromino());
    draw();

    canvas.addEventListener('keydown', (e) => {
      switch (e.key) {
        case 'a':
          movePieceLeft();
          break;
        case 'd':
          movePieceRight();
          break;
        case 'w':
          rotatePiece();
          break;
        case 's':
          movePieceDown();
          break;
        case 'f':
          document.getElementById('pause').click();
          break;
      }
    });

  </script>
</body>
</html>