Code Bots 4: Funktionale Programmierung

25

Meine Güte, ist das wirklich der 4.? Für alle alten Leute ist die Kernherausforderung dieselbe, aber wir verwenden Java anstelle einer benutzerdefinierten Sprache. Hier sind die letzten drei CodeBot- Herausforderungen , falls Sie interessiert sind.

Das Ziel von CodeBots ist es, Ihren Bot so viral wie möglich zu machen . Jeder Bot trägt eine Flagge, und Sie müssen sicherstellen, dass Ihre Flagge überall ist .

API

Die Bots folgen einem standardisierten "Protokoll" und durchlaufen synchron die folgenden Schritte:

  1. IPAddress selectMessageRecipient() Ermöglicht einem Bot zu wählen, an wen er eine "freundliche" Nachricht senden möchte.
  2. Message sendMessage() Ermöglicht einem Bot, den Inhalt der Nachricht auszuwählen, die er senden wird.
  3. processMessage(IPAddress, Message) wird für jede Nachricht aufgerufen, die ein Bot empfängt.
  4. FunctionType selectFunctionToBlock()Verhindert, dass eine Funktion für die aktuelle Runde überschrieben wird. Siehe Schritt 7.
  5. IPAddress selectAttackTarget()Ermöglicht einem Bot zu wählen, wen er zu DDOS möchte. Ein DDOS-Angriff ist erfolgreich, wenn der Bot von 3 Bots gleichzeitig angegriffen wird. Wenn ein Angriff erfolgreich ist, kann jeder Angreifer die Schritte 6 und 7 ausführen.
  6. readData(ReadonlyBot) Ermöglicht einem Bot das Lesen von Daten, die auf dem anfälligen Bot gespeichert sind.
  7. FunctionType selectFunctionToReplace()ist der Kern dieser Herausforderung . Sie dürfen 1 Funktion (von den 8 hier aufgelisteten) auswählen, um von Ihrem Bot auf ihren Bot zu kopieren. Dann wird Ihre Funktion anstelle ihrer aufgerufen . Wenn mehrere Bots dieselbe Funktion auswählen, ist eine zufällige erfolgreich.
  8. String getFlag()wird am Ende des Spiels aufgerufen und sollte eine eindeutige Zeichenfolge für Ihre Eingabe zurückgeben. Ihre Funktion sollte immer dieselbe Zeichenfolge zurückgeben. Die Einreichung mit den meisten Flaggen am Ende des Spiels gewinnt.

Lager

Sie haben drei Arten des Speichers: ein Adressbuch , ein Protokoll und eine Variable . Diese Speicherformen sind lokal für den Bot, auf dem Ihre Funktion ausgeführt wird (wenn Ihre Funktion kopiert wird, ist der Inhalt jedes dieser Objekte unterschiedlich). Alle diese Objekte können manuell geändert oder gelöscht werden. Um diese Objekte zu erhalten, haben Sie einen Getter in Ihrer Klasse (zB getLog()).

Das Adressbuch speichert eine Liste von IP-Adressen mit jeweils einem Adresstyp , mit dem Sie die verschiedenen Adresstypen klassifizieren können. Das Adressbuch enthält immer mindestens 1 Adresse (wenn es gelöscht ist, wird eine zufällige Adresse hinzugefügt). Das Löschen Ihres Adressbuchs zum Abrufen mehrerer IP-Adressen ist nicht zulässig.

Das Protokoll speichert eine Liste aller durchgeführten Aktionen sowie Daten zur Aktion. Es enthält auch einen Verlauf aller erfolgreichen Angriffe (obwohl Sie nicht wissen, welche Funktionen sie überschrieben haben).

Mit dem Variablenobjekt können Sie Zeichenfolgenvariablen speichern, die an einen Zeichenfolgennamen angehängt sind. Beim Spielstart enthalten Variablen eine einzelne Variable, IDdie eine zufällig generierte ID enthält, die für Ihren Bot-Typ eindeutig ist.

Sie haben auch andere Zugriffsfunktionen:

  • int getTurnNumber() Gibt eine Ganzzahl mit der aktuellen Runde zurück
  • bool functionsMatch(ReadonlyBot, FunctionType) Überprüft, ob die ReadonlyBot-Funktion mit Ihrer übereinstimmt
  • IPAddress personalAddress() gibt Ihre IPAdresse zurück

