Ablauf

Sebastian Stock

Für die Datenhaltung und Kommunikation mit dem Server wird bis auf wenige notwendige Modifikationen das Modell der Android-Smartphones verwendet, welches im Kapitel Datenhaltung vorgestellt wird. Daher stehen dem Agenten nur die Informationen zur Verfügung, die auch den Spielern auf den Smartphones angezeigt werden. Somit hat er keinen künstlichen Vorteil gegenüber anderen Spielern, welcher z.B. durch zusätzliche Schnittstellen zum Server denkbar gewesen wäre, allerdings auch von anderen Spielern als unfair angesehen werden könnte. Einzig bei der Routenplanung wird auf einen externen Webservice zurückgegriffen, worauf im Unterkapitel Routenberechnung genauer eingegangen wird. Aber auch dies ist mit der auf den Smartphones angezeigten GoogleMaps-Karte vergleichbar, mit der auch die Spieler eine Möglichkeit der Orientierung und Routenplanung zur Verfügung haben.

Parameter

Agenten wurden als Threads implementiert, diese können direkt vom Server heraus oder als eigenes Java-Programm gestartet werden. Im Konstruktor der Klasse Agent werden alle benötigten Parameter mitgegeben. Diese werden im Folgenden kurz vorgestellt:

  • AgentHandler handler: Wenn der Agent vom Server aus gestartet wurde, können mit diesem Handler Log-Ausgaben und Exceptions geschickt werden. Auf diese Weise kann der Server informiert werden, wenn beispielsweise ein nicht behandelbarer Fehler aufgetreten ist.
  • String host: Adresse des Servers, zu dem sich der Agent verbinden soll.
  • String agentname: Benutzername mit dem der Agent einem Spiel beitritt.
  • String password: Zum Benutzernamen gehörendes Passwort mit dem sich der Agent einloggen kann.
  • int gameId: Gibt das Spiel an dem der Agent beitreten soll.
  • GeoPoint startposition: Die Geo-Koordinaten der Startposition des Agenten im Spiel.
  • int safesToClaim: Gibt an, ob und nach welcher Anzahl geöffneter Tresore der Agent ein Spiel verlässt. Bei dem Wert 0 ist diese Anzahl unbegrenzt.
  • double speedfactor: Als Basis bewegt sich der Agent mit einer Geschwindigkeit von 4 km/h. Diese Geschwindigkeit kann mit dem hier angegebenen Faktor beeinflusst werden, um den Agenten beispielsweise für Tests schneller oder im realen Spiel evtl. auch langsamer laufen zu lassen.
  • int maxDelay: Gibt den maximalen Zeitabstand in Millisekunden an, nach dem der Agent ein Update seiner Geo-Position sendet.
  • boolean cops: Gibt an, welchem Team der Agent beitreten soll. Bei dem Wert true ist er ein Polizist und andernfalls ein Dieb.

Hauptschleife

In der run-Methode des Agenten wird sein eigentliches Verhalten realisiert. Dieses wird im folgenden Diagramm verdeutlicht:

Abb. 1: Programmblaufplan der run-Methode des Agenten

Zunächst müssen die Modelle initialisiert werden und der Agent versucht, sich mit seinem Benutzernamen und Passwort einzuloggen, einem Spiel beizutreten und seine Startposition an den Server zu senden. War dies erfolgreich, werden in einer Hauptschleife seine Aktionen im Spiel realisiert. Die Stopp-Bedingung setzt sich dabei aus mehreren Einzelbedingungen zusammen. Sie ist erfüllt, wenn von Außen ein Signal zum Beenden gesendet oder die vorgegebene maximale Anzahl gelöster Tresore erreicht wurde.

In der Schleife wird als Erstes mithilfe des UpdateModel eine Aktualisierung der Modelle durchgeführt. Anschließend werden außer der Blaupause alle im Inventar vorhandenen Gegenstände genutzt und die Chatnachrichten geparst, worauf im Unterkapitel Zielauswahl noch eingegangen wird.

Falls notwendig, wird eine neue Zielposition berechnet. Dies ist genau dann der Fall, wenn sich am Modell etwas geändert hat und z.B. Tresore hinzugekommen sind oder von einem anderen Spieler gelöst wurden, oder wenn derzeit keine Route vorhanden ist. Letzteres ist direkt nach dem Start oder nachdem im letzten Schritt das Ziel erreicht wurde erfüllt. Dann wird mit dem PathPlanner eine Zielposition und die zugehörige Route ermittelt. Auf diesen wird im Kapitel Zielauswahl noch genauer eingegangen. Wenn sich der neu berechnete Zielpunkt von dem bisherigen unterscheidet, wird die Route an den Server gesendet, damit diese im Gameviewer angezeigt werden kann.

