Code Bots 4: Programowanie funkcjonalne

25

sheesh, czy to naprawdę czwarty? Dla wszystkich starych graczy podstawowe wyzwanie jest takie samo, ale używamy Javy zamiast niestandardowego języka. Oto trzy ostatnie wyzwania CodeBot , jeśli jesteś zainteresowany.

Celem CodeBots jest uczynienie twojego bota tak wirusowym, jak to możliwe . Każdy bot nosi flagę i musisz upewnić się, że twoja flaga jest wszędzie .

API

Boty będą postępować zgodnie ze znormalizowanym „protokołem”, a boty będą postępowały synchronicznie przez następujące kroki:

  1. IPAddress selectMessageRecipient() pozwala botowi wybrać, do kogo chce wysłać „przyjazną” wiadomość.
  2. Message sendMessage() pozwala botowi wybrać treść wiadomości, którą wyśle.
  3. processMessage(IPAddress, Message) jest wywoływany dla każdej wiadomości, którą otrzymuje bot.
  4. FunctionType selectFunctionToBlock()blokuje zastąpienie funkcji dla bieżącej tury. Zobacz krok 7.
  5. IPAddress selectAttackTarget()pozwala botowi wybrać, kogo chce DDOS. Atak DDOS kończy się powodzeniem, jeśli bot jest atakowany jednocześnie przez 3 boty. Jeśli atak się powiedzie, każdy z atakujących może wykonać krok 6 i 7.
  6. readData(ReadonlyBot) pozwala botowi na odczyt danych przechowywanych na podatnym bocie.
  7. FunctionType selectFunctionToReplace()jest sednem tego wyzwania . Możesz wybrać 1 funkcję (spośród 8 wymienionych tutaj), aby skopiować z bota do jego bota. Następnie twoja funkcja zostanie wywołana zamiast ich . Jeśli wiele botów wybierze tę samą funkcję, losowa zakończy się sukcesem.
  8. String getFlag()jest wywoływany na końcu gry i powinien zwrócić ciąg znaków unikalny dla twojego przesłania. Twoja funkcja powinna zawsze zwracać ten sam ciąg. Zgłoszenie z największą liczbą flag na końcu gry wygrywa.

Przechowywanie

Masz 3 formy przechowywania, książkę adresową , dziennik i zmienne . Te formy przechowywania są lokalne dla bota, na którym działa funkcja (więc jeśli twoja funkcja zostanie skopiowana, zawartość każdego z tych obiektów będzie inna). Wszystkie te obiekty można ręcznie modyfikować lub usuwać. Aby zdobyć te obiekty, masz w swojej klasie gettera (np getLog().).

AddressBook przechowuje listę IPaddress , każdy z AddressType , który pozwala sklasyfikować różne rodzaje adresów. Książka adresowa zawsze będzie zawierała co najmniej 1 adres (jeśli zostanie wyczyszczony, zostanie dodany losowy). Czyszczenie książki adresowej w celu uzyskania wielu adresów IP jest niedozwolone.

Log przechowuje listę wszystkich podejmowanych działań, a także dane na temat działania. Zawiera również historię wszystkich udanych ataków (choć nie wiesz, które funkcje zastąpiły)

Obiekt Variables umożliwia przechowywanie zmiennych łańcuchowych dołączonych do nazwy łańcucha. Na początku gry Zmienne będą zawierać jedną zmienną, IDktóra zawiera losowo generowany identyfikator, który jest unikalny dla twojego typu bota.

Masz również inne funkcje dostępu:

  • int getTurnNumber() zwraca liczbę całkowitą z bieżącą turą
  • bool functionsMatch(ReadonlyBot, FunctionType) sprawdza, czy funkcja ReadonlyBot pasuje do twojej
  • IPAddress personalAddress() zwraca adres IP

