Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Conway's Game of Life LFO #313

Merged
merged 39 commits into from
Feb 8, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
c7db969
Initial commit of an LFO based on Conway's Game of Life. Runs way too…
chrisib Nov 18, 2023
9415297
For debugging use CV6 as a gate that is high while we calculate the g…
chrisib Nov 18, 2023
c80e684
Simple optimization: only check regions that have changed instead of …
chrisib Nov 18, 2023
88b115b
Remove the vestiges of the external clock mode, update what the six C…
chrisib Nov 18, 2023
f6ce97a
Typo in a comment
chrisib Nov 18, 2023
06b53e5
Move the get_bit and set_but functions out of the Conway class
chrisib Nov 18, 2023
6810fec
Minor re-organization, add some missing docstrings
chrisib Nov 18, 2023
c66153a
Remove the respawn without reset
chrisib Nov 18, 2023
5c6e82f
Use the standard deviation of population deltas in buckets of size 2,…
chrisib Nov 18, 2023
b2e7d58
Add a note to the readme about the inconsistent update rates. I kind …
chrisib Nov 18, 2023
0b480a5
Use CV4 as an FPS-based pulse since CV4 and CV5 were previously near-…
chrisib Nov 19, 2023
795391b
Re-add the two FrameBuffer objects; the memory-savings from only havi…
chrisib Nov 19, 2023
3e0d534
Remove the 5V magic number, add a constant for that
chrisib Nov 19, 2023
552b256
Modify how we calculate CV3, add a note to the README about the expec…
chrisib Nov 19, 2023
8ba9797
Remove some extra newlines
chrisib Nov 19, 2023
a22d921
Consider the mean and the standard deviation when checking for stasis…
chrisib Nov 19, 2023
aabc4f9
Update the readme
chrisib Nov 19, 2023
b116ab6
Reduce the spawn rate by 50%, fix a potential divide-by-zero error
chrisib Nov 20, 2023
ccf6fd4
Use bit arrays instead of Sets for tracking the changed spaces; this …
chrisib Nov 20, 2023
5fe1586
Remove the "expected" voltage ranges from the readme; i don't have en…
chrisib Nov 20, 2023
17de54f
Change CV1 to use the Shannon entropy of the field as a bit string; t…
chrisib Nov 20, 2023
eeb9bfb
Cleanup the respawn function slightly
chrisib Nov 20, 2023
89e06dd
Remove the random_spawn function and combine it with reset()
chrisib Nov 20, 2023
cc7282a
Minor cleanup & optimization
chrisib Nov 20, 2023
4845ac6
Move the bitwise operations to a new experimental module
chrisib Nov 20, 2023
5e7cf19
Fix some bugs (should use 0x07 not 0x03!), tidy up some formatting, r…
chrisib Nov 20, 2023
e57ab88
Handle the cases where either the whole field is full or the whole fi…
chrisib Nov 21, 2023
9601565
Clean up some comments
chrisib Nov 21, 2023
2eb57fb
Reduce the number of divisions in the entropy calculation
chrisib Nov 21, 2023
4b0ec09
Fix a divide-by-zero error if the whole population dies
chrisib Nov 21, 2023
07c5214
Explicitly check for zero population in the stasis checks
chrisib Nov 21, 2023
accc58a
Automatically trigger a respawn on stasis. This eliminates the need t…
chrisib Nov 21, 2023
dd9743f
Add the missing return to the make_bit_array() function
chrisib Feb 7, 2024
ad98bf6
typo
chrisib Feb 7, 2024
246f5f4
Remove the duplicate clamp function
chrisib Feb 7, 2024
86babfc
Add self-resetting behaviour to the conway docs
chrisib Feb 7, 2024
c551206
Don't explicitly clear the current field; re-use the existing cells &…
chrisib Feb 7, 2024
47b39f9
Simplify some of the math
chrisib Feb 7, 2024
df1b632
Gate -> Trigger w/r/t CV6
chrisib Feb 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions software/contrib/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ Users can morph between patterns and CV sequences during operation, with 3 gate
<i>Author: [gamecat69](https://github.com/gamecat69)</i>
<br><i>Labels: sequencer, gates, triggers, drums, randomness</i>

### Conway \[ [documentation](/software/contrib/conway.md) | [script](/software/contrib/conway.md) \]
A semi-random LFO that uses [John Conway's Game Of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) to produce CV and gate signals.

<i>Author: [chrisib](https://github.com/chrisib)</i>
<br><i>Labels: lfo, gates, randomness</i>

### CVecorder \[ [documentation](/software/contrib/cvecorder.md) | [script](/software/contrib/cvecorder.py) \]
6 channels of control voltage recording

Expand Down
102 changes: 102 additions & 0 deletions software/contrib/conway.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# John Conway's Game of LiFO

This script implements [John Conway's Game Of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) as the
procedural kernel for multiple LFOs.

The game is played on a 128x32 field (the size of the OLED). Every pixel is a cell. On every step an empty space will
spawn a new cell if it has exactly 3 neighbours. Cells with 2 or 3 neighbours stay alive. Cells with 1 or 0 neighbours
die of loneliness. Cells with 4 or more neighbours die of overcrowding.

This program acts as a free-running LFO; it is not clockable externally.

On every step, a number of random new cells will also spawn, based on the CV input provided on `ain`. `k2` acts
as an attenuator for the signal on `ain`.

## I/O Mapping

| I/O | Usage
|---------------|-------------------------------------------------------------------|
| `din` | Clear the field & start a new random spawn |
| `ain` | Offset control for spawn density |
| `b1` | Manual equivalent to `din` |
| `b2` | Manual equivalent to `din` |
| `k1` | Base spawn density |
| `k2` | Attenuverter for `ain` |
| `cv1` - `cv6` | Output signals. See below for details |

## Outputs

The six outputs are stepped CV outputs, whose values vary according to the game state.

- `cv1`: outputs 0-10V depending on the Shannon entropy of the entire field
- `cv2`: outputs 0-10V depending on the ratio between the number of new births and the current population
- `cv3`: outputs 0-10V depending on the ratio between the number of births and the number of deaths in the
latest generation
- `cv4`: outputs a 5V gate every generation
- `cv5`: outputs a 5V gate signal if the number of births in the last generation was greater than the number
of deaths
- `cv6`: outputs a 5V gate signal if the field has reached a point of stasis

## Stasis Detection

Because of the modest computing power available, this program uses some simple statistics to infer if the game has
reached a point of stasis. There is a chance that false-positives and false-negatives can be detected.

When the game is believed to have reached a state of stasis it will automatically reset, as if a signal had been
detected on `din`. The field will clear and be filled with random data with a density governed by `ain`, `k1`, and
`k2`.

The game is assumed to have reached a state of stasis under these conditions:
1. At least 12 generations have passed since the last reset
2. The number of game spaces that have changed from dead to alive or alive to dead is equal to zero OR
3. The sum of population changes in groups of 2, 3, or 4 generations has a standard deviation of 1.0 or less
and the absolute value of the mean of the group is less than 1.0.

To better-explain 3, consider the following 12 generations' of population changes:
```
[16, -17, 18, -14, 8, -23, 0, -3, 13, -12, 6, -5]
```

Grouping these changes into buckets of 2, 3, or 4 generations we produce these summed buckets:

```
Size 2: [-1, 4, -15, -3, 1, 1]
Size 3: [17, -29, 10, -11]
Size 4: [3, -18, 2]
```

We calculate the mean and standard deviation of each set of buckets, giving:
```
Size 2: -2.167, 6.69328
Size 3: -3.25, 18.08833
Size 4: -4.333, 9.672412
```

In this case none of the standard deviations nor means have a magnitude smaller than 1, so the system is not
considered to be in stasis.

Conversely, given these population changes:
```
[-12, 6, 4, 2, -12, 6, 4, 2, -12, 6, 4, 2]

Size 2: [-6, 6, -6, 6, -6, 6] -> 0.0, 6.0
Size 3: [-2, -4, -6, 12] -> 0.0, 7.071068
Size 4: [0, 0, 0] -> 0.0, 0.0
```
we would assume we have reached stasis, as the mean and standard deviation of the size-3 buckets are less than 1.0.

## LFO Rate Variablility

Because of the implementation of Conway's Game of Life, when the field is densely-populated, e.g. immediately after a
reset with a high spawn rate, the outputs will change relatively slow. As cells die off and the field becomes more
sparse the rate will increase. This is normal.

## Patch Ideas

You can patch an external LFO into DIN to periodically reset the simulation before it reaches a state of stasis.

You can create interesting feedback by patching `cv1`-`cv3` into `ain` and using the gate signals from `cv4`-`cv6`
to control the simulation reset rate & reset density.

If the variation in the LFO rate causes problems you can take the outputs from Conway and connect them to an
externally-clocked Sample & Hold module. This will smooth out the changes in the update frequency of Conway.
Loading
Loading