Wie implementieren

  • Den Code erhalten Sie von Github
  • Fügen Sie Ihren Bot dem \botsOrdner hinzu und fügen Sie dann einen Verweis auf Ihren Bot in hinzucontroller\CodeBotFactory.java
  • Ihr Bot muss codebots.bot.CodeBotoder verlängerncodebots.bots.DefaultCodeBot
  • Sie benötigen Java 8, wenn Sie den Controller ausführen möchten.
  • Sie können den Code ausführen (vorausgesetzt, Sie befinden sich im /srcOrdner), indem Sie javac codebots\*.javacompilieren und dann java codebots.Mainausführen.
  • Sie können nicht haben kein nicht-ständiges Mitglied Variablen in der Klasse
  • Reflexion ist nicht erlaubt.
  • Formen der Kommunikation zwischen Bots (gleichen oder unterschiedlichen Typs) außerhalb der oben aufgeführten Methoden sind nicht zulässig.
  • Dumme und / oder Selbstmord-Bots sind erlaubt, aber alle Bots sollten sich funktional von den vorhandenen Einträgen unterscheiden.
  • Wenn Sie Zufälligkeit in Ihrem Bot wollen, verwenden Sie getRandom()
  • Bitte versuchen Sie, Ihren Code effizient zu halten. Ich habe viel Zeit damit verbracht, Profile zu erstellen und den Controller schnell zu machen.

Scores

105.2501 Expelliarmus!
104.5803 Ich helfe!
104.2746 Wer bin ich?
103.8529 Dumb Bot
103.2028 Replacer
102.7045 Chaos
102.4046 Hermit Bot
102.2849 Swarmer
100.5598 Zufälliger Bot liebt dich
99.966 Vertrauen in Vertrauen!
99.0185 codebots.bots.DefaultCodeBot
91.2942 codebots.bots.MarkedBot
91.1423 Nur Ihr freundlicher Roboter für die Zustellung von Nachbarschaftspost.
89.4645 null

Nathan Merrill
quelle
Sie sollten Log.LogEntry wahrscheinlich endgültig machen, da es nicht endgültig ist. Ich kann Protokolle mit allen gewünschten Informationen erstellen ... die nur meine Bot-Funktion lesen oder erstellen kann.
TheNumberOne
Kann readData auf die IP-Adresse des Bot zugreifen, den es liest?
TheNumberOne
@TheNumberOne derzeit nicht, aber ich verstehe nicht, warum nicht. Ich habe den Code momentan nicht bei mir, aber ich werde den Code aktualisieren, um das zu ändern.
Nathan Merrill
3
Ich finde es interessant, dass Chaos DisarmBot und MarkedBot auf der Rangliste platziert.
TheNumberOne
1
Derzeit in Runde 7850 von 10000, um genauere Ergebnisse zu
erzielen

Antworten:

4

TrustBot

Wenn Sie ihm eine Nachricht senden, wird er tun, was es sagt. Wenn er einen Bot liest, kopiert er die Adressen direkt in sein Buch. Er greift die Bots an, die laut Adressbuch angreifen sollen.

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
quelle
4

AmnesiaBot

Ein zufälliger Bot, der anderen Bots Memory Loss Code injiziert. Jede Funktion beginnt mit einem Code zum Löschen des Protokolls, des Adressbuchs und der Variablen. Durch diesen Code verlieren intelligente Bots Speicher, um die Logik zu umgehen.

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
quelle
Ich denke, dieser gewinnt nur, weil ein schlaueres Skript nicht in der Lage ist, sich an irgendetwas zu erinnern. Dh das Löschen des Variables-Objekts ist wirklich verdammt mächtig.
Draco18s
@ Draco18s Dies war nicht wirklich eine ernsthafte Antwort zu sein ...
MegaTom
Ich kenne! Deshalb bin ich so verwirrt. XD
Draco18s
3

NullBot

Seine Flagge ist sehr ... charakteristisch ...

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

Dies soll auch den Controller testen und die Grenzen der Regel "Dumme Bots sind erlaubt" festlegen.

Die Nummer eins
quelle
Technisch passt er nicht zur Spezifikation, weil er nicht genau einen String für seine Flagge zurückgibt.
TheNumberOne
3
nullist eine Zeichenfolge. ;) Nur eine schicke Saite.
Addison Crump
Dies ließ mich einen Fehler in meiner Spezifikation erkennen, der spezifiziert wurde: "Alle Bots sollten funktional anders sein als vorhandene Einträge"
Nathan Merrill
@ NathanMerrill Behoben, um der Spezifikation genauer zu folgen.
TheNumberOne
3

RandomCodeBot

Obligatorischer zufälliger KoTH-Eintrag

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
quelle
3

DisarmerBot

