Semestrální úloha 36OSY - 2005


Téma úlohy: Hra život (úloha číslo 12)
Vypracoval: Dědourek Pavel

3.roník, obor Výpočetní technika, K336 FEL CVUT,
Karlovo nám. 13, 121 35 Praha 2

Zdadání úlohy

Systém simuluje život organismů v koloniích, podobně jako je tomu ve hře život. Změny však neprobíhají synchronně, nýbrž vždy po určité době života organismu. Vše se odehrává na hracím plánu, který je rozdělen na čtvercová políčka. V každém políčku může být v jednom okamžiku nejvýše jeden organismus. Po určité době života organismu dochází ke změně: má-li organismu dva nebo tři sousedy, přežívá dále, jinak umírá. Navíc je-li v sousedství některého organismu volné políčko se třemi sousedy, vznikne v něm nový organismus. Organismy jsou zde vlákna a každý žije svým životem, tj. neexistuje žádné centrální řízení. Vlákno organismu vždy po určité době zkontroluje, zda někde v sousedství nevzniknul nový život, pokud ano, tak vytvoří nové vlákno. Dále zjistí počet svých sousedů. Pokud je dva nebo tři, na nějakou dobu se uspí, jinak skončí.



Modifikoval jsem zadání následovně. Pokud organismus (bunka) má v okolí preddefinovaný počet (POCET_SOUSEDU) organismů tak se uspí na zvolený čas (USPI) a zvíší se jeho věk. Jeli kolem bunky dostatečný počet buněk (NAROZENI) tak vznikne nový život, který se ihned uspí (DELKA_NAROZENI) to simuluje to, že organismus není ihned po narozeni schopny reprodukce.

Dále, pokud organismus má kolem sebe menší (POCET_SOUSEDU) počet organismů tak se jeho život radikálně zmenší a umře.



Návrh a popis implementace

Program pracuje následovně, v globálních proměnných pole[][] je uloženo hrací pole jehož rozměr udávají makra MAX_X a MAX_Y. V něm mohou být uloženy následující hodnoty:

  • hodnota makra VOLNO označuje volné políčko
  • hodnota makra BUNKA označuje políčko na kterém je zdravá bunka (označeno ve výstupu: "#")
  • hodnota makra BUNKA_V_MARNICI označuje políčko bunky, která zemřela a čeká v márnici (zásobník MARNICE) na pohřeb (uvolnění z paměti a inicializace)

    Další glob. proměnnou je vlákno[], což je proměnná, ve které si uchovávám pointer na pthread_t (ke každému vláknu) a jednoducho proměnnou f - flag, který určuje, zda se daný thread používá a je v paměti, to se pak hodí při ukončování programu.


    Do proměnné pocet_bunek se ukládá počet živých buněk

    Nejprve si inicializuji obě pole. Dále si vytvořím dvě vlákna, jedno vypisuje po dané době DELAY na obrazovku stav matice
    # - živá bunka
    + - bunka v márnici
    číslo,které se nezobrazuje - udává počet sousedů daného prvku
    Druhé vlákno je hrobník, tj. vybírá z márnice (zásobníku) mrtvé bunky, do pole[][] ukládá počet bunek okolo tohoto neboštíka, snižuje proměnnou pocet_bunek a odstranuje naalokovanou pamět.

    Při prvním spuštění se vytvoří v main() nějaké bunky pomocí Narozeni(). TO je nutné, aby se vytvořil organismus schopný života. V Narozeni() se nejdrive z zamkne zámek (Mutex) a pak se může pracovat s globálními proměnnými. Vypočítám si id-bunky (tj. id=x+MAX_X*y). Zkontroluji si jestli na daném místě se nevyskytuje např. nějaká BUNKA,BUNKA_V_MARNICU. Pokud je vše vpořádku, můžu alokovat pamět pro tuto novou bunku. Jinak opustim Narozeni() stím, že musím odemknout zámek (Mutex), jinak by hrozilo uvaznuti!.

    Po alokaci paměti, tuto pamět naplním požadovanými údaji, inkrementuji prom. počet buněk a Změním pole[][] sousedů tak, že inkrementuji. Odemknu Mutex a nakonec vytvořím nové vlákno (na funkci Bunka).

    Vlastní život bunky se odehrává ve funkci Bunka(). Nejprve si bunka zjistí o sobě informace (kde je, kolik jí je) a uspí se (to je proto, že bunka hned po narození není schopná reprodukce). Doba na kterou se uspí je v makru DELKA_NAROZENI.

    Poté se bunka přesune do druhé fáze života a to do cyklu, kde zjištuje zda-li kolem ní může vzniknout nový život, nebo zda-li má usnout (počet sousedů je větší než POCET_SOUSEDU) jinak se její věk inkrementuje. Pokud bunka dosáhne věku (vek = MAX_VEK), tak umře.

    Podmínky pro nový život obstarává PodminkyProZivot(), která zjištuje zda-li někde okolo aktuální bunky (x,y) v poli[a][b] není číslo (to udává počet sousedů bunky a,b) větší než NAROZENI. Pokud je větší, spustí se Narozeni().

    Pokud bunka umře tak se nejdříve přesune do zásobníku (marnice) a tam se s ní vypořádá hrobník().

    Hrobník() vybírá ze zásobníku. Pokud se vrátí id-bunky tak hrobník zamkne mutex, zjistí údaje o neboštíkovi, dekrementuje pocet_bunek a dekrementuje okolni sousedy v pole[][] (ZmenSousedy) a na místo neboštíka uloží číslo udávající počet sousedů. Uvolní pamět a odemkne Mutex. Pokud v zásobníku (marnici) nikdo není tak se hrobník usí na 1sekundu (jelikož nemá co dělat).


    Překlad:
    gcc ./zivot_dedoup1.c -o zivot_dedoup1.o -Wall -lpthread -g

    Soubory:
    zivot_dedoup1.c zdrojový soubor v jazyku C
    vstup vstupní údaje o první bunkách (první řádek udává počet buněk a další x,y souřadnice oddělené čárkou
    preklad.sh skript pro preklad

    Ovládání

    Po možné editaci souboru vstup (zadání prvních buněk) lze program spustit a po načtení buněk lze program pomocí enteru ukončit. Velikost hraciho pole je udana makry, takze je nutne ji zmenit pred prekladem.

    Závěr

    Úlohu se mi doufám podařilo vyřešit a dle testů se zdá že se chová tak jak má. K simulaci zivota je vsak tezke najit takové konstanty v makrech aby byl videt co nejlépe vyvoj organismu. Presto vše se program jeví jako zdařilý. K nedostatkům patří nedynamický přístup k věci. Většina věcí je zadána staticky, dynamicky jsem řešil jen vlákna. Z tohoto důvodu se velikost hracího pole musí nastavit pře překladem.

    screenshot - ukazka
    Literatura
    36OSY-materiály k cvičení
    www.google.com