联系方式

  • QQ:99515681
  • 邮箱:99515681@qq.com
  • 工作时间:8:00-21:00
  • 微信:codinghelp

您当前位置:首页 >> Java编程Java编程

日期:2024-06-23 08:54

Ludwig-Maximilians-Universität München München, 03.06.2024

Institut für Informatik

Softwareentwicklungspraktikum

SoSe 2024 – Robo Rally

Protokoll Version 1.0

Übersicht

• (Neu) Support für folgende Spielfelder: Extra Crispy, Lost Bearings, Death Trap

• (Neu) Fehlerbehandlung von Verbindungsverlust

• (Neu) Support für Schadenskarten

• (Offen) Kein Support für Upgradekarten

1 Grundlagen

Die Daten werden über TCP als JSON-Objekte übertragen. Als Zeichensatz wird hierfür UTF-8

verwendet, wobei unterschiedliche Nachrichtentypen durch sogenannte Wrapper-Objekte modelliert

sind.

Ein Objekt darf dabei stets nur eine Nachricht enthalten und sieht folgendermaßen aus:

{

"messageType": "Sample",

"messageBody": {

"keyOne": "valueOne",

"keyTwo": "keyTwo"

}

}

Statt eines primitiven "value" können hier jedoch auch komplexere JSON-Objekte auftreten. So

kann ein "messageBody" z.B. mehrere Objekte und / oder Listen enthalten. Auch Kombinationen

aus primitiven Typen und Objekten sind denkbar.

12 Verbindungsaufbau

Verbindung erfolgreich

Nach dem Aufbau der TCP-Verbindung sendet der Server seine Protokollversion an den Client.

{

"messageType": "HelloClient",

"messageBody": {

"protocol": "Version 1.0"

}

}

Verbindungsverlust

Es kann jederzeit vorkommen, dass ein Client die Verbindung verliert.

Um dies regelmäßig zu kontrollieren, sendet der Server folgende Nachricht regelmäßig alle 5

Sekunden. Diese Nachricht wird mit derselben Nachricht vom Client quittiert.

{

"messageType": "Alive",

"messageBody": {}

}

Gruppenidentiffkation

Anschließend antwortet der Client mit Informationen zu seiner benutzten Protokollversion, dem

Gruppennamen und ob es sich um den Login einer KI handelt.

Die Client ID ist hier optional zu senden. Näheres dazu im Abschnitt "Verbindungsverlust".

{

"messageType": "HelloServer",

"messageBody": {

"group": "TolleTrolle",

"isAI": false,

"protocol": "Version 1.0",

"clientID": 42

}

}

Sollte der Server die Protokollversion der Gruppe nicht unterstützen, so ist die Verbindung abzubrechen.

Genaueres hierzu im Teil: Besondere Nachrichten

Übergabe der Client ID

Ist alles in Ordnung, erhält der Client vom Server eine Nummer zugewiesen.

Diese sollte im positiven Bereich liegen und muss natürlich einzigartig sein.

2{

"messageType": "Welcome",

"messageBody": {

"clientID": 42

}

}

3 Lobby

Setzen des Spielernamens und der Figur

Nach dem erfolgreichen Verbindungsaufbau kann ein Spieler seinen Namen und seine Spielffgur

auswählen. Die Spielffgur soll dabei einzigartig sein, der Spielernamen darf mehrfach vergeben

werden.

{

"messageType": "PlayerValues",

"messageBody": {

"name": "Nr. 5",

"figure": 5

}

}

Bestätigung der Spielerauswahl

Eine bereits vergebene Figur soll, wie im Bereich Besondere Nachrichten beschrieben, quittiert

werden. Valide Wünsche werden für alle verbundenen Clients sichtbar bestätigt.

{

"messageType": "PlayerAdded",

"messageBody": {

"clientID": 42,

"name": "Nr. 5",

"figure": 5

}

}

Bedenken Sie, dass neu hinzukommende Clients auch nachträglich über bereits vorhandene

Spieler informiert werden müssen.

