Überblick
Dies ist ein Bot-Kampf, um zu sehen, wer am längsten überleben kann. Diese Bots erhöhen jedoch ihre Kraft, indem sie angegriffen werden. Sie müssen also sorgfältig überlegen, bevor Sie schießen.
In jedem Zug kannst du einen Bot zum Angreifen oder Verteidigen auswählen. Ein Angriff verringert seine Lebensdauer und erhöht seine Kraft. Der letzte stehende Bot gewinnt.
Bots
Jeder Bot beginnt mit 1000 Lebenspunkten und 10 Kräften.
Wenn angegriffen:
- Die Macht deines Angreifers wird von deinem Leben abgezogen
- Deine Kraft erhöht sich um 1.
Wenn Sie also in der ersten Runde von zwei Bots angegriffen werden, haben Sie 980 Leben und 12 Kräfte.
Wenn Sie sich zur Verteidigung entscheiden:
- Deine Kraft wird um 1 verringert
- Alle Angriffe gegen dich in diesem Zug werden um die Hälfte reduziert
- Wenn du angegriffen wirst, erhältst du für jeden Angreifer 2 anstatt 1
Wenn Sie also in der ersten Runde verteidigen und von zwei Bots angegriffen werden, haben Sie 990 Leben und 13 Kräfte. Wenn du verteidigst und nicht angegriffen wirst, hast du 1000 Lebenspunkte, aber 9 Kraftpunkte.
Wenn deine Kraft am Ende einer Runde unter eins liegt, wird sie auf eins gesetzt. Wenn dein Leben unter 1 ist, stirbst du.
Input-Output
Bots werden einmal pro Spielzug aufgerufen. Es gibt ein Zeitlimit von einer Sekunde für jede Runde.
Initiale
Wenn Ihr Bot zum ersten Mal aufgerufen wird, werden ihm keine Argumente gegeben. Antworten Sie mit ok
. Dies geschieht nur, um sicherzustellen, dass Ihr Bot reagiert. Ist dies nicht der Fall, wird es nicht zur Spielerliste hinzugefügt.
Jede Runde
In jeder Runde erhält Ihr Bot Informationen zu allen Bots im Spiel als Befehlszeilenargumente. Ein Beispiel für diese Argumente ist:
1 0,1000,10,1 1,995,11,D
Das erste Argument ist die eindeutige ID Ihres Bots. Dann wird eine durch Leerzeichen getrennte Liste von Bots angezeigt. Jeder Bot ist wie folgt formatiert:
id,life,power,lastAction
lastAction
kann eine ganze Zahl sein, die angreift, D
ob sie verteidigt haben oder X
ob dies die erste Runde ist. Die anderen sind alle ganze Zahlen.
Im obigen Beispiel bist du also ein Bot 1
und verteidigst dich in deinem letzten Zug. Der Bot 0
hat dich angegriffen und ist immer noch am Starten von Gesundheit / Kraft.
Die Ausgabe für jede Runde ist sehr einfach. Geben Sie einfach den Bot aus, den Sie als Ganzzahl angreifen (z. B. 0
oder 3
) oder D
verteidigen möchten . Greife keine toten oder nicht existierenden Bots an, da dies als ungültiger Befehl gilt. Jeder ungültige Befehl führt dazu, dass Sie 1 Potenz verlieren.
Turnierstruktur
Jedes Spiel besteht aus allen Bots ab 1000 Lebenspunkten und 10 Kräften. Aktionen aller Bots werden gleichzeitig ausgeführt. Die maximale Anzahl von Runden für ein Spiel beträgt 1000.
Wenn am Ende des Zuges noch ein Bot am Leben ist (Leben> 0), erhält er einen Punkt und ein anderes Spiel wird gestartet. Wenn das Turn-Limit erreicht ist und mehrere Bots am Leben sind, bekommt niemand einen Punkt. Wenn alle verbleibenden Bots im selben Zug sterben, bekommt niemand einen Punkt.
Ein Turnier besteht aus 15 Spielen. Wer am Ende die meisten Punkte hat, gewinnt! Gleichstände werden durch die Summe der verbleibenden Lebenspunkte in jedem gewonnenen Spiel unterbrochen.
Zustand
Bots können nur aus einer einzelnen Datei mit dem Namen state
"Hero" in einem direkten Unterordner mit dem Namen "Hero" lesen oder in diese schreiben state/hero.whatever
. Diese Datei sollte nicht größer als 1024 2 Byte sein. Beachten Sie das Zeitlimit. Ihr Programm muss beenden innerhalb einer Sekunde zu zählen , nicht nur eine Antwort geben.
Diese Dateien werden vor jedem Turnier gelöscht, bleiben aber Spiel für Spiel bestehen. Alle Bot-Bezeichner ( id
) bleiben auch zwischen den Spielen gleich.
Regler
Unten ist der Turniercontroller ( Stronger.java
). Standardmäßig werden nur die Endergebnisse ausgegeben (sortierte Liste der Spieler, Gewinner oben), was eine Weile dauern kann. Es ist nicht gefroren, nur still. Wenn Sie eine detailliertere Turn-by-Turn-Ausgabe wünschen, fügen Sie das -log
Argument bei der Ausführung hinzu.
Um Bots hinzuzufügen, haben Sie zwei Möglichkeiten:
füge den Befehl als Argument hinzu (
java Stronger -log "python bot.py"
)füge den Befehl
defaultPlayers[]
in der source ("python bot.py"
) hinzu
Die Bots Hero , Bully und Coward sind in dieser Antwort zu finden und werden für Bewertungszwecke verwendet.
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;
}
}
}
Regeln
Sie können bis zu zwei Bots eingeben . Wenn Sie eines aus dem Spiel entfernen möchten, um ein drittes zu betreten, löschen Sie bitte seinen Beitrag.
Sie dürfen einen Bot nicht durch Metaanalyse anvisieren oder anderweitig herausgreifen. Verwenden Sie nur die Informationen, die Ihr Bot enthält. Dies schließt Ihre eigenen Bots ein, so dass Sie nicht zwei Bots eingeben dürfen, die zusammenarbeiten.
Versuchen Sie nicht, den Betrieb des Controllers oder anderer Bots in irgendeiner Weise zu stören.
Ihr Bot kann den Controller oder andere Bots möglicherweise nicht instanziieren oder auf andere Weise ausführen.
Ergebnisse
(von Bots, die ab dem 22.05.2015 00: 00: 00Z eingereicht wurden)
Diese Runde verlief etwas besser, da nur zwei Spiele bei 1000 Runden ausfielen. Ein großes Lob an Ralph Marshalls Santayana , der als einziger Bot drei Siege erzielte. Das war nicht genug, deshalb belegte er mit Tactician auch den dritten Platz . Stormcrow wurde mit Phantom Menace Zweiter , ein guter erster Beitrag hier. Alles in allem hatten wir eine sehr schöne Vorstellung von neuen Mitgliedern. Die ersten sechs Plätze gingen an Leute mit weniger als fünf Beiträgen. Herzlichen Glückwunsch und willkommen auf der Seite!
Bots, die null Siege erzielt haben, werden aus Platzgründen nicht aufgelistet. Alle Bots, die vor dem obigen Zeitstempel gepostet wurden, wurden ausgeführt. Wenn Sie also Ihren nicht sehen, hat er nichts gewonnen.
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
Sorta skizzenhaften parallelisierten Controller ( von anderen ):
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;
}
}
}