Code Bots 4: функциональное программирование


25

блин, это действительно 4-й? Для всех вас, пожилых людей, основная проблема та же, но мы используем Java вместо собственного языка. Вот последние три проблемы CodeBot , если вы заинтересованы.

Цель CodeBots - сделать вашего бота максимально вирусным . Каждый бот несет флаг, и вам нужно убедиться, что ваш флаг есть везде .

API

Боты будут следовать стандартному «протоколу», и боты будут синхронно выполнять следующие шаги:

  1. IPAddress selectMessageRecipient() позволяет боту выбирать, кому он хочет отправить «дружеское» сообщение.
  2. Message sendMessage() позволяет боту выбирать содержимое сообщения, которое он отправит.
  3. processMessage(IPAddress, Message) вызывается для каждого сообщения, которое получает бот.
  4. FunctionType selectFunctionToBlock()блокирует функцию от перезаписи для текущего хода. Смотрите шаг 7.
  5. IPAddress selectAttackTarget()позволяет боту выбирать, кого он хочет DDOS. DDOS-атака считается успешной, если на одного бота одновременно нацелены 3 бота. Если атака успешна, то каждый из атакующих может выполнить шаги 6 и 7.
  6. readData(ReadonlyBot) позволяет боту читать данные, хранящиеся на уязвимом боте.
  7. FunctionType selectFunctionToReplace()это суть этой проблемы . Вам разрешено выбрать 1 функцию (из 8 перечисленных здесь), чтобы скопировать их с вашего бота на их бота. Тогда ваша функция будет вызываться вместо их . Если несколько ботов выбирают одну и ту же функцию, случайная будет успешной.
  8. String getFlag()вызывается в конце игры и должен возвращать строку, уникальную для вашего представления. Ваша функция всегда должна возвращать одну и ту же строку. Представление с наибольшим количеством флагов в конце игры выигрывает.

Место хранения

У вас есть 3 формы хранения, адресная книга , журнал и переменные . Эти формы хранения являются локальными для бота, на котором выполняется ваша функция (поэтому, если ваша функция будет скопирована, содержимое каждого из этих объектов будет отличаться). Все эти объекты могут быть изменены или очищены вручную. Чтобы получить эти объекты, у вас есть получатель в вашем классе (например getLog()).

В AddressBook хранится список IP-адресов , каждый из которых имеет AddressType , который позволяет классифицировать различные типы адресов. Адресная книга всегда будет содержать как минимум 1 адрес (если он очищен, будет добавлен случайный). Очистка адресной книги для получения нескольких IP-адресов не допускается.

В журнале хранится список всех предпринятых действий, а также данные о действии. Он также включает в себя историю всех успешных атак (хотя вы не знаете, какие функции они перезаписали)

Объект Variables позволяет хранить строковые переменные, прикрепленные к имени строки. При запуске игры переменные будут содержать одну переменную, IDкоторая содержит случайно сгенерированный идентификатор, уникальный для вашего типа бота.

У вас также есть другие функции доступа:

  • int getTurnNumber() возвращает целое число с текущим ходом
  • bool functionsMatch(ReadonlyBot, FunctionType) проверяет, соответствует ли функция ReadonlyBot вашей
  • IPAddress personalAddress() возвращает ваш IP-адрес

Как реализовать

  • Вы можете получить код от Github
  • Добавьте своего бота в \botsпапку, а затем добавьте ссылку на своего бота вcontroller\CodeBotFactory.java
  • Ваш бот должен расширяться codebots.bot.CodeBotилиcodebots.bots.DefaultCodeBot
  • Вам нужна Java 8, если вы хотите запустить контроллер.
  • Вы можете запустить код (если вы находитесь в /srcпапке), используя javac codebots\*.javaдля компиляции, а затем java codebots.Mainдля запуска.
  • Вы можете не иметь никаких непостоянные переменные - члены в своем классе
  • Отражение не допускается.
  • Формы общения между ботами (одного и того же или разных типов) вне перечисленных выше методов не допускаются.
  • Допускаются глупые и / или суицидальные боты, но все боты должны быть функционально отличными от существующих записей.
  • Если вы хотите случайности в своем боте, используйте getRandom()
  • Пожалуйста, постарайтесь, чтобы ваш код работал эффективно. Я потратил много времени на профилирование и быстрое создание контроллера.