Bereitschaft signalisieren

Sobald ein Spieler seine Auswahl erfolgreich getroffen hat, kann er dem Server signalisieren

bereit zu sein. Diese Meinung kann er via Boolean aber auch zurückziehen!

3{

"messageType": "SetStatus",

"messageBody": {

"ready": true

}

}

Bereitschaft bestätigen oder widerrufen

Von Seiten des Servers wird der Spielerstatus an alle verbundenen Clients verteilt.

{

"messageType": "PlayerStatus",

"messageBody": {

"clientID": 42,

"ready": true

}

}

Auch diesen Status müssen neu verbindende Clients empfangen.

Map auswählen

Der erste Spieler, der Bereitschaft signalisiert, darf die Map auswählen, auf der gespielt wird.

Falls der erste Spieler die Bereitschaft widerruft oder das Spiel verlässt, ist der nächste Spieler

an der Reihe. Falls es nur KIs gibt, wählt der Server eine zufällige Map. Damit ein sofortiger

Spielstart bei zwei KIs vermieden wird, soll der Parameter "MinPlayer" beim Serverstart als

Flag übergeben werden können. Um eine Map auszuwählen, wird folgende Nachricht vom Server

verschickt:

{

"messageType": "SelectMap",

"messageBody": {

"availableMaps": ["Dizzy Highway"]

}

}

Daraufhin antwortet der Spieler mit folgender Nachricht (Beispiel):

{

"messageType": "MapSelected",

"messageBody": {

"map": "Dizzy Highway"

}

}

4Diese Nachricht wird vom Server auch an alle Spieler weitergeleitet, um die Auswahl des Startboards

zu erleichtern.

Sind alle Spieler bereit (mind. 2!), erstellt der Server die Karte und teilt diese den anderen mit.

Jedes Feldobjekt beinhaltet die einzelnen Feldtypen und deren Orientierung.

• Die Map wird als JSON-Dateien gespeichert und mit einem Parser weiterverarbeitet.

• Die Map wird als ListX

übertragen und ist wie ein Koordinatensystem

aufgebaut. x0,y0 ist links oben. x5,y0 liegt rechts vom ersten Feld.

• Felder können mehr als einen Typus haben. Daher die dritte verschachtelte Liste, um

Felder wie "eine Wand mit Laser" zu modellieren.

• Leere Felder (z.B. bei nicht rechteckigen Spielfeldern) werden mit null belegt.

• Valide Feldtypen sind: Empty, StartPoint, ConveyorBelt, PushPanel, Gear, Pit, EnergySpace,

Wall, Laser, Antenna, CheckPoint, RestartPoint

• Als Grundlage für die Orientierung dient die Aktion der Felder: Bei einem ConveyorBelt

die Zuffuss- bzw. Abffussrichtung, bei einem Push-Panel die Pushrichtung, usw. Felder,

die keine Effekte haben (z.B. Checkpoints) bekommen kein Attribut "orientations".

• "ConveyorBelt" hat mindestens zwei Orientierungen. Die erste gibt die "Abffussrichtung"

an, in die ein Bot geschoben wird, alle folgenden geben die "Zuffussrichtung" an. Damit

können sowohl normale als auch rotierende Conveyor Belts umgesetzt werden. Es gibt

folgende Orientierungen: "top", "bottom", "right", "left". Das Feld hat einen zusätzlichen

Wert für Speed (1 / 2 - Grün / Blau).

• Die Orientierung von "Gear" ist als Drehrichtung zu interpretieren. Hierbei ist sie z.B.

im Uhrzeigersinn als "clockwise" und gegen den Uhrzeigersinn als "counterclockwise"

anzugeben.

• Die "Antenna" Orientierung gibt die Senderichtung an.

• "EnergySpaces", "Laser" und "CheckPoint" haben einen zusätzlichen Wert "count" für die

vorhandene Energie und die Anzahl der Laser bzw. Nummer des Punktes.

• "PushPanel" inkludiert eine Liste der Register, in denen sie aktiv werden.

