Що мене не вбиває ...


106

Огляд

Це бот-битва, щоб побачити, хто може вижити найдовше. Однак ці боти збільшують свою силу шляхом нападу, тому перед тим, як стріляти, потрібно добре подумати.

Кожен виток, ви можете вибрати бота для нападу або захисту. Атака знизить її життя і збільшить її силу. Виграє останній бот, що стоїть.

Боти

Кожен бот починається з 1000 життя і 10 сил.

При нападі:

  • сила вашого нападника віднімається від вашого життя
  • ваша сила підвищується на 1.

Отже, якщо на першому кроці на вас нападуть два боти, у вас буде 980 життя і 12 сил.

Якщо ви вирішите захистити:

  • ваша потужність буде знижена на 1
  • усі напади на вас цього ходу скоротяться вдвічі
  • якщо на вас нападуть, ви отримаєте 2 сили для кожного зловмисника замість 1

Отже, якщо ти захистишся з першого кроку і нападеш на двох ботів, у тебе буде 990 життя та 13 сил. Якщо ти захистишся і не нападеш, то матимеш 1000 життя, але 9 сил.

Якщо в кінці повороту ваша потужність нижче однієї, вона буде встановлена ​​на одиницю. Якщо ваше життя нижче 1, ви помираєте.

Введення-виведення

Ботів викликається один раз за поворот. Існує обмеження часу в одну секунду на кожен поворот.

Початкові

Перший раз, коли ваш бот викликається, йому не дадуть аргументів. Відповісти с ok. Це робиться лише для того, щоб ваш бот відповів. Якщо цього не відбудеться, він не буде доданий до списку гравців.

Кожен виток

Щоразу, ваш бот отримує інформацію про всіх ботів у грі як аргументи командного рядка. Прикладом таких аргументів є:

1 0,1000,10,1 1,995,11,D

Перший аргумент - унікальний ідентифікатор вашого бота. Потім з'являється список розділених пробілами ботів. Кожен бот форматується як:

id,life,power,lastAction

lastActionможе бути цілим числом, яке представляє, на якого бота вони напали, Dякщо вони захищалися, і Xякщо це перша черга. Інші - цілі числа.

Отже, у наведеному вище прикладі ви ботом 1і захищаєтеся в останню чергу. Бот 0напав на вас і досі перебуває на стані здоров'я / сили.

Вихід на кожен виток дуже простий. Просто виведіть бота, якого ви хочете атакувати як ціле число (наприклад, 0або 3), або Dзахистити. Не нападайте на мертвих чи неіснуючих ботів, оскільки це вважається недійсною командою. Будь-яка недійсна команда призведе до втрати 1 сили.

Структура турніру

Кожна гра складається з усіх ботів, починаючи з 1000 здоров'я та 10 потужностей. Дії всіх ботів здійснюються одночасно. Максимальна кількість обертів для гри - 1000.

Якщо наприкінці повороту залишився живий один бот (життя> 0), він набирає один бал і починається інша гра. Якщо буде досягнута межа повороту, і там живуть кілька ботів, ніхто не отримує бала. Якщо всі боти, що залишилися, вмирають в одному рубежі, ніхто не отримує бала.

Турнір складається з 15 ігор. Хто в кінці має найбільшу кількість очок, той виграє! Зв'язки розбиваються на суму життя, що залишилася в кожній виграній грі.

Держава

Боти можуть читати або записувати лише в один файл, названий його самим, у прямій папці з назвою state("Герой" може записувати в state/hero.whatever). Розмір цього файлу не повинен перевищувати 1024 2 байти. Слідкуйте за дотриманням часового обмеження. Ваша програма повинна закінчитися протягом однієї секунди, щоб порахувати, а не просто дати відповідь.

Ці файли буде стерто перед кожним турніром, але збережеться гра. Усі ідентифікатори бота ( id) також залишаться однаковими між іграми.

Контролер

Нижче - контролер турніру ( Stronger.java). За замовчуванням він видає лише кінцеві результати (відсортований список гравців, переможець зверху), що може зайняти досить багато часу. Це не замерзло, просто мовчить. Якщо ви хочете більш детальний поворотний висновок, додайте -logаргумент під час запуску.

Щоб додати ботів, у вас є два варіанти:

  • додати команду як аргумент ( java Stronger -log "python bot.py")

  • додати команду до defaultPlayers[]в джерелі ( "python bot.py")

Герой ботів , хуліган та боягуз можна знайти у цій відповіді та використовуватимуться для скорингу.

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;
        }
    }
}

Правила

  • Ви можете ввести до двох ботів. Якщо ви хочете вилучити один із відтворення, щоб увійти до третього, видаліть його публікацію.

  • Ви не можете орієнтуватися на бот або іншим чином виділити його за допомогою мета-аналізу. Використовуйте лише ту інформацію, яку надано вашому боту. Сюди входять ваші власні боти, тож ви не можете вводити двох ботів, які мають змову.

  • Не намагайтеся жодним чином перешкоджати роботі контролера чи інших ботів.

  • Ваш бот може не створювати інстанцію або іншим чином запускати контролер або інші боти.

Результати

(ботів, поданих станом на 22.05.2015 00: 00: 00З)

Цей раунд гри пройшов трохи краще, лише дві гри затрималися на 1000 обертів. Престижність Ральфа Маршалла Сантаяна , який посів перше місце, будучи єдиними ботами , який здобув три перемоги. Цього було недостатньо, тому він також зайняв третє місце з « Тактиком» . 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

Сорта схематичний паралелізований контролер ( від інших ):

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;
        }
    }
}

2
@Tim Список ботів розділений пробілом. Статистика кожного бота розділяється комами.
Геобіт

3
@Mark Поточні боти орієнтовані на половину оборонно та наполовину атаку. Жоден із захисних ботів не має єдиної виграші. Я погоджуюся, що це заохочує певну оборону, але користь агресії полягає в тому, що чиста оборона взагалі не може виграти жодних очок. Ви набираєте очки, лише якщо ви єдиний вижив.
Геобіт

8
Якщо комусь цікаво, як боти складаються зараз, коли є більше заявок, ось результат мого "неофіційного" тесту: 3-809-Hero; 2-593-Велоцираптор; 1-471-СюрпризБот; 1-433-боягуз; 1-371-Сантаяна; 1-364-Wiisniper; 1-262-аналітик; 1-230-хуліган; 1-132-еквалайзер; 1-71-IKnowYou; 0-0 - precog, Berserker, BroBot, SemiRandom, MonteBot, Tactician, SnappingTurtle, Psycho, Revenger, Opportunity, PhantomMenace, Tank, Boxer, Guardian, AboveAverage, DefenceBot. Багато недійсних команд від Opportunity, AboveAvg, BroBot, Boxer та SemiRandom.
OJFord

3
У мене є паралелізована версія контролера, який запускає ігри швидше, ніж оригінальний контролер, якщо хтось зацікавлений, я можу його опублікувати ...
Інше

3
@Manu Поки кожен бот не виконується одночасно, це не має значення. Я припускаю, що паралельна версія все ще має всі боти закінчити один виток, перш ніж перейти до наступного. Як я вже сказав, я збираюсь перевірити, перш ніж використовувати його, якщо розміщено.
Геобіць

Відповіді:


25

C ++ - Монтебот

Моделює велику кількість випадкових ігор та вибирає хід, що призводить до найбільшого шансу не вмерти.

Навіщо думати про стратегію, коли ви можете дозволити комп'ютеру створити її для вас?

Примітка. Складіть це з прапором -O3 для оптимальної роботи.

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

//Monte Carlo method constants
const unsigned int total_iters=100000; //total number of simulations
double time_limit=0.7; //approximate CPU time the program is allowed to run before outputting the current best solution
const unsigned int check_interval=4096-1;

unsigned int num_players,my_bot;
const int DEFEND=-1,FIRST=-2,DEAD=-3;
struct Bot{
    short int life,power,lastAttack;
    inline bool is_alive(void){
        return life>0;
    }
    inline void damage(short int dmg){
        life-=dmg;
        if(life<0)life=0;
    }
    inline void charge(short int p){
        power+=p;
        if(power<1)power=1;
    }
    inline bool is_attacking(void){
        return lastAttack>=0;
    }
};
int main(int argc,char*argv[]){
    clock_t start=clock();
    if(argc==1){
        printf("ok");
        return 0;
    }

    srand(time(NULL));

    num_players=argc-2;
    sscanf(argv[1],"%u",&my_bot);

    Bot bots[num_players];
    for(unsigned int i=0;i<num_players;++i){
        char buf[16];
        unsigned int id;
        short int life,power;
        sscanf(argv[i+2],"%u,%hd,%hd,%s",&id,&life,&power,buf);
        Bot &cur_bot=bots[id];
        cur_bot.life=life;
        cur_bot.power=power;
        if(strcmp(buf,"D")==0)cur_bot.lastAttack=DEFEND;
        else if(strcmp(buf,"X")==0)cur_bot.lastAttack=FIRST;
        else sscanf(buf,"%hd",&cur_bot.lastAttack);
    }

    //let the other bots kill each other while we accumulate more power
    if(bots[my_bot].life>750){
        printf("D");
        return 0;
    }

    Bot cur_state[num_players];
    unsigned int won[num_players+1],visited[num_players+1];
    for(int i=0;i<num_players+1;++i){
        won[i]=0;
        visited[i]=0;
    }

    //unsigned long long int sim_length=0;
    for(unsigned int iter=0;iter<total_iters;++iter){
        //ensure that we do not exceed the time limit
        if(iter&check_interval==check_interval){
            clock_t cur_time=clock();
            if((double)(cur_time-start)/(double)CLOCKS_PER_SEC>=time_limit){
                break;
            }
        }
        int first_move=FIRST;
        memcpy(cur_state,bots,sizeof(Bot)*num_players);

        //simulate random moves in the game until
        //a. the player dies, or
        //b. the player is the only one alive
        while(true){
            //++sim_length;
            //check if our bot died
            if(!cur_state[my_bot].is_alive()){
                ++visited[first_move+1];
                break;
            }
            //check if our bot is the only bot left alive
            bool others_alive=false;
            for(unsigned int i=0;i<num_players;++i){
                if(i!=my_bot&&cur_state[i].is_alive()){
                    others_alive=true;
                    break;
                }
            }
            if(!others_alive){
                ++won[first_move+1];
                ++visited[first_move+1];
                break;
            }

            Bot new_bots[num_players];
            memcpy(new_bots,cur_state,sizeof(Bot)*num_players);

            //generate random moves for all players
            bool defend[num_players];
            int possible_moves[num_players+2];
            unsigned int num_moves;
            for(unsigned int i=0;i<num_players;++i){
                num_moves=0;
                if(cur_state[i].is_alive()){
                    possible_moves[num_moves++]=DEFEND;
                    for(unsigned int j=0;j<num_players;++j){
                        if(j!=i&&cur_state[j].is_alive()){
                            possible_moves[num_moves++]=j;
                        }
                    }
                    new_bots[i].lastAttack=possible_moves[rand()%num_moves];
                    defend[num_players]=(new_bots[i].lastAttack==DEFEND);
                }else new_bots[i].lastAttack=DEAD;
            }
            if(first_move==FIRST)first_move=new_bots[my_bot].lastAttack;

            //simulate outcome of moves
            for(unsigned int i=0;i<num_players;++i){
                if(cur_state[i].is_alive()&&new_bots[i].is_attacking()){
                    new_bots[i].charge(-1);
                    int victim=new_bots[i].lastAttack;
                    if(defend[victim]){ //if victim is defending
                        new_bots[victim].charge(2);
                        new_bots[victim].damage(cur_state[i].power/2);
                    }else{
                        new_bots[victim].charge(1);
                        new_bots[victim].damage(cur_state[i].power);
                    }
                }
            }
            memcpy(cur_state,new_bots,sizeof(Bot)*num_players);
        }
    }
    //printf("%f\n",(double)sim_length/(double)total_iters);
    double win_rate=-1;
    int best_move=DEFEND;
    for(int i=0;i<num_players+1;++i){
        if(i-1!=my_bot){
            double cur_rate=(double)won[i]/(double)visited[i];
            if(cur_rate>win_rate){
                win_rate=cur_rate;
                best_move=i-1;
            }
        }
    }
    if(best_move==DEFEND)printf("D");
    else printf("%d",best_move);

    //clock_t end=clock();
    //fprintf(stderr,"%f\n",(double)(end-start)/(double)CLOCKS_PER_SEC);

    return 0;
}

C - МонтеФастер

Крім того, цей бот можна змусити працювати швидше, використовуючи багатопотоковість. Однак, оскільки я не знаю превентивно, скільки ітерацій може оцінити бот до того, як він вийде (на суддівській платформі), я не буду використовувати цей бот (з кодом нижче) для цього змагання.

Нижче наведений код лише заради цікавості.

Примітка. Скомпілюйте це з прапорами -O3 та -fopenmp для досягнення оптимальної продуктивності.

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_PLAYERS 32

//Monte Carlo method constants
const unsigned int total_iters=60000; //total number of simulations