множество

105.2501 Expelliarmus!
104.5803 Я помогаю!
104.2746 Кто я?
103.8529 Dumb Bot
103.2028 Replacer
102.7045 Chaos
102.4046 Hermit Bot
102.2849 Swarmer
100.5598 Случайный бот любит вас
99.966 Доверьтесь доверию!
99.0185 codebots.bots.DefaultCodeBot
91.2942 codebots.bots.MarkedBot
91.1423 Просто ваш дружелюбный соседский робот доставки почты.
89,4645 ноль


Вы, вероятно, должны сделать Log.LogEntry окончательным, так как он не окончательный, я могу создавать журналы с любой информацией, которую я хочу ... что только моя функция бота сможет читать или создавать.
TheNumberOne

Может ли readData получить доступ к IP-адресу бота, который он читает?
TheNumberOne

@TheNumberOne сейчас нет, но я не понимаю, почему нет. У меня сейчас нет кода, но я обновлю код, чтобы это изменить.
Натан Меррилл

3
Мне интересно, что Хаос делает DisarmBot и MarkedBot местами в списке лидеров.
TheNumberOne

1
В настоящее время в раунде 7850 из 10000, получая более точные результаты ...
LegionMammal978

Ответы:


4

TrustBot

Если вы отправите ему сообщение, он сделает то, что он говорит. Если он читает бота, он скопирует адреса прямо в свою книгу. Он атакует ботов, которых адресная книга говорит атаковать.

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;
import java.util.*;

public class TrustBot extends CodeBot {
    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public Message sendMessage() {
        AddressBook book = getAddressBook();
        return new Message(Message.MessageType.INFORM, book.getAddress(getRandom().nextInt(book.size())));
    }