DisarmerBot ist nicht zu intelligent. Wenn er Angriffsanweisungen erhält, wählt er einen zufälligen Angreifer aus, ansonsten greift er einen zufälligen Spieler an. Es überschreibt nur ihre selectFunctionToBlockFunktion zu blockieren 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
quelle
Sie können die n-te Adresse auswählen, ohne allAddresses () ausführen zu müssen. Wenn Sie sich meinen zufälligen Bot ansehen, wird eine zufällige Adressauswahl durchgeführt. Ich habe Ihren Code auf Github aktualisiert (aus Effizienzgründen), aber wenn Sie das Gefühl haben, dass er nicht funktioniert, kann ich ihn gerne zurücksetzen.
Nathan Merrill
Oh, meine schlechte, behoben.
Nathan Merrill
3

MarkedBot

Markiert sich in der ersten Runde und verwendet diese Informationen in späteren Runden. Auf diese Weise wird ein anderer Bot wirkungslos, wenn er seinen Angriffscode erhält.

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
quelle
Ich habe mehrere Bugs in diesem Bot gefunden (Tippfehler mit == statt gleich). Sie haben auch einen Fehler in meinem System gefunden: Sie sollten keine neuen zufälligen IPAdressen erstellen können. Ich habe das Problem behoben (und dabei den Code entfernt). Den aktualisierten Code finden Sie auf github
Nathan Merrill
Herzlichen Glückwunsch auch an der Spitze!
Nathan Merrill
HelperBot ist nicht sehr schlau. Es wurde nur top, weil alle anderen Bots dumm waren. : P Dies ist wahrscheinlich der erste wirksame Bot.
Draco18s
1
@NathanMerrill Heißt das, wir dürfen keine gefälschten IPAdressen mehr zur Täuschung erstellen? (wenn das der Fall ist, muss ich meins umgestalten)
Nic Robertson
Ein Bot hat nie absichtlich Zugriff auf die Runde. Sie können gegnerische IP-Adressen als Fälschungen verwenden, das Erstellen einer solchen ist jedoch nicht zulässig. Eine Konstante ist auch eine Variable, die zur statischen Zeit oder zur Initialisierungszeit festgelegt wird.
Nathan Merrill
2

SwarmBot

Dieser nicht gut benannte Bot ist ziemlich kompliziert (und der komplizierteste, der bisher eingereicht wurde), aber ich habe versucht, einen Bot zu finden, der systematisch alle Methoden eines Ziels ersetzt, bevor ich zu einem neuen Ziel übergehe. Es versucht, Kopien von sich selbst zu identifizieren und sie als Verbündete zu behandeln, indem es sie regelmäßig überprüft, um die Integrität zu gewährleisten. Ich habe mir keinen besseren Namen ausgedacht.

Verknüpfung mit dem Github-Repo-Zweig, da dieser Bot 340 Zeilen lang ist.

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

Einige interessante Punkte:

  • Die Zeilen 14-24 sind einfach eine nicht änderbare Liste, die es einfach machte, die Reihenfolge zu ändern, in der der Bot die Methoden seines Ziels ersetzt. Es speichert, welcher Index Variablesaktiviert ist, und erhöht jede Runde. Dies sollte der Regel "keine nicht konstanten Variablen" folgen.
  • Die Zeilen 203-217 befassen sich mit der Überprüfung der Verbündeten. Es ist uns eigentlich egal, dass ein anderer Bot alle acht unserer Anweisungen ausführt. Nur vier sind wichtig, und wenn wir einen "vertrauenswürdigen" Verbündeten vermissen, ersetzen wir ihn durch unseren eigenen.
  • Die Linien 295-300 waren eine unerwartete Steigerung der Wirksamkeit. Indem wir unsere Flagge in den ersten beiden Spielzügen schützen, vermeiden wir, dass dumme Bots unsere Flagge ersetzen, bevor wir die Chance haben, uns sehr weit zu verbreiten. Wenn Sie jedoch länger warten, haben andere Bots die Möglichkeit, unsere BlockFunction zu ersetzen. Dadurch wird die Leistung beeinträchtigt (vermutet, dass RandomBot Verbündete stört, die versuchen, die Korruption rückgängig zu machen).
  • Während der längsten Zeit während der Entwicklung dieses Bots verursachte dieser Bot, dass HelperBot an einem Punkt die 130-Marke überschritt, während dieser Bot im Bereich von 81 bis 98 lag, aber die Wirksamkeit von MarkedBot und DefaultBot um mehrere Punkte nach unten zog.
  • Dieser Bot war nur mit der hinzugefügten functionsMatchMethode möglich. Ohne functionsMatches war unmöglich, einen Bot zu schreiben, der sinnvolle Entscheidungen treffen konnte, da er blind war. Es konnte seine Zielvariablen und -protokolle lesen, wusste aber nichts über den Status seines Ziels.