unsigned int num_players,my_bot;
const int DEFEND=-1,FIRST=-2,DEAD=-3;
struct Bot{
    short int life,power,lastAttack;
};
int main(int argc,char*argv[]){
    clock_t start=clock();
    if(argc==1){
        printf("ok");
        return 0;
    }

    srand(time(NULL));

    num_players=argc-2;
    sscanf(argv[1],"%u",&my_bot);

    struct Bot bots[MAX_PLAYERS];
    int A;
    for(A=0;A<num_players;++A){
        char buf[16];
        unsigned int id;
        short int life,power;
        sscanf(argv[A+2],"%u,%hd,%hd,%s",&id,&life,&power,buf);
        struct Bot *cur_bot=&bots[id];
        cur_bot->life=life;
        cur_bot->power=power;
        if(strcmp(buf,"D")==0)cur_bot->lastAttack=DEFEND;
        else if(strcmp(buf,"X")==0)cur_bot->lastAttack=FIRST;
        else sscanf(buf,"%hd",&cur_bot->lastAttack);
    }

    //let the other bots kill each other while we accumulate more power
    if(bots[my_bot].life>750){
        printf("D");
        return 0;
    }

    struct Bot cur_state[MAX_PLAYERS];
    unsigned int won[MAX_PLAYERS+1],visited[MAX_PLAYERS+1];
    for(A=0;A<num_players+1;++A){
        won[A]=0;
        visited[A]=0;
    }

    //unsigned long long int sim_length=0;
    int iter;
    #pragma omp parallel for //strangely, the code fails to compile if a variable length array is used in the loop
    for(iter=0;iter<total_iters;++iter){
        //note that we cannot break this loop when we use #pragma omp parallel
        //there is therefore no way to check if we're close to exceeding the time limit

        int first_move=FIRST;
        memcpy(cur_state,bots,sizeof(struct Bot)*num_players);

        //simulate random moves in the game until
        //a. the player dies, or
        //b. the player is the only one alive
        int sim_length=0;
        while(1){
            //++sim_length;
            //check if our bot died
            if(cur_state[my_bot].life<=0){
                ++visited[first_move+1];
                break;
            }
            //check if our bot is the only bot left alive
            int others_alive=0;
            int i;
            for(i=0;i<num_players;++i){
                if(i!=my_bot&&cur_state[i].life>0){
                    others_alive=1;
                    break;
                }
            }
            if(!others_alive){
                ++won[first_move+1];
                //won[first_move+1]+=cur_state[my_bot].life;
                ++visited[first_move+1];
                break;
            }

            struct Bot new_bots[MAX_PLAYERS];
            memcpy(new_bots,cur_state,sizeof(struct Bot)*num_players);

            //generate random moves for all players
            char defend[MAX_PLAYERS];
            //int possible_moves[num_players+2];
            int possible_moves[MAX_PLAYERS+2];
            for(i=0;i<num_players;++i){
                if(cur_state[i].life>0){
                    int j,num_moves=0;
                    possible_moves[num_moves++]=DEFEND;
                    for(j=0;j<num_players;++j){
                        if(j!=i&&cur_state[j].life>0){
                            possible_moves[num_moves++]=j;
                        }
                    }
                    new_bots[i].lastAttack=possible_moves[rand()%num_moves];
                    defend[i]=(new_bots[i].lastAttack==DEFEND);
                }else new_bots[i].lastAttack=DEAD;
            }
            if(first_move==FIRST)first_move=new_bots[my_bot].lastAttack;

            //simulate outcome of moves
            for(i=0;i<num_players;++i){
                if(cur_state[i].life>0&&new_bots[i].lastAttack>=0){
                    new_bots[i].power-=1;
                    if(new_bots[i].power<=0)new_bots[i].power=1;
                    int victim=new_bots[i].lastAttack;
                    if(defend[victim]){ //if victim is defending
                        new_bots[victim].power+=2;
                        new_bots[victim].life-=cur_state[i].power/2;
                    }else{
                        new_bots[victim].power+=1;
                        new_bots[victim].life-=cur_state[i].power;
                    }
                    if(new_bots[victim].life<0)new_bots[victim].life=0;
                }
            }
            memcpy(cur_state,new_bots,sizeof(struct Bot)*num_players);
        }
    }
    //printf("%f\n",(double)sim_length/(double)total_iters);
    double win_rate=-1;
    int best_move=DEFEND;
    for(A=0;A<num_players+1;++A){
        if(A-1!=my_bot){
            double cur_rate=(double)won[A]/(double)visited[A];
            if(cur_rate>win_rate){
                win_rate=cur_rate;
                best_move=A-1;
            }
        }
    }
    if(best_move==DEFEND)printf("D");
    else printf("%d",best_move);
    //fprintf(stderr,"%.3f%% chance (based on %d samples)\n",(double)won[best_move+1]/(double)visited[best_move+1]*100.,total_iters);

    //clock_t end=clock();
    //fprintf(stderr,"%f\n",(double)(end-start)/(double)CLOCKS_PER_SEC);

    return 0;
}

2
Цікава стратегія. Приблизно, скільки часу потрібно, щоб зробити симуляцію з опонентами 20ish?
Ральф Маршалл

2
@RalphMarshall Це може зробити 60 тисяч симуляцій досить швидко (від 0,03 секунди до 0,2 секунди) для кількох супротивників, але швидко стає надзвичайно повільним для 20 супротивників (в середньому 10 секунд). Сподіваємось, передчасне припинення роботи алгоритму все одно дасть можливість прийняти рішення.
Картопля

Я розглядаю можливість додавання багатопотокової підтримки для цього бота, щоб програма запустилася швидше, але я не маю уявлення, скільки ітерацій оцінюючий комп’ютер зможе оцінити перед тим, як вийшов час роботи бота. Я, мабуть, пожертвую першою грою для того, щоб зробити кілька профілів, щоб бот зміг виконати оптимальну кількість ітерацій.
Картопля

23

Ява Психо

Нічого не сказати, що зробить цей божевільний психолог - може напасти на когось: мертвого бота чи навіть самого себе.

import java.util.Random;

public class Psycho {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }

        Random rnd = new Random();
        rnd.setSeed( System.currentTimeMillis() );

        String[] tokens = args[ rnd.nextInt(args.length) ].split(",");
        String target = tokens[0];

        System.out.print(target);
    }
}


19

Скала - стрічкоподібний

Bandwagoner не піклується про честь чи принципи. Бандажник лежить низько, уникаючи бути найслабшим або найсильнішим. Bandwagoner йде з натовпом, орієнтуючись на ціль консенсусу, щоб уникнути уваги.

import scala.util.Try

object Bandwagoner {
    case class PlayerStatus(life:Int, power:Int, lastAction:Option[Int])

    def main(args:Array[String]):Unit={
        if(args.length==0)
            println("ok")
        else{
            val myId=args(0).toInt
            val everyonesStatus=(for(action <- args.tail) yield{
                val id :: life :: power :: lastAction :: Nil = action.split(",").toList
                (id.toInt, new PlayerStatus(life.toInt, power.toInt, Try(lastAction.toInt).toOption))
            }).toMap
            println(bandwagon(myId, everyonesStatus(myId), everyonesStatus.filter(_._1 != myId)))
        }
    }

    def bandwagon(myId:Int, self:PlayerStatus, opponents:Map[Int, PlayerStatus]):String={
        val alive=opponents.filter(_._2.life > 0)
        //If their is only one opponent left
        if(alive.size==1){
            val (opponentId, opponent)=alive.head
            //Get win projection
            val willWin=opponent.life/(self.power*1.0) <= self.life/(opponent.power*1.0)
            //If I'm stronger attack, otherwise defend
            if(willWin) opponentId.toString() else "D"

        }
        //Otherwise
        else if(alive.size > 0){
            //If I'm the strongest or weakest
            if(alive.map(_._2.life).max < self.life || alive.map(_._2.life).min > self.life){
                //If I have a good opportunity in terms or power, or passivity
                if(alive.map(_._2.power).max * 1.5 < self.power || !alive.exists(_._2.lastAction.isDefined)){
                    //Attack
                    alive.maxBy(_._2.power)._1.toString()
                }
                //Otherwise
                else 
                    //Lay low
                    "D"
            }
            //Otherwise, BANDWAGON
            else{
                //Obviously we dont want to attack dead opponents, or ourself
                val validTargets=opponents.flatMap(_._2.lastAction).filter(alive.contains(_)).filter(_ != myId)
                if(validTargets.size == 0)
                    "D"
                else
                    //Select the most targeted opponent (Sorry)
                    validTargets.groupBy(i => i).mapValues(_.size).maxBy(_._2)._1.toString()
            }
        }
        //Just to be safe..
        else 
            "D"
    }
}

Чи маєте ви ідею, чому я отримав би дурну помилку "Спробуйте не є членом scala.util" на першому рядку? Гуглінг залишив мене в збитку. У мене стандартна установка scala, 2.9.2 прямо з сховища.
Геобіць

@Geobits, це стара версія скали, ніж моя, я працюю 2.11. Якщо оновлення не є варіантом, повідомте мене, і я виправлю код, щоб він працював.
Інші

2
Зрозуміло. Я читав "З 2.10" у документах як "З 2.1.0" і не міг зрозуміти, чому це не буде в 2.9.2 :(
Геобіц

18

Java Revenger

Местик не зацікавлений у сварці заради сварки. Але якщо нападуть, помсти будуть шукати!

public class Revenger {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }

        String me = args[0], target = "D";
        int last_attacker_power = -1;

        for(int i=1; i<args.length; ++i){
            String[] tokens = args[i].split(",");
            int power = Integer.parseInt(tokens[2]);
            int life  = Integer.parseInt(tokens[1]);

            if( tokens[3].equals(me)
             && power>last_attacker_power
             && life>0  ){
                target = tokens[0];
                last_attacker_power = power;
            }
        }

        System.out.print(target);
    }
}

4
FYI: Це не припиняє атакувати навіть після того, як ціль загинула.
Геобіць

26
@Geobits О, але помста - страва найкраще подається .. вже мертва? : p Не було навмисно; оновлено.
OJFord

17

Java - герой, хуліган та боягуз

Ці три боти включені як приклад, але вони будуть грати в турнірі за рахунком. Всі вони мають спрощену поведінку.

Герой

Герой просто атакує того, хто має найбільше життя на кожному кроці.

public class Hero {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        String me = args[0], target="D";
        int best=0;
        for(int i=1;i<args.length;i++){
            String[] tokens = args[i].split(",");
            int life = Integer.valueOf(tokens[1]);
            if(life > 0 && life >= best && !tokens[0].equals(me)){
                best = life;
                target = tokens[0];
            }
        }
        System.out.print(target);
    }
}

Хуліган

Тим часом, Хулі нападає на того, хто має найменше життя на кожному кроці.

public class Bully {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        String me = args[0], target="D";
        int best=Integer.MAX_VALUE;
        for(int i=1;i<args.length;i++){
            String[] tokens = args[i].split(",");
            int life = Integer.valueOf(tokens[1]);
            if(life > 0 && life <= best && !tokens[0].equals(me)){
                best = life;
                target = tokens[0];
            }
        }
        System.out.print(target);
    }
}

Трус

Трус не робить нічого, крім захисту, поки його життя не досягне 500 чи нижче. Потім він атакує того, хто має найменшу силу кожного кроку.

public class Coward {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        String me = args[0], action="D";
        int best=Integer.MAX_VALUE;
        for(int i=1;i<args.length;i++){
            String[] tokens = args[i].split(",");
            if(tokens[0].equals(me)){
                if(Integer.valueOf(tokens[1]) > 500){
                    System.out.print("D");
                    System.exit(0);
                }
            }
        }       
        for(int i=1;i<args.length;i++){
            String[] tokens = args[i].split(",");
            int power = Integer.valueOf(tokens[2]);
            if(power <= best && !tokens[0].equals(me) && Integer.valueOf(tokens[1]) > 0){
                best = power;
                action = tokens[0];
            }
        }
        System.out.print(action);
    }
}

Насолоджуйтесь!


7
Цікаво, що Героя виявляється високоефективною технікою; навіть проти більш «складних» ботів (наприклад, MonteBot, Analyst). Це був просто простий приклад, чи ви базували це на деякому розумінні?
OJFord

1
Ні, я просто кинув перші три речі, які я вважав за приклади. Я не думав, що це буде дуже добре, якщо чесно.
Геобіць

16

Perl - Тактик

Це почалося як редагування мого бота Let 'em Fight, але я вніс достатньо змін, що вирішив ввести його як новий запис. Нова логіка полягає в наступному

  • Якщо ніхто не нападав у попередній черзі, нападайте на противника з найвищою життєвою цінністю. Це повинно запобігти закінченню, де ніхто не нападає на когось іншого, принаймні, поки я ще живий.
  • Якщо хтось напав на мене в останню чергу, вибери найпотужнішого такого нападника і відбий назад.
  • Якщо ми знизимось до двох ботів, або я в меншій середній силі, напади на супротивника з найвищим життям.
  • Якщо мій власний рейтинг потужності нижче середнього, зробіть атаку, щоб підвищити потужність до більш розумного рівня
  • В іншому випадку, зачекай мого часу

Я перевіряв це локально на інших Java-ботах, які були введені та встигли отримати кілька виграшів, але все ще не вражаючий запис з мого боку.

#!/usr/bin/perl

use strict;
use warnings;

# First round
if (!@ARGV) {
    print "ok\n";
    exit;
}

my ($self, @rest) = @ARGV;

