Tag Archives: SettlersOfCatan

Software Engineering I, SS13

Liebe SE 1 Teilnehmer,

es ist geschafft. Seit letzter Woche ist nun die Veranstaltung offiziell beendet, doch wie jedes Jahr wollen wir alle natürlich sehen, was nach 16 Wochen Entwicklungszeit bei unserem Projekt herausgekommen ist. Der Termin für unser Abschlussturnier steht fest:

SE 1 Abschlussturnier am Freitag den 13.09.2013, 13 Uhr, Labor des Fachgebiets Software Engineering

Sofern wir wie jedes Jahr einen Sponsor finden, wird es ein paar Getränke sowie einen kleinen Hauptpreis für die Sieger geben.

Bis dann,
Andreas

Software Engineering I, SS13

Da das erfolgreiche Ausspielen einer Fortschrittskarte nicht ganz trivial ist, wird in diesem Beitrag exemplarisch das Ausspielen der Fortschrittskarte “Handelshafen” vorgestellt. Das erste Szenario veranschaulicht den erfolgreichen Austausch zweier Rohstoffkarten durch 2 Handelswaren. Das zweite Szenario beschreibt einen möglichen Fehlerfall.

Hinweis: Natürlich gibt es noch eine ganze Reihe anderer Fehlerfälle, die sich jedoch analog zu dem unten dargestellten verhalten.

Szenario: Zenobios spielt die Fortschrittskarte “Handelshafen” aus und tauscht 2 Getreide gegen 2 Handelswaren.

Startsituation:

Zenobios, Bob und Charly spielen Siedler von Catan. Die momentanen Karten der jeweiligen Spieler sind:

  • Zenobios: Fortschrittskarte “Handelshafen” (Commercial Harbor), 2 Getreide
  • Bob: 1 Münze, 1 Tuch
  • Charly: 2 Holz, 1 Papier

Aktion:

Zenobios spielt seine Fortschrittskarte “Handelshafen” aus. Dazu schickt er folgenden Befehl an den Server:

{"@action":"PLAY","properties":{"entry":{"key":"id","value":"ProgressCard@473d86b3"}}}

Der Server antwortet (sofern keine Fehler auftreten) mit:

{"@ts":"1374831612034","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - offer(card,user)"}

In der Nachricht fordert der Server den Spieler nun auf, einen OFFER Befehl zu schicken, der einem anderen Spieler eine Rohstoffkarte anbietet. Zenobios schickt folgenden Befehl an den Server, um Charly ein Getreide anzubieten und bekommt vom Server (sofern keine Fehler auftreten) eine OK Meldung:

  1. {"@action":"OFFER","properties":{"entry":[{"key":"user","value":"UserAssets@551a1599"},{"key":"id","value":"Card@4051eda3"}]}}
  2. {"@ts":"1374831958351","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - offer(card,user)"}

Charly bekommt vom Server nun die Nachrichten, dass ihm Zenobios eine Rohstoffkarte vom Typ Getreide (GRAIN) angeboten hat sowie die Aufforderung, eine Handelsware auszuwählen:

  1. {"@ts":"1374831799175","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - User zenobios offered you a card of type GRAIN. Choose one of your commodity cards for exchange."}
  2. {“@ts”:”1374831799176″,”@src”:”SERVER”,”@prop”:”USER_MESSAGE”,”@nv”:”OK – choose(commodityCard)”}

Charly wählt als Handelsware Papier aus und schickt daher folgende Nachricht an den Server, die mit einem OK bestätigt wird (sofern keine Fehler auftreten):

  1. {"@action":"CHOOSE","properties":{"entry":{"key":"id","value":"Card@71f20640"}}}
  2. {"@ts":"1374833919934","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - CHOOSE"}

Analog verhält sich der Kartenaustausch mit Bob. Nachdem der Kartentausch mit Bob abgeschlossen ist, schickt der Server dem Spieler Zenobios die folgende Nachricht:

{"@ts":"1374832550656","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - yourTurn"}

Endsituation:

Die momentanen Karten der jeweiligen Spieler sind:

  • Zenobios: 1 Münze, 1 Papier
  • Bob: 1 Getreide, 1 Tuch
  • Charly: 2 Holz, 1 Getreide

Zenobios kann seinen Zug nun normal fortsetzen.

Szenario: Zenobios spielt die Fortschrittskarte “Handelshafen” aus. Kein anderer Spieler besitzt Handelswaren.

Startsituation:

Zenobios, Bob und Charly spielen Siedler von Catan. Die momentanen Karten der jeweiligen Spieler sind:

  • Zenobios: Fortschrittskarte “Handelshafen” (Commercial Harbor), 3 Getreide
  • Bob: 3 Getreide
  • Charly: Keine Karten

Aktion:

Zenobios spielt seine Fortschrittskarte “Handelshafen” aus. Dazu schickt er folgenden Befehl an den Server:

{"@action":"PLAY","properties":{"entry":{"key":"id","value":"ProgressCard@435a0940"}}}

Da kein anderer Spieler eine Handelsware besitzt, antwortet der Server mit:

  1. {"@ts":"1374832550637","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"ERROR: PLAY - Sorry, but there is no player who has a commodity card."}
  2. {"@ts":"1374832550656","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - yourTurn"}

Endsituation:

Die momentanen Karten der jeweiligen Spieler sind:

  • Zenobios: 3 Getreide
  • Bob: 3 Getreide
  • Charly: Keine Karten
Software Engineering I, SS13

Liebe SE 1 Teilnehmer,

seit kurzem ist Version 1.2.1 des SE 1 Servers online. Alle zum Spiel gehörenden Features wurden nun freigeschaltet und können von euch getestet werden. Dies betrifft im Besonderen die Fortschrittskarten. Damit ihr besser testen könnt, wird dem Spieler der einem testgame Spiel beitritt, jeweils eine Karte von jedem Typ  ausgeteilt.

Viel Spaß,
Andreas

Software Engineering I, SS13

Zur Zeit werden auf dem Server folgende Validierungen für Maps durchgeführt:

  • Mindestens 18 Land-Felder
  • Felder müssen jeweils über die korrekten Himmelsrichtungen miteinander verbunden sein.
    • Bsp: Wenn Feld 1 über S mit Feld 2 verbunden ist, muss Feld 2 über N mit Feld 1 verbunden sein
  • Die Felder BARBARIAN_START und BARBARIAN_END müssen vorhanden und korrekt über eine N->S-Verbindung miteinander verbunden sein
  • Es muss mindestens eine Wüste geben
  • Eine Wüste darf nicht direkt neben Wasser oder einem Hafen liegen
  • Die Resourcenfelder müssen gleichmäßig verteilt sein, d.h. zwischen der am seltensten vorkommenden Resource und der am häufigsten vorkommenden Resource darf maximal ein Unterschied von 1 herrschen
  • Häfen dürfen nicht direkt nebeneinander liegen
  • Jedes Wasser-Feld (dazu gehören auch Häfen) muss mit mindestens einem Land-Feld verbunden sein
  • Es darf kein Land-Feld am Rand des Spielfeldes sein, d.h. das Spielfeld muss komplett von Wasser umschlossen sein
  • Es darf keine Inseln geben, d.h. alle Land-Felder müssen miteinander verbunden sein

Diese Liste ist nicht zwangsläufig vollständig. Es können im Laufe der Zeit noch zusätzliche Validierungen ergänzt werden.

Software Engineering I, SS13

Eine dem vorgegebenen Format entsprechende Karte, ist unter Balanced zu finden. Die dazu passende Karte findet ihr auch hier auf Seite 2.

HINWEIS: Um sicherzustellen, dass eure selbst erstellten Karten auch mit unserem Server kompatibel sind, solltet ihr euch genau an das vorgegebene Format halten.

Die einzelnen Fragmente haben folgende Bedeutung:

### 
### BALANCED
###

Hier wird der Name der Karte spezifiziert.

# VERSION
VERSION: 1

Hier wird die Version der Karte bestimmt.

# OWNER
OWNER: SE

Hier ist der Besitzer der Karte zu finden (Team).

 

Um die einzelnen Felder des Spielfeldes zu spezifizieren, müssen sie zeilenweise nach folgendem Muster aufgeführt werden:

# {id};{type};{rotation};({direction},{id};)+

Mit folgendem Beispiel werden die einzelnen Bestandteile erklärt:

1;WATER;0;SE,3;S,5;SW,2;
  • 1 ist die {id} des Feldes. Jedes Feld muss eine eigene ID besitzen. Ob diese aus einer oder mehrerer Zahlen oder Buchstaben besteht ist hierbei freigestellt. Sonderzeichen sind nicht erlaubt. Im Anschluss an die {id} muss ein ; folgen.
  • WATER ist der Typ des Feldes. Im Anschluss an den {type} muss ein ; folgen. Folgende Typen sind zulässig:
    • PASTURE
    • HILL
    • MOUNTAIN
    • FIELD
    • FOREST
    • DESERT
    • WATER
    • PORT_3TO1
    • PORT_LUMBER
    • PORT_ORE
    • PORT_BRICK
    • PORT_WOOL
    • PORT_GRAIN
    • BARBARIAN_START
    • BARBARIAN_END
  •  0 ist die Drehung des Feldes. Dieser Wert ist ausschließlich bei den verschiedenen Häfen und bei den Feldern des Barbaren relevant. Bei allen übrigen sollte dieser Wert auf 0 gesetzt werden.
  • S,5;SW,2; beschreibt die Nachbarn dieses Feldes. Dazu werden komma-separierte Paare von Himmelsrichtung und {id} des dort anliegenden Feldes mittels ; voneinander getrennt.
    • Erlaubte Himmelsrichtungen: N, NW, SW, S, SE, NR
    • Felder müssen immer gegenseitig aufeinander Verweisen um eine valide Karte zu ergeben, d.h. in der Definition für das Feld mit der {id} 5, muss bei den Nachbarn N,1 aufgeführt werden.
Software Engineering I, SS13

Der Server spricht generell ein zeilenbasiertes String Protokoll. Daher kann man eine telnet Verbindung benutzen um das Protokoll zu erkunden. Nach dem öffnen einer Konsole und der Eingabe von

 telnet se1.cs.uni-kassel.de 5000

kann man mit HELP eine Liste aller verfügbaren Befehle abrufen.

Allgemeine Informationen

  • Um sich beim Server anzumelden, benötigt man zunächst einen eigenen Login. Dieser ist identisch mit eurem Jira-Login.
  • Jedes erfolgreiche Kommando wird vom Server mit einem OK beendet. Fehler werden mit einer Zeile beantwortet die mit ERROR beginnt.
  • Der Server kommuniziert durch zwei verschiedene Protokollarten:
    • “Klartextprotokoll”: Bei einloggen und in der Lobby verwendet der Server ein simples “Klartextprotokoll” um mit seinen Clients zu kommunizieren.
    • JSON-Protokoll: Nach einem erfolgreichen JOIN GAME Kommando das mit OK bestätigt wurde wechselt der Server in ein JSON basiertes Protokoll, bei dem er JSON codierte Events verschickt und JSON codierte Commands erwartet.
  • Um einen Timeout zu vermeiden sollte vom Client in regelmäßigen Abständen ein NOOP geschickt werden.

Klartextprotokoll

Sobald man eine Verbindung zum Server aufgebaut hat, kommuniziert dieser mit einem simplen Klartextprotokoll mit dem Client. Nicht alle Befehle sind überall verfügbar. Eine genaue Auflistung inkl. Gruppierung der Befehle liefert der HELP Befehl. Hier eine Übersicht über die verschiedenen Befehle:

  • Immer:
    • HELP <command>
  • Nach der Begrüßung vom Server:
    • LOGIN (<login>|<email>) <password>
    • LOGOUT
  • Nach dem Anmelden:
    • LIST MAPS
    • LIST USERS
    • LIST GAMES
    • CREATE GAME <gamename> -maxPlayers <count> (-map <mapname>)? (-testgame)?
    • JOIN GAME <gamename> (-visitor [true|false])?
    • MSG (ALL | ( ( USER | TEAM ) <recipient> ) )? <message>
    • UPLOAD MAP
    • DOWNLOAD MAP <mapname>
    • CREATE TESTPLAYER
      Beispiel:

      SE1 SettlersOfCatan-Server 1.0, Timeout set to 3600000ms
      login zenobios ******
      USER NICK=zenobios EMAIL=andreas.scharf@cs.uni-kassel.de ROLE=SE
      TEAM NAME=SE ID=3fb6101e
      OK
      help
      Available commands after greeting: LOGIN, LOGOUT
      User commands: ID, LIST USERS
      Game management: LIST MAPS, CREATE GAME, LIST GAMES, JOIN GAME, UPLOAD MAP, DOWNLOAD MAP
      Team management: LIST TEAMS
      Other commands: CREATE TESTPLAYER, MSG, CHANGELOG, UPLOAD MAP, NOOP, HELP
      send 'HELP <command>' for details
      a successfull command will be acknowledged with an 'OK' line
      an unsuccessfull command will be acknowledged with an 'ERROR' line
      OK
      help create testplayer
      Creates a temporary user e.g. for testing purposes. This user exists at least for 24h hours or until the next server restart
      Usage: "CREATE TESTPLAYER"
      OK
      create testplayer
      TEMPORARY USER NICK=tempUser0 PASSWORD=ys8ufm
      OK

JSON Protokoll

Das Ingame JSON Protokoll kennt in Serverrichtung Commands und in Clientrichtung Events.

Commands

Die Commands müssen mindestens ein action Attribut enthalten welches folgende Werte annehmen kann (keys in Klammern sind optional):

Action Keys Beispiel Bemerkung
ACTIVATE_KNIGHT id {"@action":"ACTIVATE_KNIGHT","properties":{"entry":{"key":"id","value":"Knight@a4d93e3"}}} Mit diesem Command wird der übergebene Ritter aktiviert.
BUILD type, destination {"@action":"BUILD","properties":{"entry":[{"key":"type","value":"Settlement"},{"key":"destination","value":"Intersection@a4d93e3"}]}} Mit diesem Command wird das gewünsche Modelelement (type) and der entsprechenden Position (destination) gebaut.Mögliche Belegungen für type:

  • Settlement, City, Road, Knight, CityWall

Für die Destination muss jeweils die gewünschte Intersection oder Border übergeben werden.

CHANGE_USER_COLOR color {"@action":"CHANGE_USER_COLOR","properties":{"entry":{"key":"color","value":"FFFF00"}}} Ändert die Userfarbe.
CHOOSE id {"@action":"CHOOSE","properties":{"entry":{"key":"id","value":"UserAssets@a4d93e3"}}} Mit diesem Command wird ein Modelelement ausgewählt. Je nach Kontext kann es sich dabei um ein Feld, ein Spieler oder etwas anderes handeln. Dieser Command sollte immer dann geschickt werden, wenn ihr vom Server mit einem ‘choose(Type:{Values})’ dazu aufgefordert werdet.Mit Type wird die Art von Modelelement bestimmt, welches der Server als Antwort erwartet.Mit Values werden alle zur Zeit möglichen Werte mitgegeben. Zu beachten ist, dass Values nicht immer mitgeliefert wird.
Beispiel 1: Bei einem choose(Field) müsst ihr ein Feld auswählen und dieses mit einem CHOOSE command zurückschicken
Beispiel 2: Bei einem choose(UserAssets:UserAssets@a4d93e3,UserAssets@bc43c12) müsst ihr einen Spieler auswählen und dessen UserAssets mit einem CHOOSE command zurückschicken. Alle möglichen Spieler wurden hier bereits mitgeschickt.
END_PLAY type {"@action":"END_PLAY"} Beendet das Ausspielen der aktuellen Karte. Das ist nicht in jedem Zustand beim Karte ausspielen möglich.
END_TURN keiner {"@action":"END_TURN"} Beendet den aktuellen Zug.
LEAVE_GAME keiner {"@action":"LEAVE_GAME"} Verlässt das aktuelle Spiel.
MESSAGE message, (audience)?, (recipient)? {“@action”:”MESSAGE”,”@id”:”0″,”properties”:{“entry”:[{“key”:”message”,”value”:”Hallo”},{“key”:”audience”,”value”:”USER”},{“key”:”recipient”,”value”:”zenobios”}]}} Verschickt eine Nachricht an alle oder den angegebenen User/Team. Der Parameter audience erlaubt folgende Werte:ALL, USER, TEAM.Folgende Kombinationen von audience und recipient sind möglich:

  • audience: leer, recipient:leer -> Nachricht wird an alle User im Spiel geschickt
  • audience: leer, recipient:nicht leer -> Nachricht wird nicht verschickt
  • audience: ALL, recipient:leer -> Nachricht wird an alle User im Spiel geschickt
  • audience: ALL, recipient:nicht leer-> Nachricht wird nicht verschickt
  • audience: USER, recipient:leer -> Nachricht wird nicht verschickt
  • audience: USER, recipient:username -> Nachricht wird an user username verschickt
  • audience: TEAM, recipient:leer -> Nachricht wird an das eigene Team geschickt
  • audience: TEAM, recipient:teamname -> Nachricht wird an das Team teamname verschickt

Events, die durch diesen Command ausgelöst werden übergeben die Art der Message mit, um im Client eine Unterscheidung durchführen zu können. Mögliche Werte sind:ERROR, MESSAGE, PUBLIC_MESSAGE, USER_MESSAGE, TEAM_MESSAGE

NOOP keiner {"@action":"NOOP"} Command der in regelmäßigen Abständen abgeschickt werden kann, um die Verbindung aufrecht zu erhalten.
OFFER type {"@action":"OFFER","properties":{"entry":[{"key":"id","value":"Card@c5db3a2"},{"key":"user","value":"UserAssets@a4d93e3"}]}} Bietet einem Spieler (user) eine Karte (id) an. Das ist bei bei der Fortschrittskarte “COMMERCIAL_HARBOR” nötig.
PLAY type {"@action":"PLAY","properties":{"entry":{"key":"id","value":"ProgressCard@a4d93e3"}}} Spielt die Fortschrittskarte (id) aus.
ROLL_DIES keiner {"@action":"ROLL_DIES"} Führt einen Würfelwurf aus. Dieser Command sollte immer dann geschickt werden, wenn ihr vom Server mit einem ‘rollDies’ dazu aufgefordert werdet.
START_GAME keiner {"@action":"START_GAME"} Startet das Spiel, wenn genügend Spieler angemeldet sind.
TRADE give, take {"@action":"TRADE","properties":{"entry":[{"key":"give","value":"BRICK"},{"key":"take","value":"GRAIN"}]}} Mit diesem Command kann man mit der Bank handeln. Dazu wird mit (give) der Resourcentyp übergeben, den man eintauschen und mit (take) den Typ, den man erhalten möchte.
Mögliche Belegungen für give und take: BRICK, CLOTH, COIN, GRAIN, LUMBER, ORE, PAPER, WOOL
UPGRADE_KNIGHT id {"@action":"UPGRADE_KNIGHT","properties":{"entry":{"key":"id","value":"Knight@a4d93e3"}}} Mit diesem Command wird der übergebene Ritter aufgewertet.
UPGRADE_PROGRESS type {"@action":"UPGRADE_PROGRESS","properties":{"entry":{"key":"type","value":"POLITICS"}}} Mit diesem Command wird der gewünschte Stadtausbau durchgeführt.
Mögliche Belegungen für type: POLITICS, SCIENCE, TRADE
USE_KNIGHT type {"@action":"USE_KNIGHT","properties":{"entry":[{"key":"id","value":"Knight@c5db3a2"},{"key":"target","value":"Intersection@a4d93e3"}]}} Mit diesem Command kann mit dem mit id übergebenen Knight verschiedene Aktionen ausgeführt werden. Die Belegung von target entscheidet, was passiert. Folgendes ist möglich:
Wird der Robber übergeben, so wird dieser von seinem Feld vertrieben, wenn die Spielsituation regelkonform ist.
Wird eine Intersection übergeben, wird der Knight dorthin bewegt, wenn die Spielsituation regelkonform ist.

Events

Der Server schickt Events in der Form

{"@ts":"1336475335153","@src":"User@a4d93e3","@prop":"nickname","@nv":"akoch"}

In diesem Fall wurde zum Timestamp 1336475335153 von der source User@a4d93e3 die property nickname auf akoch (new value) geändert.
Wer sich die Events vom Server genauer anschaut wird feststellen, dass Werte die null sind in JSON wegoptimiert werden. In diesem Beispiel fehlt z.B. die Property @ov.

Nicht alle Events stehen für Modelländerungen. Während eines Spiel sendet der Server euch auch Events, auf die ihr reagieren müsst. So gibt es OK und ERROR Events, die euch zusätzliche Informationen geben oder euch auffordern mit dem Server zu interagieren.

OK Events, die eine Reaktion von euch erfordern sind wie folgt aufgebaut: {“@ts”:”1372946132672″,”@src”:”SERVER”,”@prop”:”USER_MESSAGE”,”@nv”:”OK – {type} – {message}”}. Es gibt zudem auch OK Events, die rein informellen Charakter haben und erfolgreich ausgeführte Commands bestätigen

ERROR Events sind immer wie folgt aufgebaut: {“@ts”:”1372946132685″,”@src”:”SERVER”,”@prop”:”USER_MESSAGE”,”@nv”:”ERROR: {type} – {message}”}

Auf welchen {type} ihr wie reagieren müsst, findet ihr oben in der Tabelle. Der Parameter {message} wird nicht immer mitgesendet.

Empfangt ihr beispielsweise ein Event wie

{"@ts":"1372946132672","@src":"SERVER","@prop":"USER_MESSAGE","@nv":"OK - rollDies"}

erwartet der Server ein ROLL_DIES command von euch

Tipp: Das nötige Datenmodell lässt sich größtenteils aus dem Eventstream ableiten.