Panoramica
Questa è una battaglia bot per vedere chi può sopravvivere più a lungo. Questi robot aumentano il loro potere quando vengono attaccati, quindi è necessario riflettere attentamente prima di sparare.
Ad ogni turno, puoi scegliere un robot per attaccare o difendere. L'attacco diminuirà la sua vita e aumenterà il suo potere. Vince l'ultimo bot in piedi.
Motori di ricerca
Ogni bot inizia con 1000 punti vita e 10 punti potenza.
Quando attaccato:
- il potere dell'attaccante viene sottratto dalla tua vita
- il tuo potere aumenta di 1.
Quindi, se al primo turno, vieni attaccato da due robot, avrai 980 punti vita e 12 poteri.
Se scegli di difendere:
- la tua potenza sarà ridotta di 1
- tutti gli attacchi contro di te in questo turno saranno ridotti della metà
- se vieni attaccato, otterrai 2 poteri per ogni attaccante invece di 1
Quindi, se difendi al primo turno e sei attaccato da due robot, avrai 990 punti vita e 13 poteri. Se difendi e non sei attaccato, avrai 1000 punti vita, ma 9 poteri.
Se alla fine di un turno il tuo potere è inferiore a uno, sarà impostato su uno. Se la tua vita è inferiore a 1, muori.
Input Output
I robot vengono chiamati una volta per turno. C'è un limite di tempo di un secondo per ogni turno.
Iniziale
La prima volta che viene chiamato il bot, non verrà fornito alcun argomento. Rispondi con ok
. Questo viene fatto solo per assicurarsi che il tuo bot risponda. In caso contrario, non verrà aggiunto all'elenco dei giocatori.
Ogni turno
Ad ogni turno, al tuo bot vengono fornite informazioni su tutti i bot del gioco come argomenti della riga di comando. Un esempio di questi argomenti è:
1 0,1000,10,1 1,995,11,D
Il primo argomento è l'ID univoco del tuo bot. Quindi, viene visualizzato un elenco separato da spazi di bot. Ogni bot è formattato come:
id,life,power,lastAction
lastAction
può essere un numero intero che rappresenta quale bot hanno attaccato, D
se hanno difeso, e X
se questo è il primo turno. Gli altri sono tutti numeri interi.
Quindi nell'esempio sopra, sei bot 1
e difeso nel tuo ultimo turno. Bot 0
ti ha attaccato ed è ancora all'inizio di salute / potere.
L'uscita per ogni turno è molto semplice. Semplicemente emetti il bot che vuoi attaccare come intero (es. 0
O 3
), o D
da difendere. Non attaccare i robot morti o inesistenti, poiché conta come un comando non valido. Qualsiasi comando non valido ti farà perdere 1 potere.
Struttura del torneo
Ogni gioco è composto da tutti i robot a partire da 1000 punti salute e 10 punti potenza. Le azioni di tutti i robot vengono eseguite contemporaneamente. Il numero massimo di turni per una partita è 1000.
Se alla fine del turno c'è un robot rimasto in vita (vita> 0), segna un punto e inizia un'altra partita. Se viene raggiunto il limite di virata e sono attivi più robot, nessuno ottiene un punto. Se tutti i robot rimanenti muoiono nello stesso turno, nessuno ottiene un punto.
Un torneo è composto da 15 partite. Chiunque abbia più punti alla fine vince! I legami vengono interrotti dalla somma della vita rimanente in ogni partita vinta.
Stato
I robot possono solo leggere o scrivere su un singolo file chiamato dopo se stesso, in una sottocartella diretta denominata state
("Hero" può scrivere state/hero.whatever
). Questo file non deve superare le dimensioni di 1024 2 byte. Fare attenzione a rispettare il limite di tempo. Per contare, il tuo programma deve terminare entro un secondo, non solo per dare una risposta.
Questi file verranno cancellati prima di ogni torneo, ma persisteranno da gioco a gioco. Tutti gli identificatori di bot ( id
) rimarranno uguali tra i giochi.
controllore
Di seguito è riportato il controller del torneo ( Stronger.java
). Per impostazione predefinita , fornisce solo i risultati finali (elenco ordinato dei giocatori, vincitore in alto), che può richiedere del tempo. Non è congelato, solo silenzioso. Se desideri un output turn-by più dettagliato, aggiungi l' -log
argomento durante l'esecuzione.
Per aggiungere robot, hai due opzioni:
aggiungi il comando come argomento (
java Stronger -log "python bot.py"
)aggiungi il comando a
defaultPlayers[]
nel sorgente ("python bot.py"
)
I robot Hero , Bully e Coward possono essere trovati in questa risposta e saranno usati a scopo di punteggio.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Stronger {
static final String[] defaultPlayers = {
"java Hero",
"java Bully",
"java Coward"
};
final int timeout = 1000;
final int startLife = 1000;
final int startPower = 10;
final int numRounds = 15;
boolean log = false;
List<Player> players;
public static void main(String[] args){
new Stronger().run(args);
}
void run(String[] args){
init(args);
for(int i=0;i<numRounds;i++){
Collections.shuffle(players);
runGame();
}
Collections.sort(players);
for(Player player : players)
System.out.println(player.toString());
}
void runGame(){
log("Player Count: " + players.size());
for(Player player : players)
player.reset();
int turn = 0;
while(turn++ < startLife){
if(aliveCount() < 2)
break;
log("Turn " + turn);
List<Player> clones = new ArrayList<Player>();
for(Player player : players)
clones.add(player.copy());
for(Player player : players){
if(player.life < 1 || player.timedOut)
continue;
String[] args = new String[players.size()+1];
args[0] = "" + player.id;
for(int i=1;i<args.length;i++)
args[i] = players.get(i-1).toArgument();
String reply = getReply(player, args);
Player clone = player.findCopyOrMe(clones);
if(reply.equals("T")){
clone.timedOut = true;
clone.life = 0;
}
clone.lastAction = reply.trim();
}
for(Player player : players){
if(player.life < 1 || player.timedOut)
continue;
Player clone = player.findCopyOrMe(clones);
if(clone.lastAction.equals("D")){
clone.power--;
}else{
try{
int target = Integer.parseInt(clone.lastAction);
for(Player t : players)
if(t.id == target && t.life < 1)
throw new Exception();
for(Player tclone : clones){
if(tclone.id == target){
int atk = player.power;
if(tclone.lastAction.equals("D")){
atk -= player.power / 2;
tclone.power++;
}
tclone.life -= atk;
tclone.power++;
}
}
} catch (Exception e){
log(player.cmd + " returned an invalid command: (" + clone.lastAction + ")");
clone.power--;
}
}
}
players = clones;
for(Player player : players){
if(player.power < 1)
player.power = 1;
log(player.life + "\t\t" + player.power + "\t\t(" + player.id + ")\t" + player.cmd);
}
log("\n");
}
if(aliveCount() == 1)
for(Player player : players)
if(player.life > 0){
player.scoreRounds++;
player.scoreLife += player.life;
}
}
void log(String msg){if(log)System.out.println(msg);}
String getReply(Player player, String[] args){
try{
List<String> cmd = new ArrayList<String>();
String[] tokens = player.cmd.split(" ");
for(String token : tokens)
cmd.add(token);
for(String arg : args)
cmd.add(arg);
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.redirectErrorStream();
long start = System.currentTimeMillis();
Process process = builder.start();
Scanner scanner = new Scanner(process.getInputStream());
process.waitFor();
String reply = scanner.nextLine();
scanner.close();
process.destroy();
if(System.currentTimeMillis() - start > timeout)
return "T";
return reply;
}catch(Exception e){
e.printStackTrace();
return "Exception: " + e.getMessage();
}
}
void init(String[] args){
players = new ArrayList<Player>();
for(String arg : args){
if(arg.toLowerCase().startsWith("-log")){
log = true;
}else{
Player player = createPlayer(arg);
if(player != null)
players.add(player);
}
}
for(String cmd : defaultPlayers){
Player player = createPlayer(cmd);
if(player != null)
players.add(player);
}
}
Player createPlayer(String cmd){
Player player = new Player(cmd);
String reply = getReply(player, new String[]{});
log(player.cmd + " " + reply);
if(reply != null && reply.equals("ok"))
return player;
return null;
}
int aliveCount(){
int alive = 0;;
for(Player player : players)
if(player.life > 0)
alive++;
return alive;
}
static int nextId = 0;
class Player implements Comparable<Player>{
int id, life, power, scoreRounds, scoreLife;
boolean timedOut;
String cmd, lastAction;
Player(String cmd){
this.cmd = cmd;
id = nextId++;
scoreRounds = 0;
scoreLife = 0;
reset();
}
public Player copy(){
Player copy = new Player(cmd);
copy.id = id;
copy.life = life;
copy.power = power;
copy.scoreRounds = scoreRounds;
copy.scoreLife = scoreLife;
copy.lastAction = lastAction;
return copy;
}
void reset(){
life = startLife;
power = startPower;
lastAction = "X";
timedOut = false;
}
Player findCopyOrMe(List<Player> copies){
for(Player copy : copies)
if(copy.id == id)
return copy;
return this;
}
public int compareTo(Player other){
if(scoreRounds == other.scoreRounds)
return other.scoreLife - scoreLife;
return other.scoreRounds - scoreRounds;
}
public String toArgument(){
return id + "," + life + "," + power + "," + lastAction;
}
public String toString(){
String out = "" + scoreRounds + "\t" + scoreLife;
while(out.length() < 20)
out += " ";
return out + "(" + id + ")\t" + cmd;
}
}
}
Regole
Puoi inserire fino a due robot. Se vuoi rimuoverne uno dal gioco per inserire un terzo, ti preghiamo di cancellare il suo post.
Non puoi scegliere come target o altrimenti individuare un bot mediante meta-analisi. Usa solo le informazioni fornite dal tuo bot. Ciò include i tuoi robot, quindi non puoi inserire due robot che colludono.
Non tentare di interferire con il funzionamento del controller o di altri robot in alcun modo.
Il tuo bot non può creare istanze o altrimenti eseguire il controller o altri robot.
risultati
(dei robot inviati dal 22/05/2015 alle 00:00: 00Z)
Questo round di gioco è andato un po 'meglio, con solo due partite bloccate a 1000 turni. Complimenti per il Santayana di Ralph Marshall , che ha preso il primo posto, essendo l'unico bot che ha segnato tre vittorie. Non era abbastanza, quindi ha anche ottenuto il terzo posto con Tactician . Stormcrow è arrivato secondo con Phantom Menace , un ottimo primo post qui. Tutto sommato, abbiamo avuto una bella mostra di nuovi membri, con i primi sei posti assegnati a persone con meno di cinque post. Congratulazioni e benvenuti nel sito!
I robot che hanno segnato zero vincite non sono elencati per risparmiare spazio. Tutti i robot pubblicati prima che il timestamp sopra fosse eseguito, quindi se non vedi i tuoi, non ha vinto nulla.
Wins Life(tiebreaker) Name
3 561 perl Santayana.pl
2 850 java PhantomMenace
2 692 perl Tactician.pl
2 524 java Wiisniper
1 227 java Tank
1 184 java Velociraptor
1 7 java Coward
1 3 java IKnowYou
Controller parallelizzato impreciso Sorta ( di Altri ):
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.FileSystems;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.atomic.AtomicInteger;
public class Stronger {
static final String[] defaultPlayers = {
"java Hero",
"java Bully",
"java Coward",
"java Psycho",
"./monte.out",
"java Analyst",
"java Guardian",
"java Revenger",
"python precog.py",
//"python snappingTurtle.py",
"python beserker.py",
"./suprise.out",
//"python boxer.py",
"python defense.py",
"java Tank",
"java IKnowYou",
//"java BroBot",
"java Equaliser",
"java Velociraptor",
//"java AboveAverage",
"java PhantomMenace",
"java Wiisniper",
//"python semiRandom.py",
"/usr/bin/perl tactition.pl",
"/usr/bin/perl santayana.pl",
//"java GlitchUser"
"/usr/local/bin/Rscript opportunity.R",
"/usr/local/bin/scala Bandwagoner",
};
final int timeout = 5000;
final int startLife = 1000;
final int startPower = 10;
final int numRounds = 20;
boolean log = true;
List<Player> players;
public static void main(String[] args){
new Stronger().run(args);
}
void run(String[] args){
init(args);
for(int i=1;i<=numRounds;i++){
if(log) System.out.println("Begining round "+ i);
Collections.shuffle(players);
runGame();
}
Collections.sort(players);
for(Player player : players)
System.out.println(player.toString());
}
void runGame(){
log("Player Count: " + players.size());
for(Player player : players)
player.reset();
int turn = 0;
while(turn++ < startLife){
if(aliveCount() < 2)
break;
log("Turn " + turn);
List<Player> clones = new ArrayList<Player>();
for(Player player : players)
clones.add(player.copy());
AtomicInteger count=new AtomicInteger(players.size());
for(Player player : players){
new Thread(() -> {
if(player.life >= 1 && !player.timedOut){
String[] args = new String[players.size()+1];
args[0] = "" + player.id;
for(int i=1;i<args.length;i++)
args[i] = players.get(i-1).toArgument();
String reply = getReply(player, args);
Player clone = player.findCopyOrMe(clones);
if(reply.equals("T")){
clone.timedOut = true;
clone.life = 0;
}
clone.lastAction = reply.trim();
}
synchronized(count){
count.decrementAndGet();
count.notify();
}
}).start();
}
synchronized(count){
while(count.get() > 0){
//System.out.println(count);
try{
count.wait();
}catch(InterruptedException e){
}
}
}
for(Player player : players){
if(player.life < 1 || player.timedOut)
continue;
Player clone = player.findCopyOrMe(clones);
if(clone.lastAction.equals("D")){
clone.power--;
}else{
try{
int target = Integer.parseInt(clone.lastAction);
for(Player t : players)
if(t.id == target && t.life < 1)
throw new Exception();
for(Player tclone : clones){
if(tclone.id == target){
int atk = player.power;
if(tclone.lastAction.equals("D")){
atk -= player.power / 2;
tclone.power++;
}
tclone.life -= atk;
tclone.power++;
}
}
} catch (Exception e){
log(player.cmd + " returned an invalid command: (" + clone.lastAction + ")");
clone.power--;
}
}
}
players = clones;
for(Player player : players){
if(player.power < 1)
player.power = 1;
log(player.life + "\t\t" + player.power + "\t\t" + player.lastAction + "\t\t(" + player.id + ")\t" + player.cmd);
}
log("\n");
}
if(aliveCount() == 1)
for(Player player : players)
if(player.life > 0){
player.scoreRounds++;
player.scoreLife += player.life;
}
}
void log(String msg){if(log)System.out.println(msg);}
String getReply(Player player, String[] args){
try{
List<String> cmd = new ArrayList<String>();
String[] tokens = player.cmd.split(" ");
for(String token : tokens)
cmd.add(token);
for(String arg : args)
cmd.add(arg);
ProcessBuilder builder = new ProcessBuilder(cmd);
builder.directory(FileSystems.getDefault().getPath(".", "bin").toFile());
//builder.redirectError(Redirect.PIPE);
long start = System.currentTimeMillis();
Process process = builder.start();
Scanner scanner = new Scanner(process.getInputStream());
process.waitFor();
String reply = scanner.nextLine();
scanner.close();
process.destroy();
if(System.currentTimeMillis() - start > timeout)
return "T";
return reply;
}catch(Exception e){
//e.printStackTrace();
return "Exception: " + e.getMessage();
}
}
void init(String[] args){
players = new ArrayList<Player>();
for(String arg : args){
if(arg.toLowerCase().startsWith("-log")){
log = true;
}else{
Player player = createPlayer(arg);
if(player != null)
players.add(player);
}
}
for(String cmd : defaultPlayers){
Player player = createPlayer(cmd);
if(player != null)
players.add(player);
}
}
Player createPlayer(String cmd){
Player player = new Player(cmd);
String reply = getReply(player, new String[]{});
log(player.cmd + " " + reply);
if(reply != null && reply.equals("ok"))
return player;
return null;
}
int aliveCount(){
int alive = 0;;
for(Player player : players)
if(player.life > 0)
alive++;
return alive;
}
static int nextId = 0;
class Player implements Comparable<Player>{
int id, life, power, scoreRounds, scoreLife;
boolean timedOut;
String cmd, lastAction;
Player(String cmd){
this.cmd = cmd;
id = nextId++;
scoreRounds = 0;
scoreLife = 0;
reset();
}
public Player copy(){
Player copy = new Player(cmd);
copy.id = id;
copy.life = life;
copy.power = power;
copy.scoreRounds = scoreRounds;
copy.scoreLife = scoreLife;
copy.lastAction = lastAction;
return copy;
}
void reset(){
life = startLife;
power = startPower;
lastAction = "X";
timedOut = false;
}
Player findCopyOrMe(List<Player> copies){
for(Player copy : copies)
if(copy.id == id)
return copy;
return this;
}
public int compareTo(Player other){
if(scoreRounds == other.scoreRounds)
return other.scoreLife - scoreLife;
return other.scoreRounds - scoreRounds;
}
public String toArgument(){
return id + "," + life + "," + power + "," + lastAction;
}
public String toString(){
String out = "" + scoreRounds + "\t" + scoreLife;
while(out.length() < 20)
out += " ";
return out + "(" + id + ")\t" + cmd;
}
}
}