2022-04-02 16:54:46 +02:00
|
|
|
# Game of Life über mehrere Monitore
|
|
|
|
|
|
|
|
Implementierung des berühmten [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life) als verteiltes System.
|
|
|
|
Jeder Teilnehmer hat einen Bereich in dem er Game of Life berechnet und seine Kanten mit den andren Teilnehmer austauscht.
|
|
|
|
Die gesamte Koordination erfolgt dezentral, Kommunikation ist immer p2p-basiert.
|
|
|
|
|
2022-04-19 19:45:42 +02:00
|
|
|

|
|
|
|
|
2022-04-12 12:47:26 +02:00
|
|
|
## Requirements
|
|
|
|
|
|
|
|
- Python 3+
|
|
|
|
|
|
|
|
```shell
|
|
|
|
pip install -r requirements.txt
|
|
|
|
```
|
|
|
|
|
|
|
|
## Ausführen
|
|
|
|
|
|
|
|
```shell
|
|
|
|
python -m Code.Main own_ip own_port [ neighbour_ip neighbour_port (LEFT|RIGHT) ]
|
|
|
|
```
|
|
|
|
|
|
|
|
### Beispiel (auf lokalem Rechner)
|
|
|
|
|
|
|
|
Als erster Teilnehmer
|
|
|
|
|
|
|
|
```shell
|
|
|
|
python -m Code.Main 0.0.0.0 8080
|
|
|
|
```
|
|
|
|
|
|
|
|
Als zweiter Teilnehmer
|
|
|
|
|
|
|
|
```shell
|
|
|
|
python -m Code.Main 0.0.0.0 8081 0.0.0.0 8080 RIGHT
|
|
|
|
```
|
|
|
|
|
|
|
|
Als dritter Teilnehmer
|
|
|
|
|
|
|
|
```shell
|
|
|
|
python -m Code.Main 0.0.0.0 8082 0.0.0.0 8080 LEFT
|
|
|
|
```
|
|
|
|
|
2022-04-12 18:21:31 +02:00
|
|
|
## Steuerung
|
2022-04-12 12:47:26 +02:00
|
|
|
|
2022-04-12 18:21:31 +02:00
|
|
|
Es gibt zwei Zustände, pausiert und nicht pausiert.
|
|
|
|
Zwischen diesen kann mit 'Leertaste' gewechselt werden.
|
|
|
|
Im pausierten Zustand können mit der linken Maustaste eigene Strukturen gezeichnet werden.
|
|
|
|
Mit der unteren Reihe der Tastatur (y,x,v,b,n,m) können vorgefertigte Strukturen (Glider und Spaceships) gespawnt werden.
|
2022-04-02 16:54:46 +02:00
|
|
|
|
|
|
|
## Einstieg
|
2022-04-12 12:47:26 +02:00
|
|
|
|
2022-04-02 16:54:46 +02:00
|
|
|
Um an dem Spiel teilzunehmen, muss jeder Teilnehmer (außer der erste) beim Starten der Anwendung die IP-Adresse und den
|
|
|
|
Port eines anderen Teilnehmers angeben, mit dem er sich verbinden will.
|
|
|
|
Zusätzlich muss die Richtung der Kante, mit welcher er sich mit diesem verbinden will, angegeben werden.
|
2022-04-12 12:47:26 +02:00
|
|
|
Da jeder Teilnehmer an jeder seiner Kanten maximal mit einem anderen Teilnehmer verbunden sein kann, ist es möglich,
|
2022-04-02 16:54:46 +02:00
|
|
|
dass die Kante, die beim Einstieg gewählt wird, bereits besetzt ist.
|
|
|
|
Ist dies der Fall, wird der Anfragende automatisch an denjenigen weitergeleitet, der diese Kante besetzt.
|
|
|
|
Dies passiert so lange bis eine freie Kante gefunden wird und sich somit zwei Teilnehmer verbinden.
|
|
|
|
Wenn man sich also **rechts** von Teilnehmer 1 verbinden will, ist es nicht garantiert, dass man direkt mit Teilnehmer 1
|
|
|
|
verbunden wird, sondern nur, dass man räumlich **rechts** von Teilnehmer 1 liegt.
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
## Suche
|
2022-04-12 12:47:26 +02:00
|
|
|
|
2022-04-02 16:54:46 +02:00
|
|
|
Die Suche ist recht simpel.
|
|
|
|
Jeder Teilnehmer kennt nur die Knoten, welche die für ihn relevanten Informationen haben und diese verändern sich im Laufe
|
|
|
|
der Zeit auch nicht.
|
|
|
|
|
2022-04-12 12:47:26 +02:00
|
|
|
## Verbreitung
|
|
|
|
|
|
|
|
Eine relevante Information, die an das gesamte Netz verbreitet werden muss, ist eine Zustandsänderung bezüglich der
|
2022-04-02 16:54:46 +02:00
|
|
|
Pausierung der Simulation.
|
|
|
|
Hierfür wird einfaches Flooding verwendet.
|
|
|
|
D.h. jeder Teilnehmer schickt den neuen Zustand an alle seine Nachbarn und diese senden ihn wiederum an ihre Nachbarn.
|
|
|
|
Da es nur zwei mögliche Zustände für den Pause-Zustand geben kann, ist Flooding ausreichend effizient, zyklische Nachrichten
|
2022-04-12 12:47:26 +02:00
|
|
|
werden vermieden, indem ein Teilnehmer die Information nicht mehr weiterleitet, wenn er sie bereits bekommen hat, sich also
|
2022-04-02 16:54:46 +02:00
|
|
|
schon im richtigen Zustand befindet.
|
|
|
|
|
|
|
|
## Zeitliche Synchronisation
|
2022-04-12 12:47:26 +02:00
|
|
|
|
|
|
|
Um sicherzustellen, dass alle Teilnehmer gleichzeitig den Entwicklungsschritt durchführen und somit der Randaustausch auch
|
2022-04-10 18:37:33 +02:00
|
|
|
korrekt funktioniert, wird eine vereinfachte Version von Lamport Clocks verwendet.
|
|
|
|
Jeder Prozess hat einen Counter, den er bei jedem Entwicklungsschritt um eins erhöht.
|
2022-04-12 18:21:31 +02:00
|
|
|
Da für jeden Entwicklungsschritt (Tick) zuerst die Ränder der benachbarten Teilenehmer abgefragt werden müssen und dies blockierend
|
2022-04-12 12:47:26 +02:00
|
|
|
geschieht, sind alle Teilnehmer zu jedem Zeitpunkt um maximal 1 bezüglich ihres Counters versetzt.
|
|
|
|
Damit man jedoch mit seinem Entwicklungsschritt nicht warten muss, bis alle Nachbar den Rand angefragt haben, hält jeder
|
2022-04-12 18:21:31 +02:00
|
|
|
Prozess eine Kopie seiner Ränder vom vorherigen Zeitpunkt.
|
2022-04-12 12:47:26 +02:00
|
|
|
Bei der Anfrage nach dem Rand wird der nachgefragte Counter mitgeschickt, dieser muss dem aktuellen oder dem vorherigen
|
|
|
|
Counter entsprechen oder um eins größer sein, als der aktuelle Counter.
|
|
|
|
Ist der angefragte Counter um eins größer als der aktuelle, liegt also quasi in der Zukunft, wird der Request blockiert,
|
|
|
|
bis der Angefragte den nächsten Entwicklungsschritt durchgeführt hat.
|
2022-04-10 18:37:33 +02:00
|
|
|
Somit wird das gesamte Game of Life nur so schnell ausgeführt, wie der langsamste Teilenehmer ist.
|
|
|
|
|
2022-04-12 18:21:31 +02:00
|
|
|
Die Synchronisation kann auch als Variante des Awerbuch Synchronisierers angesehen werden.
|
|
|
|
Die Nachrichten über den Randaustausch entsprechen den Nachrichten beim Awerbuch Synchronisier, da sie den Counter/Tick enthalten
|
|
|
|
und blockierend sind, es wird also auf ein ACK gewartet (das wir quasi durch die tiefer liegenden Schichten gemacht).
|
|
|
|
Anstatt jedoch ein Safe zu verschicken, starte jeder Teilnehmer sofort den nächsten Tick und speichert seine Werte vom vorherigen Tick zwischen.
|
|
|
|
Die Option, den Entwicklungsschritt erst durchzuführen, nachdem alle Nachbarn die Kanten angefragt haben, wurde bei der Implementierung erwogen,
|
2022-05-23 08:36:22 +02:00
|
|
|
die Zwischenspeicherung der vorherigen Ränder erschien jedoch einfacher.
|
2022-04-12 18:21:31 +02:00
|
|
|
|
2022-04-19 19:45:42 +02:00
|
|
|
## Technische Implementierung
|
|
|
|
|
|
|
|
Das GUI ist mit pygame implementiert.
|
2022-05-23 08:36:22 +02:00
|
|
|
Parallel dazu läuft in einem separaten Thread ein simpler Webserver, über den die Kommunikation mit den anderen Teilnehmern erfolgt.
|
2022-04-19 19:45:42 +02:00
|
|
|
|
|
|
|
Dieser stellt folgende Endpoints bereit:
|
|
|
|
|
|
|
|
- /connect: Für den Verbindungsaufbau
|
|
|
|
- /pause: Für das Pausieren und Starten von GOL
|
|
|
|
- /border: Für den Randaustausch
|
|
|
|
|
2022-05-23 08:36:22 +02:00
|
|
|
## TODOS/Probleme (won't fix)
|
2022-04-12 18:21:31 +02:00
|
|
|
|
|
|
|
- [ ] Sauberer Shutdown
|
|
|
|
- [ ] Joinen wenn nicht pausiert
|
|
|
|
- [ ] Zwei Nachbarn als Parameter angeben
|
2022-05-23 08:36:22 +02:00
|
|
|
- [ ] 2D Gebiete (also verbinden an allen vier Seiten)
|
2022-04-12 18:21:31 +02:00
|
|
|
|
2022-04-10 18:37:33 +02:00
|
|
|
<!-- LocalWords: Counter
|
|
|
|
-->
|