Facciamo una guerra di carri armati!
Parzialmente ispirato a Distruggili con lacci
Obbiettivo
Il tuo compito è controllare un carro armato. Muoviti e spara ad altri carri armati e ostacoli nel campo di battaglia 2D. L'ultimo carro armato in piedi sarà il vincitore!
Formato mappa
Il tank sarà su un campo 2D basato sulla ndalla ngriglia di quadrati unitari. Deciderò cosa nsi basa sul numero di invii. Ogni quadrato può contenere solo uno di:
- Un serbatoio
- Un albero
- Una pietra
- Un muro
- Niente
Tutti gli ostacoli e i carri armati riempiono completamente i loro spazi e bloccano tutti i colpi che li colpiscono danneggiando le cose più in basso.
Ecco un esempio di un campo con #= serbatoio; T= albero; R= roccia; W= parete; .= niente con n= 10
.....#....
..T....R..
WWW...WWWW
W......T..
T...R...Ww
W...W.....
W....W...T
WWWWWW...R
W.........
WWWWWWRT..
Le coordinate sono nel formato in x, ycui xaumenta da sinistra a destra e yaumenta dal basso verso l'alto. Lo spazio in basso a sinistra ha le coordinate 0, 0. Ogni carro armato può spostarsi in qualsiasi spazio vuoto e sparare in qualsiasi direzione.
Dinamica delle mappe
Il tuo carro armato non deve solo sparare ad altri carri armati! Se spara qualcosa sulla mappa, le cose possono succedere.
- Se un muro viene colpito, verrà distrutto dopo un certo numero di colpi, che vanno da 1 a 4
- Se un albero viene colpito, verrà immediatamente distrutto
- Se viene colpito a un sasso, il colpo lo passerà sopra e danneggerà la prossima cosa che colpisce
Una volta che qualcosa viene distrutto, non è più sulla mappa (verrà sostituito con nulla). Se un tiro distrugge un ostacolo, verrà bloccato e non danneggerà più nulla lungo il suo cammino.
Dinamica del serbatoio
Ogni serbatoio inizia con life= 100. Ogni colpo in un carro armato ridurrà di 20-30 in lifebase alla distanza. Questo può essere calcolato con delta_life=-30+(shot_distance*10/diagonal_map_length)(dove si diagonal_map_lengthtrova (n-1)*sqrt(2)). Inoltre, ogni carro armato rigenera 1 lifeper turno.
Giri
Verrà eseguito un numero di round (deciderò una volta che avrò invii). All'inizio di ogni round, una mappa verrà generata casualmente e i carri armati verranno posizionati su di essa in posizioni vuote casuali. Durante ogni round, a ogni carro armato verrà dato un turno, in qualsiasi ordine arbitrario. Dopo che a ogni carro armato è stato dato un turno, gli verranno dati di nuovo turni nello stesso ordine. Il round continua fino a quando rimane solo un serbatoio. Quel carro armato sarà il vincitore e riceveranno 1 punto. Il gioco passerà quindi al turno successivo.
Una volta che tutti i round sono stati eseguiti, posterò i punteggi su questa domanda.
Durante il turno di un carro armato, può effettuare una delle seguenti operazioni
- Spostare fino a 3 spazi in una sola direzione, sia in orizzontale che in verticale. Se il serbatoio viene bloccato da un ostacolo o da un altro serbatoio, verrà spostato il più lontano possibile senza attraversare l'ostacolo o il serbatoio.
- Scatta in una direzione, rappresentata da un angolo in virgola mobile in gradi. L'asse x dello spazio locale del tuo carro armato (orizzontalmente da sinistra a destra, aka est o
TurnAction.Direction.EAST) è 0 gradi, e gli angoli aumentano in senso antiorario. I colpi non sono accurati e l'angolo effettivo del tiro può essere maggiore o minore di 5 gradi rispetto all'angolo scelto. - Fare niente.
I turni non sono limitati nel tempo, ma ciò non significa che puoi intenzionalmente perdere tempo per appendere tutto.
Inseriti / Protocollo
Ogni programma presentato controllerà un serbatoio sul campo. Il programma di controllo è in Java, quindi per ora i tuoi programmi devono essere in Java (probabilmente a un certo punto scriverò un wrapper per altre lingue, oppure potresti scriverne uno tuo).
I tuoi programmi implementeranno l' Tankinterfaccia, che ha i seguenti metodi:
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();
}
La Battlefieldclasse contiene una matrice 2D di oggetti ( Battlefield.FIELD_SIZEby Battlefield.FIELD_SIZE) che rappresenta le cose sul campo di battaglia. Battlefield.getObjectTypeAt(...)darà una FieldObjectTypeper l'oggetto alle coordinate specificate (uno FieldObjectType.ROCK, FieldObjectType.TREE, FieldObjectType.TANK, FieldObjectType.WALL, o FieldObjectType.NOTHING). Se si tenta di ottenere un oggetto fuori dal raggio della mappa (coordinate <0 o> = Battlefield.FIELD_SIZE), IllegalArgumentExceptionverrà lanciato un oggetto.
MapPointè una classe per specificare i punti sulla mappa. Utilizzare MapPoint.getX()e MapPoint.getY()per accedere alle coordinate.
EDIT: Sono stati aggiunti alcuni metodi di utilità: MapPoint.distanceTo(MapPoint), MapPoint.angleBetween(MapPoint), Battlefield.find(FieldObjectType), e TurnAction.createShootActionRadians(double)come suggerito da Wasmoo .
Ulteriori informazioni sono disponibili nei javadocs, vedere la sezione seguente.
Tutte le classi (API pubbliche) sono incluse nel pacchetto zove.ppcg.tankwar.
Programma di controllo
La fonte completa e javadocs del programma di controllo e dell'API del serbatoio sono disponibili sul mio repository GitHub: https://github.com/Hungary-Dude/TankWarControl
Sentiti libero di inviare richieste pull e / o commenti se vedi un bug o desideri un miglioramento.
Ho scritto due programmi di esempio per il serbatoio RandomMoveTanke RandomShootTank(il nome dice tutto).
Per far funzionare il tuo carro armato, aggiungi la tua classe di carro armato (nome del pacchetto + nome della classe) pienamente qualificata a tanks.list(una classe per riga), modifica le impostazioni come necessario in zove.ppcg.tankwar.Control(ritardo di virata, se mostrare o meno una rappresentazione GUI del campo, ecc.), e corri zove.ppcg.tankwar.Control. Assicurati che ci siano almeno 2 serbatoi nell'elenco o che i risultati non siano definiti. (Utilizzare i serbatoi di campionamento se necessario).
I tuoi programmi verranno eseguiti sulla mia macchina con questo programma di controllo. Includerò un link alla fonte una volta che lo scrivo. Sentiti libero di suggerire modifiche alla fonte.
Regole
- I tuoi invii devono seguire le linee guida sopra
- I tuoi programmi non possono accedere al filesystem, alla rete o tentare di attaccare la mia macchina in alcun modo
- I tuoi programmi potrebbero non tentare di sfruttare il mio programma di controllo per imbrogliare
- Nessuna pesca a traina (come ad esempio perdere intenzionalmente il tuo programma per appendere tutto)
- Potresti avere più di un invio
- Cerca di essere creativo con i contributi!
- Mi riservo il diritto di autorizzare o meno i programmi arbitrariamente
In bocca al lupo!
AGGIORNAMENTO: Dopo aver corretto il bug di teletrasporto a muro e aver implementato la rigenerazione, ho eseguito gli invii correnti per 100 round conBattlefield.FIELD_SIZE = 30
AGGIORNAMENTO 2: Ho aggiunto il nuovo invio, RunTank, dopo aver preso in giro un po 'con Groovy ...
Risultati aggiornati:
+-----------------+----+
| RandomMoveTank | 0 |
| RandomShootTank | 0 |
| Bouncing Tank | 4 |
| Richard-A Tank | 9 |
| Shoot Closest | 19 |
| HunterKiller 2 | 22 |
| RunTank | 23 |
| Dodge Tank | 24 |
+-----------------+----+
Attualmente i carri armati rigenerano 1 punto vita per turno. Dovrebbe essere aumentato?
MapPoint'sxeyfloats? Non dovrebbero essereints?