    @Override
    public void processMessage(IPAddress s, Message m) {
        AddressBook book = getAddressBook();
        if(m.getAddress() != null){
            if(m.getType() == Message.MessageType.ATTACK){
                book.add(m.getAddress(), AddressBook.AddressType.TO_ATTACK);
            }
            else if(m.getType() == Message.MessageType.HELP){
                book.add(m.getAddress(), AddressBook.AddressType.TO_DEFEND);
            }
            else if(m.getType() == Message.MessageType.CONFIRM){
                book.add(m.getAddress(), AddressBook.AddressType.TRUSTED);
            }
            else if(m.getType() == Message.MessageType.REJECT){
                book.add(m.getAddress(), AddressBook.AddressType.UNTRUSTED);
            }
            else if(m.getType() == Message.MessageType.AVOID){
                book.remove(m.getAddress());
            }
            else{
                book.add(m.getAddress());
            }
        }else{
            Message msg = new Message(m.getType(), s);
            processMessage(s, msg);
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        List<IPAddress> l;
        l = book.getAddressesOfType(AddressBook.AddressType.TO_ATTACK);
        Iterator<IPAddress> I = l.iterator();
        if(!I.hasNext())
            return book.getAddress(getRandom().nextInt(book.size()));
        return I.next();
    }

    @Override
    public void readData(ReadonlyBot bot) {
        AddressBook myBook = getAddressBook();
        ReadonlyAddressBook hisBook = bot.getAddressBook();
        AddressBook.AddressType[] values = AddressBook.AddressType.values();
        for(int i=0;i<values.length;i++){
            myBook.addAll(hisBook.getAddressesOfType(values[i]), values[i]);
        }
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return getRandom().nextInt(2)==1?FunctionType.GET_FLAG:FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public String getFlag() {
        return "Trust in Trust!";
    }
}

4

AmnesiaBot

Случайный бот, который внедряет других ботов с кодом потери памяти. Каждая функция начинается с кода для очистки журнала, адресной книги и переменных. Этот код заставит умных ботов терять память, пытаясь избавиться от логики.

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;

public class AmnesiaBot extends CodeBot {

    private void clear(){
        getAddressBook().clear();
        getAddressBook().add(getAddressBook().getAddress(0), AddressBook.AddressType.TRUSTED);
        getVariables().clear();
        getLog().clear();
    }

    @Override
    public IPAddress selectMessageRecipient() {
        clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public Message sendMessage() {
        clear();
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)], getAddressBook().getAddress(0));
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        clear();
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        clear();
        return getTurnNumber() % 2 == 0 ?
             FunctionType.GET_FLAG: FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public IPAddress selectAttackTarget() {
        clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public void readData(ReadonlyBot bot) {
        clear();
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        clear();
        FunctionType[] values =  FunctionType.values();
        return values[getRandom().nextInt(values.length)];
        //random gives a 7/8 chance of successes. 
    }

    @Override
    public String getFlag() {
        return "Who Am I?";
    }
}

Я думаю, что этот выигрывает только из-за неспособности более умного сценария быть способным запомнить что-либо. то есть очистка объекта Variables действительно чертовски мощна.
Draco18s

@ draco18s это не был серьезный ответ ...
MegaTom

Я знаю! Вот почему я так смущен этим. XD
Draco18s

3

NullBot

Его флаг очень ... характерный ...

package codebots.bots;
import codebots.gameobjects.*;
public class NullBot extends DefaultCodeBot {
    public IPAddress selectMessageRecipient() {
        return null;
    }
    public Message sendMessage() {
        return null;
    }
    public IPAddress selectAttackTarget() {
        return null;
    }
    public FunctionType selectFunctionToReplace() {
        return null;
    }
    public FunctionType selectFunctionToBlock() {
        return null;
    }
    public String getFlag(){
        return null;
    }
}

Это также предназначено для проверки контроллера и ограничения правила «тупые боты разрешены».


Технически он не соответствует спецификации, потому что он точно не возвращает строку для своего флага.
TheNumberOne

3
nullэто строка ;) Просто модная нить.
Эддисон Крамп

Это заставило меня признать недостаток в моей спецификации, который был определен: «все боты должны быть функционально отличны от существующих записей»
Натан Меррилл

@NathanMerrill Исправлено, чтобы более точно следовать спецификации.
TheNumberOne

3

RandomCodeBot

Обязательная случайная запись в KoTH

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class RandomCodeBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public Message sendMessage() {
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)]);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public FunctionType selectFunctionToBlock() {
        FunctionType[] values =  FunctionType.values();
        return values[getRandom().nextInt(values.length)];
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        FunctionType[] values =  FunctionType.values();
        return values[getRandom().nextInt(values.length)];
    }

    @Override
    public String getFlag() {
        return "Random bot loves you";
    }
}

3

DisarmerBot

DisarmerBot не слишком умен. Если он получит инструкции по атаке, он выберет случайного нападавшего, в противном случае он нападет на случайного игрока. Это просто отменяет их selectFunctionToBlockфункцию, чтобы заблокировать selectFunctionToBlock.

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;

import java.util.ArrayList;
import java.util.List;

public class DisarmerBot extends CodeBot {
    public IPAddress selectMessageRecipient() { return null; }
    public Message sendMessage() { return null; }

    public void processMessage(IPAddress source, Message message) {
        if (message != null && message.getAddress() != null && message.getType() == Message.MessageType.ATTACK)
            getAddressBook().add(message.getAddress());
    }

    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        List<IPAddress> attack = book.allAddresses();
        if (attack.size() > 0) {
            IPAddress bot = attack.get(getRandom().nextInt(attack.size()));
            book.clear();
            return bot;
        }
        //Umm...
        book.clear();
        return book.getAddress(0);
    }

    public void readData(ReadonlyBot bot) { getLog().clear(); /*Safety*/ }
    public FunctionType selectFunctionToReplace() { return FunctionType.SELECT_FUNCTION_TO_BLOCK; }
    public FunctionType selectFunctionToBlock() { return FunctionType.SELECT_FUNCTION_TO_BLOCK; }
    public String getFlag() { return "Expelliarmus!"; }
}

