Vue d'ensemble
C'est une bataille difficile pour voir qui peut survivre le plus longtemps. Cependant, ces robots augmentent leur puissance en étant attaqués. Vous devez donc bien réfléchir avant de tirer.
À chaque tour, vous pouvez choisir un bot à attaquer ou à défendre. Attaquer réduira sa durée de vie et augmentera sa puissance. Le dernier classement bot gagne.
Bots
Chaque bot commence avec 1000 points de vie et 10 points de puissance.
Lorsque attaqué:
- le pouvoir de votre attaquant est soustrait de votre vie
- votre puissance augmente de 1.
Donc, si au premier tour, vous êtes attaqué par deux bots, vous aurez 980 points de vie et 12 points de puissance.
Si vous choisissez de défendre:
- votre puissance sera réduite de 1
- toutes les attaques contre vous ce tour seront réduites de moitié
- si vous êtes attaqué, vous gagnerez 2 points de pouvoir pour chaque attaquant au lieu de 1
Donc, si vous défendez au premier tour et que vous êtes attaqué par deux robots, vous aurez 990 points de vie et 13 points de vie. Si vous défendez et que vous n'êtes pas attaqué, vous aurez 1000 points de vie, mais 9 points de puissance.
Si à la fin d'un tour votre pouvoir est inférieur à un, il sera mis à un. Si votre vie est inférieure à 1, vous mourrez.
Entrée sortie
Les bots sont appelés une fois par tour. Il y a une limite de temps d'une seconde pour chaque tour.
Initiale
La première fois que votre bot est appelé, aucun argument ne lui sera attribué. Répondre avec ok
. Ceci est fait uniquement pour vous assurer que votre bot répond. Si ce n'est pas le cas, il ne sera pas ajouté à la liste des joueurs.
Chaque tour
Chaque tour, votre bot reçoit des informations sur tous les robots du jeu sous forme d'arguments en ligne de commande. Un exemple de ces arguments est:
1 0,1000,10,1 1,995,11,D
Le premier argument est l'identifiant unique de votre bot. Ensuite, une liste de robots séparés par des espaces apparaît. Chaque bot est formaté comme suit:
id,life,power,lastAction
lastAction
peut être un entier représentant quel bot ils ont attaqué, D
s’ils ont défendu et X
si c’est le premier tour. Les autres sont tous des entiers.
Ainsi, dans l'exemple ci-dessus, vous êtes bot 1
et défendu lors de votre dernier tour. Bot 0
vous a attaqué et est toujours en train de démarrer santé / puissance.
La sortie pour chaque tour est très simple. Indiquez simplement le bot que vous souhaitez attaquer sous forme d’entier (par exemple 0
ou 3
) ou D
à défendre. N'attaquez pas les robots morts ou inexistants, car cela compte comme une commande invalide. Toute commande invalide vous fera perdre 1 puissance.
Structure du tournoi
Chaque jeu comprend tous les robots qui commencent à 1 000 points de vie et 10 points de puissance. Les actions de tous les robots sont prises simultanément. Le nombre maximum de tours pour une partie est de 1000.
Si à la fin du tour il reste un bot en vie (durée de vie> 0), il marque un point et une autre partie est lancée. Si la limite de virage est atteinte et qu'il y a plusieurs robots en vie, personne ne gagne de point. Si tous les robots restants meurent au même tour, personne ne marque un point.
Un tournoi comprend 15 parties. Celui qui a le plus de points à la fin gagne! Les égalités sont brisées par la somme de points de vie restants dans chaque match gagné.
Etat
Les robots ne peuvent lire ou écrire que dans un seul fichier nommé d'après lui-même, dans un sous-dossier direct nommé state
("Hero" peut écrire state/hero.whatever
). Ce fichier ne doit pas dépasser 1024 2 octets de taille. Veillez à respecter le délai. Votre programme doit se terminer en une seconde pour compter, pas seulement pour donner une réponse.
Ces fichiers seront effacés avant chaque tournoi, mais ils persisteront match par match. Tous les identifiants de bot ( id
) resteront également les mêmes entre les jeux.
Manette
Ci-dessous, le contrôleur de tournoi ( Stronger.java
). Par défaut , seuls les résultats finaux (liste triée des joueurs, vainqueur en haut) sont affichés, ce qui peut prendre un certain temps. Ce n'est pas gelé, juste silencieux. Si vous souhaitez une sortie détaillée plus détaillée, ajoutez l' -log
argument lors de l'exécution.
Pour ajouter des robots, vous avez deux options:
ajoute la commande en argument (
java Stronger -log "python bot.py"
)ajouter la commande à
defaultPlayers[]
la source ("python bot.py"
)
Les robots Hero , Bully et Coward peuvent être trouvés dans cette réponse et seront utilisés à des fins de notation.
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;
}
}
}
Règles
Vous pouvez entrer jusqu'à deux robots. Si vous souhaitez supprimer un joueur du jeu pour en entrer un troisième, supprimez son message.
Vous ne pouvez pas cibler ou sélectionner un bot par méta-analyse. Utilisez uniquement les informations de votre bot. Cela inclut vos propres robots, vous ne pouvez donc pas entrer deux robots qui se complètent.
N'essayez en aucun cas d'interférer avec le fonctionnement du contrôleur ou d'autres robots.
Votre bot ne peut pas instancier ni faire tourner le contrôleur ou d’autres bots.
Résultats
(de bots envoyés à partir du 2015-05-22 00: 00: 00Z)
Cette ronde de jeu s’est un peu améliorée, avec seulement deux parties en retard à 1000 tours. Félicitations à Santayana de Ralph Marshall , qui est devenu le seul bot à avoir remporté trois victoires. Cela ne suffisait pas, alors il a également pris la troisième place avec Tactician . Stormcrow a pris la deuxième place avec Phantom Menace , un excellent premier poste ici. Dans l’ensemble, nous avons eu une très belle représentation de nouveaux membres, les six premières places étant attribuées à des personnes comptant moins de cinq postes. Félicitations et bienvenue sur le site!
Les bots qui ont marqué zéro victoire ne sont pas répertoriés pour économiser de l'espace. Tous les bots postés avant le timestamp ci-dessus ont été exécutés, donc si vous ne voyez pas le vôtre, cela ne gagnera rien.
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
Contrôleur parallélisé peu précis ( par Autres ):
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;
}
}
}