• "Wall" kann mehrere Orientierungen haben. Diese geben die Seiten an, die mit einer Wand

geblockt werden.

• Jedes Feld hat einen Wert "isOnBoard", der angibt, auf welchem Feld es liegt (Unterschied

beim Reboot). Die Boardbezeichnungen können Sie dem Regelwerk entnehmen.

5Beispiel für eine Map mit komplexen Feldern

x0;y0: Blauer Belt, dessen Abflussrichtung oben ist und der rechts und unten eine Zuflussrichtung

hat.

x0;y1: Panel, das nach links schiebt, wenn Register zwei oder vier aktiv sind.

x1;y0: Wall, die oben und rechts begrenzt und einen Doppel-Laser nach unten verschießt.

x1;y1: Leeres Feld

Jedes der beschriebenen Felder liegt nicht auf dem Startboard.

{

"messageType": "GameStarted",

"messageBody": {

"gameMap": [

[

[

{

"type": "ConveyorBelt",

"isOnBoard": "1B",

"speed": 2,

"orientations": [

"top",

"right",

"bottom"

]

}

],

[

{

"type": "PushPanel",

"isOnBoard": "1B",

"orientations": [

"left"

],

"registers": [

2, 4

]

}

]

],

[

[

{

"type": "Wall",

"isOnBoard": "4A",

"orientations": [

"top",

"right"

]

},

{

"type": "Laser",

"isOnBoard": "4A",

"orientations": [

"bottom"

],

"count": 2

}

],

[

6null

]

]

]

}

}

4 Chatnachrichten

Privat senden

Spieler sollen untereinander Nachrichten austauschen können. Diese werden vom Server verteilt.

Ein Client kann eine private Nachricht an Client ID 42 wie folgt veranlassen:

{

"messageType": "SendChat",

"messageBody": {

"message": "Yoh, Bob! How is your head doing after last night?",

"to": 42

}

}

Privat verteilen

Der Server steht in der Pflicht, diese Nachricht nur dem richtigen Spieler zu schicken.

{

"messageType": "ReceivedChat",

"messageBody": {

"message": "Yoh, Bob! How is your head doing after last night?",

"from": 42,

"isPrivate": true

}

}

Öffentlich senden

Im Falle einer Nachricht für alle Spieler wird "to" zu -1.

{

"messageType": "SendChat",

"messageBody": {

"message": "Hi all! I will crush your robots in no time.",

"to": -1

}

}

Öffentlich verteilen

Hier kann die Nachricht normal im Chatfenster ausgegeben werden.

7{

"messageType": "ReceivedChat",

"messageBody": {

"message": "Hi all! I will crush your robots in no time.",

"from": 42,

"isPrivate": false

}

}

5 Besondere Nachrichten

Fehlerhafte Nachrichten

Bei einer fehlerhaften Nachricht des Clients soll der Server den Client entsprechend informieren.

Der Client soll den Fehler registrieren und die Fehlernachricht ausgeben. Dies geschieht optional

mit einer detaillierten Beschreibung oder nur mit einem generellen Hinweis. Die Fehlernachricht

dient nur zur Information des Benutzers und soll im Code nicht zur Korrektur genutzt werden.

{

"messageType": "Error",

"messageBody": {

"error": "Whoops. That did not work. Try to adjust something."

}

}

Wenn ein Verbindungsverlust auftritt, soll das den anderen natürlich mitgeteilt werden. Wie Sie

mit dieser Situation dann umgehen, ist Ihnen überlassen. Auch eine erneute Verbindung kann

gestattet werden. Natürlich macht dies nur Sinn, wenn der Roboter vorher nicht entfernt wurde.

{

"messageType": "ConnectionUpdate",

"messageBody": {

"clientID": 9001,

"isConnected": false,

"action": "AIControl"

}

}

Mögliche Optionen sind also

• Remove: Entfernt den Roboter des Clients aus dem Spiel.

• AIControl: Eine KI übernimmt die Kontrolle.