Anschließend wird die Bewegung des Agenten simuliert. Die Route besteht aus einer Liste von Geo-Koordinaten. Diese wird schon bei der Berechnung der Route so generiert, dass zwei aufeinander folgende Punkte, bei gegebener Bewegungsgeschwindigkeit, in einer Zeit, die die ebenfalls gegebene maximale Zeitdifferenz nicht überschreitet, erreicht werden. Auf Details der Generierung der Route wird im Unterkapitel Routenberechnung noch genauer eingegangen. In diesem Simulationsschritt muss also zunächst der nächste Geo-Punkt von der Route genommen und die Distanz zur aktuellen Position berechnet werden. Mit dieser lässt sich nun die Zeit ermitteln, die der Agent für diese Teilstrecke benötigt. Für diese Zeit wird der als Thread implementierte Agent daher auch pausiert.

Abschließend muss noch überprüft werden, ob mit dem letzten Schritt das Ziel erreicht wurde. In diesem Fall wird versucht, den Tresor zu öffnen bzw. zu sichern oder das gefundene Geschenk einzusammeln. Da Geschenke auch auf den Smartphones durch einfaches Anklicken eingesammelt werden können und dieser Vorgang daher für den Benutzer keinen großen Aufwand darstellt, sendet auch der Agent beim Erreichen der entsprechenden Geo-Koordinate sofort die entsprechende Anfrage an den Server.

Das Öffnen der Tresore hingegen wird den Spielern auf den Smartphones durch das zusätzliche 8-Puzzle deutlich erschwert. Zum einen wird dies eine gewisse Zeit dauern und zum anderen besteht auch die Gefahr, das Rätsel nicht zu lösen und somit einen Punktabzug zu erhalten. Daher ist es sinnvoll diese beiden Aspekte auch in das Verhalten des Agenten einzubeziehen. So öffnen auch die Agenten einen Tresor nur mit einer bestimmten Wahrscheinlichkeit und bekommen andernfalls Geld abgezogen. Hier wurde eine Wahrscheinlichkeit von 90% für erfolgreiches Öffnen bzw. Sichern angesetzt. Die Zeit die der Agent für das Puzzle benötigt ist nicht fest vorgegeben, sondern auch vom Wert des Tresors abhängig. Diese Werte liegen im Bereich 10000ms bis 40000ms. Im Falle eines erfolgreichen Lösens des Puzzles, wird die benötigte Zeit nun zufällig aus dem Intervall [10000 , 10000 + Tresorwert] ms ausgewählt. Andernfalls beträgt die Zeit 10000ms + Tresorwert ms. Der Agent wird um diese Zeit pausiert, bevor er mit der entsprechenden Anfrage an den Server fortfährt. Ein Sonderfall tritt auf, wenn eine Blaupause im Inventar vorhanden ist. Diese wird sofort genutzt und ein entsprechendes Warten bzw. Lösen des 8-Puzzles ist nicht notwendig.

Anschließend wird die Schleife gegebenenfalls erneut durchlaufen und die neue Position des Agenten gesendet. Ein Abbruch der Schleife erfolgt falls der Server dies mit einem Aufruf der logout-Methode veranlasst hat oder die vorgegebene maximale Anzahl an geöffneten Tresoren erreicht ist.

Serveranbindung

Wie bereits erwähnt, kann der Agent als Thread vom Server aus gestartet werden. Um dieses zu ermöglichen waren einige Anpassungen notwendig. So muss der Server beispielsweise über ein Beenden des Agenten informiert werden und es muss dem Server auch möglich sein, den Agenten zu beenden. Hier genügt es nicht lediglich den Thread zu beenden, sondern es muss sichergestellt werden, dass der Agent vorher noch einen Logout durchführt. Um dieses zu erreichen muss der Agent das Interface IAgent implementieren, in welchem die folgenden vier Methoden enthalten sind.

  • public void validateLogin() throws AgentException : Überprüft, ob sich der Agent mit den im Konstruktor angegebenen Nutzernamen und Passwort einloggen kann. Ist dieses nicht möglich, versucht er sich neu zu registrieren. Wenn beides fehlschlägt, wird eine AgentException geworfen um dem Server diesen Fehler mitzuteilen. Anschließend loggt er sich wieder aus.
  • public void start() : Startet den Agenten und wird bereits von der Oberklasse Thread geerbt. Dadurch wird die run()-Methode ausgeführt, deren Verhalten oben bereits beschrieben wurde.
  • public Integer getPlayerID() throws AgentException : Gibt die eindeutige ID des Agenten zurück, die er vom Server erhält, wenn er sich einloggt. Da diese Methode häufig direkt nach dem Starten des Agenten aufgerufen wird, er zu diesem Zeitpunkt allerdings nicht immer bereits eingeloggt ist, wird hier gewartet bis die geforderte ID vorliegt. Existiert diese nach einer vorgegebenen Zeitspanne immer noch nicht, wird eine AgentException geworfen.
  • public void logout() throws AgentException : Veranlasst den Agenten dazu sich zu beenden und auszuloggen. Wenn er aktiv ist, wird die aktuelle Iteration der Hauptschleife noch vollständig ausgeführt und anschließend ein Logout durchgeführt. Andernfalls loggt er sich neu ein und direkt wieder aus. So wird sichergestellt, dass er nicht im Spiel verbleiben und für die anderen Spieler weiterhin angezeigt werden kann.


Page last modified on March 21, 2011, at 03:58 PM