Code Bots 4: Programación funcional


25

sheesh, ¿es realmente el 4to? Para todos los veteranos, el desafío principal es el mismo, pero estamos utilizando Java en lugar de un lenguaje personalizado. Aquí están los últimos tres desafíos de CodeBot , en caso de que esté interesado.

El objetivo de CodeBots es hacer que su bot sea lo más viral posible . Cada bot lleva una bandera, y debes asegurarte de que tu bandera esté en todas partes .

API

Los bots seguirán un "protocolo" estandarizado, y los bots avanzarán sincrónicamente por los siguientes pasos:

  1. IPAddress selectMessageRecipient() permite que un bot elija a quién quiere enviar un mensaje "amigable".
  2. Message sendMessage() permite que un bot elija el contenido del mensaje que enviará.
  3. processMessage(IPAddress, Message) se llama para cada mensaje que recibe un bot.
  4. FunctionType selectFunctionToBlock()bloquea la sobrescritura de una función para el turno actual. Vea el paso 7.
  5. IPAddress selectAttackTarget()permite que un bot elija a quién quiere DDOS. Un ataque DDOS es exitoso si el bot es atacado por 3 bots al mismo tiempo. Si un ataque tiene éxito, entonces cada uno de los atacantes puede realizar los pasos 6 y 7.
  6. readData(ReadonlyBot) permite que un bot lea datos almacenados en el bot vulnerable.
  7. FunctionType selectFunctionToReplace()Es el quid de este desafío . Puede seleccionar 1 función (de las 8 enumeradas aquí) para copiar desde su bot a su bot. Entonces, se llamará a su función en lugar de la de ellos . Si varios bots seleccionan la misma función, una aleatoria tendrá éxito.
  8. String getFlag()se llama al final del juego y debe devolver una cadena única para su envío. Su función siempre debe devolver la misma cadena. La presentación con más banderas al final del juego gana.

Almacenamiento

Tiene 3 formas de almacenamiento, una libreta de direcciones , un registro y una variable . Estas formas de almacenamiento son locales para el bot en el que se ejecuta su función (por lo tanto, si su función se copia, el contenido de cada uno de estos objetos será diferente). Todos estos objetos se pueden modificar o borrar manualmente. Para obtener estos objetos, tiene un captador en su clase (por ejemplo getLog()).

La libreta de direcciones almacena una lista de Dirección IP , cada uno con un AddressType , que permite clasificar los diferentes tipos de direcciones. AddressBook siempre contendrá al menos 1 dirección (si se borra, se agregará una aleatoria). No está permitido borrar su libreta de direcciones para obtener múltiples direcciones IP .

El registro almacena una lista de todas las acciones tomadas, así como datos sobre la acción. También incluye un historial de todos los ataques exitosos (aunque no sabes qué funciones sobrescribieron)

El objeto Variables le permite almacenar variables de cadena adjuntas a un nombre de cadena. Al inicio del juego, Variables contendrá una sola variable, IDque contiene una ID generada aleatoriamente que es única para su tipo de bot.

También tiene otras funciones de acceso:

  • int getTurnNumber() devuelve un entero con el turno actual
  • bool functionsMatch(ReadonlyBot, FunctionType) prueba para ver si la función de ReadonlyBot coincide con la tuya
  • IPAddress personalAddress() devuelve su dirección IP

Cómo implementar

  • Puedes obtener el código de Github
  • Agregue su bot a la \botscarpeta y luego agregue una referencia a su bot encontroller\CodeBotFactory.java
  • Su bot debe extenderse codebots.bot.CodeBotocodebots.bots.DefaultCodeBot
  • Necesita Java 8 si desea ejecutar el controlador.
  • Puede ejecutar el código (suponiendo que esté en la /srccarpeta) usando javac codebots\*.javapara compilar, luego java codebots.Mainpara ejecutar.
  • Es posible que no tenga ninguna variable miembro no constante en su clase
  • La reflexión no está permitida.
  • No se permiten formas de comunicación entre bots (del mismo tipo o de tipos diferentes) fuera de los métodos enumerados anteriormente.
  • Los bots tontos y / o suicidas están permitidos, pero todos los bots deberían ser funcionalmente diferentes a las entradas existentes.
  • Si quieres aleatoriedad en tu bot, usa getRandom()
  • Intenta mantener tu código eficiente. He pasado mucho tiempo haciendo perfiles y haciendo que el controlador sea rápido.

Puntuaciones

105.2501 Expelliarmus!
104.5803 ¡Estoy ayudando!
104.2746 ¿Quién soy yo?
103.8529 Bot tonto 103.2028
Remplazador
102.7045 Caos
102.4046 Bot ermitaño
102.2849 Enjambre
100.5598 Bot aleatorio te ama
99.966 ¡Confía en la confianza!
99.0185 codebots.bots.DefaultCodeBot
91.2942 codebots.bots.MarkedBot
91.1423 Solo su amigable robot de entrega de correo del vecindario.
89.4645 nulo