my ($myAction, $myPower, $myLife,
    $myMaxAttacker, $myMaxAttackerId, 
    $maxLife, $maxLifeId, 
    $maxPower, $maxPowerId,
    $totLife, $totPower, $living, $amWeak, $numAttackers) = ('D');

# First, get a situation report
for (@rest) {
    my ($id, $life, $power, $action) = split(',');

    # Let the dead rest in peace
    next unless $life>0;

    if ($id == $self) {
        # Keep track of my own power and life for later comparison
        $myPower = $power;
        $myLife = $life;
        next;
    }

    $living++;
    $numAttackers++ if ($action ne 'D');
    $totPower += $power;
    $totLife += $life;

    if ($action == $self) {
        # Bastard hit me!
        if ($power > $myMaxAttacker) {
            $myMaxAttacker = $power;
            $myMaxAttackerId = $id;
        }
    }

    # If you're going to pick a fight, go for the biggest
    # guy in the room.
    if ($life > $maxLife) {
        $maxLife = $life;
        $maxLifeId = $id;
    }

    # Or, go for the guy with the biggest gun
    if ($power > $maxPower) {
        $maxPower = $power;
        $maxPowerId = $id;
    }
}

# If I'm being hit any attacks are back at the strongest attacker,
# otherwise simply the healthiest opponent overall
my $preferredTarget = $myMaxAttackerId;
$preferredTarget = $maxLifeId unless defined $preferredTarget;

# Check to see if I have below-average life, in which case it's time to get moving
$amWeak = $myLife < $totLife/$living;

# Now figure out what to do
if (!$numAttackers) {
    # Everybody is standing around, so let's mix it up
    $myAction = $preferredTarget;
} elsif (defined $myMaxAttackerId) {
    # My momma told me never to stand there and be hit
    $myAction = $myMaxAttackerId;
} elsif ($amWeak || $living == 1) {
    # Either we're down to two bots, or I'm fairly weak. Atack!!!
    $myAction = $preferredTarget;
} elsif ($myPower < $totPower/$living) {
    # Just lash out at random so we do not lose all of
    # our power through permanent defense
    $myAction = $preferredTarget;
} else { 
    # Work up some courage/power by drinking beer
    # in the corner. Use the default defensive action in this case.
    # Else clause exists just for debugging.
}

print "$myAction\n";

Перл - Сантаяна

Ті, хто не пам’ятає історії, приречені рано вмирати, або дещо таке. Цей бот намагається скористатися багатосторонньою природою змагань, зберігаючи історію загальної сили кожного бота за всі раунди та завжди атакуючи найсильнішого. Теоретично це повинно перешкоджати будь-якому боту виходити на руйнування, але, звичайно, я збираю лише статистику, поки я живий, так що якщо цей бот матиме коротке життя, статистика не буде дуже хорошою.

#!/usr/bin/perl

use strict;
use warnings;

# First round
if (!@ARGV) {
    print "ok\n";
    exit;
}

# Read in our multi-round/multi-game state information
my $state;
if (open STATE, "state/santayana.out") {
    $state = <STATE>;
    close STATE;
}

# Stuff the historical data into a hash keyed by opponent ID
my %state;
my @state = $state ? split(' ', $state) : ();
for (@state) {
    my ($id, $life, $power) = split ',';
    $state{$id} = [$life, $power];
}

my ($self, @rest) = @ARGV;

my ($maxLife, $maxLifeId, $living) = (0, undef, 0);

# First, get a situation report
for (@rest) {
    my ($id, $life, $power, $action) = split(',');

    # Let the dead rest in peace
    next unless $life > 0;

    $living++;

    # Update the historical hash with latest information
    my $aref = $state{$id};
    if ($aref) {
        $$aref[0] += $life * ($action eq 'D' ? 1 : 1.5);
        $$aref[1] += $power;
    } else {
        $state{$id} = [$life, $power];
    }

    next if ($id == $self);

    # Our target is based on the historically
    # strongest opponent, independent of current state,
    # unless they are actually dead
    if ($life > 0 && $state{$id}->[0] > $maxLife) {
        $maxLife = $state{$id}->[0];
        $maxLifeId = $id;
    }
}

# Write out the latest state for next time around
if (open STATE, ">state/santayana.out") {
    print STATE join(" ", map { join ",", $_, $state{$_}->[0], $state{$_}->[1] } sort { $state{$b}->[0] <=> $state{$a}->[0]} keys %state);
    close STATE;
}

# Now figure out what to do
if (defined $maxLifeId) {
    # Should always be defined, but who knows
    print "$maxLifeId\n";
} else {
    print "D\n";
}

Зауважте, що я впевнений, що я видалив інший запис (з написом Let 'em Fight), тож у мене повинно бути лише два боти, але якщо ні, будь ласка, ігноруйте цей і використовуйте лише ці два. Дякую.
Ральф Маршалл

6
Вітаємо, що зайняли як перше, так і третє місце в останньому табло :)
Геобіт

Найкраще! Це було великим викликом.
Ральф Маршалл

14

Java Guardian

Охоронець захищає слабких. Він буде атакувати того, хто провів останню чергу, вибираючи найслабшого живого бота (крім, можливо, самого себе). Однак він досить розумний, щоб не нападати:

1) Сам (якщо він не хуліган, то відчуває, що заслуговує цього.)

2) Боти, які атакують себе

3) Мертві боти

4) Боти, у яких залишилось менше десяти років життя (які, сподіваємось, засвоїли свої уроки!)

Охоронець обирає одного і того ж гравця кілька разів, якщо потрібно. Краватки для "найслабшого гравця" та "хто набрав на нього" обидва переходять до першого в списку (що означає, випадковий).

public class Guardian{
    public static void main (String[] args){
        if(args.length == 0){
            System.out.print("ok");
            System.exit(0);
        }

        String myId = args[0];
        int lowestLife = Integer.MAX_VALUE;
        int life = Integer.MIN_VALUE;
        String[] tokens = {};
        String opposingId = "";
        String weakestOpponent = "";
        String lastTarget = "";

        for(int i=1; i<args.length; i++){
            tokens = args[i].split(",");
            opposingId = tokens[0];
            life = Integer.parseInt(tokens[1]);
            lastTarget = tokens[3];
            if(life < lowestLife && life > 0 &&
                !opposingId.equals(myId) &&
                !opposingId.equals(lastTarget)){
                weakestOpponent = opposingId;
            }
        }

        for(int i=1; i<args.length; i++){
            tokens = args[i].split(",");
            opposingId = tokens[0];
            life = Integer.parseInt(tokens[1]);
            lastTarget = tokens[3];
            if (lastTarget.equals(weakestOpponent) &&
                life > 10){
                System.out.println(opposingId);
                System.exit(0);
            }
        }

        System.out.println("D");
    }
}

1
Виправте численні помилки та помилки в цьому та вашому іншому боті . Я не можу скласти жодного з них, як є.
Геобіт

Я думаю, якщо це був хуліган, він повинен подумати про те, що зроблено, тобто D efend.
користувач3819867

Виправлені помилки @ user3819867, я думав над тим, щоб додати це, але Guardian захистить слабких за будь-яку ціну, навіть ціною для себе.
Ксинаріз

13

Java - аналітик

Визначте загрозу кожного противника, помноживши його силу на 5, якщо він напав, і на 25, якщо він напав на Аналітика. У разі нічиїх ударів нападає на гравця, який має найменше життя.

Значна частина коду була запозичена з відповіді Геобітса.

public class Analyst {
    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.println("ok");
            System.exit(0);
        }
        String me = args[0], that = "D";
        int maxThreat = 200;
        for (int i = 1; i < args.length; i++) {
            String[] player = args[i].split(",");
            int threat = Integer.parseInt(player[2]) * 100
                         * (!player[3].equals("D") ? 5 : 1)
                         * (player[3].equals(me) ? 5 : 1)
                         - Integer.parseInt(player[1]);
            if (threat > maxThreat && Integer.parseInt(player[1]) > 0 && !player[0].equals(me)) {
                maxThreat = threat;
                that = player[0];
            }
        }
        System.out.println(that);
    }
}

12

Пітон 2, хапається черепаха

Приховує в його оболонці, виникає вкусити перша людина , щоб атакувати його останню чергу (якщо вони не мертві), а потім повертається в свою раковину знову
запустити зpython snapping_turtle.py <input>

import sys
class snapping_turtle:
    def bitey(self,command):


        if len(command) <=1:
            return 'ok'
        else:
            last_turn = list(command)
            bot_to_bite = -1
            me = last_turn[0]
            for k in xrange(0,len(last_turn)):
                #bot_action = last_turn.split(',')

                if len(last_turn[k]) ==1:
                    pass
                else:
                    bot_action = last_turn[k].split(',')
                    # If they hit me
                    if bot_action[3] == me:
                        # And if they're still alive, hit them
                        if int(bot_action[1]) > 0:
                            bot_to_bite = bot_action[0]
                            break
                        #Otherwise, stay in my shell
                        else:
                            pass

            if bot_to_bite > -1:
                return bot_to_bite
            else:
                return 'D'

print snapping_turtle().bitey(sys.argv[1:])

Пітон 2, Берсеркер

Берсеркер розбив! Б'є себе, поки не набере достатньої сили, потім почне атакувати найближчого живого. Також вражає себе, якщо з будь-якої причини не вдається розібратися, у кого саме б'є.

EDIT: Змінено поріг лютості Берсеркера з 50 на 25, оскільки в іншому випадку він вийде, перш ніж робити щось ...

Працює з python Berserker.py <input>

import sys
class Berserker:
    def rage(self,command):


        if len(command) <=1:
            return 'ok'
        else:
            last_turn = list(command)
            bot_to_smash = -1
            me = last_turn[0]
            my_power = last_turn[int(me)].split(',')[2]
            for k in xrange(0,len(last_turn)):
                #bot_action = last_turn.split(',')

                if len(last_turn[k]) ==1:
                    pass
                else:
                    bot_action = last_turn[k].split(',')
                    if int(my_power) < 25:
                        #Too weak! Need make stronger for smashing!
                        bot_to_smash = me
                        break
                    else:
                        #Now strong! Smash! Not smash broken things!
                        if bot_action[0] != me and bot_action[1] > 0:
                            bot_to_smash = bot_action[0]

            if bot_to_smash > -1:
                return bot_to_smash
            else:
                #Confused! Don't like! MORE POWER!
                return me

print Berserker().rage(sys.argv[1:])

12

R - можливість

Цей бот потрібно викликати за допомогою Rscript Opportunity.R. Він зберігає в пам’яті, хто що робив, і атакує противника, тим менше шансів захищати себе (тобто, хто використовував Dнайменше в минулому), якщо він не усвідомлює, що один із ботів напав на нього двічі поспіль, і в цьому випадку він починає захищати сам або атакує атакуючого бота, якщо він може вбити його швидше, ніж може нападник.

args <- commandArgs(TRUE)
if(length(args)){
    myid <- as.integer(args[1])
    data <- as.data.frame(do.call(rbind,strsplit(args[-1],",")),stringsAsFactors=FALSE)
    colnames(data) <- c('id','health','power','last')
    data$id <- as.integer(data$id)
    data$health <- as.integer(data$health)
    data$power <- as.integer(data$power)
    data <- data[order(data$id),]
    if(all(data$last=="X")){
        cat(data$last,file="state/opportunity.txt",sep="\n")
        cat(sample(data$id[data$id!=myid],1))
        }else{
            past <- as.matrix(read.table("state/opportunity.txt",sep=" "))
            lastturn <- data$last
            lastturn[data$health<1] <- "X"
            lastturn[nchar(lastturn)>1] <- "E" #If a bot returned anything else than an integer
            past <- cbind(past,lastturn)
            cat(apply(past,1,paste,collapse=" "),sep="\n",file="state/opportunity.txt")
            who_bully_me <- sapply(apply(past,1,rle),function(x)ifelse(tail(x$v,1)==myid,tail(x$l,1),0))
            if(any(who_bully_me>1)){
                bullyid <- which.max(who_bully_me)-1
                if(data$health[data$id==bullyid]%/%data$power[data$id==myid]<=data$health[data$id==myid]%/%data$power[data$id==bullyid]){
                    cat(bullyid)
                    }else{cat("D")}
                }else{
                    defend <- rowSums(past=="D")
                    defend[past[,ncol(past)]=="X"] <- NA
                    defend[myid+1] <- NA
                    choice <- which(defend%in%min(defend,na.rm=TRUE)) -1
                    if(length(choice)>1) choice <- sample(choice,1)
                    cat(choice)
                }
        }
}else{
    cat("ok")
    }

Приємно. Я почав рішення в R, але це набагато краще.
Олексій А.

Добре, якщо ви можете придумати хорошу стратегію, не соромтеся вводити на ринг новий R-бот (ви можете повторно використовувати частину мого коду, навіть якщо потрібно)! Мені було б цікаво побачити бота Джулії (оскільки ви час від часу гольфуєте в Джулії).
планування

Можливо, я спробую його зняти в Джулії. Дякуємо за заохочення. :)
Олексій А.

10

Пітон 2 - Боксер

Бот-боксер в основному буде тримати свою охорону, каченя та плетіння. Раз у раз він надсилатиме швидкий удар або перехрест сильному противнику, який не захищається добре, сподіваючись з часом знищити їх.

