134 lines
4.4 KiB
Plaintext
134 lines
4.4 KiB
Plaintext
|
Othello
|
||
|
=======
|
||
|
|
||
|
Regeln
|
||
|
------
|
||
|
Wir spielen Othello (nicht Reversi!) nach den in der Wikipedia
|
||
|
zu findenden Regeln: http://de.wikipedia.org/wiki/Othello_(Spiel)
|
||
|
|
||
|
|
||
|
Code
|
||
|
----
|
||
|
|
||
|
Interessant sind:
|
||
|
* players/example-player.cc -> Beispiel-Spieler für
|
||
|
manuelle Zugeingabe
|
||
|
* players/random-player.cc -> Dein Zufalls-Spieler
|
||
|
* players/my-player.cc -> Dein Spieler mit Strategie
|
||
|
|
||
|
Der Vollständigkeit halber:
|
||
|
* Makefile
|
||
|
* mcp.cc, mcp.h, othello.cc -> Master Control Program
|
||
|
|
||
|
|
||
|
Programmieren
|
||
|
-------------
|
||
|
|
||
|
players/my-player.cc enthält ein Code-Grundgerüst. Dieses sorgt dafür, dass
|
||
|
der aktuelle Spielzustand vom MCP geholt wird und am Ende das Ergebnis Deines
|
||
|
Zuges ans MCP zurück geschickt wird. Dazwischen fehlt jetzt noch Dein cleverer
|
||
|
Code, der bestimmt, welches momentan der beste Zug ist.
|
||
|
|
||
|
Der Zustand wird als String der Länge 65 übergeben. Das erste Zeichen gibt an,
|
||
|
welcher Spieler am Zug ist. Die nächsten 64 Zeichen enthalten *zeilenweise*
|
||
|
den Zustand des Spielfeldes. Hierbei gibt es 3 Zeichen:
|
||
|
|
||
|
O -> Spieler 1
|
||
|
X -> Spieler 2
|
||
|
. -> leeres Feld
|
||
|
|
||
|
Deine Aufgabe ist es, einen gültigen Zug zu finden und an das MCP zurück zu
|
||
|
geben. Dies geschieht über zwei Variablen (turn_row und turn_col) die jeweils
|
||
|
die Zeile und Spalte des Ziel-Zuges enthalten sollen. Gültig ist jeder Zug,
|
||
|
der in der aktuellen Situation den Othello-Regeln entspricht.
|
||
|
|
||
|
Ein Sonderfall, der in Othello auftreten kann, ist das Aussetzen. Wenn Du
|
||
|
feststellst, dass Deine Seite momentan keinen gültigen Zug machen kann (auch
|
||
|
wenn bspw. das Feld noch nicht komplett voll ist), dann setze turn_row und
|
||
|
turn_col auf 0, um dem MCP zu signalisieren, dass Du aussetzt. Setzt Du aus
|
||
|
obwohl ein Zug möglich gewesen wäre, so gilt Dein Zug als ungültig.
|
||
|
|
||
|
Bitte füge allen eigenen Code in players/my-player.cc und
|
||
|
players/random-player.cc hinzu.
|
||
|
|
||
|
|
||
|
Kompilieren
|
||
|
-----------
|
||
|
$> make
|
||
|
|
||
|
* Erzeugt werden:
|
||
|
- othello -> das MCP
|
||
|
- example-player -> der Beispiel-Client
|
||
|
- my-player und random-player -> Deine noch zu implementierenden Clients
|
||
|
|
||
|
* Zum Aufräumen gibt es zwei weitere Make-Ziele:
|
||
|
$> make clean -> löscht alle .o-Files
|
||
|
$> make cleanall -> löscht alle generierten Files (.o, Programmdateien, ...)
|
||
|
|
||
|
|
||
|
Spielen
|
||
|
-------
|
||
|
|
||
|
Gespielt wird, indem man das MCP via "othello" startet und ihm als
|
||
|
Parameter zwei beliebige Client-Programme übergibt:
|
||
|
|
||
|
$> ./othello <prog1> <prog2>
|
||
|
|
||
|
Für den Beispiel-Client wäre das also:
|
||
|
|
||
|
$> ./othello example-player example-player
|
||
|
|
||
|
Aus Einfachheitsgründen kann der Spielstart auch über vorbereitete
|
||
|
Make-Ziele vorgenommen werden. Hierzu sind beim Aufruf von make zwei
|
||
|
Umgebungsvariablen zu setzen:
|
||
|
|
||
|
PLAYER1 (default = my-player) -> Spieler 1
|
||
|
PLAYER2 (default = example-player) -> Spieler 2
|
||
|
|
||
|
Der generelle Aufruf sieht so aus:
|
||
|
$> PLAYER1=<prog1> PLAYER2=<prog2> make execute
|
||
|
|
||
|
Es gibt drei vorbereitete Ziele:
|
||
|
|
||
|
1) Start der Beispiel-Clients:
|
||
|
$> make demo
|
||
|
2) Start beliebiger Clients im *Debug-Modus*, welcher nicht sofort
|
||
|
nach einem falschen Zug das Spiel beendet:
|
||
|
$> PLAYER1=<prog1> PLAYER2=<prog2> make debug
|
||
|
3) Start der Clients im Battle Mode, der zur Auswertung benutzt wird:
|
||
|
$> PLAYER1=<prog1> PLAYER2=<prog2> make fight
|
||
|
|
||
|
Zum Testen gibt es außerdem die Möglichkeit, das Spiel mit einer
|
||
|
vordefinierten Spielsituation zu starten. Das hat dann Vorteile, wenn
|
||
|
Euer Spieler nur in bestimmten Randfällen abstürzt. Dazu gibt man beim Starten
|
||
|
von ./othello einen Startzustand mit der Option '-s' an. Dieser Startzustand
|
||
|
sieht genauso aus wie der 65-Zeichen-String, den Euer Spieler sonst vom MCP
|
||
|
bekommt.
|
||
|
|
||
|
Beispiel-Absturz:
|
||
|
|
||
|
$> ./othello player1 player2
|
||
|
[..]
|
||
|
P1's turn. State: XOOOOO...OO.OO.X.OOOXO.X..OOOXOX...OXXX.....XX......XX.......X...
|
||
|
No move from player 1.
|
||
|
|
||
|
CHILD signal: 2 (killed) status 11 (as signal: SIGSEGV)
|
||
|
|
||
|
|
||
|
(Das SIGSEGV deutet an, dass der Spieler hier einen fehlerhaften
|
||
|
Speicherzugriff gemacht hat. Das 'No move from player 1' zeigt an, dass kein
|
||
|
Zug ausgegeben wurde.) Ihr könnt nun im selben Zustand weiter machen, indem
|
||
|
Ihr Othello wie folgt startet:
|
||
|
|
||
|
$> ./othello -s XOOOOO...OO.OO.X.OOOXO.X..OOOXOX...OXXX.....XX......XX.......X... player1 player2
|
||
|
|
||
|
|
||
|
Erfolgreiche Abgabe
|
||
|
-------------------
|
||
|
Für die erfolgreiche Abgabe musst Du 2 Clients programmieren:
|
||
|
|
||
|
1) Zufallsspieler - ein Spieler, der sich alle gültigen Züge sucht und
|
||
|
dann per Zufall einen davon auswählt.
|
||
|
2) Strategie-Spieler - ein Spieler, der eine bestimmte Strategie verfolgt
|
||
|
und dabei den Random Player in mehr als 50% der Fälle besiegt.
|