Gambaran
Ini adalah pertempuran bot untuk melihat siapa yang bisa bertahan paling lama. Bot ini meningkatkan kekuatannya dengan diserang, jadi Anda harus berpikir dengan hati-hati sebelum menembak.
Setiap belokan, Anda dapat memilih bot untuk diserang, atau bertahan. Menyerang akan menurunkan hidupnya dan meningkatkan kekuatannya. Posisi bot terakhir menang.
Bot
Setiap bot dimulai dengan 1000 life dan 10 power.
Saat diserang:
- kekuatan penyerang Anda dikurangi dari hidup Anda
- kekuatanmu meningkat sebesar 1.
Jadi, jika pada belokan pertama, Anda diserang oleh dua bot, Anda akan memiliki 980 nyawa dan 12 kekuatan.
Jika Anda memilih untuk membela:
- kekuatanmu akan diturunkan 1
- semua serangan terhadap Anda giliran ini akan berkurang setengahnya
- jika Anda diserang, Anda akan mendapatkan 2 kekuatan untuk setiap penyerang, bukan 1
Jadi, jika Anda bertahan di tikungan pertama dan diserang oleh dua bot, Anda akan memiliki 990 nyawa dan 13 kekuatan. Jika Anda bertahan dan tidak diserang, Anda akan memiliki 1000 nyawa, tetapi 9 kekuatan.
Jika pada akhir putaran, kekuatan Anda di bawah satu, itu akan diatur ke satu. Jika hidup Anda di bawah 1, Anda mati.
Input output
Bot disebut sekali per giliran. Ada batas waktu satu detik untuk setiap belokan.
Awal
Pertama kali bot Anda dipanggil, ia tidak akan diberikan argumen. Tanggapi dengan ok
. Ini dilakukan hanya untuk memastikan bot Anda merespons. Jika tidak, itu tidak akan ditambahkan ke daftar pemain.
Setiap belokan
Setiap belokan, bot Anda diberikan informasi tentang semua bot dalam game sebagai argumen baris perintah. Contoh argumen ini adalah:
1 0,1000,10,1 1,995,11,D
Argumen pertama adalah id unik bot Anda. Kemudian, daftar bot yang dipisahkan spasi muncul. Setiap bot diformat sebagai:
id,life,power,lastAction
lastAction
mungkin bilangan bulat yang mewakili bot mana yang mereka serang, D
jika mereka pertahankan, dan X
jika ini adalah giliran pertama. Yang lainnya semuanya adalah bilangan bulat.
Jadi, dalam contoh di atas, Anda bot 1
dan dipertahankan pada giliran terakhir Anda. Bot 0
menyerang Anda dan masih memulai kesehatan / kekuatan.
Output untuk setiap belokan sangat sederhana. Cukup output bot yang ingin Anda serang sebagai integer (misalnya 0
atau 3
), atau D
untuk dipertahankan. Jangan menyerang bot yang mati atau tidak ada, karena dianggap sebagai perintah yang tidak valid. Perintah yang tidak valid akan menyebabkan Anda kehilangan 1 kekuatan.
Struktur Turnamen
Setiap permainan terdiri dari semua bot mulai dari 1000 kesehatan dan 10 kekuatan. Tindakan oleh semua bot dilakukan secara bersamaan. Jumlah belokan maksimum untuk game adalah 1000.
Jika pada akhir pergantian ada satu bot tersisa hidup (hidup> 0), itu mencetak satu poin dan permainan lain dimulai. Jika batas belok tercapai dan ada beberapa bot hidup, tidak ada yang mendapat poin. Jika semua bot yang tersisa mati pada giliran yang sama, tidak ada yang mendapat poin.
Turnamen terdiri dari 15 pertandingan. Siapa pun yang memiliki poin terbanyak pada akhirnya akan menang! Ikatan rusak oleh jumlah sisa hidup dalam setiap pertandingan yang dimenangkan.
Negara
Bot hanya dapat membaca dari atau menulis ke satu file bernama setelah itu sendiri, dalam subfolder langsung bernama state
("Pahlawan" dapat menulis ke state/hero.whatever
). Ukuran file ini tidak boleh lebih dari 1024 2 byte. Berhati-hatilah untuk mematuhi batas waktu. Program Anda harus berhenti dalam satu detik untuk dihitung, bukan hanya memberikan respons.
File-file ini akan dihapus sebelum setiap turnamen, tetapi akan bertahan dari pertandingan ke pertandingan. Semua pengidentifikasi bot ( id
) juga akan tetap sama di antara game.
Pengendali
Di bawah ini adalah pengontrol turnamen ( Stronger.java
). Secara default , ini hanya menampilkan hasil akhir (daftar pemain yang disortir, pemenang di atas), yang mungkin memakan waktu cukup lama. Itu tidak beku, hanya diam. Jika Anda ingin keluaran per tikungan yang lebih terperinci, tambahkan -log
argumen saat menjalankan.
Untuk menambahkan bot, Anda memiliki dua opsi:
tambahkan perintah sebagai argumen (
java Stronger -log "python bot.py"
)tambahkan perintah ke
defaultPlayers[]
dalam sumber ("python bot.py"
)
Bot Hero , Bully , dan Coward dapat ditemukan dalam jawaban ini , dan akan digunakan untuk tujuan penilaian.
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;
}
}
}
Aturan
Anda dapat memasukkan hingga dua bot. Jika Anda ingin menghapus satu dari permainan untuk memasukkan yang ketiga, harap hapus posnya.
Anda tidak boleh menargetkan atau memilih bot berdasarkan meta-analisis. Gunakan hanya informasi yang diberikan bot Anda. Ini termasuk bot Anda sendiri, jadi Anda tidak boleh memasukkan dua bot yang berkolusi.
Jangan mencoba mengganggu jalannya pengontrol atau bot lain dengan cara apa pun.
Bot Anda mungkin tidak membuat atau menjalankan controller atau bot lain.
Hasil
(bot yang dikirimkan pada 2015-05-22 00: 00: 00Z)
Putaran permainan ini berjalan sedikit lebih baik, dengan hanya dua pertandingan yang berakhir pada 1000 putaran. Kudos to Ralph Marshall's Santayana , yang mengambil tempat pertama, menjadi satu-satunya bot yang mencetak tiga kemenangan. Itu tidak cukup, jadi dia juga mengambil tempat ketiga dengan Tactician . Stormcrow mengambil posisi kedua dengan Phantom Menace , posting pertama yang bagus di sini. Semua dalam semua kami memiliki pertunjukan yang sangat bagus oleh anggota baru, dengan enam tempat teratas pergi ke orang-orang dengan kurang dari lima posting. Selamat, dan selamat datang di situs ini!
Bot yang mendapat skor nol menang tidak terdaftar untuk menghemat ruang. Semua bot yang diposting sebelum stempel waktu di atas dijalankan, jadi jika Anda tidak melihat milik Anda, itu tidak memenangkan apa pun.
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
Pengontrol paralel paralel agak samar ( oleh Orang Lain ):
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;
}
}
}