lambdaway
::
conway
2
|
list
|
login
|
load
|
|
_h1 conway's life game | [[life]] _p Following [[https://codepen.io/RBSpatz/pen/rLyNLb|https://codepen.io/RBSpatz/pen/rLyNLb]] and [[life-patterns-in-15-gliders|https://btm.qva.mybluehost.me/building-arbitrary-life-patterns-in-15-gliders/]]. _h2 rules _ul set some cells in the grid _ul Any live cell with fewer than two live neighbours dies, as if caused by under-population. _ul Any live cell with two or three live neighbours lives on to the next generation. _ul Any live cell with more than three live neighbours dies, as if by overcrowding. _ul Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. {center {input {@ id="start" type="button" value="Start" onclick="startButtonHandler()"}} {input {@ id="clear" type="button" value="Clear" onclick="clearButtonHandler()"}} {input {@ id="random" type="button" value="Random" onclick="randomButtonHandler()"}} {div {@ id="gridContainer"}} } _p See also [[life|http://lambdaway.free.fr/lambdaspeech/index.php?view=life]] and [[15 gliders|https://btm.qva.mybluehost.me/building-arbitrary-life-patterns-in-15-gliders/]] _p See also [[liquid simulation|http://www.jgallant.com/2d-liquid-simulator-with-cellular-automaton-in-unity/]] using automata. _p VIideos: _ul [[arte/video|https://www.arte.tv/fr/videos/097454-008-A/voyages-au-pays-des-maths/]] _ul [[life in life|https://youtu.be/xP5-iIeKXE8]] _ul [[life in life 2|https://youtu.be/Kk2MH9O4pXY]] {pre . ooo o o o o o o ooo o o o o o o o o o } {script ;; var rows = 40, cols = 40, playing = false, grid = new Array(rows), nextGrid = new Array(rows), timer, reproductionTime = 100; // Initialize function initialize() { createTable(); initializeGrids(); resetGrids(); } function createTable() { var gridContainer = document.getElementById('gridContainer'); if (!gridContainer) console.error("Problem: No div for the drid table!"); var table = document.createElement("table"); for (var i = 0; i < rows; i++) { var tr = document.createElement("tr"); for (var j = 0; j < cols; j++) {// var cell = document.createElement("td"); cell.setAttribute("id", i + "_" + j); cell.setAttribute("class", "dead"); cell.onclick = cellClickHandler; tr.appendChild(cell); } table.appendChild(tr); } gridContainer.appendChild(table); } function initializeGrids() { for (var i = 0; i < rows; i++) { grid[i] = new Array(cols); nextGrid[i] = new Array(cols); } } function resetGrids() { for (var i = 0; i < rows; i++) { for (var j = 0; j < cols; j++) { grid[i][j] = 0; nextGrid[i][j] = 0; } } } function cellClickHandler() { var rowcol = this.id.split("_"); var row = rowcol[0]; var col = rowcol[1]; var classes = this.getAttribute("class"); if(classes.indexOf("live") > -1) { this.setAttribute("class", "dead"); grid[row][col] = 0; } else { this.setAttribute("class", "live"); grid[row][col] = 1; } } function randomButtonHandler() { if (playing) return; clearButtonHandler(); for (var i = 0; i < rows; i++) { for (var j = 0; j < cols; j++) { var isLive = Math.round(Math.random()); if (isLive == 1) { var cell = document.getElementById(i + "_" + j); cell.setAttribute("class", "live"); grid[i][j] = 1; } } } } function clearButtonHandler() { console.log("Clear the game: stop playing, clear the grid"); playing = false; var startButton = document.getElementById('start'); startButton.value = "Start"; clearTimeout(timer); var cellsList = document.getElementsByClassName("live"); // convert to array first, otherwise, you're working on a live node list // and the update doesn't work! var cells = []; for (var i = 0; i < cellsList.length; i++) { cells.push(cellsList[i]); } for (var i = 0; i < cells.length; i++) { cells[i].setAttribute("class", "dead"); } resetGrids; } function startButtonHandler() { if (playing) { console.log("Pause the game"); playing = false; this.value = "Continue"; clearTimeout(timer); } else { console.log("Continue the game"); playing = true; this.value = "Pause"; play(); } } function play() { computeNextGen(); if (playing) { timer = setTimeout(play, reproductionTime); } } function computeNextGen() { for (var i = 0; i < rows; i++) { for (var j = 0; j < cols; j++) { applyRules(i, j); } } copyAndResetGrid(); // copy NextGrid to grid, and reset nextGrid updateView(); // copy all 1 values to "live" in the table } function copyAndResetGrid() { for (var i = 0; i < rows; i++) { for (var j = 0; j < cols; j++) { grid[i][j] = nextGrid[i][j]; nextGrid[i][j] = 0; } } } function updateView() { for (var i = 0; i < rows; i++) { for (var j = 0; j < cols; j++) { var cell = document.getElementById(i + "_" + j); if (grid[i][j] == 0) { cell.setAttribute("class", "dead"); } else { cell.setAttribute("class", "live"); } } } } // RULES // Any live cell with fewer than two live neighbours dies, as if caused by under-population. // Any live cell with two or three live neighbours lives on to the next generation. // Any live cell with more than three live neighbours dies, as if by overcrowding. // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. function applyRules(row, col) { var numNeighbors = countNeighbors(row, col); if (grid[row][col] == 1) { if (numNeighbors < 2) { nextGrid[row][col] = 0; } else if (numNeighbors == 2 || numNeighbors == 3) { nextGrid[row][col] = 1; } else if (numNeighbors > 3) { nextGrid[row][col] = 0; } } else if (grid[row][col] == 0) { if (numNeighbors == 3) { nextGrid[row][col] = 1; } } } function countNeighbors(row, col) { var count = 0; if (row-1 >= 0) { if (grid[row-1][col] == 1) count++; } if (row-1 >= 0 && col-1 >= 0) { if (grid[row-1][col-1] == 1) count++; } if (row-1 >= 0 && col+1 < cols) { if (grid[row-1][col+1] == 1) count++; } if (col-1 >= 0) { if (grid[row][col-1] == 1) count++; } if (col+1 < cols) { if (grid[row][col+1] == 1) count++; } if (row+1 < rows) { if (grid[row+1][col] == 1) count++; } if (row+1 < rows && col-1 >= 0) { if (grid[row+1][col-1] == 1) count++; } if (row+1 < rows && col+1 < cols) { if (grid[row+1][col+1] == 1) count++; } return count; } // Start everything setTimeout( initialize, 1 ) } {style ;; #gridContainer { padding-bottom: 0px; } table { background-color: #fff; border-spacing: 0; } td { border: 1px solid #ccc; border-radius: 10px; width: 10px; height: 10px; } td.dead { background-color: transparent; } td.live { background-color: #f00; border-radius: 10px; } }
lambdaway v.20211111