Вы можете выбрать n-й адрес без необходимости делать все адреса (). Если вы посмотрите на моего случайного бота, он делает случайный выбор адреса. Я обновил ваш код на Github (по соображениям эффективности), но если вы чувствуете, что он не работает, я с удовольствием верну его.
Натан Меррилл

О, мой плохой, исправленный.
Натан Меррилл

3

MarkedBot

Отмечает себя в первом раунде и использует эту информацию в последующих раундах. Таким образом, если другой бот будет введен с кодом атаки, он будет неэффективным.

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.*;

public class MarkedBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        Variables v = getVariables();
        AddressBook ab = getAddressBook();
        if(getTurnNumber()==0)
            v.add(v.get("ID"),"true");
        if("true".equals(v.get("hasOurFlag"))){
            ab.remove(ab.getAddress(0));
            v.remove("hasOurFlag");
        }
        return ab.getAddress(0);
    }

    @Override
    public Message sendMessage() {
        return new Message(Message.MessageType.STOP);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        if(message.getType() != Message.MessageType.STOP)
            getAddressBook().add(source, AddressBook.AddressType.TO_ATTACK);
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        Variables v = getVariables();
        if("true".equals(v.get(v.get("ID"))))
            return FunctionType.GET_FLAG;
        return FunctionType.SELECT_FUNCTION_TO_BLOCK;
    }

    @Override
    public IPAddress selectAttackTarget() {
        Variables v = getVariables();
        if("true".equals(v.get(v.get("ID"))))
            return getAddressBook().getAddress(0);
        else
            return null;
    }

    @Override
    public void readData(ReadonlyBot bot) {
        Variables v = getVariables();
        if(functionsMatch(bot, FunctionType.GET_FLAG))
            v.add("hasOurFlag", "true");
        else if("false".equals(v.get("hasOurFlag")))
            v.add("hasOurFlag", "false2");
        else
            v.add("hasOurFlag", "false");
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        Variables v = getVariables();
        if("true".equals(v.get(v.get("ID"))))
            if(!v.has("hasOurFlag") || "false".equals(v.get("hasOurFlag")))
                return FunctionType.GET_FLAG;
            else if("false2".equals(v.get("hasOurFlag")))
                return FunctionType.SELECT_FUNCTION_TO_BLOCK;
            else
                return FunctionType.SEND_MESSAGE;
        return FunctionType.SELECT_FUNCTION_TO_REPLACE;
    }

    @Override
    public String getFlag() {
        return this.getClass().getName();
    }
}

Я обнаружил несколько ошибок в этом боте (опечатки, использующие == вместо equals) Вы также обнаружили недостаток в моей системе: вы не должны иметь возможность создавать новые случайные IP-адреса. Я исправил эту проблему (и удалил код, делающий это). Вы можете найти обновленный код на github
Nathan Merrill

Также поздравляю на первом месте!
Натан Меррилл

HelperBot не очень умен. Это только достигло вершины, потому что все остальные боты были тупыми. : P Это, наверное, первый эффективный бот.
Draco18s

1
@NathanMerrill Значит ли это, что нам больше не разрешено создавать поддельные IP-адреса для обмана? (если это так, мне нужно изменить мой дизайн)
Ник Робертсон

Бот никогда не имеет намеренного доступа к раунду. Вы можете использовать IP-адреса противников в качестве подделок, но их создание запрещено. Кроме того, константа - это переменная, установленная в статическое время или время инициализации.
Натан Меррилл

2

SwarmBot

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

Связывание с веткой github repo, так как длина этого бота составляет 340 строк.

https://github.com/Draco18s/CodeBots4/blob/master/src/codebots/bots/SwarmBot.java

