genel bakış
Bu, kimin daha uzun süre hayatta kalabileceğini görmek için yapılan bir bot savaşı. Bu botlar saldırıya maruz kaldıklarında güçlerini arttırıyorlar, bu yüzden ateş etmeden önce dikkatlice düşünmeniz gerekiyor.
Her turda, saldırmak veya savunmak için bir bot seçebilirsiniz. Saldırmak ömrünü düşürecek ve gücünü artıracak. En son bot ayakta kazanır.
botlar
Her bot 1000 ömür ve 10 güçle başlar.
Saldırıya uğradığında:
- saldırganın gücü hayatından kesildi
- Gücün 1 artar.
Öyleyse, ilk dönüşte iki bot tarafından saldırıya uğrarsanız, 980 ömre ve 12 güce sahip olacaksınız.
Savunmayı seçerseniz:
- Gücün 1 azalacak
- bu dönüş size karşı tüm saldırıları yarı yarıya azaltacaktır
- Eğer saldırıya uğrarsanız, her saldırgan için 1 saldırı yerine 2 güç kazanacaksınız.
Yani, ilk dönüşte savunursanız ve iki bot tarafından saldırıya uğrarsanız, 990 ömre ve 13 güce sahip olacaksınız. Savunduysanız ve saldırıya uğramazsanız, 1000 ömre ancak 9 güce sahip olacaksınız.
Bir dönüşün sonunda gücünüz birin altındaysa, bire ayarlanır. Hayatın 1'in altındaysa ölürsün.
Giriş çıkış
Her turda botlar bir kere çağrılır. Her tur için bir saniyelik zaman sınırı vardır.
ilk
Botunuz ilk defa çağrıldığında, hiçbir argüman verilmez. İle cevap ver ok
. Bu sadece botunuzun yanıt verdiğinden emin olmak için yapılır. Olmazsa, oyuncu listesine eklenmeyecektir.
Her dönüş
Her turda, botunuza oyundaki tüm botlar hakkında komut satırı argümanları olarak bilgi verilir. Bu argümanların bir örneği:
1 0,1000,10,1 1,995,11,D
İlk argüman botunuzun benzersiz kimliğidir. Ardından, boşlukla ayrılmış bir bot listesi görünür. Her bot şöyle biçimlendirilir:
id,life,power,lastAction
lastAction
Hangi bota saldırdıklarını, D
savundukları X
takdirde ve bu ilk sıranın olup olmadığını gösteren bir tam sayı olabilir . Diğerleri tam sayıdır.
Yani yukarıdaki örnekte 1
, son sıranızda bot ve savunuyorsunuz. Bot 0
sana saldırdı ve hala sağlık / güç başında.
Her tur için çıktı çok basittir. Basitçe bir tamsayı olarak saldırmak istediğiniz botu seçin (örn. 0
Veya 3
) veya D
savunmak için. Ölü ya da olmayan botlara saldırmayın, çünkü bu geçersiz bir komut sayılır. Herhangi bir geçersiz komut, 1 güç kaybetmenize neden olacaktır.
Turnuva Yapısı
Her oyun 1000 sağlık ve 10 güçten başlayan tüm botlardan oluşur. Tüm botların eylemleri aynı anda gerçekleştirilir. Bir oyun için maksimum tur sayısı 1000'dir.
Dönüşün sonunda hayatta kalan bir bot varsa (hayat> 0), bir puan alır ve başka bir oyuna başlar. Dönüş limitine ulaşılırsa ve hayatta birden fazla bot varsa, kimse puan kazanmaz. Kalan tüm botlar aynı sırada ölürse kimse puan kazanmaz.
Bir turnuva 15 oyundan oluşur. Sonunda en fazla puana sahip olan kazanır! Kazanılan her maçta kalan ömürler ile bağlar kopar.
Durum
Botlar, yalnızca kendisinden sonra adlandıran tek bir dosyayı okuyabilir veya bu dosyaya yazabilir state
("Kahraman" yazabilir state/hero.whatever
). Bu dosyanın boyutu 1024 2 baytı geçmemelidir . Zaman sınırını gözetmeye özen gösterin. Programınız sadece bir yanıt vermek için değil, bir saniye içinde sona ermelidir .
Bu dosyalar her turnuvadan önce silinecek ancak oyuna devam edecek. Tüm bot tanımlayıcıları ( id
) ayrıca oyunlar arasında aynı kalacaktır.
kontrolör
Turnuva denetleyicisi aşağıdadır ( Stronger.java
). Varsayılan olarak , yalnızca uzun bir süre alabilen nihai sonuçları (sıralanan oyuncu listesini, en üstte kazanan) çıkarır. Donmuş değil, sadece sessiz. Daha ayrıntılı bir dönüşe dönüş çıkışı istiyorsanız, -log
çalıştırırken argümanı ekleyin .
Bot eklemek için iki seçeneğiniz var:
komutu argüman olarak ekle (
java Stronger -log "python bot.py"
)komutu
defaultPlayers[]
kaynağa ekleyin ("python bot.py"
)
Botlar Hero , Bully ve Coward bu cevabın içinde bulunabilir ve puanlama amacıyla kullanılacaktır.
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;
}
}
}
kurallar
İki taneye kadar bot girebilirsiniz . Üçüncüyü girmek için birini oyundan çıkarmak istiyorsanız, lütfen gönderimini silin.
Meta analizi yaparak bir botu hedefleyemez veya başka bir şekilde seçemezsiniz. Sadece botunuzun verdiği bilgileri kullanın. Bu, kendi botlarınızı içerir, bu nedenle, iki gizli kollamaya giremezsiniz.
Kontrolörün veya diğer botların çalışmasına herhangi bir şekilde müdahale etmeyin.
Botunuz denetleyiciyi veya diğer botları başlatamaz veya başlatamaz.
Sonuçlar
(2015-05-22 00: 00: 00Z tarihleri arasında gönderilen botlardan)
Bu oyun turu biraz daha iyi gitti, sadece 1000 maçta iki maç kaldı. Ralph Marshall'ın birinci olan ve üç galibiyet kazanan tek bot olan Santayana'nın şerefine . Bu yeterli değildi, bu yüzden aynı zamanda Tactician ile üçüncü oldu . Stormcrow , burada ilk güzel yazı olan Phantom Menace ile ikinci oldu . Sonuçta yeni üyelerimiz tarafından çok güzel bir gösteri yaptık, ilk altı sıra beş kişiden az insanlara gidiyor. Tebrikler ve sitemize hoş geldiniz!
Sıfır galibiyet alan botlar yer kazanmak için listelenmemiş. Yukarıdaki zaman damgasından önce gönderilen tüm botlar çalıştırıldı, bu yüzden sizinkini görmediyseniz, hiçbir şey kazanmadı.
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 yarım yamalak paralel denetleyici ( Diğerleri tarafından ):
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;
}
}
}