Uniwersytet Śląski w Katowicach
Wydział Informatyki i Nauki o Materiałach
Sztuczna Inteligencja
Automat komórkowy
Matrix
Opracowali:
Paulina Giereś
Ewelina Kania
Inżynieria biomedyczna rok III, OM1
Automat komórkowy Matrix działa na podanych zasadach:
● Każda komórka może przyjąć wartości od 0 do 255, co oznacza od koloru czarnego
do największego nasycenia danego koloru (w naszym przypadku zieleń #00ff00)
● Populacja zaczyna się od 10 komórek w losowo wybranym miejscu w oknie.
● 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
132
78) mod (81
78)
1
(
+ 1
+ 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
175
75)
6
86
(
+ 1
+ 3 = 3
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();
}