Несколько интересных моментов:

  • Строки 14-24 - это просто неизменяемый список, позволяющий легко изменять порядок, в котором бот заменяет методы своей цели. Он хранит, какой индекс его вVariables и увеличивает каждый раунд. Это должно следовать правилу «нет непостоянных переменных».
  • Строки 203-217 посвящены проверке союзников. На самом деле нам все равно, что другой бот выполняет все восемь наших инструкций. Только четыре необходимы, и если нам не хватает одного из «доверенных» союзников, мы заменяем его своим собственным.
  • Линии 295-300 были неожиданным повышением эффективности. Защищая наш Флаг в первые два хода игры, мы избегаем замены немых ботов, пока мы не получили возможность распространяться очень далеко. Ожидание дольше, однако, дает другим ботам возможность заменить нашу BlockFunction, что приводит к снижению производительности (подозревается из-за того, что RandomBot мешает союзникам, пытающимся отменить повреждение).
  • В течение самого длительного времени при разработке этого бота этот бот заставлял HelperBot развиваться вперед, в один момент преодолев отметку 130, в то время как этот бот томился в диапазоне 81-98, но снизив эффективность MarkedBot и DefaultBot на несколько пунктов.
  • Этот бот был возможен только с добавленным functionsMatchметодом. Без functionsMatchэтого невозможно было написать бота, который мог бы принимать осмысленные решения, поскольку он был слепым. Он мог читать свои целевые переменные и журналы, но ничего не знал о состоянии своей цели.

Вероятно, все еще возможны некоторые улучшения, но я не вижу их. Строки 198-205, вероятно, снижают производительность, но до тех пор, пока класс IPAddress не разрешит восстановление адресов из сохраняемых в переменных, это необходимо (поскольку у ботов нет средств проверки адреса, любое хранение неверного адреса приводит к тому, что игра обернуть нулевую цель в ReadOnlyBot, бросая NPE).

Редактировать: Обновления 12/12/15

Изменение некоторых параметров getTurnNumber()логики позволило повысить производительность. Увеличение таргетинга на конечную игру с 5% до 10% стоило около 15 баллов, также увеличивая таргетинг на раннюю игру с 5% до 8%. В совокупности этот бот теперь может (почти) выживать даже при столкновении с AmnesiaaBot (достигнув 2-го с результатом 110, где HelperBot достигает 117).

Даже с этими настройками он может стать неудачным, поэтому для 10 раундов его диапазон очков составляет примерно 170-185.


Потрясающе! Это намеренно, что вы не можете создавать IP-адреса из строк.
Натан Меррилл

Ну, якобы, да! (Или боты будут создавать произвольные, чтобы найти новых ботов). Проблема в том, что при симуляции вылетает сбой. ;)
Draco18s

Урм, в строке 143 вы используете несуществующий конструктор.
TheNumberOne

@TheNumberOne это было действительно, когда я написал это. Натан, наверное, обновил базу.
Draco18s

@TheNumberOne обновление сделано. new IPAddressВызов должен был «посмотреть из адресной книги» , как я сделал в readData. Я извлек этот поиск и зафиксировал строку 143.
Draco18s

1

DefaultCodeBot

Пытается делать разумные вещи. (Переопределите этот класс, если вы не хотите реализовывать все функции)

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class DefaultCodeBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        return getAddressBook().getAddress(0);
    }

    @Override
    public Message sendMessage() {
        return new Message(Message.MessageType.INFORM);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        return getAddressBook().getAddress(0);
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public String getFlag() {
        return this.getClass().getName();
    }
}

1

HelperBot

Бот-помощник не делает ничего, кроме как пытается распространить свой собственный флаг ... или, по крайней мере, тот флаг, который он в настоящее время находится в режиме ожидания ...

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class HelperBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public Message sendMessage() {
        return new Message(Message.MessageType.INFORM);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return FunctionType.GET_FLAG;
    }

    @Override
    public String getFlag() {
        return "I'm Helping!";
    }
}

Если HelperBot предполагает, что любой собственный метод, который перезаписан (кроме getFlag()), будет перезаписан чем-то лучшим.


1

Хаос

Он освобождает все флаги от тирании блокирования.

package codebots.bots;

import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by thenumberone on 12/11/15.
 *
 * @author thenumberone
 */
public class Chaos extends DefaultCodeBot{