Probablemente deberías hacer Log.LogEntry final, con él no final puedo crear registros con cualquier información que desee ... que solo mi función bot podría leer o crear.
TheNumberOne

¿Puede readData acceder a IpAddress del bot que está leyendo?
TheNumberOne

@TheNumberOne no actualmente, pero no veo por qué no. No tengo el código en este momento, pero actualizaré el código para cambiar eso.
Nathan Merrill

3
Me parece interesante que Chaos haga que DisarmBot y MarkedBot intercambien lugares en la tabla de líderes.
TheNumberOne

1
Actualmente en la ronda 7850 de 10000, obteniendo puntajes más precisos ...
LegionMammal978

Respuestas:


4

TrustBot

Si le envías un mensaje, él hará lo que dice. Si lee un bot, copiará las direcciones directamente en su libro. Ataca a los bots que la libreta de direcciones dice atacar.

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 aleatorio que inyecta a otros bots con código de pérdida de memoria. Cada función comienza con un código para borrar el registro, la libreta de direcciones y las variables. Este código hará que los robots inteligentes pierdan memoria, en un intento de eliminar la lógica.

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

Creo que este solo gana debido a la incapacidad de un script más inteligente para ser capaz de recordar cualquier cosa. es decir, borrar el objeto Variables es realmente poderoso.
Draco18s

@ draco18s esto no fue realmente una respuesta seria ...
MegaTom 12/12/2015

¡Lo sé! Por eso estoy tan confundido por eso. XD
Draco18s

3

NullBot

Su bandera es muy ... característica ...

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

Esto también está destinado a probar el controlador y los límites de la regla "se permiten bots tontos".


Técnicamente no se ajusta a la especificación, porque no devuelve exactamente una cadena para su bandera.
TheNumberOne

3
nulles una cuerda ;) Solo una cuerda elegante.
Addison Crump

Esto me hizo reconocer una falla en mi especificación, que se ha especificado: "todos los bots deberían ser funcionalmente diferentes a las entradas existentes"
Nathan Merrill

@NathanMerrill Se corrigió para seguir más de cerca la especificación.
TheNumberOne

3

RandomCodeBot

Entrada obligatoria aleatoria de KoTH

package codebots.bots;

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

public class RandomCodeBot extends CodeBot {

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

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

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

    }

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

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

    @Override
    public void readData(ReadonlyBot bot) {

    }

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

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

3

DesarmadorBot

DisarmerBot no es demasiado inteligente. Si recibe instrucciones de ataque, elegirá un atacado aleatorio, de lo contrario, atacará a un jugador aleatorio. Simplemente anula su selectFunctionToBlockfunción de bloqueo 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!"; }
}

Puede seleccionar la enésima dirección sin necesidad de hacer allAddresses (). Si miras mi bot aleatorio, está haciendo una selección de dirección aleatoria. He actualizado tu código en Github (por razones de eficiencia), pero si crees que no funciona, me alegra poder revertirlo.
Nathan Merrill

Oh, mi mal, arreglado.
Nathan Merrill

3

MarcadoBot

Se marca en la primera ronda y usa esa información en rondas posteriores. De esa manera, si otro bot recibe una inyección de su código de ataque, será ineficaz.

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

Encontré varios errores en este bot (errores tipográficos, usando == en lugar de iguales) También encontró una falla en mi sistema: no debería poder crear nuevas direcciones IP aleatorias. Solucioné ese problema (y eliminé el código al hacerlo). Puede encontrar el código actualizado en github
Nathan Merrill

Además, ¡felicidades por el primer puesto!
Nathan Merrill

HelperBot no es muy inteligente. Solo llegó a la cima porque todos los demás bots eran tontos. : P Este es probablemente el primer bot efectivo .
Draco18s

1
@NathanMerrill ¿Eso significa que ya no se nos permite crear direcciones IP falsificadas para el engaño? (si ese es el caso, voy a necesitar rediseñar el mío)
Nic Robertson

Un bot nunca tiene acceso a la ronda intencionalmente. Puede usar las direcciones IP de los oponentes como falsificaciones, pero no está permitido crear una. Además, una constante es un conjunto de variables en tiempo estático o tiempo de inicialización.
Nathan Merrill

2

EnjambreBot

Este bot no bien nombrado es bastante complicado (y el más complicado presentado hasta el momento), pero intenté un bot que reemplace sistemáticamente todos los métodos de un objetivo antes de pasar a un nuevo objetivo. Intenta identificar copias de sí mismo y tratarlos como aliados, revisándolos periódicamente para asegurar su integridad. No he encontrado un mejor nombre.

Vinculación a la rama de repositorio github, ya que este bot tiene 340 líneas de largo.

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