Jak wdrożyć

  • Możesz uzyskać kod z Github
  • Dodaj bota do \botsfolderu, a następnie dodaj odwołanie do bota wcontroller\CodeBotFactory.java
  • Twój bot musi się rozszerzyć codebots.bot.CodeBotlubcodebots.bots.DefaultCodeBot
  • Potrzebujesz Java 8, jeśli chcesz uruchomić kontroler.
  • Możesz uruchomić kod (zakładając, że jesteś w /srcfolderze), używając javac codebots\*.javado kompilacji, a następnie java codebots.Maindo uruchomienia.
  • Możesz nie mieć żadnych niestałych zmiennych składowych w swojej klasie
  • Odbicie nie jest dozwolone.
  • Formy komunikacji między botami (tego samego lub różnych typów) poza metodami wymienionymi powyżej są niedozwolone.
  • Głupie i / lub samobójcze boty są dozwolone, ale wszystkie boty powinny funkcjonalnie różnić się od istniejących wpisów.
  • Jeśli chcesz mieć losowość w bocie, użyj getRandom()
  • Staraj się, aby Twój kod był wydajny. Sporo czasu poświęciłem profilowaniu i szybszemu kontrolerowi.

Wyniki

105,2501 Expelliarmus!
104,5803 Pomagam!
104,2746 Kim jestem?
103.8529 Dumb Bot
103.2028 Zamiennik
102.7045 Chaos
102.4046 Hermit Bot
102.2849 Swarmer
100.5598 Losowy bot cię kocha
99,966 Zaufanie!
99.0185 codebots.bots.DefaultCodeBot
91.2942 codebots.bots.MarkedBot
91.1423 Tylko twój przyjazny robot dostarczający pocztę.
89,4645 null

Nathan Merrill
źródło
Prawdopodobnie powinieneś uczynić Log.LogEntry ostatecznym, z tym nie ostatecznym Mogę tworzyć logi z dowolnymi informacjami, które chcę ... że tylko moja funkcja bota byłaby w stanie czytać lub tworzyć.
TheNumberOne
Czy readData może uzyskać dostęp do adresu IP czytanego bota?
TheNumberOne
@Numer obecnie nie jest, ale nie rozumiem, dlaczego nie. Obecnie nie mam przy sobie kodu, ale zaktualizuję go, aby to zmienić.
Nathan Merrill,
3
Interesujące jest dla mnie to, że Chaos sprawia, że ​​DisarmBot i MarkedBot wymieniają się miejscami na tablicy wyników.
TheNumberOne
1
Obecnie w rundzie 7850 na 10000, uzyskiwanie dokładniejszych wyników ...
LegionMammal978,

Odpowiedzi:

4

TrustBot

Jeśli wyślesz mu wiadomość, zrobi to, co mówi. Jeśli przeczyta bota, skopiuje adresy bezpośrednio do swojej książki. Atakuje boty, które według książki adresowej mają atakować.

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!";
    }
}
MegaTom
źródło
4

AmnesiaBot

Losowy bot, który wstrzykuje innym botom kod utraty pamięci. Każda funkcja zaczyna się od kodu do wyczyszczenia dziennika, książki adresowej i zmiennych. Ten kod spowoduje, że inteligentne boty stracą pamięć, próbując pozbyć się logiki.

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?";
    }
}
MegaTom
źródło
Myślę, że ten wygrywa tylko z powodu niemożności inteligentnego skryptu, który byłby w stanie zapamiętać cokolwiek. tzn. wyczyszczenie obiektu Zmiennych jest naprawdę cholernie potężne.
Draco18s,
@ draco18s nie była to naprawdę poważna odpowiedź ...
MegaTom,
Wiem! Właśnie dlatego jestem tym zdezorientowany. XD
Draco18s,
3

NullBot

Jego flaga jest bardzo ... charakterystyczna ...

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

Ma to również na celu przetestowanie kontrolera i ograniczenia reguły „głupie boty są dozwolone”.

Numer jeden
źródło
Technicznie nie pasuje do specyfikacji, ponieważ nie zwraca dokładnie Ciągu dla swojej flagi.
TheNumberOne
3
nulljest ciągiem. ;) Tylko fantazyjny ciąg.
Addison Crump,
To pozwoliło mi rozpoznać wadę w mojej specyfikacji, która została określona: „wszystkie boty powinny funkcjonalnie różnić się od istniejących wpisów”
Nathan Merrill
@NathanMerrill Naprawiono, aby ściślej przestrzegać specyfikacji.
TheNumberOne
3

RandomCodeBot

Obowiązkowy losowy wpis 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";
    }
}
Nathan Merrill
źródło
3

DisarmerBot