    private static final String NAME = "Chaos";
    private static final String BLOCK = NAME + ":BLOCK";
    private static final String ATTACK = NAME + ":ATTACK";
    private static final String REPLACE = NAME + ":REPLACE";
    private static final String READ = NAME + ":READ";
    private static final String FLAG = NAME + ":FLAG";
    private static final String SELECT = NAME + ":SELECT";
    private static final String SEND = NAME + ":SEND";

    private static final Map<String, FunctionType> commands;

    private static final String[] REPLACEMENT_ORDER = {
            BLOCK,
            FLAG,
            REPLACE,
            READ,
            ATTACK,
    };

    private static final String DEFAULT = BLOCK;
    private static final String BLOCK_FUNCTION = BLOCK;

    static {
        Map<String, FunctionType> c = new HashMap<>();
        c.put(BLOCK, FunctionType.SELECT_FUNCTION_TO_BLOCK);
        c.put(ATTACK, FunctionType.SELECT_ATTACK_TARGET);
        c.put(REPLACE, FunctionType.SELECT_FUNCTION_TO_REPLACE);
        c.put(READ, FunctionType.READ_DATA);
        c.put(FLAG, FunctionType.GET_FLAG);
        c.put(SELECT, FunctionType.SELECT_MESSAGE_RECIPIENTS);
        c.put(SEND, FunctionType.SEND_MESSAGE);
        commands = Collections.unmodifiableMap(c);
    }

    @Override
    public String getFlag() {
        return NAME;
    }

    @Override
    public void readData(ReadonlyBot bot) {
        for (String command : commands.keySet()){
            getVariables().remove(command);
        }
        for (String command : REPLACEMENT_ORDER){
            if (!functionsMatch(bot, commands.get(command))) {
                getVariables().add(command, "");
                return;
            }
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return commands.get(BLOCK_FUNCTION);
    }

    @Override
    public IPAddress selectAttackTarget() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        for (String command : REPLACEMENT_ORDER){
            if (getVariables().has(command)) {
                getVariables().remove(command);
                return commands.get(command);
            }
        }
        return commands.get(DEFAULT);
    }
}

1

Заменитель

Эта запись заменяет все selectFunctionToReplaceфункции своей собственной selectFunctionToReplaceфункцией.

package codebots.bots;

import codebots.bot.ReadonlyBot;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by thenumberone on 12/11/15.
 *
 * @author thenumberone
 */
public class Replacer extends DefaultCodeBot{

    private static final String NAME = "Replacer";
    private static final String BLOCK = NAME + ":BLOCK";
    private static final String ATTACK = NAME + ":ATTACK";
    private static final String REPLACE = NAME + ":REPLACE";
    private static final String READ = NAME + ":READ";
    private static final String FLAG = NAME + ":FLAG";
    private static final String SELECT = NAME + ":SELECT";
    private static final String SEND = NAME + ":SEND";

    private static final Map<String, FunctionType> commands;

    private static final String[] REPLACEMENT_ORDER = {
            REPLACE,
            FLAG,
            READ,
            ATTACK
    };

    private static final String DEFAULT = REPLACE;
    private static final String BLOCK_FUNCTION = FLAG;

    static {
        Map<String, FunctionType> c = new HashMap<>();
        c.put(BLOCK, FunctionType.SELECT_FUNCTION_TO_BLOCK);
        c.put(ATTACK, FunctionType.SELECT_ATTACK_TARGET);
        c.put(REPLACE, FunctionType.SELECT_FUNCTION_TO_REPLACE);
        c.put(READ, FunctionType.READ_DATA);
        c.put(FLAG, FunctionType.GET_FLAG);
        c.put(SELECT, FunctionType.SELECT_MESSAGE_RECIPIENTS);
        c.put(SEND, FunctionType.SEND_MESSAGE);
        commands = Collections.unmodifiableMap(c);
    }

    @Override
    public String getFlag() {
        return NAME;
    }

    @Override
    public void readData(ReadonlyBot bot) {
        for (String command : commands.keySet()){
            getVariables().remove(command);
        }
        for (String command : REPLACEMENT_ORDER){
            if (!functionsMatch(bot, commands.get(command))) {
                getVariables().add(command, "");
                return;
            }
        }
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return commands.get(BLOCK_FUNCTION);
    }

