152 lines
4.6 KiB
JavaScript
152 lines
4.6 KiB
JavaScript
// core functions to generate initial states and evolve them
|
|
|
|
import { Cell } from "./cell.js";
|
|
|
|
// get the next evolution of a 1D CA initial state
|
|
// buggy BUT produces interesting results
|
|
// function evolve1d(state, rules) {
|
|
// const sl = state.length - 1;
|
|
// return [
|
|
// rules[[state[sl - 1], state[sl], state[sl + 1]].join("")],
|
|
// ...state.map((_,x) => (rules[[state[x - 1], state[x], state[x + 1]].join("")])).slice(0, sl),
|
|
// rules[[state[0], state[1], state[2]].join("")]
|
|
// ]
|
|
// }
|
|
|
|
// get the next evolution of a 1D CA initial state
|
|
function evolve1d(state, rules) {
|
|
const sl = state.length - 1;
|
|
const edge1 = [state[sl - 2], state[sl - 1], state[sl]].join("");
|
|
const edge2 = [state[0], state[1], state[2]].join("");
|
|
// normal case (3 neighbor cells)
|
|
const center = state
|
|
.map((_, x) => rules[[state[x - 1], state[x], state[x + 1]].join("")])
|
|
.slice(1, sl);
|
|
return [rules[edge1], ...center, rules[edge2]];
|
|
}
|
|
|
|
// Get the next evolution of a cell according to
|
|
// Conway's game of life rules
|
|
function conwayRules(cell, neighbors) {
|
|
// loneliness rule
|
|
if (cell === 1 && neighbors < 2) return 0;
|
|
// overpopulation rule
|
|
if (cell === 1 && neighbors > 3) return 0;
|
|
// born when three live neighbors rule
|
|
if (cell === 0 && neighbors === 3) return 1;
|
|
// the cell remains the same if none apply
|
|
return cell;
|
|
}
|
|
|
|
// Get the next evolution of a cell according to
|
|
// Conway's game of life rules
|
|
function servietteRules(cell, neighbors) {
|
|
// loneliness rule
|
|
if (cell === 0 && [2, 3, 4].find((x) => x == neighbors)) return 1;
|
|
// the cell remains the same if none apply
|
|
return 0;
|
|
}
|
|
|
|
// variation of the game of life where a
|
|
// cell comes to live if 6 neigbor cells are alive
|
|
function highLifeRules(cell, neighbors) {
|
|
// loneliness rule
|
|
if (cell === 1 && neighbors < 2) return 0;
|
|
// overpopulation rule
|
|
if (cell === 1 && neighbors > 3) return 0;
|
|
// born when three live neighbors rule
|
|
if (cell === 0 && neighbors === 2) return 1;
|
|
// highlife rules
|
|
if ((cell === 0 && neighbors === 3) || neighbors === 6) return 1;
|
|
// the cell remains the same if none apply
|
|
return cell;
|
|
}
|
|
|
|
// variation on the game of life's rules,
|
|
// where the "three live neighbors" rule is ignored
|
|
function threebornRules(cell, neighbors) {
|
|
// loneliness rule
|
|
if (cell === 1 && neighbors < 2) return 0;
|
|
// overpopulation rule
|
|
if (cell === 1 && neighbors > 3) return 0;
|
|
// born when three live neighbors rule
|
|
return cell;
|
|
}
|
|
|
|
// variation on the game of life's rules,
|
|
// where the loneliness rule is ignored
|
|
function lonelinessRules(cell, neighbors) {
|
|
// overpopulation rule
|
|
if (cell === 1 && neighbors > 3) return 0;
|
|
// born when three live neighbors rule
|
|
if (cell === 0 && neighbors === 3) return 1;
|
|
// the cell remains the same if none apply
|
|
return cell;
|
|
}
|
|
|
|
// variation on the game of life's rules,
|
|
// where the overpopulation rule is ignored
|
|
function overpopulationRules(cell, neighbors) {
|
|
// loneliness rule
|
|
if (cell === 1 && neighbors < 2) return 0;
|
|
// born when three live neighbors rule
|
|
if (cell === 0 && neighbors === 3) return 1;
|
|
// the cell remains the same if none apply
|
|
return cell;
|
|
}
|
|
|
|
// get the next evolution of a 2D CA initial state
|
|
// Rules : Moore neighborhood
|
|
function evolve2d(grid, width, rulesFn) {
|
|
const bh = grid.length - 1;
|
|
const bw = width;
|
|
return grid.reduce((acc, cell, y) => {
|
|
const sum =
|
|
grid[Math.abs((y - 1) % bh)].state +
|
|
grid[Math.abs((y + 1) % bh)].state +
|
|
grid[Math.abs((y - bw - 1) % bh)].state +
|
|
grid[Math.abs((y - bw) % bh)].state +
|
|
grid[Math.abs((y - bw + 1) % bh)].state +
|
|
grid[Math.abs((y + bw - 1) % bh)].state +
|
|
grid[Math.abs((y + bw) % bh)].state +
|
|
grid[Math.abs((y + bw + 1) % bh)].state;
|
|
acc[y] = new Cell(rulesFn(cell.state, sum));
|
|
acc[y].prevState = cell.state;
|
|
return acc;
|
|
}, []);
|
|
}
|
|
|
|
// Populates the first state with a single living cell in the center
|
|
function create1dStateOneCell(width) {
|
|
return [...Array(width)].map((cell, index) => {
|
|
if (index === Math.floor(width / 2)) return 1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
// Populates the first state of a 1D CA with cells returned
|
|
// by initFn
|
|
function create1dState(width, initFn, args) {
|
|
return [...Array(width)].map(() => initFn(...args));
|
|
}
|
|
|
|
// Populates the first state of a 2D CA with cells returned
|
|
// by initFn
|
|
function create2dState(width, height, initFn, args) {
|
|
return [...Array(height * width)].map(() => new Cell(initFn(...args)));
|
|
}
|
|
|
|
export {
|
|
create1dState,
|
|
create2dState,
|
|
create1dStateOneCell,
|
|
conwayRules,
|
|
overpopulationRules,
|
|
lonelinessRules,
|
|
threebornRules,
|
|
highLifeRules,
|
|
servietteRules,
|
|
evolve1d,
|
|
evolve2d,
|
|
};
|