• Ignore: Der Client wird ignoriert, verbleibt aber (regungslos) im Spiel. Sein Roboter kann

weiterhin Interaktionen auslösen, wird aber nicht mehr aktiv bewegt.

8• Reconnect: Der Client ist wieder online und verbunden. Dafür sollen die Nachrichten aus

dem Abschnitt "Verbindungsaufbau" mit einer zusätzlichen Client ID verwendet werden.

Es ist nicht nötig, jede dieser Optionen umzusetzen. Es ist ausreichend, die "Remove" Version

zu implementieren.

6 Spielkarten

Karten spielen

Basiskarten werden ganz rudimentär als String übertragen. Natürlich sollten diese Karten in

Ihrem Modell trotzdem in Objektform hinterlegt sein!

{

"messageType": "PlayCard",

"messageBody": {

"card": "MoveI"

}

}

Der Server gibt dies an die anderen Clients weiter.

{

"messageType": "CardPlayed",

"messageBody": {

"clientID": 2,

"card": "MoveI"

}

}

Programmierkarten

MoveI, MoveII, MoveIII, TurnLeft, TurnRight, UTurn, BackUp, PowerUp und Again.

Schadenskarten

Spam, Worm, Virus und Trojan.

Achtung: Die Beschreibung des Viruskarteneffekts im Regelwerk weicht vom Kartentext ab (s.

Regeln S. 15). Wir gehen folgendermaßen vor: Jeder Roboter innerhalb des 6-Feld-Radius bekommt

eine SPAM Karte.

Besondere Programmierkarten

EnergyRoutine, SandboxRoutine, WeaselRoutine, SpeedRoutine, SpamFolder und RepeatRoutine.

Upgradekarten

sind in dieser Version des Protokolls noch nicht inkludiert.

97 Spielzug abhandeln

Aktiven Spieler setzen

Der Server gibt eine kurze Nachricht aus, um den aktuell aktiven Spieler zu bestimmen. Entgegen

der offiziellen Anleitung beginnt derjenige, der zuerst die Verbindung aufgebaut hat.

{

"messageType": "CurrentPlayer",

"messageBody": {

"clientID": 7

}

}

(Druck-)fehler in der englischen Spieleanleitung (S. 4, Reihenfolge der Roboter):

• Falsch: Zoom Bot (grün), Smash Bot (gelb), Hulk x90 (rot)

• Richtig: Smash Bot (gelb), Zoom Bot (grün), Hulk x90 (rot)

Aktive Spielphase setzen

Die aktuelle Phase wird mittels einer eigenen ID übertragen. Hierbei gilt:

0 => Aufbauphase, 1 => Upgradephase, 2 => Programmierphase, 3 => Aktivierungsphase

{

"messageType": "ActivePhase",

"messageBody": {

"phase": 3

}

}

7.1 Aufbauphase

Startpunkt wählen

Spieler setzen ihren Startpunkt wie folgt:

{

"messageType": "SetStartingPoint",

"messageBody": {

"x": 4,

"y": 2

}

}

Bestätigen des Startpunktes

Wenn die gewünschte Position valide ist, werden alle Spieler darüber benachrichtigt.

10{

"messageType": "StartingPointTaken",

"messageBody": {

"x": 4,

"y": 2,

"clientID": 42

}

}

7.2 Upgradephase

Kommt in einer späteren Version des Protokolls. Diese Phase wird in dieser Version des Protokolls

nicht an den Client übermittelt sondern übersprungen. Nach der Aufbauphase wird direkt

zur Programmierphase übergegangen.

7.3 Programmierphase

Spieler zieht Karten

Es werden die obersten neun Programmierkarten gezogen. Die Nachricht vom Server sollte natürlich

nur von dem jeweils betroffenen Spieler empfangen werden können!

{

"messageType": "YourCards",

"messageBody": {

"cardsInHand": [

"card1",

"..."

]

}

}

Die anderen Spieler werden lediglich über die Anzahl der Karten benachrichtigt.

