Projekt:2019/RoverArena

Aus HG Wiki
Zur Navigation springen Zur Suche springen

Die russische Raumfahrtbehörde Roskosmos hat ihren eigenen Rover auf den Mars geschickt. Nicht nur das Elon Musk hat seine Firma Space X angewiesen, mehrere autonome Fahrzeuge in Richtung des roten Planeten zu schicken. Und wo Elon ist, da sind Jeff Bezos und Tim Cook nicht weit. Alle Rover haben ein Ziel: Möglichst viel Wasser auf dem Mars zu finden und die enthaltenen Mineralien auszufiltern. Wer die größte Beute mit nach Hause bringt, hat dieses "Spacerace" gewonnen.

RoverArena Spielfeld.jpeg

Im Greenfoot-Szenario RoverArena sollt ihr einen möglichst autonomen Mars-Rover programmieren, der möglichst viele Gesteine analysiert und das enthaltene Wasser in Mineralien umwandelt. Doch jeder Rover hat nur einen begrenzte Batterie und jede Aktion auf dem Mars kostet wertvolle Energie. Daher gilt es zu entscheiden, wieviel von dem Wasser in Mineralien, und wieviel in Energie konvertiert werden soll.

Icon Info.png Download der RoverArena: RoverArena.zip (Version vom 10.12.2019)

Download von Greenfoot: Greenfoot.org

Die Rover in der RoverArena beherrschen die gewohnten Anfragen und Aufträge. Dazu haben sie noch einiges neues gelernt:

Getter und Setter der Objektvariablen
Name Beschreibung
getWasser() Die Menge an Wasser im Wassertank. Wasser muss zuerst mit analysiereGestein() gesammelt werden und kann dann mit konvertiereWasser(int menge, String produkt) in Mineralien oder Energie konvertiert werden.
getEnergie() Die verbleibende Energieladung in der Batterie des Rovers. Jede Aktion kostet ein wenig Energie. Ist die Batterie leer, kann der Rover nichts mehr machen. Daher sollte er versuchen vorher etwas Wasser in Energie zu konvertieren. Jeder Rover startet mit einer volen Ladung von 1000.
getMineralien() Die Menge an Mineralien, die biher konvertiert wurde. Der Rover, der am Ende die meisten Mineralien gesammlet hat, gewinnt die Runde.
Anfragen des Rovers
Name Beschreibung
boolean markeVorhanden() Prüft, ob auf dem aktuellen Feld eine Marke vorhanden ist.
boolean eigeneMarkeVorhanden() Prüft, ob auf dem aktuellen Feld eine Marke vorhanden ist, die der Rover selber gesetzt hat.
boolean huegelVorhanden( String richtung ) Prüft, ob sich "vorne", "rechts" oder "links" von der Position des Rovers ein Hügel befindet. (Zur Vereinfachung wird angenommen, dass sich hinter dem Rand der Welt auch Hügel befinden. Ist der Rover am Rand der Karte, wird also auch true zurückgegeben.)
boolean gesteinVorhanden() Prüft, ob auf dem aktuellen Feld ein Gestein vorhanden ist.
boolean roverVorhanden( String richtung ) Prüft, ob sich "vorne", "rechts" oder "links" von der Position des Rovers ein anderer Rover befindet.
Aufträge des Rovers
Name Beschreibung Energie-Kosten
void fahre() Bewegt den Rover ein Feld in Blickrichtung vorwärts. 4
void drehe( String richtung ) Dreht den Rover um 90 Grad nach "links" oder "rechts". 2
void setzeMarke() Setzt eine Marke auf dem aktuellen Feld des Rovers. Jeder Rover startet mit fünf Marken, kann aber Marken (auch von anderen Rovern) aufsammeln und diese neu setzen. 1
void entferneMarke() Entfernt eine Marke, wenn eine vorhanden ist und der Laderaum des Rovers noch nicht voll ist. Jeder Rover kann maximal 8 Marken tragen. 1
void analysiereGestein() Falls ein Gestein an der aktuellen Position des Rovers vorhanden ist, wird es auf Wasser analysiert und das gefundene Wasser dem Wasserspeicher hinzugefügt. 4
void konvertiereWasser( int menge, String produkt ) Konvertiert die angegebene Menge an Wasser in "energie" oder "mineralien". Ist weniger Wasser vorhanden, oder kann nicht die volle Menge konvertiert werden, dann wird nur soviel Wasser konvertiert, wie maximal möglich ist.

Wasser kann 1-zu-1 in Energie konvertiert werden. Wasser kann 1-zu-2 in Mineralien konvertiert werden (aus 1 Wasser kann 2 Mineralien gewonnen werden), dafür kostet die Konvertierung in Mineralien zusätzlich die gleiche Menge Energie.

variiert
boolean entzieheEnergie() Entzieht einem anderen Rover eine zufällige Menge Energie, wenn sich dieser auf dem Feld vor dem Rover befindet. Die Menge liegt zwischen 50 und 250 Energieeinheiten. Die Energie wird dem anderen Rover abgezogen, auch wenn die eigene Batterie schon voll ist. Das eigene Batterielimit kann aber nicht überschritten werden. -50 bis -250

