概要
これは、誰が最も長く生き残ることができるかを確認するためのボットバトルです。ただし、これらのボットは攻撃されることでパワーを高めますので、撮影する前に慎重に考える必要があります。
ターンごとに、攻撃または防御するボットを選択できます。攻撃するとライフが低下し、パワーが増加します。最後のボットが勝ちます。
ボット
各ボットは1000のライフと10のパワーで始まります。
攻撃されたとき:
- 攻撃者の力があなたの人生から差し引かれます
- あなたの力は1上昇します。
したがって、最初のターンで2つのボットに攻撃された場合、980のライフと12のパワーがあります。
防御することを選択した場合:
- あなたの力は1低下します
- このターンのあなたに対するすべての攻撃は半分に減少します
- 攻撃を受けた場合、攻撃者ごとに1から2のパワーが得られます
したがって、最初のターンで防御し、2つのボットに攻撃された場合、990のライフと13のパワーがあります。防御して攻撃されない場合、1000のライフがありますが、パワーは9です。
ターンの終わりにあなたのパワーが1未満の場合、1に設定されます。あなたの人生が1歳未満の場合、あなたは死にます。
入出力
ボットは1ターンに1回呼び出されます。各ターンに1秒の時間制限があります。
初期
ボットが初めて呼び出されたとき、引数は与えられません。で応答しok
ます。これは、ボットが応答することを確認するためにのみ行われます。そうでない場合は、プレーヤーリストに追加されません。
各ターン
各ターンで、ボットにはコマンドライン引数としてゲーム内のすべてのボットに関する情報が与えられます。これらの引数の例は次のとおりです。
1 0,1000,10,1 1,995,11,D
最初の引数はボットの一意のIDです。次に、スペースで区切られたボットのリストが表示されます。各ボットの形式は次のとおりです。
id,life,power,lastAction
lastAction
攻撃したボットD
、防御したX
場合、およびこれが最初のターンである場合を表す整数です。その他はすべて整数です。
したがって、上記の例では、あなたは1
最後のターンでボットであり、防御されています。ボット0
はあなたを攻撃し、まだヘルス/パワーを開始しています。
各ターンの出力は非常に簡単です。攻撃するボットを整数(0
または3
)として出力するかD
、防御するだけです。無効なボットや存在しないボットを攻撃しないでください。無効なコマンドとしてカウントされます。無効なコマンドがあると、パワーが1つ失われます。
トーナメント構造
各ゲームは、体力1000、パワー10で始まるすべてのボットで構成されています。すべてのボットによるアクションは同時に実行されます。ゲームの最大ターン数は1000です。
ターンの終わりに1つのボットが生きている(ライフ> 0)場合、1ポイントを獲得し、別のゲームが開始されます。ターン制限に達し、複数のボットが生きている場合、誰もポイントを獲得しません。残りのすべてのボットが同じターンに死亡した場合、誰もポイントを獲得しません。
トーナメントは15ゲームで構成されています。最後に最もポイントを持っている人が勝ちます!勝った各ゲームに残っているライフの合計によってネクタイが壊れます。
状態
ボットは、名前が付けられた直接のサブフォルダーstate
( "Hero"は書き込み可能state/hero.whatever
)内で、名前が付けられた単一のファイルからのみ読み取りまたは書き込みを行うことができます。このファイルは、サイズが1024 2バイトを超えてはなりません。時間制限に注意してください。プログラムは、応答するだけでなく、カウントするために1秒以内に終了する必要があります。
これらのファイルは、各トーナメントの前に消去されますが、ゲーム間で保持されます。すべてのボット識別子(id
)もゲーム間で同じままです。
コントローラ
以下はトーナメントコントローラー(Stronger.java
)です。デフォルトでは、最終結果(プレイヤーのソートされたリスト、勝者が一番上)のみを出力しますが、これにはかなり時間がかかる場合があります。凍結されていません、ただ静かです。より詳細なターンバイターン出力が必要-log
な場合は、実行時に引数を追加してください。
ボットを追加するには、2つのオプションがあります。
引数としてコマンドを追加します(
java Stronger -log "python bot.py"
)defaultPlayers[]
ソースにコマンドを追加します("python bot.py"
)
ボットのHero、Bully、およびCowardは、この回答で見つけることができ、スコアリングの目的で使用されます。
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;
}
}
}
ルール
最大2つのボットを入力できます。プレイから1つを削除して3つ目を入力する場合は、その投稿を削除してください。
メタ分析によってボットをターゲットにしたり、その他の方法でボットを選択することはできません。ボットに提供された情報のみを使用してください。これには独自のボットが含まれるため、共謀する2つのボットを入力することはできません。
コントローラーや他のボットの実行を一切妨害しないでください。
ボットは、コントローラーまたは他のボットをインスタンス化または実行することはできません。
結果
(2015-05-22 00:00:00Z時点で提出されたボットの)
このラウンドのプレイは少し良くなり、1000ターンで2ゲームしかストールしませんでした。Ralph MarshallのSantayanaへの称賛は、1位を獲得し、3つの勝利を獲得した唯一のボットでした。それは十分ではなかったので、彼はまたして第三位を取った戦術家。StormcrowはPhantom Menaceで2位になりました。ここで最初の素晴らしい投稿です。全体として、新しいメンバーによる非常に素晴らしいショーが行われ、上位6か所が5未満の投稿を持つ人々に行きました。おめでとう、サイトへようこそ!
勝利をゼロにしたボットは、スペースを節約するためにリストされていません。上記のタイムスタンプの前に投稿されたすべてのボットが実行されたため、自分のボットが表示されない場合、何も勝ちませんでした。
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
ソータスケッチパラレルコントローラー(その他):
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;
}
}
}