{

"messageType": "NotYourCards",

"messageBody": {

"clientID": 42,

"cardsInHand": 9

}

}

Programmierkarten mischen

Sind nicht mehr genug Karten auf dem Kartenstapel, muss der Ablegestapel gemischt werden.

11Dazu werden zuerst alle restlichen Karten vergeben, dann wird der Ablegestapel gemischt und

danach die verbleibende Kartenanzahl versandt.

{

"messageType": "ShuffleCoding",

"messageBody": {

"clientID": 42

}

}

Karten auswählen

Die Kartenauswahl wird vom Spieler zum Server übertragen, jede Karte einzeln. Überschreibungen

und ein Leeren des Registers sind möglich, indem "card = Null" gesetzt wird.

{

"messageType": "SelectedCard",

"messageBody": {

"card": "Again",

"register": 5

}

}

Kartenwahl bestätigen

Der Server gibt das belegte Register, natürlich ohne Karteninformation, an alle weiter. "Filled"

steht hierbei für die Information, ob eine Karte in ein Register gelegt oder entfernt wurde.

{

"messageType": "CardSelected",

"messageBody": {

"clientID": 42,

"register": 5,

"filled": true

}

}

Auswahl beendet

Sobald ein Spieler die fünfte Karte gelegt hat, sind keine Änderungen mehr möglich! Dies wird

für alle sichtbar übertragen.

{

"messageType": "SelectionFinished",

"messageBody": {

"clientID": 42

}

}

12Timer gestartet

Als Folge des ersten fertigen Spielers startet der 30 Sekunden Timer.

{

"messageType": "TimerStarted",

"messageBody": {}

}

Timer beendet

Zum Ende des Timers wird eine Meldung an die Clients geschickt. Diese beinhaltet auch die

Information über evtl. zu langsam reagierende Spieler.

{

"messageType": "TimerEnded",

"messageBody": {

"clientIDs": [

1,

3,

6

]

}

}

Hand abwerfen und blind ziehen

Diese Karten werden in der vorgegebenen Reihenfolge auf die noch offenen Register gelegt.

{

"messageType": "CardsYouGotNow",

"messageBody": {

"cards": [

"card1",

"..."

]

}

}

7.4 Aktivierungsphase

Aktive Programmierkarten

Jede der fünf Runden wird durch eine Nachricht mit den nun aktiven Karten eingeläutet. Es wird

jeweils nur die Karte aus dem aktuellen Register angezeigt. Bedenken Sie, dass die Prioritäten

nach jedem Register neu berechnet werden müssen. Beachten Sie außerdem, dass bestimmte

Karten auch während der Aktivierung des Registers ersetzt werden können, wie z.B. Spam Karten.

13{

"messageType": "CurrentCards",

"messageBody": {

"activeCards": [

{

"clientID": 1,

"card": "MoveI"

},

{

"clientID": 2,

"card": "Spam"

}

]

}

}

{

"messageType": "ReplaceCard",

"messageBody": {

"register": 3,

"newCard": "MoveI",

"clientID": 9001

}

}

8 Aktionen, Ereignisse und Effekte

Bewegung

Bewegungen einer Spielfigur werden vom Server übertragen, jedoch ohne den Auslöser zu nennen.

Wichtig: Es handelt sich rein um die Bewegung zwischen Feldern. Ohne Drehung!

{

"messageType": "Movement",

"messageBody": {

"clientID": 42,

"x": 4,

"y": 2

}

}

Drehung

Die Richtung wird hier mit "clockwise" (Uhrzeigersinn), bzw. "counterclockwise" (gegen den

Uhrzeigersinn) angegeben.

14{

"messageType": "PlayerTurning",

"messageBody": {

"clientID": 42,

"rotation": "counterclockwise"

}

}

Schadensmeldungen

Es werden immer alle auf einmal übertragen. Wenn ein Spieler also drei Schaden bekommt, wird

trotzdem nur eine Nachricht verschickt.

{

"messageType": "DrawDamage",

"messageBody": {

"clientID": 42,

"cards": [

"Spam",

"..."

]

}

}