Regeln

Ihr könnt euren Rover implementieren wie ihr möchtet und könnt. Jeder Rover in der RoverArena muss sich an die folgenden Regeln halten.

  1. Jeder Rover wird in der act()-Methode implementiert.
  2. Pro Runde wird die act()-Methode jedes Rovers einmal ausgeführt.
  3. Pro Runde darf ein Rover bis zu zwei Aktionen ausführen. Als Aktion gelten alle Aufträge, die zur Ausführung Energie kosten.
  4. Die act()-Methode darf keine Endlosschleife (oder sehr lange laufende Schleifen) enthalten.
  5. Ein Rover darf sich nicht einfach Energie, Mineralien oder Wasser "erschaffen", außer über die zur Verfügung stehenden Methoden.
  6. Hat ein Rover keine Energie mehr zur Verfügung, um Aktionen auszuführen; kein Wasser, um es in Energie zu verwandeln; oder hat er längere Zeit keine sinnvolle Aktion mehr ausgeführt, dann scheidet der Rover aus dem Wettkampf aus und muss warten, bis alle anderen Rover ausgeschieden sind.

Erste Schritte

RoverArena Klassen.jpeg

Um einen Rover für die RoverArena zu erstellen müsst ihr zuerst eine neue Rover-Klasse anlegen. Am einfachsten ist es, wenn ihr die Vorlage RoverVorlage verwendet. Öffnet dazu Greenfoot und klickt doppelt auf den Eintrag RoverVorlage rechts unter Rover.

Nun gebt eurer Rover-Klasse einen eigenen Namen. Tauscht dazu in der Zeile

public class RoverVorlage extends Rover {

den Bezeichner RoverVorlage gegen einen eigenen aus (beispielsweise BesterRover, TimUndHaticesRover oder SearxhAndDestroyRover).

Dann solltet ihr euren Rover einen eigenen Namen geben. Dieser kann sich vom Bezeichner der Klasse unterscheiden. Ändert dazu in der Methode roverErstellen() den String in der Zeile

name = "Mark Watney";

auf etwas eigenes um.

Wenn ihr eurer Rover-Klasse den Bezeichner SimonRabeaNiwaRover und den Namen "Ronald van Rover" gegeben hättet, dann müsste eure Rover-Klasse jetzt zum Beispiel so aussehen:

public class SimonRabeaNiwaRover extends Rover {

	protected void roverErstellen() {
		name = "Ronald van Rover";
	}

	public void act() {
		// Hier programmiert ihr euren Rover. 
		// Pro Aufruf von act() darf der Rover zwei Aktionen ausführen. 
	}

}

Den Rover programmieren

Ihr programmiert das Verhalten eures Rovers in der act()-Methode. Wie ihr das macht, das ist euch überlassen, solange die Regeln oben eingehalten werden. Im Spiel gibt es einen Siedsrichter (Klasse Referee), der darauf aufpasst, dass euer Rover nicht mogelt.

Ein Beispiel für einen Rover findet ihr in der Klasse BoringRover. Das Verhalten des dieses Rovers ist recht ... langweilig. Aber immerhin bewegt er sich und führt Aktionen aus. Es ist aber leicht möglich, einen deutlich effizienteren Rover zu erstellen.

Icon Info.png Du kannst unten im BoringRover eine Ausgabe aktivieren. Dann sagt dir der Rover an, was er gerade tut.

Oftmals ist es sinnvoll, den Rover Aktionen mit einer gewissen Wahrscheinlichkeit ausführen zu lassen. Er könnte zum Beispiel nicht immer zuerst versuchen rechts abzubiegen, sondern zufällig entscheiden, ob er sich nach rechts oder links dreht. Dazu gibt es einige hilfreiche Klassenmethoden in der Klasse Utils.

Klassenmethoden lassen sich nutzen, ohne vorher ein Objekt der Klasse erstellt zu haben. Zum Beispiel erzeugt zufallsBool(50) einen Wahrheitswert, der zu 50% true ist.

if( Utils.zufallsBool(50) ) {
    drehe("rechts");
} else {
    drehe("links");
}

Die Verfügbaren Hilfsmethoden sind hier aufgelistet.

Hilfsmethoden in der Klasse Utils
Name Beschreibung Beispiel
int zufallsInt( int max ) Erzeugt eine zufällige Zahl zwischen 0 (inklusive) und max (exklusive). Utils.zufallsInt(50) // 0,1,...,49
int zufallsInt( int min, int max ) Erzeugt eine zufällige Zahl zwischen min (inklusive) und max (inklusive). Utils.zufallsInt(10,50) // 10,11,...,50
int zufallsBool() Erzeugt einen zufälligen Wahrheitswert, wobei das Ergebnis zu 50% true und zu 50% false ist. if( Utils.zufallsBool() ) { }
int zufallsBool( int wkeit ) Erzeugt einen zufälligen Wahrheitswert, wobei das Ergebnis zu wkeit Prozent true und zu 100-wkeit Prozent false ist. if( Utils.zufallsBool(75) ) { }