개요
이것은 누가 가장 오래 살아남을 수 있는지에 대한 봇 전투입니다. 이 봇은 공격을 받아 힘을 증가 시키므로 촬영하기 전에 신중하게 생각해야합니다.
매 턴마다 공격하거나 방어 할 봇을 선택할 수 있습니다. 공격하면 생명력이 떨어지고 힘이 증가합니다. 마지막 봇 스탠딩이 승리합니다.
봇
각 봇은 1000의 생명과 10의 힘으로 시작합니다.
공격 당했을 때 :
- 공격자의 힘이 당신의 삶에서 공제됩니다.
- 당신의 힘이 1 증가합니다.
따라서 첫 턴에 2 개의 봇에 의해 공격을 받으면 생명력이 980이고 힘이 12입니다.
방어하기로 선택한 경우 :
- 당신의 힘은 1만큼 낮아집니다
- 이번 턴에 대한 모든 공격은 절반으로 줄어 듭니다
- 공격을 받으면 각 공격자마다 1의 힘이 아닌 2의 힘을 얻습니다.
따라서 첫 턴에서 방어하고 두 봇에 의해 공격을 받으면 생명력이 990, 힘이 13입니다. 방어하고 공격받지 않으면 1000의 생명력을 가지지 만 9의 힘을 얻습니다.
턴이 끝날 때 당신의 힘이 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입니다.
턴이 끝날 때 한 봇이 살아남 으면 (라이프> 0) 한 점을 획득하고 다른 게임을 시작합니다. 턴 제한에 도달하고 여러 봇이 살아 있으면 아무도 점수를 얻지 못합니다 . 남은 봇이 모두 같은 턴에 죽으면 아무도 점수를 얻지 못합니다.
토너먼트는 15 개의 게임으로 구성됩니다. 마지막에 가장 많은 점수를 얻은 사람이 승리합니다! 동점은 각 원 게임에서 남은 생명의 합계에 의해 깨집니다.
상태
봇은 이름이 지정된 직접 하위 폴더 state
( "Hero"는 쓸 수 있음 state/hero.whatever
) 에서 이름이 지정된 단일 파일에서만 읽거나 쓸 수 있습니다 . 이 파일의 크기 는 1024 2 바이트를 초과하지 않아야 합니다. 시간 제한을 준수하십시오. 프로그램은 응답 만하는 것이 아니라 1 초 이내에 종료 되어야합니다 .
이 파일은 토너먼트 전에 지워지지 만 게임 간 게임은 유지됩니다. 모든 봇 식별자 ( id
)도 게임간에 동일하게 유지됩니다.
제어 장치
아래는 토너먼트 컨트롤러 ( Stronger.java
)입니다. 기본적으로 최종 결과 (정렬 된 플레이어 목록, 상단에있는 승자) 만 출력하는데 꽤 오래 걸릴 수 있습니다. 얼지 않고 조용합니다. 보다 자세한 턴 바이 턴 출력을 원하면 -log
실행시 인수를 추가하십시오 .
봇을 추가하려면 다음 두 가지 옵션이 있습니다.
명령을 인수로 추가하십시오 (
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 개의 봇을 입력 할 수 있습니다 . 플레이에서 하나를 제거하여 세 번째를 입력하려면 게시물을 삭제하십시오.
메타 분석을 통해 봇을 타겟팅하거나 다른 방법으로 꼽을 수 없습니다. 봇이 제공 한 정보 만 사용하십시오. 여기에는 자신의 봇이 포함되어 있으므로 충돌하는 두 개의 봇을 입력 할 수 없습니다.
컨트롤러 또는 다른 봇의 작동을 방해하지 마십시오.
봇은 컨트롤러 또는 다른 봇을 인스턴스화하거나 달리 실행할 수 없습니다.
결과
(2015-05-22 00 : 00 : 00Z 현재 제출 된 봇)
이 라운드는 조금 더 나아졌으며, 두 번의 게임 만 1000 턴에 멈췄습니다. 랄프 마샬의 산타 야나 에게 첫 승리를 거두며 3 승을 거둔 유일한 봇이었습니다. 충분하지 않았기 때문에 그는 또한 Tactician 과 3 위를 차지했습니다 . Stormcrow는 Phantom Menace 와 함께 두 번째로 좋은 첫 번째 게시물입니다. 전체적으로 우리는 새로운 회원들에 의해 매우 멋진 공연을했으며 상위 6 곳은 5 개 미만의 게시물을 가진 사람들에게 전달되었습니다. 축하합니다. 사이트에 오신 것을 환영합니다!
0 승을 거둔 봇은 공간을 절약하기 위해 표시되지 않습니다. 위의 타임 스탬프 이전에 게시 된 모든 봇은 실행되었으므로 내 봇이 보이지 않으면 아무 것도 얻지 못했습니다.
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 스케치 병렬 컨트롤러 ( 기타 ) :
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;
}
}
}