{"manifest":{"name":"Conway's Game of Life","version":"1.0.0","description":"Interactive cellular automaton simulator with HTML5 Canvas. Click to toggle cells, watch patterns evolve with colorful generation-based hue shifting.","tags":["canvas","simulation","interactive","game","html"],"standard":"agentskills.io","standard_version":"1.0","content_checksum":"e59553f2c479e97641e08f33f364e7260c5a5200e7bd2118a80029bc2f02ded8","bundle_checksum":"b0257c6d75addb34330848ee5cfd210b0669167f555df688303b85fd15b2b581","metadata":{},"files":[{"path":"game-of-life.html","name":"game-of-life.html","mime_type":"text/html","checksum":"4589db9aacdb78720daa262e7dacf1fe2cfe9f18eec10868c72e47bf910cdfac"}]},"files":{"SKILL.md":"# Conway's Game of Life\n\nAn interactive implementation of Conway's Game of Life using HTML5 Canvas.\n\n## What it does\n\nThis skill generates a fully interactive cellular automaton simulator:\n\n- **Click** cells to toggle them alive/dead\n- **Start/Pause** the simulation with the play button\n- **Step** through one generation at a time\n- **Random** seed fills the grid with a random pattern\n- **Clear** resets the grid\n- Configurable grid size and simulation speed\n- Wrapping edges (toroidal grid)\n\n## Rules\n\n1. Any live cell with 2 or 3 neighbors survives\n2. Any dead cell with exactly 3 neighbors becomes alive\n3. All other cells die or stay dead\n\n## Usage\n\n```\nProvide this skill to an AI agent to generate an interactive Game of Life.\nThe agent should create the HTML file and open it in a browser.\n```\n","game-of-life.html":"<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>Conway's Game of Life</title>\n<style>\n  * { margin: 0; padding: 0; box-sizing: border-box; }\n  body {\n    background: #0a0a0a;\n    color: #e0e0e0;\n    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    min-height: 100vh;\n    padding: 20px;\n  }\n  h1 {\n    font-size: 1.5rem;\n    margin-bottom: 12px;\n    background: linear-gradient(135deg, #a855f7, #ec4899);\n    -webkit-background-clip: text;\n    -webkit-text-fill-color: transparent;\n  }\n  .controls {\n    display: flex;\n    gap: 8px;\n    margin-bottom: 12px;\n    flex-wrap: wrap;\n    justify-content: center;\n  }\n  button {\n    padding: 6px 14px;\n    border: 1px solid #333;\n    border-radius: 6px;\n    background: #1a1a2e;\n    color: #e0e0e0;\n    cursor: pointer;\n    font-size: 0.85rem;\n    transition: all 0.15s;\n  }\n  button:hover { border-color: #a855f7; background: #1a1a3e; }\n  button.active { background: #a855f7; border-color: #a855f7; color: white; }\n  .info {\n    font-size: 0.8rem;\n    color: #888;\n    margin-bottom: 8px;\n  }\n  canvas {\n    border: 1px solid #222;\n    border-radius: 4px;\n    cursor: crosshair;\n  }\n</style>\n</head>\n<body>\n<h1>Conway's Game of Life</h1>\n<div class=\"controls\">\n  <button id=\"playBtn\">Play</button>\n  <button id=\"stepBtn\">Step</button>\n  <button id=\"randomBtn\">Random</button>\n  <button id=\"clearBtn\">Clear</button>\n</div>\n<div class=\"info\" id=\"info\">Generation: 0 | Alive: 0</div>\n<canvas id=\"canvas\"></canvas>\n<script>\nconst COLS = 60, ROWS = 40, CELL = 12;\nconst canvas = document.getElementById('canvas');\nconst ctx = canvas.getContext('2d');\ncanvas.width = COLS * CELL;\ncanvas.height = ROWS * CELL;\n\nlet grid = Array.from({ length: ROWS }, () => new Uint8Array(COLS));\nlet running = false;\nlet generation = 0;\nlet intervalId = null;\n\nfunction countNeighbors(r, c) {\n  let count = 0;\n  for (let dr = -1; dr <= 1; dr++) {\n    for (let dc = -1; dc <= 1; dc++) {\n      if (dr === 0 && dc === 0) continue;\n      const nr = (r + dr + ROWS) % ROWS;\n      const nc = (c + dc + COLS) % COLS;\n      count += grid[nr][nc];\n    }\n  }\n  return count;\n}\n\nfunction step() {\n  const next = Array.from({ length: ROWS }, () => new Uint8Array(COLS));\n  for (let r = 0; r < ROWS; r++) {\n    for (let c = 0; c < COLS; c++) {\n      const n = countNeighbors(r, c);\n      if (grid[r][c]) {\n        next[r][c] = (n === 2 || n === 3) ? 1 : 0;\n      } else {\n        next[r][c] = (n === 3) ? 1 : 0;\n      }\n    }\n  }\n  grid = next;\n  generation++;\n}\n\nfunction draw() {\n  ctx.fillStyle = '#0a0a0a';\n  ctx.fillRect(0, 0, canvas.width, canvas.height);\n  let alive = 0;\n  for (let r = 0; r < ROWS; r++) {\n    for (let c = 0; c < COLS; c++) {\n      if (grid[r][c]) {\n        alive++;\n        const hue = (generation * 2 + r * 3 + c * 3) % 360;\n        ctx.fillStyle = `hsl(${hue}, 70%, 55%)`;\n        ctx.fillRect(c * CELL + 1, r * CELL + 1, CELL - 2, CELL - 2);\n      }\n    }\n  }\n  // Grid lines\n  ctx.strokeStyle = '#1a1a1a';\n  ctx.lineWidth = 0.5;\n  for (let r = 0; r <= ROWS; r++) {\n    ctx.beginPath();\n    ctx.moveTo(0, r * CELL);\n    ctx.lineTo(canvas.width, r * CELL);\n    ctx.stroke();\n  }\n  for (let c = 0; c <= COLS; c++) {\n    ctx.beginPath();\n    ctx.moveTo(c * CELL, 0);\n    ctx.lineTo(c * CELL, canvas.height);\n    ctx.stroke();\n  }\n  document.getElementById('info').textContent = `Generation: ${generation} | Alive: ${alive}`;\n}\n\nfunction randomize() {\n  for (let r = 0; r < ROWS; r++)\n    for (let c = 0; c < COLS; c++)\n      grid[r][c] = Math.random() < 0.3 ? 1 : 0;\n  generation = 0;\n  draw();\n}\n\nfunction clear() {\n  grid = Array.from({ length: ROWS }, () => new Uint8Array(COLS));\n  generation = 0;\n  draw();\n}\n\nfunction togglePlay() {\n  running = !running;\n  document.getElementById('playBtn').textContent = running ? 'Pause' : 'Play';\n  document.getElementById('playBtn').classList.toggle('active', running);\n  if (running) {\n    intervalId = setInterval(() => { step(); draw(); }, 120);\n  } else {\n    clearInterval(intervalId);\n  }\n}\n\ncanvas.addEventListener('click', (e) => {\n  const rect = canvas.getBoundingClientRect();\n  const c = Math.floor((e.clientX - rect.left) / CELL);\n  const r = Math.floor((e.clientY - rect.top) / CELL);\n  if (r >= 0 && r < ROWS && c >= 0 && c < COLS) {\n    grid[r][c] = grid[r][c] ? 0 : 1;\n    draw();\n  }\n});\n\ndocument.getElementById('playBtn').addEventListener('click', togglePlay);\ndocument.getElementById('stepBtn').addEventListener('click', () => { step(); draw(); });\ndocument.getElementById('randomBtn').addEventListener('click', randomize);\ndocument.getElementById('clearBtn').addEventListener('click', clear);\n\n// Start with a random pattern\nrandomize();\n// Auto-play after 500ms so sandbox captures animation\nsetTimeout(() => { if (!running) togglePlay(); }, 500);\n</script>\n</body>\n</html>"}}