Es sind wahrscheinlich noch einige Verbesserungen möglich, aber ich kann sie nicht sehen. Die Zeilen 198-205 sind wahrscheinlich ein Leistungsproblem, aber bis die IPAddress-Klasse die Wiederherstellung von Adressen aus dem Speichern in Variablen zulässt, ist dies erforderlich (da Bots keine Möglichkeit haben, eine Adresse zu validieren, führt das Speichern einer ungültigen Adresse zum Spiel Wrap ein Null-Ziel in einen ReadOnlyBot (wirft NPE aus).

Bearbeiten: Updates 12.12.15

Das Optimieren einiger Parameter in der getTurnNumber()Logik ermöglichte einige Leistungssteigerungen. Der Anstieg des Endspiel-Targetings von 5% auf 10% war ungefähr 15 Punkte wert und erhöhte das Frühspiel-Targeting von 5% auf 8%. Kombiniert kann dieser Bot jetzt (fast) überleben, selbst wenn er mit AmnesiaaBot konfrontiert wird (er erreicht den 2. Platz mit einer Punktzahl von 110, wo HelperBot ungefähr 117 erreicht).

Selbst mit diesen Optimierungen kann es unglücklich werden. Für 10 Runden beträgt die Punktezahl ungefähr 170-185.

Draco18s
quelle
Genial! Es ist beabsichtigt, dass Sie IPAddresses nicht aus Zeichenfolgen erstellen können.
Nathan Merrill
Nun, angeblich ja! (Oder Bots erstellen beliebige, um neue Bots zu finden). Das Problem ist, dass wenn Sie die Simulation durchführen, abstürzt. ;)
Draco18s
Urm, in Zeile 143 verwenden Sie einen nicht vorhandenen Konstruktor.
TheNumberOne
@TheNumberOne es war gültig, als ich es schrieb. Nathan hat wahrscheinlich die Basis aktualisiert.
Draco18s
@TheNumberOne Update gemacht. Der new IPAddressAnruf sollte ein "Nachschlagen vom Adressbuch" sein, wie ich es in getan hatte readData. Ich extrahierte diese Suche und die feste Linie 143.
Draco18s
1

DefaultCodeBot

Versucht vernünftige Dinge zu tun. (Überschreiben Sie diese Klasse, wenn Sie nicht alle Funktionen implementieren möchten.)

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
quelle
1

HelperBot

Der Hilfsbot versucht nur, seine eigene Flagge zu verbreiten ... oder zumindest die Flagge, die er gerade trägt ...

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

Wenn HelperBot davon ausgeht, dass jede eigene Methode, die überschrieben wird (außer getFlag()), mit etwas Besserem überschrieben wird.

Draco18s
quelle
1

Chaos

Er befreit alle Flaggen von der Tyrannei des Blockierens.

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);
    }
}
Die Nummer eins
quelle
1

Ersatz

Dieser Eintrag ersetzt alle selectFunctionToReplaceFunktionen durch einen eigenenselectFunctionToReplace Funktion.

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);
    }
}
Die Nummer eins
quelle
1

MailBot

Mailbot verarbeitet nur Nachrichten. Es ist nicht erfolgreich, eine eigene Flagge in die Welt zu bringen (durchschnittliche Punktzahl ~ 50, geringfügig höher als nullbot bei ~ 45), aber senden Sie eine Nachricht, und Ihre Adresse wird an eine andere Person weitergeleitet.

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

Ich überlegte, Details zu speichern, um die gesamte Nachricht an einen neuen Bot (Inhalt und Flag) weiterzuleiten , anstatt nur die IP des Absenders, aber das hätte eine starke Verwendung von Variablen ohne funktionellen Gewinn zur Folge gehabt, insbesondere wenn man bedenkt, dass AmnesiaBot im Spiel ist.

Draco18s
quelle
1

DumbBot

Ugh, das fühlt sich schmutzig an. Dies ist wahrscheinlich das einzige, was AmnesiaBot schlägt. In Wirklichkeit ist es nur ein spezieller RandomBot: Er erhält einen zufälligen Bot in der Simulation (via getAddressBook().clear()) und ersetzt zufällig entweder die Block-Funktion oder die Flag-Funktion. Das ist es. Wenn Sie nur diese beiden auswählen, ist die Flaggenausbreitungsrate höher als bei AmnesiaBot oder HelperBot, jedoch nur geringfügig nach 3000 Runden:

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

Ich habe ein bisschen an der Ersetzungsfunktion herumgespielt, aber am Ende war dies die Version, die am erfolgreichsten war.

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
quelle
0

Einsiedler Bot

Er lebt alleine und redet nur mit sich. Wenn weniger Menschen wissen, wer er ist, wird er weniger gestört. Wenn ihn jemand stört, greift er ihn an, bis ihn jemand anderes stört.

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
quelle