← 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>