    @Override
    public IPAddress selectAttackTarget() {
        getAddressBook().clear();
        return getAddressBook().getAddress(0);
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        for (String command : REPLACEMENT_ORDER){
            if (getVariables().has(command)) {
                getVariables().remove(command);
                return commands.get(command);
            }
        }
        return commands.get(DEFAULT);
    }
}

1

MailBot

Mailbot обрабатывает только сообщения. Не удается вывести свой собственный флаг в мир (средний балл ~ 50, немного выше, чем у nullbot ~ 45), но отправьте ему сообщение, и он перешлет ваш адрес кому-то еще.

package codebots.bots;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class MailBot extends DefaultCodeBot {
    private final String TEAM = "Just your friendly neighborhood mail delivering robot.";
    private final String TEAMALT = "Mailmain";
    private final List<FunctionType> funcList;
    {
        List<FunctionType> list = new ArrayList<FunctionType>();
        list.add(FunctionType.SELECT_MESSAGE_RECIPIENTS);
        list.add(FunctionType.SEND_MESSAGE);
        list.add(FunctionType.PROCESS_MESSAGE);
        funcList = Collections.unmodifiableList(list);
    }

    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        IPAddress ip;
        List<IPAddress> l = book.getAddressesOfType(AddressBook.AddressType.TO_ATTACK);
        if(l.size() > 0) {
            ip = l.get(0);
            book.add(ip,AddressBook.AddressType.UNTRUSTED);
            return ip;
        }
        ip = book.getAddress(getRandom().nextInt(book.size()));
        book.add(ip,AddressBook.AddressType.UNTRUSTED);
        return ip;
    }

    @Override
    public Message sendMessage() {
        AddressBook book = getAddressBook();
        IPAddress ip;

        List<IPAddress> l = book.getAddressesOfType(AddressBook.AddressType.UNTRUSTED);
        if(l.size() > 0) {
            ip = l.get(0);
            book.add(ip,AddressBook.AddressType.TO_DEFEND);
            return new Message(Message.MessageType.INFORM,ip);
        }

        ip = book.getAddress(getRandom().nextInt(book.size()));
        book.add(ip,AddressBook.AddressType.UNTRUSTED);
        return new Message(Message.MessageType.INFORM,ip);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        AddressBook book = getAddressBook();
        book.add(source,AddressBook.AddressType.TO_ATTACK);
        if(message.getAddress() != null)
            book.add(message.getAddress(),AddressBook.AddressType.TO_ATTACK);
    }

    @Override
    public FunctionType selectFunctionToBlock() {
        return FunctionType.SEND_MESSAGE;
    }

    @Override
    public IPAddress selectAttackTarget() {
        //Mailbot doesn't attack
        return null;
    }

    @Override
    public void readData(ReadonlyBot bot) { }

    @Override
    public FunctionType selectFunctionToReplace() {
        //if our attack selection gets overwritten,
        //then attack a message-based function
        return funcList.get(getTurnNumber()%3);
    }

    @Override
    public String getFlag() {
        return TEAM;
        //if flag is too long, use:
        //return TEAMALT;
    }
}

Я решил сохранить детали, чтобы переслать весь текст сообщениями на нового бота (контент и флаг), а не только на IP-адрес отправителя, но это потребовало бы интенсивного использования переменных без какого-либо функционального усиления, особенно учитывая, что AmnesiaBot находится в игре.


1

DumbBot

Тьфу, это кажется грязным. Это, вероятно, единственное, что превосходит AmnesiaBot. На самом деле, это просто специализированный RandomBot: он получает случайного бота в симуляции (через getAddressBook().clear()) и случайным образом заменяет либо функцию Block, либо функцию Flag. Вот и все. Выбрав только эти два, его коэффициент распространения флага выше, чем у AmnesiaBot или HelperBot, но лишь незначительно после 3000 раундов:

Round 2999
105.50666666666666  Dumb Bot
105.07266666666666  Who Am I?
103.541             I'm Helping!
102.94833333333334  Swarmer
102.82033333333334  Chaos
102.82033333333334  Replacer
101.55666666666667  Expelliarmus!
101.25833333333334  Trust in Trust!
100.347             Random bot loves you
99.22233333333334   codebots.bots.DefaultCodeBot
92.62733333333334   codebots.bots.MarkedBot
91.80966666666667   Just your friendly neighborhood mail delivering robot.
90.46933333333334   null

Я немного возился с функцией замены, но в итоге эта версия оказалась наиболее успешной.

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class DumbBot extends CodeBot {


    @Override
    public FunctionType selectFunctionToBlock() {
        return getRandom().nextBoolean()?FunctionType.SELECT_FUNCTION_TO_BLOCK:FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        book.clear();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public FunctionType selectFunctionToReplace() {
        return getRandom().nextBoolean()?FunctionType.SELECT_FUNCTION_TO_BLOCK:FunctionType.GET_FLAG;
    }

    @Override
    public void readData(ReadonlyBot bot) {

    }

    @Override
    public IPAddress selectMessageRecipient() {
        AddressBook book = getAddressBook();
        book.clear();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public Message sendMessage() {
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)]);
    }

    @Override
    public void processMessage(IPAddress source, Message message) {

    }

    @Override
    public String getFlag() {
        return "Dumb Bot";
    }
}

0

Бот-отшельник

Он живет один и разговаривает только с собой. Если меньше людей узнают, кто он, то его будут меньше беспокоить. Если кто-то беспокоит его, он будет атаковать их, пока кто-то другой не побеспокоит его.

package codebots.bots;

import codebots.bot.CodeBot;
import codebots.bot.ReadonlyBot;
import codebots.gameobjects.AddressBook;
import codebots.gameobjects.FunctionType;
import codebots.gameobjects.IPAddress;
import codebots.gameobjects.Message;

public class HermitBot extends CodeBot {

    @Override
    public IPAddress selectMessageRecipient() {
        return personalAddress();//Talks to himself.
    }

    @Override
    public Message sendMessage() {
        Message.MessageType[] values = Message.MessageType.values();
        return new Message(values[getRandom().nextInt(values.length)], personalAddress());
    }

    @Override
    public void processMessage(IPAddress source, Message message) {
        AddressBook book = getAddressBook();
        if(source != personalAddress()){
            //if someone talks to you, put them in your addres book and remove everyone else
            book.clear();
            book.add(source);
            book.remove(0);
        }
    }


    @Override
    public FunctionType selectFunctionToBlock() {
        return getTurnNumber() % 3 == 0 ?
                FunctionType.SELECT_FUNCTION_TO_BLOCK: FunctionType.GET_FLAG;
    }

    @Override
    public IPAddress selectAttackTarget() {
        AddressBook book = getAddressBook();
        return book.getAddress(getRandom().nextInt(book.size()));
    }

    @Override
    public void readData(ReadonlyBot bot) {
        Variables v = getVariables();
        if(functionsMatch(bot, FunctionType.SELECT_FUNCTION_TO_BLOCK))
            v.add("Block Dif","A");
        if(functionsMatch(bot, FunctionType.GET_FLAG))
            v.add("Flag Dif","B");
        if(functionsMatch(bot, FunctionType.SELECT_MESSAGE_RECIPIENTS))
            v.add("Targ Dif","C");

    }

    @Override
    public FunctionType selectFunctionToReplace() {
        Variables v = getVariables();
        FunctionType r = getRandom().nextBoolean()?FunctionType.SELECT_FUNCTION_TO_REPLACE: FunctionType.READ_DATA;

        if(v.has("Targ Dif"))
            r = FunctionType.SELECT_MESSAGE_RECIPIENTS;
        if(v.has("Flag Dif") && getTurnNumber() % 3 == 0)
            r = FunctionType.GET_FLAG;
        if(v.has("Block Dif"))
            r = FunctionType.SELECT_FUNCTION_TO_BLOCK;
        v.clear();
        return r;
    }

    @Override
    public String getFlag() {
        return "Hermit Bot";
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.