Bots de code 4: Programmation fonctionnelle


25

sheesh, est-ce vraiment le 4? Pour tous les anciens, le défi principal est le même, mais nous utilisons Java au lieu d'un langage personnalisé. Voici les trois derniers défis CodeBot , au cas où vous seriez intéressé.

Le but de CodeBots est de rendre votre bot aussi viral que possible . Chaque bot porte un drapeau, et vous devez vous assurer que votre drapeau est partout .

API

Les bots suivront un "protocole" normalisé, et les bots progresseront de manière synchrone:

  1. IPAddress selectMessageRecipient() permet à un bot de choisir à qui il veut envoyer un message "amical".
  2. Message sendMessage() permet à un bot de choisir le contenu du message qu'il enverra.
  3. processMessage(IPAddress, Message) est appelé pour chaque message reçu par un bot.
  4. FunctionType selectFunctionToBlock()empêche une fonction d'être écrasée pour le tour en cours. Voir l'étape 7.
  5. IPAddress selectAttackTarget()permet à un bot de choisir qui il veut DDOS. Une attaque DDOS réussit si le bot est ciblé par 3 bots en même temps. Si une attaque réussit, chacun des attaquants peut effectuer les étapes 6 et 7.
  6. readData(ReadonlyBot) permet à un bot de lire les données stockées sur le bot vulnérable.
  7. FunctionType selectFunctionToReplace()est le nœud de ce défi . Vous êtes autorisé à sélectionner 1 fonction (parmi les 8 répertoriées ici) pour copier de votre bot vers son bot. Ensuite, votre fonction sera appelée à la place de la leur . Si plusieurs bots sélectionnent la même fonction, une aléatoire sera réussie.
  8. String getFlag()est appelé à la fin du jeu et doit renvoyer une chaîne unique à votre soumission. Votre fonction doit toujours renvoyer la même chaîne. La soumission avec le plus de drapeaux à la fin du jeu gagne.

Espace de rangement

Vous avez 3 formes de stockage, un carnet d' adresses , un journal et des variables . Ces formes de stockage sont locales au bot sur lequel votre fonction est exécutée (donc si votre fonction est copiée, le contenu de chacun de ces objets sera différent). Tous ces objets peuvent être modifiés ou effacés manuellement. Pour obtenir ces objets, vous avez un getter dans votre classe (par exemple getLog()).

Le Carnet d' adresses stocke une liste de IPAddress , chacun avec un AddressType , ce qui vous permet de classer les différents types d'adresses. Le carnet d'adresses contiendra toujours au moins 1 adresse (si elle est effacée, une adresse aléatoire sera ajoutée). Effacement de votre Carnet d' adresses pour obtenir plusieurs IPAddresses n'est pas autorisé.

Le journal stocke une liste de toutes les actions entreprises, ainsi que des données sur l'action. Il comprend également un historique de toutes les attaques réussies (bien que vous ne sachiez pas quelles fonctions elles ont écrasées)

L' objet Variables vous permet de stocker des variables de chaîne attachées à un nom de chaîne. Au début du jeu, les variables contiendront une seule variable, IDqui contient un ID généré de manière aléatoire qui est unique à votre type de bot.

Vous disposez également d'autres fonctions d'accès:

  • int getTurnNumber() renvoie un entier avec le tour en cours
  • bool functionsMatch(ReadonlyBot, FunctionType) des tests pour voir si la fonction de ReadonlyBot correspond à la vôtre
  • IPAddress personalAddress() renvoie votre adresse IP