import sys, re, random
if sys.argv[1:]:
    rows = [map(int, re.sub('[DX]', '-1', b).split(',')) for b in sys.argv[2:]]
    bots = dict((r.pop(0),r) for r in rows if r[1]>0 and r[0]!=int(sys.argv[1]))
    target = max(bots, key=lambda b: bots[b][0]-300*(bots[b][2]==-1))
    print target if random.randint(1,100) > 70 else 'D'
else:
    print 'ok'

ОНОВЛЕННЯ: Виправлена ​​помилка, яка спричинила деякі недійсні результати.


4
354 символи? Що це, код гольфу? ;)
Кейсі Кубалл

1
@Darthfett: тільки тому, що тут багато представлень на Java, це не означає, що всім потрібно засмічувати свій код подібними кількостями котлована ...
перестала повертати контр годинник

11
Боксер худорлявий - він легко відповідає своїй бойовій вазі. Він насолоджується здоровим харчуванням розумінь і лямбда. Ви не знайдете його, що їсть статичний бургер, або жує фрі на брекетах.
Логічний лицар

4
@CarpetPython Терсмічність заради лаконічності так само погана, як і багатослівність.
Кролтан

9

C - сюрпризBot

Припускає, що перша черга буде безладом і захищає. Після цього нападайте на когось, хто не захищав останню чергу - вони ніколи не побачать, що це настане!

Ця відповідь нерозумна, але я хотів написати досить загальну платформу для побудови відповіді на мові С, тож ось вам.

//What doesn't kill me...
//SurpriseBot

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

int myself;

typedef struct s_Bot {
    int id;
    int life;
    int power;
    /* -1 is defending */
    int lastAction;
} Bot;

int compare_bots(const void* a, const void* b) {
    Bot one = *(Bot*)a;
    Bot two = *(Bot*)b;

    /* Never, ever target myself */
    if (one.id == myself) {
        return 1;
    }
    else if (two.id == myself) {
        return -1;
    }

    /* Also, don't target any bot that is dead */
    if (one.life < 1) {
        return 1;
    }
    else if (two.life < 1) {
        return -1;
    }

    /* Prefer those who did not defend last turn */
    /* They'll never see it coming!              */
    if (one.lastAction >= 0 && two.lastAction < 0) {
        return -1;
    }
    else if (one.lastAction < 0 && two.lastAction >= 0) {
        return 1;
    }

    /* Try to target the lowest health */
    if (one.life < two.life) {
        return -1;
    }
    else if (one.life > two.life) {
        return 1;
    }

    /* Try to target the more powerful bot */
    if (one.power < two.power) {
        return 1;
    }
    else if (one.power > two.power) {
        return -1;
    }
    else return 0;
}

int main(int argc, char** argv) {
    if (argc == 1) {
        printf("ok");
    }

    else {
        int quit = 0;
        myself = atoi(argv[1]);

        /* Populate a list of all bots */
        int num = argc - 2;
        Bot bots[num];

        int i;
        for (i = 0; i < num; i++) {
            char buf[100];
            sscanf(argv[2 + i], "%d,%d,%d,%s", &bots[i].id, &bots[i].life, &bots[i].power, buf);
            switch (buf[0]) {
                case 'X':
                    /* Assume the first turn is a bloodbath and we don't want any part of it */
                    printf("D");
                    quit = 1;
                    break;
                case 'D':
                    bots[i].lastAction = -1;
                    break;
                default:
                    sscanf(buf, "%d", &bots[i].lastAction);
                    break;
            }
            if (quit) {
                goto done;
            }
        }

        qsort(bots, num, sizeof(Bot), compare_bots);

        printf("%d", bots[0].id);
    }

done:
    return 0;
}

9

Python 2 - Precog

Precog намагається передбачити кроки всіх інших, спираючись на минулу частоту дій, потім намагається виконати кілька симуляцій і вибирає той, який максимально збільшує його бал. Це не особливо надійно, але тоді ... ESP не справжній. : D

import json, sys
from random import choice

#'S'/'W' = attack high/low power (strong/weak)
#'H'/'F'  = attack high/low health (hale/frail)
#'A' = attack defender (armor)
#'R' = attack random (it doesn't know)
#'D' = defend

amin = lambda x: x.index(min(x))
amax = lambda x: x.index(max(x))

def pick(history, ids, action):
    if action == 'D':
        return 'D'
    if action == 'R' or len(history['all'][-1][action]) < 1:
        return choice(ids)
    return choice(history['all'][-1][action])

args = sys.argv
if len(args) == 1:
    print 'ok'
    sys.exit()
me = args[1]

def notme(l):
    tmp = list(l)
    try:
        tmp.remove(me)
    except ValueError:
        pass
    return tuple(tmp)

args = args[2:]
try:
    with open('precog.state') as f:
        history = json.load(f)
except (IOError, ValueError):
    history = {}
if len(history) == 0:
    history = {'all':[]}

args = [a.split(',') for a in args]
ids,hps,pows,acts = zip(*args)
hps,pows = map(int,hps), map(int,pows)

for i,h,p,a in args:
    if a == 'X': #most people will try not to attack armored
        history[i] = {'a':'SWHFRD','health':[],'power':[],'score':[]}
    elif acts == 'D':
        history[i]['a'] += 'D'
    else:
        for x in 'SWHFA':
            if a in history['all'][-1][x]:
                history[i]['a'] += x
                break
        else:
            history[i]['a'] += 'R'
    history[i]['health'] += int(h),
    history[i]['power'] += int(p),
    history[i]['score'] += int(h)*int(p),

history['all'] += {'S':[ids[amax(pows)]],
                   'W':[ids[amin(pows)]],
                   'H':[ids[amax(hps)]],
                   'F':[ids[amin(hps)]],
                   'A':[ids[i] for i in filter(lambda x:acts[x]=='D',range(len(acts)))]},

with open('precog.state','w') as f:
    json.dump(history,f)

scores = dict(zip('SWHFRAD',[0]*7))
for _ in range(50):
    for act in 'SWHFRAD':
        _score = {}
        p,h,a = dict(zip(ids,pows)),dict(zip(ids,hps)),{i:0 for i in ids}
        opp = {i:choice(history[i]['a']) for i in ids if i != me}
        opp[me] = act
        m = {o:[1,2][opp[o]=='D'] for o in opp}
        for o in opp:
            if opp[o] != 'D':
                if o == me:
                    target = pick(history, notme(ids), opp[o])
                else:
                    target = pick(history, ids, opp[o])
                h[target] -= p[o]/m[target]
                a[target] += 1
        for o in opp:
            p[o] += m[o] * a[o]
            _score[o] = p[o] * h[o]
        scores[act] += _score.pop(me) - sum(_score.values())

target = pick(history, notme(ids), scores.keys()[amax(scores.values())])
if target == me:
    target = choice(notme(ids))
print target

2
Здається, цей бот час від часу нападає на інших ботів, які вже мертві. В іншому випадку це досить сильний бот (адже це змусило мого бота перемагати весь час проти тестових ботів до лише 50% часу, коли ваш бот був включений у мої тести).
Картопля

9

bash - CopyCat

CopyCat захоплюється сильними, здоровими та агресивними та атакує так само, як і вони. Коли у неї "враження", що більшість ботів атакує тут, вона починає захищати себе або атакувати слабких, якщо вона не стає сильнішою або більшість інших ботів не припиняють атакувати тут.

Просто виконайте це за допомогою /bin/bash copycat.sh

#!/bin/bash

if [[ "$1" == "" ]]; then echo "ok"; exit; fi

debug() {
    #echo "$(date): $*" >> copycat.log 
    return;
}

me=$1; shift
meAsTarget=0
myAction="D" #better than an invalid command
topBot=-1
topBotAwe=0
worstBot=-1
worstBotAwe=100
aliveBots=0

myMostWeakAttacker=-1
mmwaAwe=0

if [[ -e "./state/copycat.state" ]]; then
    . ./state/copycat.state
fi

