Web: https://aperocky.com/cellular-automata/, this simulation runs entirely in client.
Creating a cellular automata with a couple lines of descriptive language and watch how it evolves:
^^ Logo generated using slightly modified Generate Pretty Logo
example.
Use descriptive conditions described in json to control a simulation:
{
"InitialCondition": "1 0.2",
"0": [
"CountAdjacent eq 1 3 1"
],
"1": [
"CountAdjacent lt 1 2 0",
"CountAdjacent gt 1 3 0"
]
}
^^ This correspond to conway's game of life, with initial map being generated at 20% "filled".
{
"0": [
"SpontaneousChange 1 0.02",
"CountAdjacentChance gt 1 0 1 0.1"
],
"1": [
"SpontaneousChange 2 0.002",
"CountAdjacent gt 2 0 2"
],
"2": [
"SpontaneousChange 0 1"
],
"colorMap": {
"0": "black",
"1": "green",
"2": "red"
},
"timeStep": 100
}
This correspond to a forest fire (more complex);
More examples: https://github.com/Aperocky/cellular-automata/tree/main/sample
CountAdjacent [comparison-operator] [target] [threshold] [destination]
CountDirectlyAdjacent [comparison-operator] [target] [threshold] [destination]
This compares the total adjacent blocks that are target
with threshold
to determine if it will changes to destination
. Adjacent counts 8 neighboring cells, DirectlyAdjacent only counts the 4 blocks in cardinal directions.
CountAdjacentChance [comparison-operator] [target] [threshold] [destination] [chance]
CountDirectlyAdjacentChance [comparison-operator] [target] [threshold] [destination] [chance]
This compares the total adjacent blocks that are target
with threshold
to determine if it will changes to destination
, however, it only does so on chance
.
SpontaneousChange [destination] [chance]
This will change into destination
on chance
.
ChangeByBlockAge [comparison-operator] [threshold] [destination] [chance]
This will change the block by comparing the age of the block (when it remains the same) against the threshold
, and if satisfy the comparison, will change into destination
on chance
.
There are a few initial condition available:
When there are no initialCondition in the map, the map is initiated as all 0s.
"initialCondition": "[INITIAL_CONDITION]"
When INITIAL_CONDITION
is in the format of:
"1 0.2": all blocks in the map will have 1 with a possibility of 20%
"CentralDot 1": A single 1 in the center.
"CentralSquare 1": A square of 1 (2x2) in the center, this is also perfectly in the middle of the whole map (100x100)
"cornerDot 1": A dot of 1 in the top left corner
{
"InitialCondition": "1 0.2",
Currently I only support 1 kind of initial value that are not zero, the first one being target.
"0": [
"CountAdjacent eq 1 3 1"
],
"1": [
"CountAdjacent lt 1 2 0",
"CountAdjacent gt 1 3 0"
]
list of function associated with the current values in the locations, these 3 means:
- If this square is 0, Count All Adjacent 1s, if it equals 3, make the value 1.
- If this square is 1, Count All Adjacent 1s, if it is less than 2, make the value 0.
- If this square is 1, Count All Adjacent 1s, if it is greater than 3, make the value 0.
"colorMap": {
"0": "black",
"1": "red"
},
"timestep": 100,
}
There is a default color map, you can make your own too. However, custom colormap need to cover all cases.
timestep are measured in milliseconds.