Przegląd
To bitwa z botami, która ma na celu sprawdzenie, kto przetrwa najdłużej. Boty te zwiększają swoją moc poprzez atak, więc musisz dokładnie przemyśleć, zanim strzelisz.
W każdej turze możesz wybrać bota do ataku lub obrony. Atakowanie obniży jego życie i zwiększy jego siłę. Ostatni stojący bot wygrywa.
Boty
Każdy bot zaczyna od 1000 punktów życia i 10 mocy.
Po zaatakowaniu:
- moc twojego napastnika jest odejmowana od twojego życia
- Twoja siła wzrasta o 1.
Tak więc, jeśli w pierwszej turze zaatakują cię dwa boty, będziesz miał 980 punktów życia i 12 mocy.
Jeśli zdecydujesz się bronić:
- twoja moc zostanie obniżona o 1
- wszystkie ataki przeciwko tobie w tej turze zostaną zmniejszone o połowę
- jeśli zostaniesz zaatakowany, zyskasz 2 moce na każdego atakującego zamiast 1
Jeśli więc bronisz się w pierwszej turze i zostaniesz zaatakowany przez dwa boty, będziesz miał 990 punktów życia i 13 mocy. Jeśli się bronisz i nie zostaniesz zaatakowany, będziesz miał 1000 punktów życia, ale 9 mocy.
Jeśli pod koniec tury Twoja moc spadnie poniżej jednej, zostanie ustawiona na jedną. Jeśli twoje życie jest poniżej 1, umierasz.
Wejście wyjście
Boty są wywoływane raz na turę. Dla każdej tury obowiązuje limit jednej sekundy.
Inicjał
Przy pierwszym wywołaniu twojego bota nie otrzyma żadnych argumentów. Odpowiedz z ok
. Odbywa się to tylko po to, aby upewnić się, że bot odpowiada. Jeśli nie, nie zostanie dodany do listy graczy.
Każda kolej
W każdej turze twój bot otrzymuje informacje o wszystkich botach w grze jako argumenty linii poleceń. Przykładem tych argumentów jest:
1 0,1000,10,1 1,995,11,D
Pierwszym argumentem jest unikalny identyfikator twojego bota. Następnie pojawi się lista botów oddzielona spacjami. Każdy bot jest sformatowany jako:
id,life,power,lastAction
lastAction
może być liczbą całkowitą wskazującą, którego bota zaatakowali, D
jeśli bronili i X
jeśli jest to pierwsza tura. Pozostałe są liczbami całkowitymi.
Tak więc w powyższym przykładzie jesteś botem 1
i bronisz się podczas ostatniej tury. Bot 0
cię zaatakował i wciąż zaczyna zdrowie / moc.
Wydajność dla każdej tury jest bardzo prosta. Po prostu wypuść bota, który chcesz zaatakować, jako liczbę całkowitą (np. 0
Lub 3
) lub D
do obrony. Nie atakuj martwych lub nieistniejących botów, ponieważ liczy się to jako nieprawidłowe polecenie. Każde nieprawidłowe polecenie spowoduje utratę 1 mocy.
Struktura turnieju
Każda gra składa się ze wszystkich botów zaczynających się od 1000 zdrowia i 10 mocy. Działania wszystkich botów są podejmowane jednocześnie. Maksymalna liczba tur w grze to 1000.
Jeśli na końcu tury pozostanie jeden żywy bot (życie> 0), zdobywa jeden punkt i rozpoczyna się kolejna gra. Jeśli limit obrotu zostanie osiągnięty i żyje wiele botów, nikt nie otrzymuje punktu. Jeśli wszystkie pozostałe boty zginą w tej samej turze, nikt nie otrzyma punktu.
Turniej składa się z 15 gier. Kto ma najwięcej punktów na końcu, wygrywa! Więzy są przerywane przez sumę życia pozostałą w każdej wygranej grze.
Stan
Boty mogą odczytywać lub zapisywać tylko jeden plik nazwany po sobie, w bezpośrednim podfolderze o nazwie state
(„Hero” może zapisywać do state/hero.whatever
). Rozmiar tego pliku nie powinien przekraczać 1024 2 bajtów. Zachowaj ostrożność, aby dotrzymać terminu. Twój program musi zakończyć się w ciągu jednej sekundy, aby liczyć, a nie tylko dać odpowiedź.
Pliki te zostaną wyczyszczone przed każdym turniejem, ale pozostaną w grze. Wszystkie identyfikatory botów ( id
) również pozostaną takie same między grami.
Kontroler
Poniżej znajduje się kontroler turnieju ( Stronger.java
). Domyślnie wyświetla tylko końcowe wyniki (posortowana lista graczy, zwycięzca na górze), co może trochę potrwać. Nie jest zamrożony, tylko cichy. Jeśli chcesz uzyskać bardziej szczegółowe dane wyjściowe krok po kroku, dodaj -log
argument podczas działania.
Aby dodać boty, masz dwie opcje:
dodaj polecenie jako argument (
java Stronger -log "python bot.py"
)dodaj polecenie do
defaultPlayers[]
w source ("python bot.py"
)
Boty Bohater , Łobuz i Tchórz znajdują się w tej odpowiedzi i będą wykorzystywane do punktowania.
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;
}
}
}
Zasady
Możesz wprowadzić maksymalnie dwa boty. Jeśli chcesz usunąć jeden z gry, aby wprowadzić trzeci, usuń jego post.
Metaanalizy nie można kierować na bota ani wyróżniać go w inny sposób. Używaj tylko informacji podanych przez twojego bota. Dotyczy to również twoich botów, więc nie możesz wprowadzić dwóch botów, które zmawiają się.
Nie próbuj w żaden sposób zakłócać działania kontrolera lub innych botów.
Twój bot nie może utworzyć instancji ani w inny sposób uruchomić kontrolera lub innych botów.
Wyniki
(botów zgłoszonych na dzień 22.05.2015 00: 00: 00Z)
Ta runda gry poszła trochę lepiej, ponieważ tylko dwie gry zatrzymały się na 1000 tur. Uznanie dla Santayana Ralpha Marshalla , który zajął pierwsze miejsce, będąc jedynym botem, który zdobył trzy zwycięstwa. To nie wystarczyło, więc zajął także trzecie miejsce z taktykiem . Stormcrow zajął drugie miejsce z Phantom Menace , świetnym pierwszym postem tutaj. Podsumowując, mieliśmy bardzo fajne pokazy nowych członków, w których sześć najlepszych miejsc trafiło do osób z mniej niż pięcioma stanowiskami. Gratulacje i witamy na stronie!
Boty, które uzyskały zero zwycięstw, nie są wymienione, aby zaoszczędzić miejsce. Wszystkie boty wysłane przed powyższym znacznikiem czasu zostały uruchomione, więc jeśli go nie widzisz, nic nie wygrał.
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
Sortuj szkicowy równoległy kontroler ( przez innych ):
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;
}
}
}