for rawBot 
do
    if [[ "$rawBot" == "" ]]; then continue; fi
    if [[ $(echo $rawBot | grep -Fo ',' | wc -l) -ne 3 ]]; then continue; fi

    bot=(${rawBot//,/ })
    id=${bot[0]}; life=${bot[1]}; power=${bot[2]}; lastAction=${bot[3]}

    printf "%d\n" "$lastAction" > /dev/null 2>&1
    if [[ "$?" -ne 0 && "$lastAction" != "D" ]]; then continue; fi

    if [[ "$life" -le 0 ]]; then continue; fi
    ((aliveBots++))

    awesomeness=$(( 2 * (((life/10) * power) / (life/10 + power)) ))
    if [[ "$id" -eq "$me" ]]; then
        myLastAction="$lastAction"
        myAwe="$awesomeness"
    else
        lastBot=$id
    fi

    if [[ "$awesomeness" -gt "$topBotAwe"
        && "$lastAction" != "D"
        && "$lastAction" != "$me" ]]; then
            topBot=$id
            topBotAwe=$awesomeness
            topBotTarget=$lastAction
    fi

    if [[ "$awesomeness" -lt "$worstBotAwe" ]]; then
        worstBot=$id
        worstBotAwe=$awesomeness
    fi

    if [[ "$lastAction" -eq "$me" ]]; then
        ((meAsTarget++))
        if [[ "$awesomeness" -lt "$mmwaAwe" ]]; then
            myMostWeakAttacker=$id
            mmwaAwe=$awesomeness
        fi
    fi
done

backupStrategy() {
    if [[ "$myMostWeakAttacker" != "-1" && "$mmwaAwe" -lt "$myAwe" ]]; then
        debug "attacking my most weak attacker ($myMostWeakAttacker) who is weaker then me"
        myAction=$myMostWeakAttacker
    elif [[ "$worstBot" != "-1" && "$worstBot" != "$me" ]]; then
        debug "attacking the worst bot $worstBot"
        myAction=$worstBot
    elif [[ "$myMostWeakAttacker" != "-1" ]]; then
        debug "attacking my most weak attacker $myMostWeakAttacker"
        myAction=$myMostWeakAttacker
    else
        debug "no one is attacking me anymore; attacking the last ones"
        myAction=$lastBot
    fi
}

if [[ "$meAsTarget" -gt "$((aliveBots/2))" ]]; then
    #hit-and-run
    if [[ "$myLastAction" == "D" && "$myAwe" -gt "$worstBotAwe" ]]; then
        debug "I am still under fire, but not the worst one.."
        backupStrategy
    else
        debug "I was attacked to much; defending now (attack level: $meAsTarget)"
        myAction="D"
        meAsTarget=$((meAsTarget-aliveBots/2))
    fi
elif [[ "$topBotTarget" != "" ]]; then
    myAction=$topBotTarget

    for rawBot
    do
        if [[ "$rawBot" == "" ]]; then break; fi
        bot=(${rawBot//,/ })
        if [[ "${bot[0]}" -eq "$topBotTarget" ]]; then
            if [[ "${bot[1]}" -le 0 ]]; then
                backupStrategy
            else
                debug "copying strategy from bot $topBot attacking $myAction"
            fi
            break
        fi
    done
else
    backupStrategy
fi

if ! [[ -d "./state" ]]; then mkdir -p "./state"; fi
cat <<EOF_STATE > "./state/copycat.state"
topBotTarget="$topBotTarget"
meAsTarget="$meAsTarget"
EOF_STATE

echo "$myAction"
exit 0

Її слабкість: вона, можливо, ніколи не покращиться, як ті, на кого вона виглядає. :()


8

Python 3 DefenceBot

Бот намагається знайти ворога з найвищою силою, яку він може вбити за допомогою своєї нинішньої сили. Інакше захищайте. Бігайте зpython DefensiveBot.py id bot1 etc

import sys

def resolve(bots, power, life):
    highPowerCanKill = -1
    highPower = 0
    for i in bots:
        if int(i[1]) < int(power):
            if(int(i[2]) > int(highPower)) and (int(i[1]) > 0):
                highPower = i[2]
                highPowerCanKill = i[0]
    if highPowerCanKill != -1:
        return highPowerCanKill
    else:
        return "D"

args = sys.argv
if len(args) == 1:
    print("ok")
    sys.exit()
fileName = str(__file__).split('\\')
fileName = fileName[len(fileName)-1]
myId = args[1]

bots = []

for i in args:
    i = i.split(',')
    if len(i) == 1:
        continue
    if i[0] == myId:
        power = i[2]
        life = i[1]
        continue
    elif i[0] == fileName:
        continue

    bots.append(i)

kill = resolve(bots, power, life)
print(kill)

Схоже, це не працює правильно без аргументів: коли перший бот викликається, йому не дадуть аргументів. Відповісти с ok . Це робиться лише для того, щоб ваш бот відповів. Якщо цього не відбудеться, він не буде доданий до списку гравців.
Геобіць

@Geobits виправлено.
Ілля Бенедес

Гаразд, вона працює, але надрукована друк триває. Я повинен прокоментувати рядки 28 та 32, щоб дати правильні відповіді. Інакше воно просто гине.
Геобіць

Ви також можете переконатися, що бот живий, перш ніж націлити їх. Це націлюється на мертвих досить часто, що вважається недійсним кроком і знижує вашу силу.
Геобіць

зітхання виправлено. У мене таке відчуття, що це не останнє виправлення: P
Elias Benevedes

8

Java танк

Танк не думає, йому все одно, він просто атакує першого бота, який він бачить! Він досить розумний, щоб не нападати на себе чи мертвих.

public class Tank{
    public static void main (String[] args){
        if(args.length == 0){
            System.out.print("ok");
            System.exit(0);
        }

        String myId = args[0];
        int life = Integer.MIN_VALUE;
        String[] tokens = {};
        String opposingId = "";

        for(int i=1; i<args.length; i++){
            tokens = args[i].split(",");
            opposingId = tokens[0];
            life = Integer.parseInt(tokens[1]);
            if(life > 0 && !opposingId.equals(myId)){
                System.out.println(opposingId);
                System.exit(0);
            }
        }
        System.out.println("D");
    }
}

1
Як зазначалося на вашому іншому боті, це не компілюється як є.
Геобіць

8

Ява - фантомна загроза

Привіт! Це моє перше повідомлення тут у коді гольфу. Я хлопець C #, тож вибачте, будь ласка, французький. Я використав частини зразків кодів героя та боягуза.

Мій бот - простий хлопець з досить політичним ставленням. Більшу частину часу він просто ховається у фойє, випиваючи каву та готуючи свої схеми. Але коли виникає шанс і перспектива прибутку досить сильна, він підстрибує зі свого зручного крісла у фойє, викидає газету та йде за гроші.

Він просто захищається після того, як йому заподіяна будь-яка шкода. Інакше він поводиться як справжній Герой (Це теж політичне рішення, оскільки це цілком безпечно). Коли у нього всього три конкуренти, він іде на перемогу.

Він дотримується кількох основних принципів. Кожен серйозний політик повинен мати якісь непорушні принципи та чітко визначений профіль ...

Не допомагайте нікому, крім себе! (Егоїст)

Слава означає смерть! (Скептичний)

Після смерті нічого немає! (Атеїст)

public class PhantomMenace {
    public static void main(String[] args) {
        if(args.length < 1)
        {
            System.out.print("ok");
            System.exit(0);
        }

           String me = args[0], target="D", secondTarget="D", worstTarget="D";
           int best=0;
           int attackerCount = 0;
           int numBots= 0;
           int secondBest=0;
           int worst=0;

        for(int i=1;i<args.length;i++)
        {
            String[] tokens = args[i].split(",");
            int life = Integer.valueOf(tokens[1]);
            if(life > 0 && life >= best)
            {
                secondBest = best;
                secondTarget = target;
                best = life;
                target = tokens[0];

            }
            else if(life > 0 && life >= secondBest)
            {
                secondBest= life;
                secondTarget = tokens[0];
            }

            if(life > 0 && life <= best)
            {
            worst = life;
            worstTarget = tokens[0];
            }
            // count incoming attacks
            if(tokens[3].equals(me))
            attackerCount++;
            // count living bots
            if(life>0)
            numBots++;
        }

        // activate offensive regime?!
        if(numBots<5)
        {
            if(target.equals(me))
              System.out.print(secondTarget);
            else
              System.out.print(target);
        }
        else
        {
          if(worstTarget.equals(me))
            System.out.print("D");
          if(target.equals(me))
            System.out.print("D");
          else if(attackerCount>0)
            System.out.print("D");
          else
            System.out.print(target);
        }

    }
}

1
Дуже приємно, і зараз на другому місці. Ласкаво просимо на сайт :)
Геобіц

О, дякую, хоча це приємна несподіванка, я мушу визнати, що ніколи не переставав вірити в свого бота: P.
Stormcrow

7

Я тебе знаю - Ява

Аналізує всіх ворогів і використовує цю інформацію для кращої захисту. На жаль, він схильний до атак помсти.

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class IKnowYou {
    final static int LINES = 40;
    Bot me;
    final List<Bot> bots = new ArrayList<>();
    final List<Bot> livingEnemies = new ArrayList<>();
    final File file = new File("state/IKnowYou");
    final long lineCount;

    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        new IKnowYou(args).run();
    }

    public IKnowYou(String[] args) {
        for (int i = 1; i < args.length; i++) {
            Bot bot = new Bot(args[i], args[0]);
            bots.add(bot);
            if (bot.isMe) {
                me = bot;
            } else if (bot.life > 0) {
                livingEnemies.add(bot);
            }
        }
        lineCount = lineCount();
    }

    void run() {
        if (me.lastAction.equals("X")) {
            createFile();
            updateFile();
            System.out.println(livingEnemies.get(0).id);
            System.exit(0);
        }
        if (lineCount % LINES != 0) {
            updateFile();
        }
        if (underAttack()) {
            System.out.println("D");            
        } else {
            for (Bot bot : livingEnemies) {
                if (bot.lastAction.equals(me.id)){
                    System.out.println(bot.id);
                    return;
                }
            }
            int maxP = 0;
            Bot maxPowerBot = null;
            for (Bot bot : livingEnemies) {
                if (bot.power > maxP){
                    maxP = bot.power;
                    maxPowerBot = bot;
                }
            }
            System.out.println(maxPowerBot.id);
        }
    }

    void createFile() {
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {}
        }
    }

    void updateFile() {
        List<Bot> oldBots = new ArrayList<>();
        if (me.lastAction.equals("X")) {
            for (Bot bot : bots) {
                Bot copyBot = bot.copy();
                bot.life = 1000;
                bot.power = 10;
                oldBots.add(copyBot);
            }
        } else {
            String oldState = "";
            try (BufferedReader input = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = input.readLine()) != null && !line.equals("\n")) {
                    oldState = line;
                }
            } catch (Exception e) {}
            String[] parts = oldState.split(" ");
            for (int i = 0; i < parts.length; i++) {
                oldBots.add(new Bot(parts[i]));
            }
        }
        List<List<String>> ids = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            ids.add(new ArrayList<String>());
        }
        int maxL = -1, minL = 1001, maxP = 0;
        for (Bot bot : oldBots) {
            if (bot.life > maxL) {
                ids.get(0).clear();
                maxL = bot.life;
                ids.get(0).add(bot.id);
            } else if (bot.life == maxL) {
                ids.get(0).add(bot.id);
            }
            if (bot.life < minL) {
                ids.get(1).clear();
                minL = bot.life;
                ids.get(1).add(bot.id);
            } else if (bot.life == minL) {
                ids.get(1).add(bot.id);
            }
            if (bot.power > maxP) {
                ids.get(2).clear();
                maxP = bot.power;
                ids.get(2).add(bot.id);
            } else if (bot.power == maxP) {
                ids.get(2).add(bot.id);
            }
        }
        StringBuilder[] output = new StringBuilder[3];
        for (int i = 0; i < 3; i++) {
            output[i] = new StringBuilder();
        }
        output[0].append("maxL");
        output[1].append("minL");
        output[2].append("maxP");
        for (Bot bot : bots) {
            if (bot.isMe) 
                continue;
            for (int i = 0; i < 3; i++) {
                if (ids.get(i).contains(bot.lastAction)) {
                    output[i].append(' ').append(bot.id);
                }
            }
        }
        try(FileWriter wr = new FileWriter(file, true)) {
            for (int i = 0; i < 3; i++) {
                output[i].append('\n');
                wr.append(output[i].toString());
            }
            StringBuilder sb = new StringBuilder();
            for (Bot bot : bots) {
                sb.append(bot.id).append(',').append(bot.life).append(',').append(bot.power).append(' ');
            }
            wr.append(sb.toString().trim() + "\n");
        } catch (IOException e) {}
    }

    boolean underAttack() {
        Bot attacker = null;
        for (Bot bot : bots) {
            if (bot.lastAction.equals(me.id)) {
                if (attacker != null) {
                    return true;
                } else {
                    attacker = bot;
                }
            }
        }

        int maxL = 0, minL = 1001, maxP = 0;
        for (Bot bot : bots) {
            if (bot.life > maxL)
                maxL = bot.life;
            if (bot.life < minL)
                minL = bot.life;
            if (bot.power > maxP)
                maxP = bot.power;
        }
        if ((me.life < maxL && me.life > minL && me.power < maxP) || livingEnemies.size() == 1) {
            return false;
        }
        List<Map<String, Integer>> stats = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            stats.add(new HashMap<String, Integer>());
        }
        for (Bot bot : bots) {
            for (int i = 0; i < 3; i++) {
                stats.get(i).put(bot.id, 0);
            }
        }
        try (BufferedReader input = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = input.readLine()) != null) {
                if (line.startsWith("m")) {
                    int map = line.startsWith("maxL") ? 0 : line.startsWith("minL") ? 1 : 2;
                    String[] parts = line.split(" ");
                    for (int i = 1; i < parts.length; i++) {
                        int count = stats.get(map).get(parts[i]);
                        stats.get(map).put(parts[i], count+1);
                    }
                }
            }
        } catch (Exception e) {}
        for (int i = 0; i < 3; i++) {
            if ((me.life == maxL && i == 0) || (me.life == minL && i == 1) || (me.power == maxP && i == 2)) {
                for (String id : stats.get(i).keySet()) {
                    int count = stats.get(i).get(id);
                    if (count / ((float)lineCount / 4) > 0.65) {
                        for (Bot bot : bots) {
                            if (bot.id.equals(id)) {
                                if (bot.life > 0) {
                                    return true;
                                } else {
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    long lineCount() {      
        try (LineNumberReader  lnr = new LineNumberReader(new FileReader(file))) {
            lnr.skip(Long.MAX_VALUE);
            return lnr.getLineNumber();
        } catch (IOException e) {
            return 0;
        }
    }

    class Bot {
        String id, lastAction;
        int life, power;
        boolean isMe;

        public Bot() {}

        public Bot(String bot, String myId) {
            String[] parts = bot.split(",");
            id = parts[0];
            life = Integer.valueOf(parts[1]);
            power = Integer.valueOf(parts[2]);
            lastAction = parts[3];
            isMe = id.equals(myId);
        }

        public Bot(String oldBot) {
            String[] parts = oldBot.split(",");
            id = parts[0];
            life = Integer.valueOf(parts[1]);
            power = Integer.valueOf(parts[2]);
        }

        Bot copy() {
            Bot bot = new Bot();
            bot.id = id;
            bot.lastAction = lastAction;
            bot.life = life;
            bot.power = power;
            bot.isMe = isMe;
            return bot;
        }
    }
}

7

Ява - Велоцираптор

Велоцираптор - злий вбивця. Вона буде чекати, поки нападе, спостерігаючи за потенційною здобиччю. Потім вона йде на швидке вбивство, знімаючи ціль, яку вона може вбити найшвидше. Після початку нападу грабіжник не знає страху і продовжить приймати жертв, поки вона не стане єдиною жертвою.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class Velociraptor {

    public static void main(String[] args) {
        if (args.length < 1) {
            System.out.print("ok");
            System.exit(0);
        }
        Velociraptor raptor = new Velociraptor(args);
        System.out.print(raptor.determineVictim());
    }

    private final String observationsFilePath = "state/velociraptor.txt";
    private final File observationsFile = new File(observationsFilePath);

    private int id, life, power, round;
    private List<Bot> preyList;
    private Map<Integer, Integer> preyDefendCounts;

    public Velociraptor(String[] preyStates) {
        loadObservations();
        observePrey(preyStates);
        saveObservations();
    }

    private void observePrey(String[] preyStates) {
        this.id = Integer.valueOf(preyStates[0]);
        preyList = new ArrayList<>();
        for (int i = 1; i < preyStates.length; i++) {
            String[] tokens = preyStates[i].split(",");
            int preyId = Integer.valueOf(tokens[0]);
            int preyLife = Integer.valueOf(tokens[1]);
            int preyPower = Integer.valueOf(tokens[2]);
            String lastAction = tokens[3];

            if (preyId == this.id) {
                this.life = preyLife;
                this.power = preyPower;
            } else if (preyLife > 0) {
                Bot prey = new Bot();
                prey.id = preyId;
                prey.life = preyLife;
                prey.power = preyPower;
                prey.lastAction = lastAction;
                preyList.add(prey);
                //Clever girl!
                if (prey.lastAction.equals("D")) {
                    int preyDefendCount = preyDefendCounts.getOrDefault(prey.id, 0);
                    preyDefendCount++;
                    preyDefendCounts.put(prey.id, preyDefendCount);
                }
            }
        }
    }

    public String determineVictim() {
        if (this.life == 1000) { //lay in wait until attacked
            return "D";
        }
        double fastestKill = 1000; //max game rounds
        Bot victim = null;
        for (Bot prey : preyList) {
            int preyDefendCount = preyDefendCounts.getOrDefault(prey.id, 0);
            double effectiveMultiplier = 1 - (.5 * preyDefendCount / round);
            double turnsToKill = prey.life / (this.power * effectiveMultiplier);
            //target whoever can be killed fastest
            //in case of tie, kill the prey with more power first
            if (turnsToKill < fastestKill || (victim != null && turnsToKill == fastestKill && prey.power > victim.power)) {
                fastestKill = turnsToKill;
                victim = prey;
            }
        }
        return String.valueOf(victim.id);
    }

    private void loadObservations() {
        preyDefendCounts = new HashMap<>();
        if (observationsFile.exists()) {
            try (Scanner scanner = new Scanner(observationsFile)) {
                round = Integer.valueOf(scanner.nextLine());
                while (scanner.hasNext()) {
                    String line = scanner.nextLine();
                    String[] tokens = line.split(",");
                    int preyId = Integer.valueOf(tokens[0]);
                    int preyDefendCount = Integer.valueOf(tokens[1]);
                    preyDefendCounts.put(preyId, preyDefendCount);
                }

            } catch (FileNotFoundException ex) {
                System.out.println(ex.getMessage());
            }
        }
        round++;
    }

    private void saveObservations() {
        if (!observationsFile.exists()) {
            try {
                observationsFile.createNewFile();
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
            }
        }
        try (PrintWriter writer = new PrintWriter(observationsFile)) {
            writer.println(round);
            if (preyDefendCounts != null) {
                preyDefendCounts.entrySet().stream().forEach(entry -> writer.println(entry.getKey() + "," + entry.getValue()));
            }
        } catch (FileNotFoundException ex) {
            System.out.println(ex.getMessage());
        }
    }

    private class Bot {

        public int id, life, power;
        public String lastAction;
    }
}

7

Python 3 - SemiRandom

Вибір між атакою та захистом на основі випадковості, зваженої попередніми змінами сили після атаки та захисту. Якщо атака обрана, вона атакує найсильнішого гравця. Міцність визначається як life * power.

Проти трьох ботів-прикладів він рідко виграє. Можливо, в дикій природі ...

import sys, random

def get_goodness(r,d):
    if len(d)==0:
        return 0
    return sum(v/(r-k+5) for k,v in d.items())/sum(1/(r-k+5) for k,v in d.items())

def get_att_chance(r,ad,dd,b):
    ag=get_goodness(r,ad)+500+p/2/len(b)
    dg=get_goodness(r,dd)+500    
    return ag/(ag+dg)

args=sys.argv
if len(args)==1:
    print("ok")
    with open('state/semirandom.txt','w') as f:
        f.write('-1\n1000\n10\n{}\n{}\n"S"\n')
    sys.exit()
me=int(args[1])
b=[]
for ae in args[2:]:
    if ae[-1] in 'DX':    
        ae=ae[:-1]+'-1'
    ae=ae.split(',')
    if int(ae[0])!=me:
        b+=[[int(ae[i]) for i in range(4)]]
    else:
        l,p=int(ae[1]),int(ae[2])
with open('state/semirandom.txt','r') as f:
    data=f.read()
co,lo,po,ad,dd,h=map(eval,data.split('\n')[:-1])
r=len(ad)+len(dd)
vc=l*p-lo*po
if co==0:
    ad[r]=vc
if co==1:
    dd[r]=vc   
ll=sum([be[1] for be in b])
em=ll/p/len(b)/(1000-r)*2
target_id=max(b,key=lambda be:be[1]*be[2])[0]
if random.random()<em:
    action=0
else:
    if random.random()<get_att_chance(r,ad,dd,b):
        action=0
    else:
        action=1        
if action==0:
    act=str(target_id)
else:
    act='D'
with open('state/semirandom.txt','w') as f:
    f.write('{}\n{}\n{}\n{}\n{}\n"{}"\n'.format(action,l,p,ad,dd,h+act))        
print(act)

7

Ява- Римська черепаха

Римська черепаха нападе на кожного, хто підходить до нього, але також випадково вирішить напасти на інших ботів, оскільки це не боягуз. Це періодично (1 на 50) показує прощення.

import java.util.NoSuchElementException;
import java.util.Random;

public class RomanTortoise {

    public static void main(String[] args) {
        Random r = new Random();
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        try{
            String me = args[0];
            try{
            if(args[1].split(",")[3].equals("X"))
            {
                 System.out.print("D");
                 System.exit(0);
            }
            }
            catch(NoSuchElementException nse)
            {

            }
            for(int i = 1; i<args.length; i++)
            {
                try{
                    String[] tokens = args[i].split(",");
                    if(tokens.length>3)
                    {
                        String lastAction = tokens[3];

                        if(lastAction.equals(me) && (Integer.parseInt(tokens[1])>0))
                        {
                            //probably attack that bot
                            if(r.nextInt()%50 != 0)
                            {
                                System.out.print(tokens[0]);
                                System.exit(0);
                            }
                        }
                    }
                }
                catch(NoSuchElementException nse)
                {

                }
            }
            if(r.nextInt()%2 == 0)
            {
                for(int i = 0; i<100; i++)
                {
                    try{
                        int j = (r.nextInt() % (args.length-1)) + 1;
                        String[] tokens = args[j].split(",");
                        if(tokens.length>3)
                        {
                            if(Integer.valueOf(tokens[1])>0)
                            {
                                System.out.print(tokens[0]);
                                System.exit(0);
                            }
                        }
                    }
                    catch(NoSuchElementException nse)
                    {

                    }
                }
            }
        }
        catch(Exception e){}
        System.out.print("D");
        System.exit(0);
    }

}

Чи є якась конкретна причина, чому ви намагаєтеся зловити NoSuchElementExceptionмомент, коли його, здається, не кинули в tryблок? Або я щось пропускаю?
ТНТ

@TNT вже не. Я отримував це виняток іноді, коли отримував доступ до одного з елементів масиву. Виправили мою помилку, але щойно залишили спробу ловити - краще безпечно, ніж вибачте :)
euanjt

7

Java - BroBot

BroBot буде атакувати найпотужнішого супротивника, якщо ворог із атакою, що перевищує деяку прогресивно меншу цінність, не вирішить напасти на BroBot, і в такому випадку він захистить цю чергу.

public class BroBot {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("ok");
            return;
        }

        int health = 0, id = Integer.parseInt(args[0]);
        for (int k = 1; k < args.length; k++) {
            if (Integer.parseInt(args[k].split(",")[0]) == id) {
                health = Integer.parseInt(args[k].split(",")[1]);
                break;
            }
        }

        String action = "";
        for (String s : args) {
            if (!s.contains(",")) continue;
            String[] botInfo = s.split(",");
            int botId = Integer.parseInt(botInfo[0]);
            if (botId == id) continue;
            if (!botInfo[3].equals("D")) {
                try {
                    if (Integer.parseInt(botInfo[3]) == id && Integer.parseInt(botInfo[2]) >= health / 4) {
                        action = "D";
                        break;
                    }
                } catch (NumberFormatException ex) {
                    continue;
                }
            }
        }

        if (action.isEmpty()) {
            int max = 0;
            for (String s : args) {
                if (!s.contains(",")) continue;
                String[] botInfo = s.split(",");
                if (Integer.parseInt(botInfo[0]) == id ||
                    Integer.parseInt(botInfo[1]) <= 0) continue;
                int attack = Integer.parseInt(botInfo[2]);
                if (attack > max) {
                    attack = max;
                    action = botInfo[0];
                }
            }
        }
        System.out.println(action);
    }
}

Java - SisBot

Що брат без сестри? Багато речей ... але це не до речі. Будучи розумнішим ботом, SisBot зберігає останні дії кожного бота, аналізує їхні поточні та останні дії та змушує її рухатися - вона атакує бота з найвищою силою без другої думки за умови, що її здоров’я та сила досить високі та що жоден інший бот зі статусом потужності вище певного значення не вирішує напасти на неї; у такому випадку вона переключатиметься між атакуючими та захищаючими, або просто прямими, захищаючими, якщо потужність нападника справді велика.

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class SisBot {
    private static final Path directoryPath = Paths.get("state");
    private static final Path filePath = Paths.get("state" + java.io.File.separator + "SisBot.txt");
    private List<Bot> botList;
    private List<String> fileContents;
    private int id, health, power, turn;

    public SisBot(String[] args) throws IOException {
        if (args.length == 0) {
            createSaveFile();
            System.out.println("ok");
            System.exit(0);
        }
        fileContents = Files.readAllLines(filePath, Charset.defaultCharset());
        for (int k = 1; k < args.length; k++) {
            if (args[k].split(",")[3].equals("X")) {
                Files.write(filePath, "".getBytes());
                fileContents.clear();
                break;
            }
        }
        getBots(args);
        makeMove();
        writeBots();
    }

    private void createSaveFile() throws IOException {
        if (!Files.exists(filePath)) {
            if (!Files.exists(directoryPath))
                Files.createDirectory(directoryPath);
            Files.createFile(filePath);
        }
        else
            Files.write(filePath, "".getBytes());
    }

    private void getBots(String[] args) {
        id = Integer.parseInt(args[0]);
        botList = new ArrayList<Bot>();
        for (int k = 1; k < args.length; k++) {
            String[] botInfo = args[k].split(",");
            if (Integer.parseInt(botInfo[0]) != id && Integer.parseInt(botInfo[1]) > 0)
                botList.add(new Bot(args[k]));
            else if (Integer.parseInt(botInfo[0]) == id) {
                health = Integer.parseInt(botInfo[1]);
                power = Integer.parseInt(botInfo[2]);
            }
        }
    }

    private void makeMove() throws IOException {
        if (fileContents.isEmpty()) {
            System.out.println(botList.get((int)(Math.random()*botList.size())).getId());
            return;
        }
        getLastAction();
        String action = "";
        int maxHealth = 0, maxPower = 0;
        for (Bot b : botList) {
            if (power >= 40 && health >= 250) {
                if (b.getPower() > maxPower && (!b.getAction().equals("D") || botList.size() == 1)) {
                    maxPower = b.getPower();
                    action = String.valueOf(b.getId());
                }
            }
            else if (b.getAction().equals(String.valueOf(id)) && b.getLastAction() != null && b.getLastAction().equals(String.valueOf(id))) {
                System.out.println(health % 2 == 0 ? b.getId() : "D");
                return;
            }
            else if (b.getAction().equals(String.valueOf(id)) && b.getPower() > 50) {
                System.out.println("D");
                return;
            }
            else {
                if (b.getHealth() > maxHealth) {
                    maxHealth = b.getHealth();
                    action = String.valueOf(b.getId());
                }
            }
        }
        System.out.println(action);
    }

    private void getLastAction() {
        boolean endNext = false;
        for (String s : fileContents) {
            if (s.startsWith("Turn")) {
                turn = Integer.parseInt(s.split(" ")[1]);
                if (endNext)
                    break;
                else {
                    endNext = true;
                    continue;
                }
            }
            if (s.isEmpty()) break;
            String[] botInfo = s.split(",");
            for (Bot b : botList) {
                if (b.getId() == Integer.parseInt(botInfo[0]))
                    b.setLastAction(botInfo[4]);
            }
        }
    }

    private void writeBots() throws IOException {
        StringBuilder sb = new StringBuilder();
        String s = System.lineSeparator();
        sb.append("Turn " + ++turn + s);
        for (Bot b : botList) {
            b.setLastAction(b.getAction());
            sb.append(b.toString() + s);
        }
        sb.append(s);
        for (String str : fileContents)
            sb.append(str + s);
        Files.write(filePath, sb.toString().getBytes());
    }

    public static void main(String[] args) throws IOException {
        new SisBot(args);
    }

    private class Bot {
        private int id, health, power;
        private String action, lastAction;

        public Bot(String info) {
            String[] botInfo = info.split(",");
            id = Integer.parseInt(botInfo[0]);
            health = Integer.parseInt(botInfo[1]);
            power = Integer.parseInt(botInfo[2]);
            action = botInfo[3];
        }

        public int getId() {
            return id;
        }

        public int getHealth() {
            return health;
        }

        public int getPower() {
            return power;
        }

        public String getAction() {
            return action;
        }

        public void setLastAction(String lastAction) {
            this.lastAction = lastAction;
        }

        public String getLastAction() {
            return lastAction;
        }

        @Override
        public String toString() {
            return new StringBuilder()
                    .append(id).append(",")
                    .append(health).append(",")
                    .append(power).append(",")
                    .append(action).append(",")
                    .append(lastAction).toString();
        }
    }
}

Мені справді треба вивчити іншу мову ...: P


Здається, вам потрібна перевірка на те, що вибрана ціль уже загинула.
Ральф Маршалл

Я думав, що це вже маю ... але потім знову створив іншу стратегію перед публікацією тут. Дякуємо, що це зробили.
ТНТ

6

Java-еквалайзер

Незважаючи на те, що захист - це явно найефективніша стратегія (: P), цей хлопець вважає, що бити людей над головою, поки вони не скинуть гігантів, здається веселим. Але накручуйте тих людей, які весь час захищають. Вони не отримують сили від цього хлопця.

public class Equaliser {
    public static void main (String[] args) {
        if (args.length == 0) {
            System.out.print("ok");
            System.exit(0);
        }

        String myId = args[0];
        String[] tokens;
        int life, power;
        int lowestPower = Integer.MAX_VALUE;
        String lowest = "";
        int lowestLife = 1000;
        int myLife = 0;

        for (int i=1; i<args.length; i++) {
            tokens = args[i].split(",");
            life = Integer.parseInt(tokens[1]);
            power = Integer.parseInt(tokens[2]);
            if (!tokens[0].equals(myId)) {
                if (life > 0 && power < lowestPower && !tokens[3].equals("D")) {
                    lowest = tokens[0];
                    lowestPower = power;
                }
                lowestLife = Math.min(life, lowestLife);
            } else {
                myLife = life;
            }
        }

        if (myLife < lowestLife*5/4) {
            // IT'S TIME TO DEFEND!
            System.out.println("D");
        } else if (lowestPower != Integer.MAX_VALUE) {
            System.out.println(lowest);
        } else {
            // Them buffed up perma-defenders don't need no power
            System.out.println("D");
            // And if you can't beat 'em, join 'em
        }
    }
}

6

Java - Wiisniper - рефлекторний агент

Простий рефлекторний агент, який за допомогою простого евристичного ідентифікує найнебезпечнішого бота, а потім атакує його.

public class Wiisniper {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        String me = args[0], target="D";
        double bestRatio = Integer.MIN_VALUE;

        String[] tokens = args[Integer.valueOf(me)].split(",");
        double myLife = Integer.valueOf(tokens[1]);
        double myPower = Integer.valueOf(tokens[2]);

        for(int i=1;i<args.length;i++){
            tokens = args[i].split(",");
            double life = Integer.valueOf(tokens[1]);
            double power = Integer.valueOf(tokens[2]);
            double ratio = myLife/power - life/myPower;
            if(tokens[3].equals(me)) //attacks my bot
                ratio = ratio * 5;
            if(life > 0 && power > 0 && !tokens[0].equals(me) && myPower > 0 && ratio > bestRatio){
                bestRatio = ratio;
                target = tokens[0];
            }
        }
        System.out.print(target);
    }
}

6

Java - вище середнього

Намагається підтримувати свою статистику у верхньому кварталі. Використовує технологію прогнозування, щоб передбачити, що зробить противник.

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

public class AboveAverage {

    private static final String FILE_NAME = "state" + File.separator + "AboveAverage";

    private File file = new File(FILE_NAME);
    private List<Bot> bots = new ArrayList<>();
    private Bot me;
    private List<List<Bot>> history = new ArrayList<>();
    private String[] args;

    public AboveAverage(String[] args) {
        this.args = args;
        this.bots = readBotArray(args);
        bots.stream().filter(bot -> bot.isMe).forEach(bot -> me = bot); //Intellij told me to do this...
        if (!file.exists()){
            try {
                file.getParentFile().mkdirs();
                file.createNewFile();
            } catch (IOException ignored) {}
        }
        readHistory();
        updateFile();
    }

    private List<Bot> readBotArray(String[] args){ //First parameter is my id.
        List<Bot> bots = new ArrayList<>();
        String myId = args[0];
        for (String arg : args) {
            if (arg.equals(myId)) {    // `==` not `.equals()`
                continue;
            }
            Bot bot = new Bot(arg, myId);
            bots.add(bot);
        }
        bots.sort(Comparator.comparingDouble((Bot a) -> a.life).reversed());
        return bots;
    }

    private void updateFile() {
        PrintStream out;
        try {
            out = new PrintStream(new FileOutputStream(file, true), true);
            for (String s : args){
                if (!s.matches("\\d+|\\d+,-?\\d+,\\d+,(\\d+|D)")){
                    s.replaceAll("(\\d+,-?\\d+,\\d+,).*", "$1Invalid");
                }
                out.print(s + " ");
            }
            out.println();
        } catch (FileNotFoundException ignored) {}
    }

    private void readHistory() {
        try {
            Scanner scanner = new Scanner(file);
            while (scanner.hasNextLine()){
                String line = scanner.nextLine().trim();
                if (line.length() > 0) {
                    history.add(readBotArray(line.split("\\s+")));
                }
            }
        } catch (FileNotFoundException ignored) {}
    }

    public static void main(String[] args) throws FileNotFoundException {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        try {
            System.out.print(new AboveAverage(args).normalize());
        } catch (Exception e){
            Writer writer = new StringWriter();
            PrintWriter printWriter = new PrintWriter(writer);
            e.printStackTrace(printWriter);
            String s = writer.toString();
            System.out.print("error: " + s.replace("\n", " | "));
        }
    }

    String normalize() {
        if (history.size() == 0 || me.lastAction.equals("X")){
            return "D";
        }

        if (bots.stream().mapToInt(bot -> (bot.life + me.power - 1)/me.power).sum() < me.life/bots.stream().mapToInt(bot -> bot.power).sum()){
            return bots.stream().max(Comparator.comparingInt(a->a.power)).get().id;
        }

        List<Bot> bestHistory = history.stream().max((a,b) -> {
            int differenceA = 0;
            int differenceB = 0;
            for (int i = 0; i < a.size(); i++){
                if (!a.get(i).equals(bots.get(i))){
                    differenceA++;
                }
                if (!b.get(i).equals(bots.get(i))){
                    differenceB++;
                }
            }
            if (differenceA != differenceB){
                return differenceA - differenceB;
            }
            for (int i = 0; i < a.size(); i++){
                differenceA += Math.abs(bots.get(i).life - a.get(i).life) + Math.abs(bots.get(i).power - a.get(i).power) * 10;
                differenceB += Math.abs(bots.get(i).life - b.get(i).life) + Math.abs(bots.get(i).power - b.get(i).power) * 10;
            }
            return differenceA - differenceB;
        }).get();


        int i = history.indexOf(bestHistory) + 1;
        List<Bot> after = i == history.size() ? bots : history.get(i);

        Map<Bot, String> actions = new HashMap<>();
        for (Bot bot : bots){
            if (bot.equals(me)){
                continue;
            }
            after.stream().filter(future -> future.equals(bot)).forEach(future -> actions.put(bot, future.lastAction));
        }

        List<String> myActions = new ArrayList<>();
        myActions.add("D");
        myActions.add("InvalidChoice");
        myActions.addAll(bots.stream().map(bot -> bot.id).collect(Collectors.toList()));

        Map<String,List<Bot>> scenarios = new HashMap<>();
        for (String action : myActions){
            List<Bot> simulatedBots = bots.stream().map(Bot::copy).collect(Collectors.toList());  //IntelliJ told me to (kind of) golf these lines.
            actions.put(me, action);
            simulatedBots.stream().filter(bot -> actions.get(bot).equals("D")).forEach(Bot::defend);
            simulatedBots.stream().filter(bot -> !actions.get(bot).equals("D")).forEach(bot -> bot.attack(actions.get(bot), simulatedBots));
            scenarios.put(action, simulatedBots);
        }

        return scenarios.keySet().stream().min(Comparator.comparingInt((String action) -> {
            List<Bot> scenario = scenarios.get(action);
            Bot me = scenario.stream().filter(a->a.isMe).findAny().get();
            scenario.removeIf(a->a.life<1||a.equals(me));
            scenario.sort(Comparator.comparingInt(a->a.life));
            int bestLife = scenario.get(scenario.size() * 3 / 4).life;
            scenario.sort(Comparator.comparingInt(a->a.power));
            int bestPower = scenario.get(scenario.size() * 3 / 4).power;
            scenario.add(me);
            return Math.abs(me.power - bestPower)*20 + Math.abs(me.life - bestLife);
        })).get();
    }

    class Bot {
        String id, lastAction;
        int life, power;
        boolean isMe;
        boolean isDefending = false;

        public Bot() {}

        public Bot(String bot, String myId) {
            String[] parts = bot.split(",");
            id = parts[0];
            life = Integer.valueOf(parts[1]);
            power = Integer.valueOf(parts[2]);
            lastAction = parts[3];
            isMe = id.equals(myId);
        }

        Bot copy() {
            Bot bot = new Bot();
            bot.id = id;
            bot.lastAction = lastAction;
            bot.life = life;
            bot.power = power;
            bot.isMe = isMe;
            return bot;
        }

        void defend(){
            this.isDefending = true;
            this.power--;
        }

        void attack(int power){
            if (isDefending) {
                this.power += 2;
                this.life -= power / 2;
            } else {
                this.power++;
                this.life -= power;
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Bot bot = (Bot) o;

            return id.equals(bot.id);

        }

        @Override
        public int hashCode() {
            return id.hashCode();
        }

        void attack(String attackId, List<Bot> bots) {
            if (life < 1){
                return;
            }
            Bot attacked = bots.stream().filter((Bot a) -> a.id.equals(attackId)).findFirst().orElse(null);
            if (attacked == null){
                power--;
                return;
            }
            if (attacked.life < 1){
                power--;
                return;
            }
            attacked.attack(power);
        }
    }
}

Передбачається використання state/whateverне status. Також здається хіба що IndexOutOfBoundsна першій черзі.
OJFord

5

Java - пустушка

перше подання будь-коли! \ o / Працював над ботом для цього конкурсу, який використовує величезну економію даних і намагається знайти шаблон, і продумав цей. В основному, якщо він вважає, що його збитки занадто низькі, щоб зробити щось корисне, він захистить себе. В іншому випадку він нападе на більш загрозливого суперника, який визначається кількістю ударів, необхідних для його вбивства, і це пошкодження. Не міг би спробувати, але я думаю, що він може зробити хорошу роботу!

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class Pacifier
{
    private static final File DATA_FILE = new File("state"+File.separator+"Pacifier.whatever");
    public static void main(String[] args)
    {

        if(args.length==0)
        {

            if(DATA_FILE.exists())
            {
                try {
                    DATA_FILE.delete();
                } catch (Exception e) {System.out.println("D");System.exit(0);}
            }
            try{
                DATA_FILE.createNewFile();
            }catch (IOException e) {}
            System.out.println("ok");
            System.exit(0);
        }

        int ownId=0,ownHp=1,ownAt=1;
        String known = null;
        BufferedReader bf = null;

        try{
            bf=new BufferedReader(new FileReader(DATA_FILE));
            known=bf.readLine();
        }catch(Exception e){System.out.println("D");System.exit(0);}

        boolean firstTurn = known==null;
        String[] mk = null,iniData=null;
        if(!firstTurn)
        {       
            mk = known.split(" ");
            iniData = mk[0].split(",");
            iniData[1] = String.valueOf(Integer.parseInt(iniData[1])+1);

        }

        String[] datas = new String[args.length-1]; 
        boolean hasReseted = true;
        for(String s : args)
        {
            if(!s.contains(","))
                ownId=Integer.parseInt(s);

            else
            {
                String[] tmp = s.split(",");
                hasReseted=(Integer.parseInt(tmp[1])==1000)?hasReseted:false;
                if(Integer.parseInt(tmp[0])==ownId)
                {
                    ownHp=Integer.parseInt(tmp[1]);
                    ownAt=Integer.parseInt(tmp[2]);
                }
                int id=Integer.parseInt(tmp[0]);
                datas[id]=s;

                if(!firstTurn)
                {
                    if(tmp[3]!="D"){
                        int to =Integer.parseInt(mk[id+1].split(",")[4]);
                        int pa = Integer.parseInt(mk[id+1].split(",")[2]);
                        datas[id]+=","+(to+pa);
                    }
                    else
                        datas[id]+=","+Integer.parseInt(mk[id+1].split(",")[4]);
                }
                else
                    datas[id]+=",0";
            }
        }

        if(firstTurn||hasReseted)
        {
            iniData = new String[2];
            iniData[0]=ownId+"";
            iniData[1]="0";
        }

        int target=(ownId==0)?1:0;
        float best=-100.f;
        if(Integer.parseInt(iniData[1])<40
                &&Integer.parseInt(iniData[1])%3==0)
            target=-1;
        else
            for(String s:datas)
            {
                if(s!=null&&s.contains(","))
                {
                    String[] tmp = s.split(",");
                    int id = Integer.parseInt(tmp[0]);
                    float hp =Float.parseFloat(tmp[1]);
                    float at = Float.parseFloat(tmp[2]);

                    float curr=((hp/(float)ownAt)*at)*(0.1f*at);
                    float dangerOverall= Float.parseFloat(tmp[4])/(100*hp);
                    target=(curr*dangerOverall>=best
                            &&id!=ownId
                            &&hp>0)?Integer.parseInt(tmp[0]):target;
                    best=(curr*dangerOverall>=best
                            &&id!=ownId
                            &&hp>0)?curr:best;
                }
            }
        store(iniData,datas);
        System.out.println((target>=0)?target:"D");
    }

    private static void store(String[] iniData,String[] datas)
    {
        StringBuffer sb = new StringBuffer();
        sb.append(iniData[0]+","+iniData[1]);
        for(String s:datas)
        {
            if(s==null)
                break;
            sb.append(" "+s);
        }
        FileWriter fw = null;
        try{
            fw=new FileWriter(DATA_FILE);
            fw.write(sb.toString());
            fw.flush();
            fw.close();
        }catch(Exception e){e.printStackTrace();}
    }
}

У нього немає великого мозку, тому він нічого не пам’ятає, але я думаю, це могло б зробити гарну роботу. Кумедний момент: якщо він останній живий, він спробує вибити кілька трупів, зомбі його лякають!

Редагувати:

Я надіслав нормально на першому кроці, щойно перевірив його на зразки, він важко пропрацює, перед цим трохи попрацюю.

Редагувати 2:

тепер він запам'ятовує деякі дані, і, набагато краще, ніколи не вигравав, але насправді програвав щоразу <50 к.с. ... хо, і один із пробіжок, які я робив проти зразків, дав мені це:

14 3170 java Bully
0 0 java Pacifier
0 0 java Hero
0 0 java Coward

Це більше не відбувається (Він фактично набрав деякі очки :)), але було смішно: D.

Редагувати 3:

Використання правильного імені файлу та деяке вдосконалення. Працюйте досить добре, і набагато краще, коли тут багато ботів :).


3

Java - Meta Fighter

Примітка. Скажіть, будь ласка, якщо це не працює

Мета-винищувач не розглядає кожного противника як індивідуального ворога. Він розглядає всіх їх як єдине ціле. Мета-винищувач додає загальну силу і силу всіх ворогів і вважає, що це він проти них. Потім він підраховує, який хід буде найбільш ефективним для зниження обох цих балів. Вбивство слабкого супротивника є корисним, оскільки воно одночасно знижує силу та силу. Однак якщо атака противника дасть йому більше корисної сили, ніж це забирає сили, він вирішує, що цього не варто, або захищається, або атакує себе. Мета-винищувач цікавиться лише тим, чому противник воює сам із собою ...

(BTW, My Second Entry Ever to Codegolf)

package folder;

public class MetaFighter {
    public static void main(String[] args) {
        if(args.length < 1){
            System.out.print("ok");
            System.exit(0);
        }
        String me = args[0], target = "D";
    int weakestAmount = 2000, weakest = 0, totalLife = 0, totalPower = 0, threat = 0, enemies = 0;
    int life = 0,power = 0;
        for(int i = 1; i < args.length; i++){
        String[] data = args[i].split(",");
        if(me.equals(data[0])){
            life = Integer.parseInt(data[1]);
            power = Integer.parseInt(data[2]);
        }else{
            if(Integer.parseInt(data[1]) > 0){
                if(Integer.parseInt(data[1]) < weakestAmount){
                    weakest = Integer.parseInt(data[0]);
                    weakestAmount = Integer.parseInt(data[1]);
            }
            totalLife += Integer.parseInt(data[1]);
            totalPower += Integer.parseInt(data[2]);
            enemies++;
            }
        }
    }
    int powerV,totalPowerV,lifeV,totalLifeV,Defend = 0,AttackSelf = 0;
     powerV = power;
     totalPowerV = totalPower;
     lifeV = life;
     totalLifeV = totalLife;
    MetaFighter m = new MetaFighter();

    threat = m.calculateThreat(0, 0,totalLifeV,lifeV,powerV,totalPowerV, enemies);
    if (threat < 0){
        target = Integer.toString(weakest);
    }else{
    lifeV = lifeV - powerV;
    powerV++;
    AttackSelf = m.calculateThreat(0, 1,totalLifeV,lifeV,powerV,totalPowerV, enemies);  
     powerV = power;
     totalPowerV = totalPower;
    lifeV = life;
    totalLifeV = totalLife;
    Defend = m.calculateThreat(0, 2,totalLifeV,lifeV,powerV,totalPowerV, enemies);
    if(threat > AttackSelf && threat > Defend){
        target = Integer.toString(weakest);
    }
    if(Defend > AttackSelf && Defend > threat){
        target = "D";
    }
    if(AttackSelf > threat && AttackSelf > Defend){
        target = me;
    }
    if (Defend == threat){
        target = Integer.toString(weakest);
    }
    if (enemies < 3){
        target = Integer.toString(weakest);
    }
    }
    System.out.print(target);
    System.exit(0);
}
private int calculateThreat(int i, int s,int totalLifeV,int lifeV,int powerV, int totalPowerV, int enemies){
    if(totalLifeV > 0 && lifeV > 0){
        if(s == 0){
            totalLifeV += (0-powerV);
        }
        if (s != 2){
            lifeV += (0-totalPowerV);
        }else{
            lifeV += 0.5*(0-totalPowerV);
            powerV--;
        }
        powerV += enemies;
        totalPowerV++;
        i++;
    return calculateThreat(i, 0,totalLifeV,lifeV,powerV,totalPowerV, enemies);
    }
    if(lifeV > 0){
        return -1;
    }
    return i;
}

}

Остаточне редагування: додана функція, тому вона атакує, якщо залишилось лише 3 бота.

Найбільша слабкість: хуліган.


Чому мета-винищувач "цікавиться, чому опонент воює сам з собою", але також вважає нападу на себе?
rudi

@rudi Йому цікаво, чому опонент бився би самим собою так, що не вигідно супернику. Також теоретично він буде атакувати себе, але у всіх моїх тестах цього ніколи не буває.
colorado777

3

python 2.7 - Тревор Філліпс GTA V та Майкл Де Санта


Редагувати 25.05.2015: додана перша версія Майкла Де Санта.
Ось невеликий шанс GTA V. Я створив два бота Python, що представляють двох з трьох головних героїв GTA V. Будь ласка, знайомтесь Тревор Філліпс та Майкл Де Санта. У Тревора немає нічого надто тонкого щодо нього. У Майкла хороша пам’ять - і список хітів. Після того, як ви на ньому, ваші дні підраховуються.

Примітка1: Коли у мене буде час, я покладу трохи більше інтелекту на Майкла і, можливо, навіть додам Франкліна (щоб замінити вихваляного Тревора).

Примітка 2: Майкл, здається, працює цілком гаразд. У мене є ще кілька ідей, але я хотів викласти це. Можливо, прийде «краща» його версія.

Тревор Філіпс

# "Computer gamers with their computer rigs. 
#  All they do is cry. 
#  They will never get the game."
#                         - Trevor Phillips.
#
import sys, random
from __builtin__ import str

# YES!!! I'm alive!!!
args=sys.argv
if len(args)==1:
    print("ok")
    sys.exit()

# Basic strategy: Hit whoever hits me or just anyone; sometimes brag a Trevor quote.
me=int(args[1])
botnrs=[]
action=''
quotes=["Now would you get me a f*cking drink! I'm not gonna ask you again!",
        "Grumble grumble grumble I've got my work grumble grumble grumble I've got my life, never the two shall meet.",
        "Well hello there beautiful. here go buy yourself something nice",
        "I'm driving, you can jerk me off if I get bored... I'm joking, you can suck me off.",
        "Do you want me to get my dick out again?!",
        "Floyd..we're having people over.  We need chips, dip, and prostitutes"]
for bot in args[2:]:
    nr,life,power,lastaction=bot.split(',')
    botnrs.append(nr)
    if lastaction==str(me):
        action=int(nr)
if action=='':
    action=int(random.choice(botnrs))
if random.random()<0.05:
    action=random.choice(quotes)
print(action)

Майкл Де Санта

# Surviving is winning, Franklin, everything else is bullshit. 
# Fairy tales spun by people too afraid to look life in the eye. 
# Whatever it takes, kid: survive. 
#                                            - Michael De Santa.
#
import sys, pickle, re, operator

# List of power values for a certain bot in a given round range
def getpower( history, botid, roundrange ):
    return [sum([bot[2] for bot in history[i] if bot[0]==botid]) for i in roundrange]

# If you say nothing, I say "ok".
if len(sys.argv)==1:
    print("ok")
    historyfile=open('state/MichaelDeSanta.bin','w+')
    pickle.dump([[],{},0,0],historyfile)
    historyfile.close()
    sys.exit()

# Get data from file
myid=int(sys.argv[1])
historyfile=open('state/MichaelDeSanta.bin','r')
history,hitlist,botcount,roundnr=pickle.load(historyfile)
historyfile.close()
history.append([map(int,re.sub('[DX]','-1', bot).split(',')) for bot in sys.argv[2:]])

# Update hitlist:
if roundnr==0:
    hitlist=dict.fromkeys([bot[0] for bot in history[0]],0)

maxhealth=maxpower=[0,0]
for bot in history[roundnr]:
    if bot[0] != myid:
        if bot[1]<=0:
            hitlist[bot[0]]=0
        else:
            # If you hit me, you're on the list!
            if bot[3]==myid:
                hitlist[bot[0]]+=4
            # If I can kill you with one hit... You're on my list!
            if bot[1]<getpower(history,myid,[roundnr]):
                hitlist[bot[0]]+=1
            # If you're super healthy, you deserve PUNISHMENT!
            if bot[1]>maxhealth[1]:
                maxhealth=[bot[0],bot[1]]
            # If you're powerfull... Well... I'm not afraid!
            if bot[2]>maxpower[1]:
                maxpower=[bot[0],bot[1]]
hitlist[maxhealth[0]]+=3
hitlist[maxpower[0]]+=2

action=max(hitlist.iteritems(),key=operator.itemgetter(1))[0]
hitlist[action]-=1

# Save data to file
roundnr+=1
historyfile=open('state/MichaelDeSanta.bin','w+')
pickle.dump([history,hitlist,botcount,roundnr],historyfile)
historyfile.close()

# Wrap up and print the action
print(action)

2

Ява- Патрокла

Патрокл - агресивний бот, який налаштований шукати слави. У нього досить хороша пам’ять (навіть якщо я це так і кажу), і він вважає, що найкращий спосіб шукати славу - це атакувати найагресивнішого ворога. Він пам’ятає, хто напав на більшість до цих пір у всіх іграх і болить їх головою великим мечем.

Його найбільшою слабкістю є ставлення Камікадзе до захисту - кому це потрібно, коли ви носите броні Ахілла?

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;


public class Patroclus {

    final static File file = new File("state/Patroclus.txt");   
    static List<bot> enemies;
    static String me;

    public static void main(String[] args) {
            if(args.length < 1){
                if(file.exists())
                {
                    file.delete();
                }
                System.out.print("ok");
                System.exit(0);
            }
            me = args[0];
            enemies = new LinkedList<Patroclus.bot>();

            if(!file.exists())
            {
                createFile();               
                for(int i = 1; i<args.length; i++)
                {

                    String[] tokens = args[i].split(",");
                    bot newBot = new bot();
                    newBot.id = tokens[0];
                    newBot.life = Integer.valueOf(tokens[1]);
                    enemies.add(newBot);
                }               
            }
            else
            {

                openFile(args);

            }

            Collections.sort(enemies);
            Collections.reverse(enemies);

            String target = "D";
            for(int i = 0; (i<enemies.size()) && (i>-1); i++)
            {                               
                if(enemies.get(i).canAttack())
                {
                    target = enemies.get(i).id;
                    i = -10;
                }
            }
            saveFile();
            System.out.print(target);
            System.exit(0);
}


    private static void saveFile() {
        BufferedWriter writer;
        try {
            writer = new BufferedWriter(new FileWriter(file));
            for (bot b : enemies) {
                writer.write(b.toString());
                writer.write("#");
            }
            writer.flush();
            writer.close();
        } catch (IOException e) {           
        }
    }

    private static void openFile(String[] args) {       
            Scanner sc;
            try {
                sc = new Scanner(file);                     
                String[] lines = sc.next().split("#");

                for(int i = 0; i<lines.length; i++)
                {

                    bot newBot = new bot(lines[i]);


                    int j = 1;
                    for(; j<args.length && j>0; j++)
                    {
                        String[] tokens = args[j].split(",");
                        if(tokens[0].equals(newBot.id))
                        {
                            newBot.life=Integer.valueOf(tokens[1]);
                            if(newBot.life>0 && !tokens[3].equals("D"))
                            {
                                newBot.agression++;
                            }
                            j = -10;
                        }
                    }               
                    enemies.add(newBot);
                }           
            } catch (FileNotFoundException e) {
            }       
    }

    private static void createFile() {
        try {
            file.createNewFile();
        } catch (IOException e) {               
        }       
    }

    private static class bot implements Comparable<bot>
    {
        int agression, life;
        String id;

        public bot(String toParse)
        {
            String[] tokens = toParse.split(",");
            id = tokens[0];
            agression = Integer.valueOf(tokens[1]);
        }

        public bot()
        {
            this.agression = 0;
            this.life = 0;
            this.id = "D";
        }

        @Override
        public int compareTo(bot o) {
            if(this.agression>o.agression)
                return 1;
            else if (this.agression==o.agression)
                return 0;
            else
                return -1;
        }

        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append(id);
            sb.append(",");
            sb.append(agression);

            return sb.toString();
        }

        public Boolean canAttack()
        {
            return life>0 && !id.equals(me);
        }
    }
}

