diff --git a/README.md b/README.md
index 56e84db..f983f13 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# Cellular Automata Evolution Simulator
-## [Full article](https://github.com/xcontcom/evolving-cellular-automata/blob/main/docs/article.md)
+## [Full article](https://xcontcom.github.io/evolving-cellular-automata/docs/article.html)

@@ -41,6 +41,8 @@ cellular-automata-evolution/
└── README.md # Project documentation
```
+[Repository](https://github.com/xcontcom/evolving-cellular-automata)
+
## Installation
### Prerequisites
- **Node.js** (v14 or higher)
diff --git a/docs/article.md b/docs/article.md
index 4818d0f..e6e733a 100644
--- a/docs/article.md
+++ b/docs/article.md
@@ -1,5 +1,7 @@
# Evolving Cellular Automata
+[Repository](https://github.com/xcontcom/evolving-cellular-automata)
+
## Introduction
Hello, curious minds! Let’s explore the fascinating intersection of cellular automata and genetic algorithms to uncover emergent patterns and behaviors.
@@ -10,11 +12,11 @@ This article is a translation and adaptation of my 2019 piece, originally publis
The simplest form of cellular automata is the one-dimensional variant. (While zero-dimensional oscillators exist, we’ll set them aside for now.) In a one-dimensional cellular automaton, we start with a single array representing the initial state, where each cell holds a binary value (0 or 1). The next state of each cell depends on its current state and those of its two immediate neighbors, determined by a predefined rule.
-With three cells (the cell itself and its two neighbors), there are \(2^3 = 8\) possible configurations:
+With three cells (the cell itself and its two neighbors), there are 2^3 = 8 possible configurations:

-For each configuration, we define the cell’s next state (0 or 1), forming an 8-bit rule, known as the Wolfram code. This results in \(2^8 = 256\) possible one-dimensional cellular automata.
+For each configuration, we define the cell’s next state (0 or 1), forming an 8-bit rule, known as the Wolfram code. This results in 2^8 = 256 possible one-dimensional cellular automata.

@@ -30,7 +32,7 @@ For consistency, we order the neighbors as follows:

-With a cell and its eight neighbors, there are \(2^9 = 512\) possible configurations, and the rules are encoded as a 512-bit string, yielding \(2^{512} \approx 1.34 \times 10^{154}\) possible two-dimensional automata—a number far exceeding the estimated atoms in the observable universe (\(\sim 10^{80}\)).
+With a cell and its eight neighbors, there are 29 = 512 possible configurations, and the rules are encoded as a 512-bit string. This yields 2512 ≈ 1.34 × 10154 possible two-dimensional automata — a number far exceeding the estimated ~1080 atoms in the observable universe.

@@ -481,7 +483,818 @@ Results with 5% and 25% mutations:

-## Conclusion
+---
+
Using genetic algorithms to evolve cellular automata reveals a vast landscape of patterns and behaviors. From static grids to dynamic oscillators and complex shapes like “habr,” the interplay of selection, crossover, and mutation uncovers solutions that would be impossible to find manually. Experimenting with mutation rates and crossover methods highlights the robustness and flexibility of this approach, offering endless possibilities for discovery.
-Try running these experiments yourself to find new patterns—each run is a new adventure!
+Try running these experiments yourself to find new patterns — each run is a new adventure!
+
+[Repository](https://github.com/xcontcom/evolving-cellular-automata)
+
+That's all for natural selection. For artificial selection, we'll use second-order cellular automata.
+
+---
+
+# Artificial selection
+
+---
+
+## Second-order cellular automaton
+
+Let us look at a zero-dimensional first-order cellular automaton (all the automata we discussed above are first-order).
+A zero-dimensional automaton consists of a single cell.
+The cell can be in one of two states, 0 or 1.
+Its next state at time t depends only on its state at time t−1.
+There are exactly four such zero-dimensional first-order automata (one of them is an oscillator):
+
+
+
+In a second-order cellular automaton, the next state of the cell at time t depends on both the current state at time t−1 and the previous state at time t−2.
+There are four possible combinations of two cell states.
+Hence 2^4 = 16 zero-dimensional second-order cellular automata:
+
+
+
+These automata already produce more complicated oscillators.
+
+For third order there are 2^8 = 256 zero-dimensional automata:
+
+
+
+For fourth order we would have 2^16 = 65,536 zero-dimensional automata, which can’t be shown in a single picture.
+
+Finding, for an n-th order automaton, a rule whose oscillation period is exactly n is a non-trivial and very interesting task. It deserves a separate article.
+
+In a one-dimensional second-order cellular automaton the next state of a cell is determined by the current state of three cells (itself and its two neighbours, as usual) and by the previous state of the same cell:
+
+
+
+There are 2^16 = 65,536 one-dimensional second-order cellular automata.
+
+Code (JavaScript):
+
+```javascript
+var rule = [];
+for (var i = 0; i < 16; i++) rule[i] = Math.round(Math.random());
+
+var a = [];
+var b = [];
+var temp;
+for (var x = 0; x < sizex; x++) {
+ a[x] = 0;
+ b[x] = 0;
+}
+b[63] = 1;
+
+var xm, xp, q;
+for (var y = 2; y < sizey; y++) {
+ temp = [];
+ for (var x = 0; x < sizex; x++) {
+ xm = x - 1;
+ if (xm < 0) xm = sizex + xm;
+ xp = x + 1;
+ if (xp >= sizex) xp = xp - sizex;
+
+ q = b[xm];
+ q = (q << 1) + b[x];
+ q = (q << 1) + b[xp];
+ q = (q << 1) + a[x];
+
+ temp[x] = rule[q];
+ if (temp[x]) context.fillRect(x * size, y * size, size, size);
+ }
+ a = b;
+ b = temp;
+}
+```
+
+Second-order cellular automata produce more complex patterns than first-order ones.
+
+Below are several random second-order rules (on each image, the left half shows the evolution from a single active cell at t−1, and the right half shows evolution from random states at t−1 and t−2; the binary code is the contents of the array `rule`):
+
+0011111011001000:
+
+
+
+0101101110011110:
+
+
+
+0110000110010010:
+
+
+
+0110011010010110:
+
+
+
+1110011010010110:
+
+
+
+0110111010000101:
+
+
+
+1111101001110110:
+
+
+
+1001010001100000:
+
+
+
+The same automaton as above on a 256×256 grid:
+
+
+
+And on a 512×512 grid:
+
+
+
+You can see more automata here:
+
+[One-dimensional second-order CA](http://xcont.com/cell/2order/)
+[One-dimensional third-order CA](http://xcont.com/cell/3order/)
+
+You can read more about one-dimensional second-order cellular automata in Stephen Wolfram’s book *A New Kind of Science*.
+
+## Artificial selection
+
+By analogy with the one-dimensional second-order automaton, in a two-dimensional second-order cellular automaton we also use one additional bit that encodes the cell’s state from time t−2.
+
+For convenience we place this bit at the beginning of the binary string that represents the neighbourhood:
+
+
+
+The convenience here is that if the first and second halves of the genotype coincide, then the automaton can be regarded as a first-order automaton:
+
+
+
+By adding just one additional cell (one bit from the previous state), we multiplied the number of possible automata by 2^512.
+The total number of second-order two-dimensional automata is therefore:
+
+(2^512) × (2^512) = 2^1024.
+
+In the previous sections, when we spoke about “natural selection”, we defined some explicit criterion and compared automata according to this criterion.
+
+In the case of artificial selection we choose automata manually, using a very fuzzy heuristic: “this automaton looks interesting, that one doesn’t”.
+
+This principle does not help much when we try to pick out the “best” automaton from a bunch of random ones:
+
+
+
+
+
+
+
+
+
+There are several ways to make the selection process more meaningful.
+Below I will describe four approaches.
+
+### 1. Single active cell in the initial state
+
+One approach is to observe the evolution of an automaton that starts from a single active cell in the initial configuration.
+
+We create an initial population filled with random automata.
+A few examples from the initial population (30 iterations for each automaton):
+
+
+
+
+
+Within the population there is a small subset of automata that behave less chaotically.
+Those are the ones we will select for crossover:
+
+
+
+
+
+
+
+
+
+Below are 20 random automata from the initial population (their states at iteration 30):
+
+
+
+After three generations of evolution:
+
+
+
+After eight generations of evolution:
+
+
+
+Eight generations were enough for the automaton with a particular visual feature (the one that draws triangles) to take over the entire population.
+
+### 2. Partially filled genotype
+
+If we change the balance between zeros and ones in the genotype, then the balance between zeros and ones in the phenotype (the actual configuration of the automaton) will also change.
+
+The rule (genotype) of an automaton specifies the next state of a cell for every possible combination of the cell and its neighbours.
+If the genotype contains more zeros (or more ones), then in subsequent states of the automaton zeros (or ones) will gradually dominate.
+
+It is interesting to look at the correlation between the proportion of ones and zeros in the genotype and the proportion of ones and zeros in the phenotype.
+
+Let’s plot this relationship.
+
+We create a series of populations, 200 automata in each.
+The genotype of each second-order automaton contains 1024 genes.
+For the first population we set all genes to zero.
+For each subsequent population we set n genes to one (the rest remain zero).
+For the first population n = 0, for the 513-th population n = 512.
+
+On the x-axis we put the population index.
+On the y-axis (white dots) we plot the ratio of ones to zeros in the gene pool of that population.
+We get a hyperbola:
+
+
+
+For each automaton (on a grid of size 89×89) we run 100 iterations.
+On the 100-th iteration we count the number of ones and zeros in the state (phenotype) of each automaton.
+On the graph we then plot the ratio of ones to zeros in the phenotypes (the total number of ones divided by the total number of zeros across all automata in the population).
+We get the following curve:
+
+
+
+Instead of the total ratio over all phenotypes, we can also look at the ratio within each individual phenotype:
+
+
+
+On the left side of the graph we can see points that deviate the most from the average value.
+We can hypothesize that these are precisely the automata whose 0-th gene is equal to one.
+Let’s test that hypothesis.
+We force the 0-th gene to always be zero and plot a new graph:
+
+
+
+Now compare with the case where the 0-th gene is always equal to one:
+
+
+
+Second-order automata have another “zero” gene — number 512.
+Let us see how this gene affects the phenotype.
+
+0-th and 512-th genes are always zero:
+
+
+
+0-th gene is zero, 512-th gene is one:
+
+
+
+To avoid torturing photosensitive people with excessive flickering, in the genetic algorithm we will set both the 0-th and 512-th genes to zero in the initial population.
+
+Now let us look at the automata we effectively removed by fixing genes 0 and 512 to zero.
+
+The first 8 states of the automaton where only the 0-th gene is set (gene 0 = 1, all others are zero):
+
+
+
+The automaton where only the 512-th gene is set:
+
+
+
+The automaton where only genes 0 and 512 are set:
+
+
+
+Now highlight on the graph the region where the population starts to split into distinct clusters:
+
+
+
+In this region the genotypes are 25% filled with ones.
+
+Let’s compare two populations.
+
+**First population.**
+30 random automata at iteration 1000.
+Genotypes are 50% filled (512 ones and 512 zeros):
+
+
+
+**Second population.**
+30 random automata at iteration 1000.
+Genotypes are 25% filled (256 ones and 768 zeros):
+
+
+
+The second population is well suited for artificial selection.
+We can easily highlight certain visual traits in these automata—for example “darker ones”, “less chaotic ones” (where white cells cluster together), and so on.
+
+Let us select the “darker” automata.
+Mutation probability is 10%, up to 4 genes mutate at a time.
+After the first selection step:
+
+
+
+After the second selection step:
+
+
+
+An interesting automaton has appeared in the population.
+
+Here it is on a 256×256 grid, at iteration 1000:
+
+
+
+This automaton gradually takes over the population.
+
+After the eighth selection step:
+
+
+
+Another interesting automaton appears.
+
+Again on a 256×256 grid, iteration 1000:
+
+
+
+The population after thirteen selection steps:
+
+
+
+Below are several automata from this population.
+Each is shown on a 256×256 grid at iteration 1000.
+Under each picture there is a link where you can watch the automaton evolve in time:
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/0/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/1/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/2/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/3/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/4/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/5/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/6/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/7/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/8/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/2d_2order/9/)
+
+### 3. Conway’s Game of Life and similar automata
+
+The most famous two-dimensional first-order cellular automaton is Conway’s *Game of Life*.
+
+Its rules can be stated as follows:
+– If a dead cell has exactly 3 live neighbours, it becomes alive (otherwise it stays dead).
+– If a live cell has 2 or 3 live neighbours, it survives (otherwise it dies).
+We represent a dead cell as 0 and a live cell as 1.
+
+A cell can have between 0 and 8 live neighbours.
+There are therefore 9 possible neighbour counts around a dead cell and 9 around a live cell.
+We can encode these in an array `r`:
+
+```javascript
+r = [
+ 0,0,0,1,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0
+];
+```
+
+The first half of the array corresponds to a dead cell, the second half to a live cell.
+
+We can now expand Conway’s rule for all possible (512) combinations of the cell and its 8 neighbours:
+
+```javascript
+r = [
+ 0,0,0,1,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0
+];
+var rule = [];
+var q1, q2;
+for (var i = 0; i < 512; i++) {
+ var ii = i.toString(2);
+ for (var j = ii.length; j < 9; j++) ii = '0' + ii;
+ q1 = 1 * ii[4];
+ q2 = 1 * ii[0] + 1 * ii[1] + 1 * ii[2] + 1 * ii[3] + 1 * ii[5] + 1 * ii[6] + 1 * ii[7] + 1 * ii[8];
+ if (q1 == 0)
+ rule[i] = r[q2];
+ else
+ rule[i] = r[q2 + 9];
+}
+```
+
+An optimized variant:
+
+```javascript
+r = [
+ 0,0,0,1,0,0,0,0,0,
+ 0,0,1,1,0,0,0,0,0
+];
+var rule = [];
+for (var i = 0; i < 512; i++) {
+ var q = ((i >> 4) & 1) * 8;
+ for (var j = 0; j < 9; j++) {
+ q += (i >> j) & 1;
+ }
+ rule[i] = r[q];
+}
+```
+
+For the second-order version we simply copy the second half of the `rule` array from the first one:
+
+```javascript
+for (var i = 0; i < 512; i++) {
+ if (rule[i] == 0)
+ rule[i + 512] = 0;
+ else
+ rule[i + 512] = 1;
+}
+```
+
+If we run the automaton with this rule, we see characteristic gliders and oscillators.
+Here are several iterations of this automaton:
+
+
+
+The array `r` has 18 entries.
+There are therefore 2^18 = 262,144 rules of “Conway-type” (i.e. rules that can be written in the same language: for which neighbour counts dead cells are born, and for which neighbour counts live cells die).
+You can explore these rules here:
+
+[Conway-type automata](http://xcont.com/cell/conway/)
+(Conway’s rule is loaded by default; the “Change rule” button fills array `r` randomly.)
+
+Here are some random automata of this type (the binary code shown under each picture is the contents of `r`):
+
+110010011001111111
+
+
+
+100001100110111110
+
+
+
+011111000100101110
+
+
+
+010000110000110010
+
+
+
+001111010011100111
+
+
+
+000111001000000110
+
+
+
+000101100010100001
+
+
+
+000001111101011111
+
+
+
+000001100110111111
+
+
+
+For the genetic algorithm we can use either the array `r` as the genotype (2^18 possible combinations), or the full array `rule` (2^512 combinations for a first-order automaton and 2^1024 combinations for a second-order automaton).
+
+The space of 2^18 rules is relatively small.
+It is small enough that one can search it manually without a genetic algorithm (which is essentially what Conway did).
+
+If, however, we fill the array `rule` with random Conway-type automata and use it as the genotype, then the experiment, to some extent, becomes unsuccessful (unsuccessful enough to not include those results here).
+The point is that Conway-type rules have a built-in symmetry.
+For example, for the following neighbourhood patterns:
+
+
+
+… and for these ones:
+
+
+
+the next state of the central cell is the same.
+After the first crossover this symmetry is broken in the offspring rules.
+The parent rules accumulate mutations that also destroy the symmetry.
+Breaking the symmetry in the genotype destroys the symmetry in the phenotype as well.
+
+We can see this symmetry in the phenotype if we start from a single live cell in the initial configuration.
+
+Let’s run an experiment.
+To preserve symmetry, we will use the array `r` as the genotype.
+Mutation probability is 5%, one gene mutates at a time.
+The initial configuration contains a single live cell.
+
+Below are 30 random automata from the initial population.
+Each image shows the state of the automaton at iteration 30:
+
+
+
+We will try to select automata that expand (grow) from a single live cell as slowly as possible.
+
+
+
+
+
+
+
+
+
+
+
+After the first selection step we get rid of automata that do not develop at all:
+
+
+
+In the new population some non-developing automata still appear — these are unsuccessful offspring or mutants.
+
+From this point on we will mostly select automata whose background remains white (cells that the wave front has not yet reached).
+
+The black automata in these pictures are blinking.
+
+If the 0-th gene is zero (if a cell with all black neighbours remains black), then all such automata expand at the same speed.
+Such automata do not match our selection criterion (minimal growth speed).
+The number of such rules decreases with each selection.
+If the 0-th gene is equal to one, then on the first (odd-numbered) iteration the background flips to white.
+Later the background may either stay white or blink (white on odd iterations, black on even ones).
+We do selection at iteration 30, which is even.
+By discarding automata with a black background at iteration 30, we also discard the blinking ones (again, out of respect for photosensitive viewers).
+
+Population after the second selection step:
+
+
+
+After 3 selections:
+
+
+
+After 5 selections:
+
+
+
+After 8 selections:
+
+
+
+After 13 selections:
+
+
+
+The same automata at iteration 60:
+
+
+
+After 21 selections.
+States at iteration 30:
+
+
+
+States at iteration 60:
+
+
+
+After 34 selections.
+States at iteration 30:
+
+
+
+States at iteration 60:
+
+
+
+After that, the system essentially stops evolving.
+
+Here are three automata from this final population (100 iterations each).
+Below each image is the corresponding array `r`:
+
+[1,0,1,1,1,0,0,1,0,0,1,1,0,1,0,1,1,1]
+
+
+
+[1,0,1,1,1,0,0,1,0,0,0,1,0,1,0,1,1,1]
+
+
+
+[1,0,0,1,1,0,0,1,1,0,1,0,1,1,0,1,1,1]
+
+
+
+For comparison, here is a random automaton:
+
+[1,0,0,1,1,1,0,1,1,1,0,0,1,1,0,0,0,1]
+
+
+
+### 4. Conway-type automata (variant 2)
+
+In Conway-type rules we count the total number of live cells in the Moore neighbourhood.
+We can modify this by grouping the cells of the neighbourhood into four pairs and counting live cells within each pair:
+
+
+
+This increases the number of distinct rules while still preserving symmetry in the phenotype.
+
+Each pair can contain 0, 1 or 2 live cells.
+There are four pairs.
+So there are 3^4 = 81 possible combinations for the neighbourhood of a dead cell, and 81 combinations for the neighbourhood of a live cell.
+In total we get 2^162 automata of this type.
+
+The number
+
+2^162 ≈ 5.846 × 10^48
+
+is suitably astronomical and is large enough to serve as a search space for a genetic algorithm.
+
+The genotype of each individual in our GA population has length 162 bits.
+
+We initialize the population with random automata:
+
+```javascript
+var rulesize = 162;
+for (var n = 0; n < PopulationSize; n++) {
+ population[n] = [];
+ fitness[n] = 0;
+ for (var i = 0; i < rulesize; i++) {
+ population[n][i] = Math.round(Math.random());
+ }
+}
+```
+
+Next we expand each such rule to all possible combinations of the central cell and its eight neighbours, filling an array `rule` for each individual:
+
+```javascript
+function fillrule() {
+ var r;
+ for (var n = 0; n < PopulationSize; n++) {
+ rule[n] = [];
+ r = population[n];
+ var q1, q2, q3, q4, q5;
+ var q;
+ for (var i = 0; i < 512; i++) {
+ var ii = i.toString(2);
+ for (var j = ii.length; j < 9; j++) ii = '0' + ii;
+ q1 = 1 * ii[4];
+ q2 = 1 * ii[0] + 1 * ii[8];
+ q3 = 1 * ii[1] + 1 * ii[7];
+ q4 = 1 * ii[2] + 1 * ii[6];
+ q5 = 1 * ii[3] + 1 * ii[5];
+ q = parseInt('' + q2 + q3 + q4 + q5, 3);
+ if (q1 == 0)
+ rule[n][i] = r[q];
+ else
+ rule[n][i] = r[q + 81];
+ }
+ }
+}
+```
+
+We use the array `rule` when computing the next state of each automaton.
+The function `fillrule()` is called once at page load and again after each call of `evolute()` (which performs reproduction and mutation).
+
+The initial population looks chaotic.
+Here are 30 random automata at iteration 1000:
+
+
+
+This chaos, however, is somewhat different from rule to rule when viewed dynamically, so the automata are still suitable for selection.
+But we can simplify the task and again select the “darkest” ones (those with the most live cells, if we render live cells as black).
+
+Population after five selections:
+
+
+
+From here we can start looking for automata with the most complex oscillators.
+There is no point in showing the entire process in detail.
+Below are several of the most interesting automata found by the genetic algorithm.
+
+Each image shows a 256×256 grid at iteration 10,000.
+Under each image there is a link where you can see the automaton evolve:
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/0/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/1/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/2/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/3/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/4/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/5/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/6/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/7/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/8/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/9/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/10/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/11/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/12/)
+
+
+
+[Watch in dynamics](http://xcont.com/cell/conway2/13/)
+
+
+
+[Matrix-style rendering in green](http://xcont.com/cell/conway2/matrix/)
+[Slower version on a 512×512 grid](http://xcont.com/cell/conway2/matrix512/)
+
+## Repository
+
+[https://github.com/xcontcom/evolving-cellular-automata](https://github.com/xcontcom/evolving-cellular-automata)
+
+## Conclusion
+
+In this project we used a genetic algorithm to explore the enormous space of two-dimensional cellular automata.
+Already for first-order, two-state, two-dimensional automata there are 2^512 possible rules, and for second-order automata there are 2^1024.
+This is an astronomically large space: far more automata than there are atoms in the observable universe.
+
+The famous Conway *Game of Life* is just one particular point in this space, and in fact belongs to a tiny, very special subclass of rules.
+When people hear “cellular automata”, they almost always think only of Conway’s automaton, without realizing how many other rules are possible and how rich their behaviour can be.
+The experiments in this article illustrate that even simple genetic selection, based on informal visual criteria (“less chaotic”, “darker”, “slower growth”, “more interesting oscillators”), is enough to discover a wide variety of non-trivial automata.
+
+In this work we used the rule of the automaton itself as the genotype and tried to evolve rules that match some chosen criterion.
+
+In the next project we will fix the rule (for example, Conway’s Game of Life or any other chosen rule) and instead use the *initial configuration* of the automaton as the genotype:
+
+[https://github.com/xcontcom/initial-state-evolution](https://github.com/xcontcom/initial-state-evolution)
+
+On a common toroidal grid we place two automata, A and B.
+The field is wrapped around horizontally for each automaton, and vertically the upper and lower boundaries of the two automata are shared—so each automaton interacts with the other along a common border.
+
+As a fitness function for automaton A we use the state of automaton B at iteration n, and as the fitness function for B we use the state of A at iteration n.
+In other words, each automaton’s goal is to influence the configuration of its opponent (or partner).
+
+Conway’s Game of Life is known to be Turing-complete; therefore, in principle, any algorithm or system of arbitrary complexity can be implemented within it.
+By co-evolving automata that compete (or cooperate) with each other, we hope to obtain increasingly complex patterns and behaviours.
+Unlike the current project, we will not prescribe a fixed target or end state.
+Instead, the “goal” of the system is the ongoing competition (or collaboration) between automata.
+This makes the evolutionary process more open-ended and may lead to structures that are unexpected and qualitatively different from what we would obtain by optimizing a manually chosen criterion.
+
+---
+
+## About the Author
+
+Serhii Herasymov
+*Programmer & Math Enthusiast* (Ukraine → Ireland)
+
+Email: sergeygerasimofff@gmail.com
+GitHub: [xcontcom](https://github.com/xcontcom)
+X (Twitter): [@xcontcom](https://x.com/xcontcom)
+
+Feedback welcome.
diff --git a/docs/images/100.png b/docs/images/100.png
new file mode 100644
index 0000000..3de4cd1
Binary files /dev/null and b/docs/images/100.png differ
diff --git a/docs/images/101.png b/docs/images/101.png
new file mode 100644
index 0000000..43c3599
Binary files /dev/null and b/docs/images/101.png differ
diff --git a/docs/images/102.png b/docs/images/102.png
new file mode 100644
index 0000000..a8690fe
Binary files /dev/null and b/docs/images/102.png differ
diff --git a/docs/images/103.png b/docs/images/103.png
new file mode 100644
index 0000000..2f810c4
Binary files /dev/null and b/docs/images/103.png differ
diff --git a/docs/images/104.png b/docs/images/104.png
new file mode 100644
index 0000000..9ca98ad
Binary files /dev/null and b/docs/images/104.png differ
diff --git a/docs/images/105.png b/docs/images/105.png
new file mode 100644
index 0000000..c0bcab4
Binary files /dev/null and b/docs/images/105.png differ
diff --git a/docs/images/106.png b/docs/images/106.png
new file mode 100644
index 0000000..f7155a1
Binary files /dev/null and b/docs/images/106.png differ
diff --git a/docs/images/107.png b/docs/images/107.png
new file mode 100644
index 0000000..c6627f4
Binary files /dev/null and b/docs/images/107.png differ
diff --git a/docs/images/108.png b/docs/images/108.png
new file mode 100644
index 0000000..af79a1c
Binary files /dev/null and b/docs/images/108.png differ
diff --git a/docs/images/109.png b/docs/images/109.png
new file mode 100644
index 0000000..bcf484a
Binary files /dev/null and b/docs/images/109.png differ
diff --git a/docs/images/110.png b/docs/images/110.png
new file mode 100644
index 0000000..ef9a740
Binary files /dev/null and b/docs/images/110.png differ
diff --git a/docs/images/111.png b/docs/images/111.png
new file mode 100644
index 0000000..992167e
Binary files /dev/null and b/docs/images/111.png differ
diff --git a/docs/images/112.png b/docs/images/112.png
new file mode 100644
index 0000000..f1ebee4
Binary files /dev/null and b/docs/images/112.png differ
diff --git a/docs/images/113.png b/docs/images/113.png
new file mode 100644
index 0000000..9c3c0f7
Binary files /dev/null and b/docs/images/113.png differ
diff --git a/docs/images/114.png b/docs/images/114.png
new file mode 100644
index 0000000..7b64d5c
Binary files /dev/null and b/docs/images/114.png differ
diff --git a/docs/images/115.png b/docs/images/115.png
new file mode 100644
index 0000000..1c6403c
Binary files /dev/null and b/docs/images/115.png differ
diff --git a/docs/images/116.png b/docs/images/116.png
new file mode 100644
index 0000000..61088e1
Binary files /dev/null and b/docs/images/116.png differ
diff --git a/docs/images/117.png b/docs/images/117.png
new file mode 100644
index 0000000..5cebe01
Binary files /dev/null and b/docs/images/117.png differ
diff --git a/docs/images/118.png b/docs/images/118.png
new file mode 100644
index 0000000..296816e
Binary files /dev/null and b/docs/images/118.png differ
diff --git a/docs/images/119.png b/docs/images/119.png
new file mode 100644
index 0000000..7a0301f
Binary files /dev/null and b/docs/images/119.png differ
diff --git a/docs/images/120.png b/docs/images/120.png
new file mode 100644
index 0000000..1305955
Binary files /dev/null and b/docs/images/120.png differ
diff --git a/docs/images/121.png b/docs/images/121.png
new file mode 100644
index 0000000..d6de3bd
Binary files /dev/null and b/docs/images/121.png differ
diff --git a/docs/images/122.png b/docs/images/122.png
new file mode 100644
index 0000000..10bba0c
Binary files /dev/null and b/docs/images/122.png differ
diff --git a/docs/images/123.png b/docs/images/123.png
new file mode 100644
index 0000000..c7f32b9
Binary files /dev/null and b/docs/images/123.png differ
diff --git a/docs/images/124.png b/docs/images/124.png
new file mode 100644
index 0000000..81282ab
Binary files /dev/null and b/docs/images/124.png differ
diff --git a/docs/images/125.gif b/docs/images/125.gif
new file mode 100644
index 0000000..5641b6a
Binary files /dev/null and b/docs/images/125.gif differ
diff --git a/docs/images/126.png b/docs/images/126.png
new file mode 100644
index 0000000..29b64ca
Binary files /dev/null and b/docs/images/126.png differ
diff --git a/docs/images/127.gif b/docs/images/127.gif
new file mode 100644
index 0000000..252291d
Binary files /dev/null and b/docs/images/127.gif differ
diff --git a/docs/images/128.gif b/docs/images/128.gif
new file mode 100644
index 0000000..31dfb33
Binary files /dev/null and b/docs/images/128.gif differ
diff --git a/docs/images/129.gif b/docs/images/129.gif
new file mode 100644
index 0000000..7532d7b
Binary files /dev/null and b/docs/images/129.gif differ
diff --git a/docs/images/200.gif b/docs/images/200.gif
new file mode 100644
index 0000000..4db06d4
Binary files /dev/null and b/docs/images/200.gif differ
diff --git a/docs/images/201.gif b/docs/images/201.gif
new file mode 100644
index 0000000..5d1a4f6
Binary files /dev/null and b/docs/images/201.gif differ
diff --git a/docs/images/202.gif b/docs/images/202.gif
new file mode 100644
index 0000000..4373f77
Binary files /dev/null and b/docs/images/202.gif differ
diff --git a/docs/images/203.png b/docs/images/203.png
new file mode 100644
index 0000000..9008120
Binary files /dev/null and b/docs/images/203.png differ
diff --git a/docs/images/204.png b/docs/images/204.png
new file mode 100644
index 0000000..ccaf083
Binary files /dev/null and b/docs/images/204.png differ
diff --git a/docs/images/205.png b/docs/images/205.png
new file mode 100644
index 0000000..4ab8795
Binary files /dev/null and b/docs/images/205.png differ
diff --git a/docs/images/206.png b/docs/images/206.png
new file mode 100644
index 0000000..2739fb1
Binary files /dev/null and b/docs/images/206.png differ
diff --git a/docs/images/207.png b/docs/images/207.png
new file mode 100644
index 0000000..bb0a7b9
Binary files /dev/null and b/docs/images/207.png differ
diff --git a/docs/images/208.png b/docs/images/208.png
new file mode 100644
index 0000000..0681afe
Binary files /dev/null and b/docs/images/208.png differ
diff --git a/docs/images/209.png b/docs/images/209.png
new file mode 100644
index 0000000..8141833
Binary files /dev/null and b/docs/images/209.png differ
diff --git a/docs/images/210.png b/docs/images/210.png
new file mode 100644
index 0000000..b3b055a
Binary files /dev/null and b/docs/images/210.png differ
diff --git a/docs/images/211.png b/docs/images/211.png
new file mode 100644
index 0000000..26c68a6
Binary files /dev/null and b/docs/images/211.png differ
diff --git a/docs/images/212.png b/docs/images/212.png
new file mode 100644
index 0000000..b030ada
Binary files /dev/null and b/docs/images/212.png differ
diff --git a/docs/images/213.png b/docs/images/213.png
new file mode 100644
index 0000000..c02e885
Binary files /dev/null and b/docs/images/213.png differ
diff --git a/docs/images/214.png b/docs/images/214.png
new file mode 100644
index 0000000..69b4247
Binary files /dev/null and b/docs/images/214.png differ
diff --git a/docs/images/215.png b/docs/images/215.png
new file mode 100644
index 0000000..1f54ded
Binary files /dev/null and b/docs/images/215.png differ
diff --git a/docs/images/216.png b/docs/images/216.png
new file mode 100644
index 0000000..b20af1b
Binary files /dev/null and b/docs/images/216.png differ
diff --git a/docs/images/217.png b/docs/images/217.png
new file mode 100644
index 0000000..ffa9c1b
Binary files /dev/null and b/docs/images/217.png differ
diff --git a/docs/images/218.png b/docs/images/218.png
new file mode 100644
index 0000000..4edf31a
Binary files /dev/null and b/docs/images/218.png differ
diff --git a/docs/images/219.png b/docs/images/219.png
new file mode 100644
index 0000000..b66deac
Binary files /dev/null and b/docs/images/219.png differ
diff --git a/docs/images/220.png b/docs/images/220.png
new file mode 100644
index 0000000..71881d0
Binary files /dev/null and b/docs/images/220.png differ
diff --git a/docs/images/221.png b/docs/images/221.png
new file mode 100644
index 0000000..861347b
Binary files /dev/null and b/docs/images/221.png differ
diff --git a/docs/images/222.png b/docs/images/222.png
new file mode 100644
index 0000000..2a65be2
Binary files /dev/null and b/docs/images/222.png differ
diff --git a/docs/images/223.png b/docs/images/223.png
new file mode 100644
index 0000000..639bc6e
Binary files /dev/null and b/docs/images/223.png differ
diff --git a/docs/images/224.gif b/docs/images/224.gif
new file mode 100644
index 0000000..82daf07
Binary files /dev/null and b/docs/images/224.gif differ
diff --git a/docs/images/225.gif b/docs/images/225.gif
new file mode 100644
index 0000000..27405a6
Binary files /dev/null and b/docs/images/225.gif differ
diff --git a/docs/images/226.gif b/docs/images/226.gif
new file mode 100644
index 0000000..051e036
Binary files /dev/null and b/docs/images/226.gif differ
diff --git a/docs/images/227.gif b/docs/images/227.gif
new file mode 100644
index 0000000..50ddcaf
Binary files /dev/null and b/docs/images/227.gif differ
diff --git a/docs/images/228.png b/docs/images/228.png
new file mode 100644
index 0000000..a3ca622
Binary files /dev/null and b/docs/images/228.png differ
diff --git a/docs/images/229.png b/docs/images/229.png
new file mode 100644
index 0000000..e30244e
Binary files /dev/null and b/docs/images/229.png differ
diff --git a/docs/images/230.png b/docs/images/230.png
new file mode 100644
index 0000000..01fe8c4
Binary files /dev/null and b/docs/images/230.png differ
diff --git a/docs/images/231.png b/docs/images/231.png
new file mode 100644
index 0000000..de41d16
Binary files /dev/null and b/docs/images/231.png differ
diff --git a/docs/images/232.png b/docs/images/232.png
new file mode 100644
index 0000000..235c1a1
Binary files /dev/null and b/docs/images/232.png differ
diff --git a/docs/images/233.png b/docs/images/233.png
new file mode 100644
index 0000000..810da97
Binary files /dev/null and b/docs/images/233.png differ
diff --git a/docs/images/234.png b/docs/images/234.png
new file mode 100644
index 0000000..0c1538d
Binary files /dev/null and b/docs/images/234.png differ
diff --git a/docs/images/235.png b/docs/images/235.png
new file mode 100644
index 0000000..e57b395
Binary files /dev/null and b/docs/images/235.png differ
diff --git a/docs/images/236.png b/docs/images/236.png
new file mode 100644
index 0000000..1212f0f
Binary files /dev/null and b/docs/images/236.png differ
diff --git a/docs/images/237.png b/docs/images/237.png
new file mode 100644
index 0000000..07c83dc
Binary files /dev/null and b/docs/images/237.png differ
diff --git a/docs/images/238.png b/docs/images/238.png
new file mode 100644
index 0000000..01fec07
Binary files /dev/null and b/docs/images/238.png differ
diff --git a/docs/images/239.png b/docs/images/239.png
new file mode 100644
index 0000000..444089a
Binary files /dev/null and b/docs/images/239.png differ
diff --git a/docs/images/240.png b/docs/images/240.png
new file mode 100644
index 0000000..4b9f44d
Binary files /dev/null and b/docs/images/240.png differ
diff --git a/docs/images/241.png b/docs/images/241.png
new file mode 100644
index 0000000..bce8eb9
Binary files /dev/null and b/docs/images/241.png differ
diff --git a/docs/images/242.png b/docs/images/242.png
new file mode 100644
index 0000000..3bd8a0e
Binary files /dev/null and b/docs/images/242.png differ
diff --git a/docs/images/243.png b/docs/images/243.png
new file mode 100644
index 0000000..65a5bda
Binary files /dev/null and b/docs/images/243.png differ
diff --git a/docs/images/244.png b/docs/images/244.png
new file mode 100644
index 0000000..9e7aa38
Binary files /dev/null and b/docs/images/244.png differ
diff --git a/docs/images/245.png b/docs/images/245.png
new file mode 100644
index 0000000..6d35053
Binary files /dev/null and b/docs/images/245.png differ
diff --git a/docs/images/62.png b/docs/images/62.png
index c99602f..602259b 100644
Binary files a/docs/images/62.png and b/docs/images/62.png differ
diff --git a/docs/images/65.png b/docs/images/65.png
new file mode 100644
index 0000000..5c009a7
Binary files /dev/null and b/docs/images/65.png differ
diff --git a/docs/images/66.png b/docs/images/66.png
new file mode 100644
index 0000000..9491cbf
Binary files /dev/null and b/docs/images/66.png differ
diff --git a/docs/images/67.png b/docs/images/67.png
new file mode 100644
index 0000000..2fb9f10
Binary files /dev/null and b/docs/images/67.png differ
diff --git a/docs/images/68.png b/docs/images/68.png
new file mode 100644
index 0000000..66a4bb6
Binary files /dev/null and b/docs/images/68.png differ
diff --git a/docs/images/69.png b/docs/images/69.png
new file mode 100644
index 0000000..45aacbf
Binary files /dev/null and b/docs/images/69.png differ
diff --git a/docs/images/70.png b/docs/images/70.png
new file mode 100644
index 0000000..9750e43
Binary files /dev/null and b/docs/images/70.png differ
diff --git a/docs/images/71.png b/docs/images/71.png
new file mode 100644
index 0000000..22cc6ab
Binary files /dev/null and b/docs/images/71.png differ
diff --git a/docs/images/72.png b/docs/images/72.png
new file mode 100644
index 0000000..fc5a7dd
Binary files /dev/null and b/docs/images/72.png differ
diff --git a/docs/images/73.png b/docs/images/73.png
new file mode 100644
index 0000000..2e76595
Binary files /dev/null and b/docs/images/73.png differ
diff --git a/docs/images/74.png b/docs/images/74.png
new file mode 100644
index 0000000..b208ad3
Binary files /dev/null and b/docs/images/74.png differ
diff --git a/docs/images/75.png b/docs/images/75.png
new file mode 100644
index 0000000..05d663d
Binary files /dev/null and b/docs/images/75.png differ
diff --git a/docs/images/76.png b/docs/images/76.png
new file mode 100644
index 0000000..e958066
Binary files /dev/null and b/docs/images/76.png differ
diff --git a/docs/images/77.png b/docs/images/77.png
new file mode 100644
index 0000000..8e02e57
Binary files /dev/null and b/docs/images/77.png differ
diff --git a/docs/images/78.png b/docs/images/78.png
new file mode 100644
index 0000000..95fe8c9
Binary files /dev/null and b/docs/images/78.png differ
diff --git a/docs/images/79.png b/docs/images/79.png
new file mode 100644
index 0000000..cadea47
Binary files /dev/null and b/docs/images/79.png differ
diff --git a/docs/images/80.png b/docs/images/80.png
new file mode 100644
index 0000000..2914da3
Binary files /dev/null and b/docs/images/80.png differ
diff --git a/docs/images/81.gif b/docs/images/81.gif
new file mode 100644
index 0000000..da18254
Binary files /dev/null and b/docs/images/81.gif differ
diff --git a/docs/images/82.gif b/docs/images/82.gif
new file mode 100644
index 0000000..fde1b3a
Binary files /dev/null and b/docs/images/82.gif differ
diff --git a/docs/images/83.gif b/docs/images/83.gif
new file mode 100644
index 0000000..b10aee0
Binary files /dev/null and b/docs/images/83.gif differ
diff --git a/docs/images/84.gif b/docs/images/84.gif
new file mode 100644
index 0000000..fde1b3a
Binary files /dev/null and b/docs/images/84.gif differ
diff --git a/docs/images/85.gif b/docs/images/85.gif
new file mode 100644
index 0000000..fc1ea01
Binary files /dev/null and b/docs/images/85.gif differ
diff --git a/docs/images/86.gif b/docs/images/86.gif
new file mode 100644
index 0000000..b3a38ca
Binary files /dev/null and b/docs/images/86.gif differ
diff --git a/docs/images/87.gif b/docs/images/87.gif
new file mode 100644
index 0000000..6adf75e
Binary files /dev/null and b/docs/images/87.gif differ
diff --git a/docs/images/88.gif b/docs/images/88.gif
new file mode 100644
index 0000000..966a066
Binary files /dev/null and b/docs/images/88.gif differ
diff --git a/docs/images/89.gif b/docs/images/89.gif
new file mode 100644
index 0000000..12a4bb9
Binary files /dev/null and b/docs/images/89.gif differ
diff --git a/docs/images/9.png b/docs/images/9.png
index 783d89e..565c714 100644
Binary files a/docs/images/9.png and b/docs/images/9.png differ
diff --git a/docs/images/90.gif b/docs/images/90.gif
new file mode 100644
index 0000000..2a64ef3
Binary files /dev/null and b/docs/images/90.gif differ
diff --git a/docs/images/91.gif b/docs/images/91.gif
new file mode 100644
index 0000000..13fb4a9
Binary files /dev/null and b/docs/images/91.gif differ
diff --git a/docs/images/92.gif b/docs/images/92.gif
new file mode 100644
index 0000000..1917583
Binary files /dev/null and b/docs/images/92.gif differ
diff --git a/docs/images/93.png b/docs/images/93.png
new file mode 100644
index 0000000..05406b1
Binary files /dev/null and b/docs/images/93.png differ
diff --git a/docs/images/94.png b/docs/images/94.png
new file mode 100644
index 0000000..82d9b5f
Binary files /dev/null and b/docs/images/94.png differ
diff --git a/docs/images/95.png b/docs/images/95.png
new file mode 100644
index 0000000..54187d1
Binary files /dev/null and b/docs/images/95.png differ
diff --git a/docs/images/96.png b/docs/images/96.png
new file mode 100644
index 0000000..c98ffc3
Binary files /dev/null and b/docs/images/96.png differ
diff --git a/docs/images/97.png b/docs/images/97.png
new file mode 100644
index 0000000..dc533ea
Binary files /dev/null and b/docs/images/97.png differ
diff --git a/docs/images/98.png b/docs/images/98.png
new file mode 100644
index 0000000..11c5735
Binary files /dev/null and b/docs/images/98.png differ
diff --git a/docs/images/99.png b/docs/images/99.png
new file mode 100644
index 0000000..4fe9eba
Binary files /dev/null and b/docs/images/99.png differ