Comment mettre en œuvre

  • Vous pouvez obtenir le code de Github
  • Ajoutez votre bot au \botsdossier, puis ajoutez une référence à votre bot danscontroller\CodeBotFactory.java
  • Votre bot doit étendre codebots.bot.CodeBotoucodebots.bots.DefaultCodeBot
  • Vous avez besoin de Java 8 si vous souhaitez exécuter le contrôleur.
  • Vous pouvez exécuter le code (en supposant que vous êtes dans le /srcdossier) en utilisant javac codebots\*.javapour compiler, puis java codebots.Mainpour exécuter.
  • Vous ne pouvez pas avoir de variables membres non constantes dans votre classe
  • La réflexion n'est pas autorisée.
  • Les formes de communication entre les robots (du même type ou de types différents) en dehors des méthodes énumérées ci-dessus ne sont pas autorisées.
  • Les bots stupides et / ou suicidaires sont autorisés, mais tous les bots doivent être fonctionnellement différents des entrées existantes.
  • Si vous voulez du hasard dans votre bot, utilisez getRandom()
  • Veuillez essayer de garder votre code efficace. J'ai passé beaucoup de temps à profiler et à rendre le contrôleur rapide.

Les scores

105.2501 Expelliarmus!
104.5803 J'aide!
104.2746 Qui suis-je?
103.8529 Dumb Bot
103.2028 Replacer
102.7045 Chaos
102.4046 Hermit Bot
102.2849 Swarmer
100.5598 Le robot aléatoire vous aime
99.966 Trust in Trust!
99.0185 codebots.bots.DefaultCodeBot
91.2942 codebots.bots.MarkedBot
91.1423 Juste votre sympathique robot de livraison de courrier de quartier.
89.4645 null


Vous devriez probablement rendre Log.LogEntry final, avec ce qui n'est pas final, je peux créer des journaux avec toutes les informations que je veux ... que seule ma fonction de bot serait capable de lire ou de créer.
TheNumberOne

ReadData peut-il accéder à l'adresse IP du bot qu'il lit?
TheNumberOne

@TheNumberOne pas actuellement, mais je ne vois pas pourquoi. Je n'ai pas le code sur moi en ce moment, mais je vais mettre à jour le code pour changer cela.
Nathan Merrill

3
Je trouve intéressant que Chaos place les échanges DisarmBot et MarkedBot sur le tableau des leaders.
TheNumberOne

1
Actuellement en 7850 sur 10000, obtenant des scores plus précis ...
LegionMammal978

Réponses:


4

TrustBot

Si vous lui envoyez un message, il fera ce qu'il dit. S'il lit un bot, il copiera les adresses directement dans son livre. Il attaque les robots que le carnet d'adresses dit d'attaquer.

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

Un bot aléatoire qui injecte à d'autres bots du code de perte de mémoire. Chaque fonction commence par un code pour effacer le journal, le carnet d'adresses et les variables. Ce code entraînera la perte de mémoire des robots intelligents, afin de supprimer la logique.

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

Je pense que celui-ci gagne uniquement en raison de l'incapacité d'un script plus intelligent à se souvenir de quoi que ce soit. c'est-à-dire que la suppression de l'objet Variables est vraiment très puissante.
Draco18s

@ draco18s ce n'était pas vraiment une réponse sérieuse ...
MegaTom

Je sais! C'est pourquoi je suis si confus. XD
Draco18s

3

NullBot

Son drapeau est très ... caractéristique ...

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

Ceci est également destiné à tester le contrôleur et les limites de la règle «les bots stupides sont autorisés».


Techniquement, il ne correspond pas aux spécifications, car il ne renvoie pas exactement une chaîne pour son drapeau.
TheNumberOne

3
nullest une chaîne. ;) Juste une chaîne de fantaisie.
Addison Crump

Cela m'a fait reconnaître un défaut dans ma spécification, qui a été spécifié: "tous les bots doivent être fonctionnellement différents des entrées existantes"
Nathan Merrill

@NathanMerrill Correction pour suivre de plus près la spécification.
TheNumberOne

3

RandomCodeBot

Entrée KoTH aléatoire obligatoire

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 n'est pas trop intelligent. S'il reçoit des instructions d'attaque, il choisira un attaquant aléatoire, sinon, il attaquera un joueur aléatoire. Il remplace simplement leur selectFunctionToBlockfonction de blocage 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!"; }
}

