● Dla każdej komórki bierze się pod uwagę komórki z jej ortogonalnego sąsiedztwa, oznacza to, że pod uwagę bierzemy czterech sąsiadów, na rysunku zaznaczonych zielonym kolorem.
rys. 1
● Jeśli suma wartości komórek na dole i na górze nie jest równa zero, wtedy stan branej pod uwagę komórki zmienia się zgodnie z modulo (resztą z dzielenia) sumy wartości komórek po prawej i lewej stronie przez wartości komórek na dole i na górze.
rys. 2
rys. 3
1
( 32 + 7
1 8) mod (81 + 7
1 8) = 1
5
(dla ułatwienia nie zmieniono wartości sąsiadów na rys. 3)
● Jeśli suma komórek na dole oraz na górze wynosi zero, wtedy należy brać pod uwagę jedynie sumę wartości komórek po lewej i prawej stronie i dodać ją do obecnego stanu komórki.
Uwaga: najwyższa wartość 255! W przypadku, gdy suma wyniesie więcej, stan zmienia się na 255.
rys. 4
rys.5
1
( 75 + 175) + 6
3 = 8
3 6
Przypadek, w którym bierzemy najwyższą możliwą wartość, 255
● Automat posiada trzy tryby, które zmienia się za pomocą klawiszy 1,2 i 3. Różnią się od siebie sposobem rozwoju.
● Kliknięcie LPM prowadzi do ponownej populacji w oknie
Tryb 1
Tryb 2
Tryb 3
KOD PROGRAMU
int W = 600; // szerokość okna (powinno być dzielne przez S) int H = 400; // wysokość okna (powinno być dzielne przez S) int S = 2; // rozmiar komórek w pikselach
int C = W / S; // ilość column w automacie
int R = H / S; // ilość wierszy w automacie
int mode=1; // która wersja jest wyświetlana na początku int [][] curr; // obecne pokolenie
int [][] prev; // poprzednie pokolenie
color [] palette; // 256 kolorów
void setup() {
size(W,H);
frameRate(15); // im więcej tym szybciej
background(0);
noStroke();
curr = new int[R][C];
prev = new int[R][C];
populate();
palette = new int[256];
for (int i=0; i<256; i++) {
int k = (int)(pow(i/256.0,2)*255.0); // intensywność wybranego koloru,(pow(x,y)=x^y) palette[i] = color(0,k,0); // kolor (R,G,B)
}
}
void populate() {
for (int r=0; r<R; r++) {
for (int c=0; c<C; c++) {
prev[r][c] = curr[r][c] = (int)random(10); // można zmieniać!
// (10) - mała populacja początkowa, w miarę szybko się rozwija
}
}
}
void update() {
for (int r=0; r<R; r++) {
for (int c=0; c<C; c++) {
int state = curr[r][c];
int lr = prev[r][(c-1+C)%C] + prev[r][(c+1)%C]; // modulo %
int tb = prev[(r-1+R)%R][c] + prev[(r+1)%R][c]; int breed = 0;
switch(mode) { // tryby
case 1 : breed = (state+lr)&0xff; break;
// aktywny
case 2 : breed = ((state+lr))&0xf; break;
// najbardziej “matrixowy” efekt, usuwa najwyższe wartości bitów, wolniejszy rozwój case 3 : breed = (state+100)&0xff; break;
// bardzo zaszumiony efekt
// itd
}
curr[r][c] = (tb==0) ? breed : (lr%tb)&0xff;
}
}
}
void render() {
for (int r=0,y=0; r<R; y+=S,r++) {
for (int c=0,x=0; c<C; x+=S,c++) {
fill(palette[curr[r][c]]);
rect(x,y,S,S); // kształt
}
}
}
void swap() {
int [][] temp = curr;
curr = prev;
prev = temp;
}
void ui() {
fill(255,42,0,120);
text("mode: " + mode, 5, H-5);
}
void draw() {
update();
render();
ui();
swap();
}
void keyPressed() {
if ((key>='1') && (key<='3'))
mode = key - '0';
}
void mousePressed() {
populate();
}