2

Іржа - параноїда

Триває порівнювати себе з найжвавішими на полі бою.

struct Bot {
    id: i32,
    life: i32,
    power: i32,
    action: String,
}

fn main() {
    let args: Vec<_> = std::env::args().collect();
    if args.len() < 2 {
        print!("ok");
    } else {
        let id: i32 = args[1].to_string().trim().parse()
            .ok()
            .expect("Please type a number!");

        let mut target_bot = Bot { id:-1, life:-1, power:-1, action:"D".to_string() };
        let mut own_bot = Bot { id:id, life:0, power:1, action:"D".to_string() };

        for arg in args {
            let split: Vec<&str> = arg.split(",").collect();
            if split.len() == 4 {
                let bot_id: i32 = split[0].to_string().trim().parse()
                    .ok()
                    .expect("Please type a number!");
                let bot_life: i32 = split[1].to_string().trim().parse()
                    .ok()
                    .expect("Please type a number!");
                let bot_power: i32 = split[2].to_string().trim().parse()
                    .ok()
                    .expect("Please type a number!");
                let bot_action: String = split[3].to_string();

                let bot = Bot { id:bot_id, life:bot_life, power:bot_power, action:bot_action };

                if bot.id != id && bot.life > target_bot.life {
                    target_bot = bot;
                } else if bot.id == id {
                    own_bot = bot;
                }
            }
        }

        /* If I am not stronger than the strongest, defend */
        let turns_to_kill = target_bot.life/own_bot.power + 1;
        let turns_to_be_killed = own_bot.life/target_bot.power;

        if target_bot.id > -1 && turns_to_kill < turns_to_be_killed {
            print!("{}", target_bot.id);
        } else {
            print!("D");
        }
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.