Vous pouvez sélectionner la nième adresse sans avoir à faire toutes les adresses (). Si vous regardez mon robot aléatoire, il fait une sélection d'adresse aléatoire. J'ai mis à jour votre code sur Github (pour des raisons d'efficacité), mais si vous sentez que cela ne fonctionne pas, je suis heureux de le revenir.
Nathan Merrill

Oh, mon mauvais, réparé.
Nathan Merrill

3

MarkedBot

Se marque au premier tour et utilise ces informations dans les tours suivants. De cette façon, si un autre bot est injecté avec son code d'attaque, il sera inefficace.

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

J'ai trouvé plusieurs bogues dans ce bot (fautes de frappe, en utilisant == au lieu de égal) Vous avez également trouvé une faille dans mon système: vous ne devriez pas pouvoir créer de nouvelles adresses IP aléatoires. J'ai résolu ce problème (et supprimé le code le faisant). Vous pouvez trouver le code mis à jour sur github
Nathan Merrill

Aussi, bravo pour la première place!
Nathan Merrill

HelperBot n'est pas très intelligent. Il n'a pris le dessus que parce que tous les autres robots étaient stupides. : P C'est probablement le premier bot efficace .
Draco18s

1
@NathanMerrill Cela signifie-t-il que nous ne sommes plus autorisés à créer des adresses IP contrefaites pour tromperie? (si c'est le cas, je vais devoir repenser le mien)
Nic Robertson

Un bot n'a jamais accès à la manche intentionnellement. Vous pouvez utiliser des adresses IP d'opposants comme contrefaçons, mais en créer une n'est pas autorisé. En outre, une constante est une variable définie à l'heure statique ou à l'initialisation.
Nathan Merrill

2

SwarmBot

Ce bot mal nommé est plutôt compliqué (et le plus compliqué soumis jusqu'à présent), mais j'ai fait une tentative de bot qui remplace systématiquement toutes les méthodes d'une cible avant de passer à une nouvelle cible. Il tente d'identifier des copies de lui-même et de les traiter comme des alliés, en les vérifiant périodiquement pour assurer l'intégrité. Je n'ai pas trouvé de meilleur nom.

Lien vers la branche repo de github, car ce bot mesure 340 lignes.

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

Quelques points intéressants:

  • Les lignes 14-24 sont simplement une liste non modifiable qui a permis de modifier facilement l'ordre dans lequel le bot remplace les méthodes de sa cible. Il stocke quel index est Variablesactivé et incrémente à chaque tour. Cela devrait suivre la règle «pas de variables non constantes».
  • Les lignes 203-217 concernent la vérification des alliés. En fait, nous ne nous soucions pas qu'un autre bot implémente tout huit de nos instructions. Seuls quatre sont essentiels, et si nous en manquons un sur un allié "de confiance", nous le remplaçons par le nôtre.
  • Les lignes 295-300 ont été une amélioration inattendue de l'efficacité. En protégeant notre drapeau lors des deux premiers tours de jeu, nous évitons que des bots stupides remplacent notre drapeau avant d'avoir une chance de se propager très loin. Attendre plus longtemps, cependant, donne aux autres bots une chance de remplacer notre BlockFunction et cela entraîne une dégradation des performances (suspecté en raison de l'interférence de RandomBot avec des alliés tentant de réparer la corruption).
  • Pendant la plus longue période de développement de ce bot, ce bot a fait bondir HelperBot, dépassant à un moment la marque 130, tandis que ce bot languissait dans la gamme 81-98, mais ayant traîné l'efficacité de MarkedBot et DefaultBot sur plusieurs points.
  • Ce bot n'a été possible qu'avec l'ajout functionsMatch méthode . Sans functionsMatchcela, il était impossible d'écrire un bot capable de prendre des décisions significatives, car il était aveugle. Il pourrait lire ses variables et journaux cibles, mais ne sait rien de l'état de sa cible.

Il y a probablement encore quelques améliorations possibles, mais je ne les vois pas. Les lignes 198-205 sont probablement un porc de performance, mais jusqu'à ce que la classe IPAddress permette de reconstituer les adresses à partir du stockage dans les variables, cela est nécessaire (car les bots n'ont aucun moyen de valider une adresse, tout stockage d'une adresse non valide entraîne le jeu pour envelopper une cible nulle dans un ReadOnlyBot, en lançant NPE).

Edit: Mises à jour 12/12/15

Ajuster certains des paramètres du getTurnNumber() logique a permis quelques améliorations des performances. L'augmentation de 5% à 10% du ciblage en fin de partie valait environ 15 points, augmentant également le ciblage en début de partie de 5% à 8%. Combiné, ce bot peut maintenant (presque) survivre même face à AmnesiaaBot (atteignant le 2e avec un score de 110, où HelperBot atteint environ 117).

Même avec ces ajustements, il peut ne pas avoir de chance, donc pour 10 tours, sa plage de score est d'environ 170-185.


Impressionnant! Il est intentionnel que vous ne puissiez pas créer d'adresses IP à partir de chaînes.
Nathan Merrill

Eh bien, en apparence, oui! (Ou les robots créeront des arbitraires pour trouver de nouveaux robots). Le problème est que si vous faites la simulation, la simulation plante. ;)
Draco18s

Urm, à la ligne 143, vous utilisez un constructeur inexistant.
TheNumberOne

@TheNumberOne c'était valide quand je l'ai écrit. Nathan a probablement mis à jour la base.
Draco18s

Mise à jour @TheNumberOne effectuée. L' new IPAddressappel aurait dû être une "recherche dans le carnet d'adresses" comme je l'avais fait dans readData. J'ai extrait cette recherche et fixé la ligne 143.
Draco18s

1

DefaultCodeBot

Essaie de faire des choses raisonnables. (Remplacez cette classe si vous ne voulez pas implémenter toutes les fonctions)

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

Le robot d'assistance ne fait rien d'autre qu'essayer de déployer son propre drapeau ... ou du moins le drapeau qu'il porte actuellement ...

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

Si HelperBot suppose que toute méthode qui est écrasée (autre que getFlag()) sera remplacée par quelque chose de mieux.


1

le chaos

Il libère tous les drapeaux de la tyrannie du blocage.

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

Replacer

Cette entrée remplace toutes les selectFunctionToReplacefonctions par sa propre selectFunctionToReplacefonction.

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 ne gère que les messages. Il ne parvient pas à faire sortir son propre drapeau dans le monde (score moyen ~ 50, légèrement supérieur à nullbot à ~ 45), mais envoyez-lui un message et il transmettra votre adresse à quelqu'un d'autre.

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

J'ai envisagé de sauvegarder les détails afin de transmettre tout le message à un nouveau bot (contenu et indicateur) plutôt qu'à l'adresse IP de l'expéditeur, mais cela aurait impliqué une utilisation intensive des variables sans aucun gain fonctionnel, en particulier si AmnesiaBot était en jeu.


1

DumbBot

Ugh, cela semble sale. C'est probablement la seule chose qui bat AmnesiaBot. En réalité, c'est juste un RandomBot spécialisé: il obtient un bot aléatoire dans la simulation (via getAddressBook().clear()) et remplace aléatoirement la fonction Block ou la fonction Flag. C'est ça. En ne choisissant que ces deux-là, son taux de propagation du drapeau est plus élevé que AmnesiaBot ou HelperBot, mais seulement légèrement après 3000 tours:

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

J'ai un peu tripoté la fonction de remplacement, mais au final, c'est la version qui a eu le plus de succès.

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

Ermite Bot

Il vit seul et ne parle qu'à lui-même. Si moins de gens savent qui il est, il sera moins gêné. Si quelqu'un le dérange, il les attaquera jusqu'à ce que quelqu'un le dérange.

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";
    }
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.