Der Spielleiter (Server)

Die beiden Computerspieler kommunizieren nicht direkt miteinander, sondern übertragen ihre Nachrichten über einen Mittelmann: den Spielleiter. Dadurch ist zum einen sichergestellt, dass man seinen Gegner nicht mit illegalen Nachrichten belästigen kann, zum anderen sorgt der Spielleiter dafür, dass sich die Kontrahenten an die Spielregeln halten.

Der Spielleiter ist direkt im Wettkampfsystem integriert, so dass alle Turnierspiele regelkonform gespielt werden müssen. Zum Testen des eigenen Computerspielers gibt es eine spezielle Version des Spielleiters, die im Downloadbereich (http://www.software-challenge.de) heruntergeladen werden kann. Diese Download-Version, die in diesem Abschnitt beschrieben wird, besitzt eine grafische Oberfläche, durch die man das Spiel gut verfolgen und sogar als Mensch mitspielen kann.

System vorbereiten und Spielleiter starten

Die einzige Vorraussetzung ist, dass auf dem Rechner mindestens die Laufzeitumgebung für Java 8 installiert ist. Siehe Installation von Java.

Nach der erfolgreichen Installation kann man den Server durch einen Doppelklick auf die Datei software-challenge-gui starten.

Die Programmoberfläche

Die Programmoberfläche besteht aus dem Menü oben sowie der Spielfläche darunter.

Spielleiter
Figure 3. Die Spielleiteroberfläche direkt nach dem Programmstart

Unter dem ersten Menüpunkt (Symbol der Software-Challenge) findet man alle möglichen Aktionen.

Zu Beginn ist die Spielfläche leer.

Ein neues Spiel erstellen

Um ein Spiel zu spielen, muss zunächst "Neues Spiel starten" angeklickt werden.

Neues Spiel
Figure 4. Dialog für ein neues Spiel

In diesem Fenster werden die Spieler ausgewählt, die an dem Spiel teilnehmen sollen. Für jeden Spieler gibt es folgende Optionen:

  • Text-Eingabefeld: Hier kann für jeden Spieler ein Name eingegeben werden, der dann im Spiel angezeigt wird.

  • Spielertyp: Es kann zwischen 4 verschiedenen Spielertypen gewählt werden:

    1. Mensch: Ein menschlicher Spieler, der über die Programmoberfläche spielt.

    2. Beispiel-Computerspieler: Ein Computerspieler, der im Server integriert ist.

    3. Computerspieler, von GUI gestartet: Ein Computerspieler in Form eines separaten Programms, das beim Starten des Spiels automatisch vom Server gestartet wird.

    4. Manuell gestarteter Client: Ein Computerspieler in Form eines separaten Programms, das manuell durch den Benutzer gestartet werden muss.

Nach Eingabe der erforderlichen Werte kann das Spiel mithilfe des unteren Knopfs "Erstellen" erstellt werden.

Die Spielfeldoberfläche

spielfeldoberflaeche
Figure 5. Die Spielfeldoberfläche (hier mit dem Spiel "Blokus")

Auf dem Spielbrett werden das eigentliche Spiel (hier z.B. "Blokus"), die Züge und weitere für das Spiel wichtige Informationen dargestellt. Hier setzt der menschliche Spieler auch seine Züge.

Die Steuerelemente unterscheiden sich je nach Spiel und Spielsituation. Unten gibt es immer die Schaltflächen "Anhalten/Weiter",

Für das Spiel Blokus:

  • Der aktuell gewähle Spielstein wird unten angezeigt, über das Menü Steurung kann man diesen rotieren (auch über Mausrad) und spiegeln (auch über rechte Maustaste)

  • Aus der Menge noch verfügbarer Spielsteine kann man mit Mausklick einen anderen Spielstein auswählen.

  • Mithilfe der Maus wird der gewählte Spielstein auf dem Feld abgelegt.

Spielwiederholungen

Spielwiederholungen oder Replay-Dateien sind aufgezeichnete frühere Spiele, die man sich beliebig oft wieder ansehen kann, um beispielsweise einen Fehler des eigenen Spielers zu analysieren oder eine Strategie zu verbessern.

Um das aktuelle Spiel als Spielwiederholung zu speichern, klickt man auf das Icon ganz rechts unten im Spielbereich. Dann kann man einen Dateinamen und Speicherort festlegen.

Um eine gespeicherte Spielwiederholung zu laden verwendet man den Eintrag "Replay laden" in der linken Leiste. Nachdem man eine Datei ausgewählt hat, kann man das gespeicherte Spiel abspielen oder Schritt für Schritt durchgehen.

Testdurchläufe

Wenn man einen grundsätzlich funkionierenden Computerspieler programmiert hat, ist es sinnvoll, diesen mit vielen verschiedenen Spielsituationen zu konfrontieren. Dadurch lassen sich Fehler entdecken und die Spielstärke des Computerspielers beurteilen. Für solche Testdurchläufe wird ein Testserver und TestClient zur Verfügung gestellt. Wie man diese verwendet, ist weiter unten unter den Überschrift Automatische Spiele: Der Testserver und Massentests beschrieben.

Spielsituation nachstellen

Wenn ein Fehlerverhalten des Computerspielers nur in einer bestimmten Situation in einem Spiel auftritt, kann es oft wünschenswert sein, diese Situation erneut nachzuspielen um den Computerspieler gezielt zu verbessern.

Dies ist zur Zeit nur auf etwas kompliziertem Wege möglich. Es folgt eine Schritt-für-Schritt Anleitung:

  1. Laden Sie das betreffende Replay aus dem Wettkampfsystem herunter (.xml.gz Datei).

  2. Entpacken Sie das Replay, sodass sie eine .xml-Datei erhalten.

  3. Starten Sie den Server und erstellen Sie ein neues Spiel. Wählen Sie den Computerspieler, der für diese Spielsituation getestet werden soll. Dieser Spieler muss als Spieler 1 gestartet werden und ist dann direkt als erstes dran. Der Gegenspieler kann dann ein beliebiger Computerspieler oder auch ein Mensch sein.

  4. Setzen Sie einen Haken bei "Spiel aus Datei laden". Wählen Sie über "Datei wählen" das entsprechende Replay aus und spezifizieren sie den Zug in dem gestartet werden soll. Starten Sie dann das Spiel. Das Spiel sollte sich nun in genau der Situation befinden, in der das Fehlerverhalten aufgetreten ist. Dabei ist der Spieler, der nun dran ist immer der rote Spieler. Falls der blaue Spieler eigentlich dran war, werden die Farben der Spieler getauscht.

  5. Nun kann der nächste Zug beim Spieler angefordert werden und dabei durch Debugging kontrolliert werden, wo sich der Spieler falsch verhalten hat. Achtung: Wenn weitere Züge angefordert werden, kann das Verhalten vom normalen Spielverlauf abweichen, da evtl. nicht alle Daten für das Spiel in der XML vorhanden sind.

Replay mit Server ohne graphische Oberfläche speichern

Wenn der Server ohne die graphische Oberfläche gestartet wird, kann das --saveReplay Attribut gesetzt werden, damit bei Ende jedes Spiels das Replay des Spiels unter ./replays gespeichert wird.

  java -Dfile.encoding=UTF-8 -Dlogback.configurationFile=logback.xml -jar softwarechallenge-server.jar --port 13051 --saveReplay true

Automatische Spiele: Der Testserver

Wenn Sie automatisiert Spiele mit Ihrem Computerspieler spielen wollen, um bestimmte Verhaltensweisen bei der Weiterentwicklung regelmäßig zu testen, können Sie dafür einen speziellen Server ohne grafische Oberfläche verwenden, den sogenannten Testserver. Hier ist zu beachten, dass der Testserver auf dem Port 13051 gestartet wird und nicht, wie im normalen Spiel auf Port 13050.

Gehen Sie dazu wie folgt vor:

  1. Laden Sie den Testserver von der Download-Seite herunter.

  2. Entpacken Sie das heruntergeladene Archiv.

  3. Wechseln Sie in einer Kommandozeilenumgebung (Windows: cmd.exe oder Powershell, Linux: beliebige Shell oder Terminal) in das Verzeichnis des entpackten Archives.

  4. Starten Sie den Testserver auf dem Port 13051 mit folgendem Befehl:

      java -Dfile.encoding=UTF-8 -Dlogback.configurationFile=logback.xml -jar softwarechallenge-server.jar --port 13051
  5. Starten Sie Ihren Computerspieler und einen zweiten Computerspieler manuell auf dem Port 13051 (im SimpleClient geht dies mit der Option --port 13051) in weiteren Kommandozeilenumgebungen. Die Computerspieler verbinden sich automatisch zum Testserver und es wird ein Spiel gespielt. Danach sollten sich die Computerspieler automatisch beenden.

  6. Wenn Sie weitere Testspiele starten wollen, können Sie die Computerspieler erneut starten. Der Testserver muss nicht neu gestartet werden.

Beachten Sie, dass der Testserver keine Spielaufzeichnungen anlegt, wie es der Server mit grafischer Oberfläche tut. Die Auswertung der Spiele muss in einem der teilnehmenden Computerspieler geschehen (z.B. durch Log-Ausgaben).

Es ist ebenfalls möglich, statt eines Zufällig generierten vollständigen Spielplanes eine Spielsituation zu laden und zu testen. Die Spielsituation muss vorher wie unter Spielsituation nachstellen erzeugt werden. Dann kann die Datei mit dem Argument --loadGameFile geladen werden und optional mit --turn ein Zug spezifiziert werden.

  java -Dfile.encoding=UTF-8 -Dlogback.configurationFile=logback.xml -jar softwarechallenge-server.jar --port 13051 --loadGameFile ./replay.xml --turn 10

Unerwartete Zugzeitüberschreitungen (Soft-Timeout)

Wenn Sie den Testserver einige Zeit laufen lassen, um eine größere Anzahl von Testspielen durchzuführen, kann es dazu kommen, dass Computerspieler wegen Zugzeitüberschreitungen vom Server disqualifiziert werden (Soft-Timeout). Dies passiert, obwohl sie ihren Zug innerhalb der erlaubten Zugzeit (abhängig vom Spiel, bisher aber immer zwei Sekunden) an den Server geschickt haben. Der Garbage Collector der Java Virtual Machine löst dieses Verhalten aus. Er pausiert die Anwendung, um nicht mehr genutzten Speicher freizugeben. Wenn der Server dadurch zu einem ungünstigen Zeitpunkt angehalten wird, bemerkt er den Eingang des Zuges vom Computerspieler nicht rechtzeitig und disqualifiziert ihn daraufhin. Damit dieses Problem möglichst selten auftritt, haben sich die folgenden Parameter beim Starten des Servers bewährt:

Unter Linux:

java -Dfile.encoding=UTF-8 \
     -Dlogback.configurationFile=logback.xml \
     -server \
     -XX:MaxGCPauseMillis=100 \
     -XX:GCPauseIntervalMillis=2050 \
     -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled \
     -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \
     -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark \
     -jar softwarechallenge-server.jar --port 13051

Unter Windows (unterscheidet sich nur durch die Art, den langen Befehl auf mehrere Zeilen zu verteilen):

java -Dfile.encoding=UTF-8 ^
     -Dlogback.configurationFile=logback.xml ^
     -server ^
     -XX:MaxGCPauseMillis=100 ^
     -XX:GCPauseIntervalMillis=2050 ^
     -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled ^
     -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 ^
     -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark ^
     -jar softwarechallenge-server.jar --port 13051

Um das Verhalten des Garbage Collectors noch weiter zu verbessern, kann man auch noch mittels der Optionen

-XX:+PrintGCDateStamps -XX:+PrintGC -XX:+PrintGCDetails -Xloggc:"pfad_zum_gc.log"

eine Logdatei über die Aktivitäten des Garbage Collectors anlegen. Darin sieht man genau, wann er wie lange lief. Man kann dann die Einstellungen verändern und testen, ob sich das Verhalten verbessert.

Die Konfiguration des Garbage Collectors ist kein Allheilmittel und kann zu neuen Problemen führen, auf die man gefasst sein sollte. Dazu gehören erhöhter Resourcenverbrauch und Instabilität der Anwendung.

Massentests mit Server ohne graphische Oberfläche

Massentests mit dem eigenen Computerspieler können sehr nützlich sein, beispeilsweise um die Stärke gegenüber einer früheren Version zu Testen. Dabei gibt es zwei Varianten:

Variante mit TestClient

Der TestClient muss vom Terminal mit den entsprechenden Argumenten aufgerufen werden. Diese werden unter den Beispielen näher erläutert.

Unter Linux:

java -jar -Dlogback.configurationFile=logback-tests.xml test-client.jar \
    --tests 4 \
    --name1 "displayName1" \
    --player1 "./player1.jar" \
    --name2 "displayName2" \
    --player2 "./player2.jar" \
    --start-server \
    --port 13051

Unter Windows (unterscheidet sich nur durch die Art, den langen Befehl auf mehrere Zeilen zu verteilen):

java -jar -Dlogback.configurationFile=logback-tests.xml test-client.jar ^
    --tests 4 ^
    --name1 "displayName1" ^
    --player1 "./player1.jar" ^
    --name2 "displayName2" ^
    --player2 "./player2.jar" ^
    --start-server ^
    --port 13051
Der TestClient kann sich auch mit einem bereits laufenden Server verbinden, wie bei der Variante ohne TestClient, bei Angabe des Arguments --start-server startet er jedoch einfach selbst einen. Wichtig ist, dass nicht versucht wird, zwei Server auf dem selben Port zu starten.
Argumente des TestClients
Attribut Standardwert (Typ) Beschreibung

--tests

100 (int)

Anzahl der Tests, die gespielt werden sollen

--player1

"./defaultplayer.jar" (Dateipfad)

Erster Computerspieler

--player2

"./defaultplayer.jar" (Dateipfad)

Zweiter Computerspieler

--name1

"player1" (String)

Name des ersten Spielers

--name2

"player2" (String)

Name des zweiten Spielers

--no-timeout

false (bool)

Deaktiviere ausscheiden durch Timeouts. Kann durch --no-timeout1 bzw. --no-timeout2 für beide Spieler unabhängig gesetzt werden.

--start-server

false (bool)

Starte einen Server auf dem angegebenen Port vor dem Starten der Clients.

--server

'server.jar aus dem Classpath' (Dateipfad)

Gib einen bestimmten server an, der für die tests gestartet werden soll.

--port

13051 (int)

Der Port, auf dem der Server läuft.

--host

localhost (IP)

Die Adresse, auf dem der Server läuft.

--loglevel

INFO - ensprechend der logback-tests.xml (Level)

Setzt das Loglevel, um ausführliche oder besonders kompakte Ausgaben zu erhalten.

Boolesche Parameter werden als true gewertet, sobald sie angegeben werden. Ein Wert hinter dem Parameter hat keine Wirkung.

Bei Argumenten, die nicht angegeben wurden, werden die Standardwerte aus der Tabelle verwendet. Die Ausgabe der Daten erfolgt nach jedem Spiel anhand von gerundeten Werten. Der TestClient beendet sich selbst, nachdem alle Spiele gespielt wurden.

Die Ergebnisse der Spiele werden für den jeweiligen Spielernamen vom Server zusammengezählt, auch über mehrere Starts des TestClients. Die Ergebnisse werden erst zurückgesetzt, wenn der Server neu gestartet wird. Achte also nach einer Veränderung der Spieler darauf, den Server neuzustarten oder andere Spielernamen zu verwenden.

Variante ohne TestClient

Starte den Server aus dem Terminal:

java -Dfile.encoding=UTF-8 -Dlogback.configurationFile=logback.xml -jar softwarechallenge-server.jar --port 13051

Starte ein Spiel mit Reservierungscode (siehe Spielverlauf in der XML-Dokumentation). Aktiviere mit dem erstellten Administratorclient den Testmodus:

<testMode testModus="true"/>

Darauf antwortet der Server:

<testing testModus="true"/>

Mit false als entsprechenden Parameter kann dieser wieder deaktiviert werden. Nun können jederzeit die Testdaten der Spieler anhand ihres Anzeigenamens erfragt werden:

<scoreForPlayer displayName="player1" />

Der Server antwortet mit:

<playerScore>
  <score displayName="player1" numberOfTests="4">
    <values>
      <fragment name="Gewinner">
        <aggregation>SUM</aggregation>
        <relevantForRanking>true</relevantForRanking>
      </fragment>
      <value>4</value>
    </values>
    <values>
      <fragment name="∅ Feldnummer">
        <aggregation>AVERAGE</aggregation>
        <relevantForRanking>true</relevantForRanking>
      </fragment>
      <value>5.0000013</value>
    </values>
    <values>
      <fragment name="∅ Karotten">
        <aggregation>AVERAGE</aggregation>
        <relevantForRanking>true</relevantForRanking>
      </fragment>
      <value>40.500011</value>
    </values>
  </score>
</playerScore>

Bei dieser Variante muss sich selbst um das Starten der Clients gekümmert werden.