ภาพรวม
นี่คือการต่อสู้บอทเพื่อดูว่าใครสามารถอยู่รอดได้นานที่สุด บอทเหล่านี้เพิ่มพลังของพวกเขาโดยการถูกโจมตีดังนั้นคุณต้องคิดให้รอบคอบก่อนยิง
ทุกเทิร์นคุณสามารถเลือกบอทเพื่อโจมตีหรือป้องกัน การโจมตีจะลดพลังชีวิตและเพิ่มพลัง ธ ปทที่ยืนอยู่สุดท้ายชนะ
บอท
บอทแต่ละอันเริ่มต้นด้วย 1,000 ชีวิตและ 10 พลัง
เมื่อถูกโจมตี:
- พลังโจมตีของคุณถูกลบออกจากชีวิตของคุณ
- พลังของคุณเพิ่มขึ้น 1
ดังนั้นถ้าในเทิร์นแรกคุณถูกโจมตีโดยบอทสองตัวคุณจะมีพลังชีวิต 980 และพลัง 12
หากคุณเลือกที่จะปกป้อง:
- พลังของคุณจะลดลง 1
- การโจมตีกับคุณในเทิร์นนี้จะลดลงครึ่งหนึ่ง
- หากคุณถูกโจมตีคุณจะได้รับ 2 Power สำหรับผู้โจมตีแต่ละคนแทนที่จะเป็น 1
ดังนั้นถ้าคุณป้องกันในเทิร์นแรกและถูกโจมตีโดยสองบอทคุณจะมีชีวิต 990 และพลัง 13 หากคุณปกป้องและไม่ถูกโจมตีคุณจะมี 1,000 ชีวิต แต่มีพลัง 9 อย่าง
หากในตอนท้ายของการเปิดพลังงานของคุณต่ำกว่าหนึ่งก็จะถูกตั้งค่าเป็นหนึ่ง หากชีวิตของคุณต่ำกว่า 1 คุณจะตาย
Input / Output
บอทจะถูกเรียกหนึ่งครั้งต่อเทิร์น มีการ จำกัด เวลาหนึ่งวินาทีในแต่ละเทิร์น
แรกเริ่ม
ครั้งแรกที่บอทของคุณถูกเรียกมันจะไม่มีการโต้แย้ง ok
ตอบสนองกับ สิ่งนี้ทำเพื่อให้แน่ใจว่าบอทของคุณตอบสนองเท่านั้น หากไม่เป็นเช่นนั้นจะไม่ถูกเพิ่มลงในรายการผู้เล่น
แต่ละเทิร์น
ทุกเทิร์นบอทของคุณจะได้รับข้อมูลเกี่ยวกับบอตทั้งหมดในเกมเป็นอาร์กิวเมนต์บรรทัดคำสั่ง ตัวอย่างของข้อโต้แย้งเหล่านี้คือ:
1 0,1000,10,1 1,995,11,D
อาร์กิวเมนต์แรกคือรหัสที่ไม่ซ้ำกันของบอทของคุณ จากนั้นรายการบ็อตที่คั่นด้วยช่องว่างจะปรากฏขึ้น แต่ละบอทถูกจัดรูปแบบเป็น:
id,life,power,lastAction
lastAction
อาจเป็นจำนวนเต็มแทนบอทที่พวกเขาโจมตีD
ถ้าพวกเขาปกป้องและX
ถ้านี่คือเทิร์นแรก ส่วนอื่นเป็นจำนวนเต็มทั้งหมด
ดังนั้นในตัวอย่างข้างต้นคุณเป็นบอท1
และได้รับการปกป้องในเทิร์นสุดท้ายของคุณ บอท0
โจมตีคุณและยังอยู่ในช่วงเริ่มต้นสุขภาพ / พลัง
ผลลัพธ์สำหรับการเลี้ยวในแต่ละครั้งนั้นง่ายมาก เพียงแค่ส่งบ็อตที่คุณต้องการโจมตีเป็นจำนวนเต็ม (เช่น0
หรือ3
) หรือD
เพื่อปกป้อง อย่าโจมตีบ็อตที่ตายแล้วหรือไม่มีอยู่เพราะนั่นจะถือว่าเป็นคำสั่งที่ไม่ถูกต้อง คำสั่งที่ไม่ถูกต้องจะส่งผลให้คุณสูญเสียอำนาจ 1
โครงสร้างการแข่งขัน
แต่ละเกมประกอบด้วยบอตทั้งหมดเริ่มต้นที่ 1,000 พลังและพลัง 10 การกระทำของบอตทั้งหมดจะถูกดำเนินการพร้อมกัน จำนวนรอบการหมุนสูงสุดสำหรับเกมคือ 1,000
หากในตอนท้ายของการหมุนมีบอทหนึ่งที่เหลืออยู่ (ชีวิต> 0) มันบอทหนึ่งคะแนนและเกมอื่นเริ่มต้นขึ้น หากถึงขีด จำกัด การเลี้ยวและมีหลายบอทยังมีชีวิตอยู่ไม่มีใครได้รับคะแนน หากบอทที่เหลือทั้งหมดตายในเทิร์นเดียวกันก็ไม่มีใครได้คะแนน
การแข่งขันประกอบด้วย 15 เกม ใครก็ตามที่มีคะแนนมากที่สุดในตอนท้ายชนะ! ความสัมพันธ์จะถูกทำลายโดยผลรวมของชีวิตที่เหลืออยู่ในแต่ละเกมที่ชนะ
สถานะ
บอตสามารถอ่านหรือเขียนไฟล์เดียวที่ตั้งชื่อตามตัวมันเองในโฟลเดอร์ย่อยโดยตรงชื่อstate
("ฮีโร่" สามารถเขียนได้state/hero.whatever
) ไฟล์นี้ควรมีขนาดไม่เกิน 1024 2ไบต์ ดูแลสังเกตการ จำกัด เวลา โปรแกรมของคุณจะต้องสิ้นสุดภายในหนึ่งวินาทีเพื่อนับไม่เพียง แต่ให้การตอบสนอง
ไฟล์เหล่านี้จะถูกล้างก่อนการแข่งขันแต่ละครั้ง แต่จะยังคงมีอยู่ในเกมต่อเกม ตัวระบุบอต ( 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;
}
}
}
กฎระเบียบ
คุณสามารถป้อนบอตไม่เกินสองรายการ หากคุณต้องการที่จะลบหนึ่งจากการเล่นเพื่อป้อนหนึ่งในสามโปรดลบโพสต์
คุณไม่สามารถกำหนดเป้าหมายหรือทำบอตเดี่ยวโดยใช้เมตาวิเคราะห์ ใช้ข้อมูลที่บอทของคุณได้รับเท่านั้น ซึ่งรวมถึงบ็อตของคุณเองดังนั้นคุณไม่สามารถป้อนบอทสองตัวที่สมรู้ร่วมคิดได้
อย่าพยายามแทรกแซงการทำงานของคอนโทรลเลอร์หรือบ็อตอื่น ๆ ในทางใดทางหนึ่ง
บอทของคุณต้องไม่ยกตัวอย่างหรือเรียกใช้คอนโทรลเลอร์หรือบอทอื่น ๆ
ผล
(จากบอตที่ส่งมาตั้งแต่วันที่ 2015-05-22 00: 00: 00Z)
การเล่นรอบนี้ดีขึ้นนิดหน่อยโดยมีเพียงสองเกมที่หยุดอยู่ที่ 1000 รอบ ความรุ่งโรจน์ของSantayanaของราล์ฟมาร์แชลล์ซึ่งเกิดขึ้นเป็นครั้งแรกเป็น ธ ปท. เพียงคนเดียวที่ทำคะแนนได้ถึงสามครั้ง ที่ไม่เพียงพอดังนั้นเขายังเอาสถานที่ที่สามกับอุบาย Stormcrow ใช้เวลาที่สองกับPhantom Menaceซึ่งเป็นการโพสต์แรกที่ดี โดยรวมแล้วเรามีการแสดงที่ดีมากจากสมาชิกใหม่โดยที่หกอันดับแรกไปถึงคนที่มีโพสต์น้อยกว่าห้าคน ขอแสดงความยินดีและยินดีต้อนรับสู่เว็บไซต์!
บอทที่ได้คะแนนเป็นศูนย์ชนะจะไม่ปรากฏเพื่อประหยัดพื้นที่ บอททั้งหมดที่โพสต์ก่อนเวลาประทับข้างต้นจะถูกเรียกใช้ดังนั้นหากคุณไม่เห็นของคุณแสดงว่ามันไม่ชนะอะไรเลย
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 sketchy คอนโทรลเลอร์แบบขนาน ( โดยอื่น ๆ ):
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;
}
}
}