Lass uns einen Panzerkrieg führen!
Teilweise inspiriert von Destroy Them With Lazers
Zielsetzung
Ihre Aufgabe ist es, einen Panzer zu steuern. Bewege dich und schieße auf andere Panzer und Hindernisse im 2D-Schlachtfeld. Der letzte Panzer ist der Gewinner!
Kartenformat
Ihr Tank wird auf einem 2D - Feld auf einer Basis sein , n
durch n
Gitter von Einheit Plätzen. Ich werde entscheiden, was n
auf der Anzahl der Einsendungen basiert. Jedes Quadrat kann nur eines der folgenden Elemente enthalten:
- Ein Panzer
- Ein Baum
- Ein Stein
- Eine Mauer
- Nichts
Alle Hindernisse und Panzer füllen ihre Räume vollständig aus, und sie blockieren alle Schüsse, die sie treffen, davor, Dinge weiter unten zu beschädigen.
Hier ist ein Beispiel für ein Feld mit #
= tank; T
= Baum; R
= Rock; W
= Wand; .
= nichts mit n
= 10
.....#....
..T....R..
WWW...WWWW
W......T..
T...R...Ww
W...W.....
W....W...T
WWWWWW...R
W.........
WWWWWWRT..
Koordinaten haben das Format, x, y
in dem von x
links nach rechts und von y
unten nach oben erhöht wird. Das untere linke Feld enthält die Koordinate 0, 0
. Jeder Panzer darf sich in einen beliebigen freien Raum bewegen und in eine beliebige Richtung schießen.
Kartendynamik
Ihr Panzer muss nicht nur andere Panzer abschießen! Wenn es etwas auf der Karte schießt, können Dinge passieren.
- Wenn auf eine Wand geschossen wird, wird sie nach einer gewissen Anzahl von Schüssen im Bereich von 1 bis 4 zerstört
- Wird auf einen Baum geschossen, wird dieser sofort zerstört
- Wenn auf einen Stein geschossen wird, überschreitet der Schuss diesen und beschädigt den nächsten Treffer
Sobald etwas zerstört ist, befindet es sich nicht mehr auf der Karte (es wird durch nichts ersetzt). Wenn ein Schuss ein Hindernis zerstört, wird es blockiert und beschädigt nichts weiter auf seinem Weg.
Panzerdynamik
Jeder Tank beginnt mit life
= 100. Jeder Schuss auf einen Panzer verringert life
sich je nach Entfernung um 20-30 . Dies kann mit delta_life=-30+(shot_distance*10/diagonal_map_length)
(wo diagonal_map_length
ist (n-1)*sqrt(2)
) berechnet werden . Zusätzlich regeneriert jeder Tank 1 life
pro Runde.
Wendet sich
Es werden einige Runden abgehalten (ich werde entscheiden, sobald ich Einsendungen habe). Zu Beginn jeder Runde wird nach dem Zufallsprinzip eine Karte erstellt und Panzer werden an zufälligen leeren Stellen darauf platziert. In jeder Runde erhält jeder Panzer eine Drehung in beliebiger Reihenfolge. Nachdem jeder Panzer gedreht wurde, werden sie in der gleichen Reihenfolge erneut gedreht. Die Runde wird fortgesetzt, bis nur noch ein Panzer übrig ist. Dieser Panzer wird der Gewinner sein und 1 Punkt erhalten. Das Spiel geht dann in die nächste Runde.
Sobald alle Runden gelaufen sind, werde ich die Punktzahlen zu dieser Frage veröffentlichen.
Während des Zuges eines Panzers kann es eine der folgenden Aktionen ausführen
- Bewegen Sie sich horizontal oder vertikal um bis zu 3 Felder in eine Richtung. Wenn der Tank durch ein Hindernis oder einen anderen Tank blockiert ist, wird er so weit wie möglich bewegt, ohne das Hindernis oder den Tank zu passieren.
- Schießen Sie in eine Richtung, dargestellt durch einen Gleitpunktwinkel in Grad. Die x-Achse des lokalen Raums Ihres Panzers (horizontal von links nach rechts, auch bekannt als Ost oder
TurnAction.Direction.EAST
) ist 0 Grad, und die Winkel nehmen gegen den Uhrzeigersinn zu. Aufnahmen sind ungenau und der tatsächliche Schusswinkel kann 5 Grad größer oder kleiner sein als der von Ihnen gewählte Winkel. - Nichts tun.
Abbiegungen sind nicht zeitlich begrenzt, aber dies bedeutet nicht, dass Sie absichtlich Zeit verschwenden können, um alles aufzuhängen.
Einreichungen / Protokoll
Jedes eingereichte Programm kontrolliert einen Panzer auf dem Feld. Das Steuerungsprogramm ist in Java, daher müssen Ihre Programme vorerst in Java sein (ich werde wahrscheinlich irgendwann einen Wrapper für andere Sprachen schreiben, oder Sie könnten Ihren eigenen schreiben).
Ihre Programme implementieren die Tank
Schnittstelle mit den folgenden Methoden:
public interface Tank {
// Called when the tank is placed on the battlefield.
public void onSpawn(Battlefield field, MapPoint position);
// Called to get an action for the tank on each turn.
public TurnAction onTurn(Battlefield field, MapPoint position, float health);
// Called with feedback after a turn is executed.
// newPosition and hit will be populated if applicable.
public void turnFeedback(MapPoint newPosition, FieldObjectType hit);
// Called when the tank is destroyed, either by another tank,
// or because the tank won. The won parameter indicates this.
public void onDestroyed(Battlefield field, boolean won);
// Return a unique name for your tank here.
public String getName();
}
Die Battlefield
Klasse enthält eine 2D-Anordnung von Objekten ( Battlefield.FIELD_SIZE
von Battlefield.FIELD_SIZE
), die Dinge auf dem Schlachtfeld darstellen. Battlefield.getObjectTypeAt(...)
gibt a wird FieldObjectType
für das Objekt an den angegebenen Koordinaten (eine von FieldObjectType.ROCK
, FieldObjectType.TREE
, FieldObjectType.TANK
, FieldObjectType.WALL
, oder FieldObjectType.NOTHING
). Wenn Sie versuchen, ein Objekt aus dem Kartenbereich zu bringen (Koordinaten <0 oder> = Battlefield.FIELD_SIZE
), IllegalArgumentException
wird ein geworfen.
MapPoint
ist eine Klasse zum Festlegen von Punkten auf der Karte. Verwenden Sie MapPoint.getX()
und, MapPoint.getY()
um auf die Koordinaten zuzugreifen.
EDIT: Einige Utility - Methoden wurden hinzugefügt: MapPoint.distanceTo(MapPoint)
, MapPoint.angleBetween(MapPoint)
, Battlefield.find(FieldObjectType)
, und TurnAction.createShootActionRadians(double)
wie vorgeschlagen Wasmoo .
Weitere Informationen finden Sie in den Javadocs, siehe unten.
Alle (öffentlichen API-) Klassen sind im Paket enthalten zove.ppcg.tankwar
.
Steuerungsprogramm
Den vollständigen Quellcode und die Javadocs des Steuerprogramms und der Tank-API finden Sie auf meinem GitHub-Repository: https://github.com/Hungary-Dude/TankWarControl
Sie können Pull-Anfragen und / oder Kommentare senden, wenn Sie einen Fehler sehen oder eine Verbesserung wünschen.
Ich habe zwei Beispieltankprogramme geschrieben RandomMoveTank
und RandomShootTank
(der Name sagt schon alles).
Um Ihren Panzer zu betreiben, fügen Sie Ihre vollqualifizierte Panzerklasse (Paketname + Klassenname) zu tanks.list
(einer Klasse pro Zeile) hinzu, bearbeiten Sie die Einstellungen nach Bedarf in zove.ppcg.tankwar.Control
(Abbiegeverzögerung, ob eine GUI-Darstellung des Feldes angezeigt werden soll usw.) und renne zove.ppcg.tankwar.Control
. Stellen Sie sicher, dass mindestens 2 Tanks auf der Liste sind, da sonst die Ergebnisse undefiniert sind. (Verwenden Sie ggf. die Probentanks).
Ihre Programme werden auf meinem Computer unter diesem Steuerungsprogramm ausgeführt. Ich werde einen Link zur Quelle hinzufügen, sobald ich es schreibe. Sie können der Quelle gerne Änderungen vorschlagen.
Regeln
- Ihre Einsendungen müssen den oben genannten Richtlinien entsprechen
- Ihre Programme greifen möglicherweise nicht auf das Dateisystem, das Netzwerk oder versuchen, meinen Computer in irgendeiner Weise anzugreifen
- Ihre Programme versuchen möglicherweise nicht, mein Steuerungsprogramm zum Schummeln auszunutzen
- Kein Trolling (z. B. dass Ihr Programm absichtlich Zeit verschwendet, um alles aufzulegen)
- Möglicherweise haben Sie mehr als eine Einreichung
- Versuche kreativ zu sein mit Einsendungen!
- Ich behalte mir das Recht vor, Programme willkürlich zuzulassen oder nicht zuzulassen
Viel Glück!
UPDATE: Nachdem ich den Mauerteleportationsfehler behoben und die Regeneration durchgeführt hatte, lieferte ich die aktuellen Einreichungen für 100 Runden mitBattlefield.FIELD_SIZE = 30
UPDATE 2: Ich habe die neue Submission RunTank hinzugefügt, nachdem ich mich ein bisschen mit Groovy getäuscht hatte ...
Aktualisierte Ergebnisse:
+-----------------+----+
| RandomMoveTank | 0 |
| RandomShootTank | 0 |
| Bouncing Tank | 4 |
| Richard-A Tank | 9 |
| Shoot Closest | 19 |
| HunterKiller 2 | 22 |
| RunTank | 23 |
| Dodge Tank | 24 |
+-----------------+----+
Derzeit regenerieren Panzer 1 Leben pro Runde. Sollte das erhöht werden?
quelle
MapPoint
'sx
undy
floats
? Sollten sie nicht seinints
?Antworten:
HunterKiller
Dieser intelligente Jäger wird versuchen, eine sichere Position zu finden, in der er sauber auf genau ein Ziel schießen kann. (Und somit kann nur ein Ziel darauf schießen.)
Funktioniert am besten, wenn viel Deckung vorhanden ist.
Und das ist es. Ich bin ausgegeben.
quelle
Dieser geradlinige Panzer findet den nächsten feindlichen Panzer und schießt darauf. Wäre schön, wenn
find
,distance
undangle
eingebaut wären, und wenncreateShootAction
ein Double im Bogenmaß (dh das Ergebnis vonangle
) akzeptiert würdeBearbeiten: Die Klasse wurde umgeschrieben, um neue Dienstprogrammmethoden aufzunehmen
quelle
Would be nice if find, distance, and angle were built in, and if createShootAction accepted a double in radians (i.e. the result of angle)
- Tolle Idee, ich werde es hinzufügen.Ich bin nicht sehr gut darin, aber ich dachte, ich würde es trotzdem versuchen, weißt du, üben und so.
Mein Panzer wird nach dem Zufallsprinzip entscheiden, ob er sich bewegt oder schießt. Wenn es beschließt zu schießen, wird es versuchen, auf das nächste verfügbare Ziel zu schießen.
Den vollständigen Code einschließlich des Steuerungsprogramms finden Sie hier .
quelle
Direction.getRandom()
Dodge Tank
Dieser Panzer schießt auf den nächsten Panzer. Abhängig von seiner Gesundheit und der letzten Bewegung versucht er von Zeit zu Zeit, sich senkrecht zum nächstgelegenen Panzer zu bewegen, um seinen Lasern auszuweichen.
quelle
Das war viel komplizierter als ich dachte ..
Dies ist mein Eintrag in Groovy, Sie müssen Groovy installiert und kompilieren
Um es aufzurufen, müssen Sie $ GROOVY_HOME / Groovy / Groovy-2.3.4 / lib / groovy-2.3.4.jar (oder welche Version auch immer) zum Klassenpfad hinzufügen.
Ich könnte Ihnen eine kompilierte .class-Datei und die Bibliothek senden, wenn Sie sie nicht installieren möchten.
Es scheint eine Situation zu geben, in der Panzer es nicht sehen können. Ich weiß nicht, ob das beabsichtigt ist. Das verursachte Deadlocks beim Testen.
Wie auch immer, hier ist RunTank: RunTank bewegt sich mutig in die entgegengesetzte Richtung des nächstgelegenen Panzers, wenn es sich um den nächstgelegenen Panzer handelt oder mehr als ein Panzer sich in FIELD_SIZE / 3 befindet. Ich hoffe, das macht Sinn, ich bin betrunken :)
Ich habe einen Vorschlag: Hinzufügen von Farben zum Tank und eine Methode, um es zu implementieren. Auch Labels wären nett in der GUI :)
quelle
def RandomMoveTank() {}
- soll das da sein? (Ich weiß nicht, groovy)Dies ist eine Variante des Shoot-Closest in dem es sich in jeder zweiten Runde in eine Richtung bewegt, bis es nicht mehr kann. Es schießt jede zweite Runde.
Es hat ein praktisches Hilfsprogramm,
path
mit dem alle Punkte (und damit Objekte) zwischen zwei Punkten identifiziert werden können.quelle