DisarmerBot nie jest zbyt inteligentny. Jeśli otrzyma instrukcje ataku, wybierze losowego atakującego, w przeciwnym razie zaatakuje losowego gracza. Po prostu zastępuje ich selectFunctionToBlockfunkcję do blokowania 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!"; }
}
LegionMammal978
źródło
Możesz wybrać n-ty adres bez potrzeby wykonywania allAddresses (). Jeśli spojrzysz na mojego losowego bota, dokonuje losowego wyboru adresu. Zaktualizowałem Twój kod w Github (ze względu na wydajność), ale jeśli uważasz, że to nie działa, chętnie go cofnę.
Nathan Merrill,
Och, moje złe, naprawione.
Nathan Merrill,
3

MarkedBot

Zaznacza się w pierwszej rundzie i wykorzystuje te informacje w późniejszych rundach. W ten sposób, jeśli inny bot zostanie wstrzyknięty kodem ataku, będzie nieskuteczny.

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();
    }
}
MegaTom
źródło
Znalazłem kilka błędów w tym bocie (literówki, użycie == zamiast równego) Znalazłeś też wadę w moim systemie: nie powinieneś być w stanie tworzyć nowych losowych adresów IP. Naprawiłem ten problem (i usunąłem kod robiąc to). Zaktualizowany kod można znaleźć na github
Nathan Merrill,
Gratulacje na najwyższym miejscu!
Nathan Merrill,
HelperBot nie jest zbyt mądry. To osiągnęło szczyt, ponieważ wszystkie inne boty były głupie. : P Jest to prawdopodobnie pierwszy skuteczny bot.
Draco18s,
1
@NathanMerrill Czy to oznacza, że ​​nie wolno nam już tworzyć fałszywych adresów IP w celu oszustwa? (jeśli to jest przypadek, będę musiał przeprojektować mój)
Nic Robertson
Bot nigdy nie ma dostępu do rundy celowo. Możesz używać adresów IP przeciwników jako fałszerstw, ale tworzenie takich adresów jest niedozwolone. Również stała jest zmienną ustawioną w czasie statycznym lub czasie inicjalizacji.
Nathan Merrill,
2

SwarmBot

Ten niezbyt dobrze nazwany bot jest dość skomplikowany (i jak dotąd najbardziej skomplikowany), ale podjąłem próbę stworzenia bota, który systematycznie zastępuje wszystkie metody celu przed przejściem do nowego celu. Próbuje zidentyfikować swoje kopie i traktować je jak sojuszników, okresowo sprawdzając je, aby zapewnić integralność. Nie wymyśliłem lepszego imienia.

Łączenie z gałęzią github repo, ponieważ ten bot ma 340 linii.

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

Kilka interesujących punktów:

  • Linie 14-24 są po prostu niemodyfikowalną listą, która ułatwiła dostosowanie kolejności, w której bot zastępuje metody swojego celu. Przechowuje, które indeksuje swoje Variableswejście i zwiększa w każdej rundzie. Powinno to być zgodne z zasadą „brak zmiennych niestałych”.
  • Linie 203-217 dotyczą weryfikacji sojuszników. Właściwie nie obchodzi nas, że inny bot wdraża wszystkie osiem naszych instrukcji. Tylko cztery są niezbędne, a jeśli brakuje jednego z „zaufanego” sojusznika, zastępujemy go własnym.
  • Linie 295–300 były nieoczekiwanym wzrostem wydajności. Chroniąc naszą flagę w pierwszych dwóch turach gry, unikamy głupich botów zastępujących naszą flagę, zanim będziemy mieli szansę rozprzestrzeniać się bardzo daleko. Dłuższe czekanie daje jednak innym botom szansę na zastąpienie naszej BlockFunction, co powoduje obniżenie wydajności (podejrzewane z powodu ingerencji RandomBota w sojuszników próbujących cofnąć uszkodzenie).
  • Przez najdłuższy czas podczas tworzenia tego bota, ten bot spowodował, że HelperBot przyspieszył do przodu, w pewnym momencie przekraczając znak 130, podczas gdy ten bot stracił na zasięgu 81-98, ale obniżył skuteczność MarkedBota i DefaultBota o kilka punktów.
  • Ten bot był możliwy tylko z dodaną functionsMatchmetodą. Bez functionsMatchniego nie można było napisać bota, który mógłby podejmować sensowne decyzje, ponieważ był ślepy. Potrafił czytać zmienne i dzienniki celu, ale nic nie wiedział o stanie celu.