Sollten alle Spamkarten vergeben sein, fragt der Server vorher nach der Auswahl des Spielers

und schickt nach der Wahl des Spielers die Schadensmeldung.

{

"messageType": "PickDamage",

"messageBody": {

"count": 2,

"availablePiles": ["Virus", "Trojan"]

}

}

{

"messageType": "SelectedDamage",

"messageBody": {

"cards": [

"Virus",

"Trojan"

]

}

}

"availablePiles" beinhaltet hierbei die Kartenstapel, auf denen sich noch Schadenskarten befinden.

Achten Sie auf Sonderfälle, wie z.B. folgenden: Sollte ein letzter Stapel nur noch eine Karte

15beinhalten, der Client allerdings zwei Karten ziehen müssen, reicht es aus, diese eine Karte zu

verteilen. Sollte der Fall eintreten, dass alle Schadenskarten aufgebraucht sind, können keine

neuen Karten mehr gezogen werden. Das gilt bis es wieder Schadenskarten im Stapel gibt.

Animationen

Für Animationen (wie BlueConveyorBelt, GreenConveyorBelt, PushPanel, Gear, CheckPoint,

PlayerShooting, WallShooting, EnergySpace) hilfreich, ansonsten überflüssig.

{

"messageType": "Animation",

"messageBody": {

"type": "PlayerShooting"

}

}

Neustart

Der Neustart wird sofort nach dem betreffenden Register durchgeführt. Roboter werden standardmäßig

immer nach Oben / Norden (top) ausgerichtet. Es werden zusätzlich die Koordinaten

des Rebootfeldes per "Movement"-Nachricht verschickt. Der Client, den der Neustart betrifft,

quittiert die Nachricht mit der Richtung, in die der Bot ausgerichtet werden soll (top, right,

bottom, left). Sollte die Nachricht zur Ausrichtung nicht bis zum Ende der aktuellen Runde

angekommen sein, wird die Standardausrichtung verwendet.

Startet ein Roboter auf dem Startfeld neu, während sich ein weiterer auf seinem Neustart-Feld

befindet, schiebt der neustartende Roboter den Roboter, der das Feld besetzt, in Richtung des

Pfeils auf dem Neustart-Feld weg. Sollte der Fall auftreten, dass ein Roboter zwischen Wand

und Startfeld steht, sodass dieser gegen die Wand geschoben würde, wenn ein Roboter auf dem

Startfeld rebooted, dann soll der Roboter auf einem anderen, freien Startfeld rebooten.

{

"messageType": "Reboot",

"messageBody": {

"clientID": 42

}

}

{

"messageType": "RebootDirection",

"messageBody": {

"direction": "right"

}

}

Energie

Anpassungen an Energiewerten werden mit der neuen Summe übertragen.

16Ein zusätzlicher Wert liefert die Info, woher die Veränderung kam (PowerUpCard,

EnergySpace). Sie können Client-seitig entscheiden, wie Sie damit umgehen wollen.

{

"messageType": "Energy",

"messageBody": {

"clientID": 42,

"count": 1,

"source": "EnergySpace"

}

}

Erreichte Checkpoints

Hier entspricht der Key "number" den Kontrollpunkt-Marken der physischen Version. Ein Spieler

mit dem Wert 3 hat also die ersten drei Checkpoints erreicht.

{

"messageType": "CheckPointReached",

"messageBody": {

"clientID": 42,

"number": 3

}

}

Spielsieg

Sobald ein Spieler den letzten Checkpoint erreicht, gilt das Spiel als gewonnen.

{

"messageType": "GameFinished",

"messageBody": {

"clientID": 42

}

}

17


版权所有:编程辅导网 2021 All Rights Reserved 联系方式:QQ:99515681 微信:codinghelp 电子信箱:99515681@qq.com
免责声明:本站部分内容从网络整理而来,只供参考!如有版权问题可联系本站删除。 站长地图

python代写
微信客服:codinghelp