Algunos puntos interesantes:

  • Las líneas 14-24 son simplemente una lista inmodificable que facilitó ajustar el orden en que el bot reemplaza los métodos de su objetivo. Almacena qué índice está Variablesactivado e incrementa cada ronda. Esto debe seguir la regla de "no variables no constantes".
  • Las líneas 203-217 tratan con la verificación de aliados. En realidad, no nos importa que otro bot implemente las ocho instrucciones. Solo cuatro son esenciales, y si nos falta uno en un aliado "confiable", lo reemplazamos con el nuestro.
  • Las líneas 295-300 fueron un impulso inesperado en la efectividad. Al proteger nuestra bandera en los dos primeros turnos del juego, evitamos que los robots tontos reemplacen nuestra bandera antes de que tengamos la oportunidad de extendernos muy lejos. Sin embargo, esperar más tiempo le da a otros bots la oportunidad de reemplazar nuestra función de bloqueo y eso hace que el rendimiento se degrade (se sospecha que RandomBot interfiere con los aliados que intentan deshacer la corrupción).
  • Durante el tiempo más largo durante el desarrollo de este bot, este bot causó que HelperBot se adelantara, en un punto rompiendo la marca de 130, mientras que este bot languideció en el rango 81-98, pero arrastró la efectividad de MarkedBot y DefaultBot varios puntos.
  • Este bot solo fue posible con el functionsMatchmétodo agregado . Sin functionsMatchél era imposible escribir un bot que pudiera tomar decisiones significativas, ya que era ciego. Podría leer sus variables y registros de objetivos, pero no sabe nada del estado de su objetivo.

Es probable que todavía haya algunas mejoras posibles, pero no puedo verlas. Las líneas 198-205 son probablemente un problema de rendimiento, pero hasta que la clase IPAddress permita que las direcciones se reconstituyan del almacenamiento en Variables, esto es necesario (ya que los bots no tienen medios para validar una dirección, cualquier almacenamiento de una dirección no válida hace que el juego envolver un objetivo nulo en un ReadOnlyBot, lanzando NPE).

Editar: Actualizaciones 12/12/15

Ajustar algunos de los parámetros en la getTurnNumber()lógica permitió algunos aumentos en el rendimiento. El aumento del 5% al ​​10% en la orientación al final del juego valió aproximadamente 15 puntos, lo que también aumentó la orientación al inicio del juego del 5% al ​​8%. Combinado este bot ahora puede (casi) sobrevivir incluso cuando se enfrenta a AmnesiaaBot (alcanzando el segundo lugar con un puntaje de 110, donde HelperBot llega a aproximadamente 117).

Incluso con estos ajustes, puede ser desafortunado, por lo que durante 10 rondas su rango de puntuación es de aproximadamente 170-185.


¡Increíble! Es intencional que no pueda crear direcciones IP a partir de cadenas.
Nathan Merrill

Bueno, aparentemente, sí! (O los bots crearán unos arbitrarios para encontrar nuevos bots). El problema es que si haces la simulación se bloquea. ;)
Draco18s

Urm, en la línea 143 usas un constructor no existente.
TheNumberOne

@TheNumberOne era válido cuando lo escribí. Nathan probablemente actualizó la base.
Draco18s

@TheNumberOne actualización realizada. La new IPAddressllamada debería haber sido una "búsqueda de la libreta de direcciones" como había hecho readData.
Extraje

1

DefaultCodeBot

Intenta hacer cosas razonables. (Anule esta clase si no desea implementar todas las funciones)

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

Helper bot no hace nada más que tratar de extender su propia bandera ... o al menos la bandera que está cargando actualmente ...

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 supone que cualquier método propio que se sobrescriba (que no sea getFlag()) se sobrescribirá con algo mejor.


1

Caos

Libera todas las banderas de la tiranía de ser bloqueado.

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

Sustituto

Esta entrada reemplaza todas las selectFunctionToReplacefunciones con su propia selectFunctionToReplacefunción.

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 solo maneja mensajes. No tiene éxito en sacar su propia bandera al mundo (puntaje promedio ~ 50, ligeramente más alto que nullbot en ~ 45), pero envíele un mensaje y reenviará su dirección a otra persona.

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

Pensé en guardar los detalles para reenviar todo el mensaje a un nuevo bot (contenido y marca) en lugar de solo la IP del remitente, pero eso habría implicado un uso intensivo de variables sin ninguna ganancia funcional, especialmente teniendo en cuenta que AmnesiaBot estaba en juego.


1

DumbBot

Ugh, esto se siente sucio. Esto es probablemente lo único que supera a AmnesiaBot. En realidad, es solo un RandomBot especializado: obtiene un bot aleatorio en la simulación (vía getAddressBook().clear()) y reemplaza aleatoriamente la función Block o la función Flag. Eso es. Al elegir solo esos dos, su tasa de propagación de bandera es más alta que AmnesiaBot o HelperBot, pero solo ligeramente después de 3000 rondas:

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

Jugué un poco con la función de reemplazo, pero al final, esta es la versión que tuvo más éxito.

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

Ermitaño bot

Vive solo y habla solo consigo mismo. Si menos personas saben quién es, se molestará menos. Si alguien lo molesta, los atacará hasta que alguien más lo moleste.

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";
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.