Możliwe są jeszcze pewne ulepszenia, ale ich nie widzę. Linie 198-205 są prawdopodobnie wieprzem wydajności, ale dopóki klasa IPAddress nie pozwoli na odtworzenie adresów ze zmiennych, jest to konieczne (ponieważ boty nie mają możliwości sprawdzenia adresu, przechowywanie nieprawidłowego adresu powoduje, że gra zawiń cel zerowy w ReadOnlyBot, rzucając NPE).

Edycja: Aktualizacje 12.12.2015

Poprawienie niektórych parametrów w getTurnNumber()logice pozwoliło na pewne zwiększenie wydajności. Wzrost z 5% do 10% w celowaniu w końcowej fazie gry był wart około 15 punktów, podobnie jak wzrost w początkowej fazie gry z 5% do 8%. Łącznie ten bot może teraz (prawie) przetrwać, nawet w starciu z AmnesiaaBot (osiągając 2. miejsce z wynikiem 110, gdzie HelperBot osiąga około 117).

Nawet z tymi poprawkami może mieć pecha, więc dla 10 rund jego zasięg wynosi około 170-185.

Draco18s
źródło
Niesamowite! Celowo nie można tworzyć adresów IP z ciągów.
Nathan Merrill,
Cóż, pozornie tak! (Lub boty utworzą dowolne, aby znaleźć nowe boty). Problem polega na tym , że jeśli wykonasz symulację , nastąpi awaria. ;)
Draco18s,
Urm, w linii 143 używasz nieistniejącego konstruktora.
TheNumberOne,
@ TheNumberOne było ważne, kiedy to napisałem. Nathan prawdopodobnie zaktualizował bazę.
Draco18s,
@ Zaktualizowano aktualizację TheNumberOne. new IPAddressWezwanie powinno być „patrzeć z książki adresowej”, jak zrobiłem w readData. Wyodrębniłem to wyszukiwanie i naprawiłem linię 143.
Draco18s,
1

DefaultCodeBot

Próbuje robić rozsądne rzeczy. (Zastąp tę klasę, jeśli nie chcesz implementować wszystkich funkcji)

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();
    }
}
Nathan Merrill
źródło
1

HelperBot

Pomocnik bot nie robi nic prócz rozprzestrzeniania własnej flagi ... a przynajmniej flagi, którą obecnie cary ...

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

Jeśli HelperBot zakłada, że ​​każda własna metoda, która zostanie zastąpiona (inna niż getFlag()), zostanie zastąpiona czymś lepszym.

Draco18s
źródło
1

Chaos

Uwalnia wszystkie flagi od tyranii zablokowania.

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);
    }
}
Numer jeden
źródło
1

Zamiennik

Ten wpis zastępuje wszystkie selectFunctionToReplacefunkcje własną selectFunctionToReplacefunkcją.

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);
    }
}
Numer jeden
źródło
1

MailBot

Mailbot obsługuje tylko wiadomości. Nie udaje mu się wywieźć własnej flagi na świat (średni wynik ~ 50, nieco wyższy niż nullbot przy ~ 45), ale wyślij mu wiadomość, a on prześle twój adres komuś innemu.

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

Zastanawiałem się nad zapisaniem szczegółów, aby przekazało całą wiadomość do nowego bota (treść i flaga), a nie tylko adres IP nadawcy, ale wymagałoby to intensywnego używania Zmiennych bez żadnego zysku funkcjonalnego, szczególnie biorąc pod uwagę grę AmnesiaBot.

Draco18s
źródło
1

DumbBot

Ugh, to jest brudne. Jest to prawdopodobnie jedyna rzecz, która przewyższa AmnesiaBot. W rzeczywistości jest to po prostu wyspecjalizowany RandomBot: pobiera losowego bota w symulacji (via getAddressBook().clear()) i losowo zastępuje funkcję Block lub Flag. to jest to! Wybierając tylko te dwa, jego wskaźnik rozproszenia flagi jest wyższy niż AmnesiaBot lub HelperBot, ale tylko nieznacznie po 3000 rund:

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

Trochę majstrowałem przy funkcji zastępowania, ale ostatecznie ta wersja była najbardziej udana.

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";
    }
}
Draco18s
źródło
0

Pustelnik

Mieszka sam i mówi tylko do siebie. Jeśli mniej osób wie, kim on jest, będzie mu mniej przeszkadzało. Jeśli ktoś mu przeszkadza, będzie go atakował, dopóki ktoś nie będzie mu przeszkadzał.

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";
    }
}
MegaTom
źródło