Equipo de The Hill!

27

Este desafío fue inspirado por el excelente desafío de @HelkaHomba Red vs. Blue - Pixel Team Battlebots . Ese desafío fue probablemente el mejor que he visto en este sitio. Siempre.

Mi desafío sigue siendo muy diferente, pero @HelkaHomba merece crédito por la inspiración.

Visión general

Este es un equipo donde su equipo gana al tener a todos los jugadores vivos en su equipo. En otras palabras, el último equipo en pie gana. Los sorteos se volverán a hacer.

Estás en un tablero Conoces tu posición en la primera ronda (marca 0). También sabes quién está en el área que te rodea:

Un solo cuadrado rojo en una cuadrícula de 9x9, rodeado de glóbulos blancos.

En este caso, estás solo (o eso crees) sin nadie a tu alrededor. Puede ver los elementos circundantes en el primer argumento para su ontickcontrolador. Más información sobre la API más adelante.

Tu equipo

Su equipo está determinado por su ID de usuario. Para descubrirlo, haga clic en su foto de perfil:

Mi foto de perfil

Luego encuentre su ID de usuario en la barra de direcciones:

Está entre / users / y / yourusername

Si es extraño, estás en el equipo azul.

Si es par, estás en el equipo rojo.

De nada para los círculos dibujados a mano.

Su nombre (bot)

El nombre de su bot comienza con la primera letra de su equipo ("r" o "b"). Debe coincidir con la expresión regular /^(r|b)[A-Za-z_-]$/. Aparte de eso, puedes elegir el nombre de tu bot. Por favor, no use uno ya existente.

Comenzando

Los jugadores rojos comenzarán cerca de la parte superior del mapa, y el azul comenzará cerca de la parte inferior. Se le proporciona información especial sobre el primer tic (giro) en el environmentparámetro para la ontickfunción. Recomiendo almacenar eso. Vea la API para más detalles.

En tu turno

El orden de giro es aleatorio inicialmente, pero luego permanece igual.

Convertir acciones

Solo puedes hacer una acción por turno.

  • Movimiento

    Cuando desee mudarse, llame this.move(num)a la API. numes la celda a la que te gustaría mover:

    0 es la parte superior izquierda, 1 es la parte superior central, 2 es la parte superior derecha, 3 es la parte central derecha, 4 es la parte central izquierda, 5 es la parte inferior izquierda, 6 es la parte inferior central y 7 es la parte inferior derecha.

    Las ubicaciones relativas de los números a los que puede moverse se almacenan en la constante global threeByThree:

[
    [0, 1, 2],
    [3, undefined, 4],
    [5, 6, 7]
]

Si te mueves hacia una pared u otro jugador, no pasa nada.

  • Girar

    Para rotar, usted llama this.rotate(num). Num es la dirección que desea rotar:

    0 es arriba, 1 es derecho, 2 está abajo y 3 queda

    La rotación es absoluta.

  • Matar

    Si hay otro jugador (de otro equipo) en la celda a la que te enfrentas, puedes llamarlos this.kill()y matarlos. Si no hay nadie allí, o están en su equipo, esto no hace nada. Ejemplo:

    Los mismos números que arriba, la celda 0 es verde, el 1 es azul, el 2 es naranja y el 3 es amarillo

    Si te vuelven 0, puedes matar al verde. Si eres convertido en 1, puedes matar el azul. Si eres convertido en 2, puedes matar a naranja. Si eres convertido en 3, puedes matar el amarillo.

  • Bomba

    Los bombardeos matan a todos los jugadores, incluidos usted y sus compañeros de equipo, en las 9 casillas a su alrededor. Ejemplo:

    Hay una cuadrícula de 9x9 con "x" s en cada celda.

    ¿Por qué querrías hacer esto? Kamikaze . Si hay más jugadores que no están en su equipo en las 9 celdas a su alrededor, entonces hay en su equipo, podría considerar bombardear. (¡Te sugiero que notifiques a tus camaradas primero!)

  • Coloque una mina terrestre

    Esto crea un cuadro de muerte para otros que no están en tu equipo. Cuando colocas una mina terrestre, también te mueves para no pisarla. Usted llama this.landMine(num), donde num es la plaza que desea ir. Ejemplo:

    Un solo cuadrado rojo en una cuadrícula de 9x9, rodeado de glóbulos blancos.

    Entonces llamas this.landMine(4):

    [Una cuadrícula de 9x9, con una "M" roja en el centro y un glóbulo rojo en el centro a la derecha.

    ¿Ves esa "M"? Es una mina terrestre. Otros pueden verlo ... por ahora. Cualquiera, incluso aquellos que no están en su equipo, puede ver una mina terrestre en la marca que se coloca. Pero después de que termina el tic, nadie, ni siquiera usted puede verlo. Pero explotará tan pronto como un enemigo lo cruce. Ejemplo:

    Dos cuadrículas de 9x9, una celda azul en el medio a la izquierda en la primera, una "M" roja en el medio de la primera, una "x" roja en el medio de la segunda y una flecha entre ellas.

    El azul se movió en tu mina terrestre, ¡y BOOM! Acabas de recibir otra muerte.

    Por cada 2 asesinatos que obtienes (de asesinatos directos o minas terrestres), obtienes 1 mina extra para colocar. También obtienes uno al comienzo.

  • Cavar

    Cuando cavas, buscas minas terrestres en un área de 5x5 centrada a tu alrededor. Esto no muestra al equipo del bot que colocó la mina terrestre. (Recuerde que no puede ser asesinado por una mina terrestre colocada por alguien en su equipo). Por ejemplo, si esta fuera la grilla a su alrededor:

    Entonces el valor de retorno de this.dig()sería:

[undefined,undefined,undefined,true,undefined,
undefined,undefined,undefined,undefined,undefined,
undefined,undefined,undefined,undefined,
undefined,undefined,true,undefined,undefined,
true,undefined,undefined,undefined,undefined]

Los índices de la matriz comienzan desde arriba a la izquierda, van hacia la derecha y hacia abajo, sin incluirse a usted mismo:

Hay 23 en total, y sus ubicaciones relativas se almacenan en la constante global fiveByFive:

[
    [0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9],
    [10, 11, undefined, 12, 13],
    [14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23]
]

Tenga en cuenta que cavar revela minas colocadas en ticks anteriores, a diferencia aroundMe.

Comunicación

Cuando quieres hablar con alguien, llamas this.sendMessage(recipients, team, data). Los datos pueden ser lo que quieras y puedes enviárselos a quien quieras, incluso a jugadores de otros equipos. Esto se puede usar para engañar a los robots mal programados, pero todos los jugadores pueden ver quién envió un mensaje y en qué equipo están.

Ejemplo:

Enviar algo a un bot llamado "redisbest":

this.sendMessage("redisbest", undefined, "Hi!");

Enviar algo a un bot llamado "redisbest" y "blueiscool":

this.sendMessage(["redisbest", "blueiscool"], undefined, {hello: "there"});

Enviar algo a todo el equipo rojo

this.sendMessage(undefined, "red", {hello: "red"});

Envía algo a todos

this.sendMessage(undefined, "*", {hello: "everyone"});

Enviar algo a todo el equipo rojo y un bot llamado "blueiscool":

this.sendMessage("blueiscool", "red", {hello: "bots"});

API

Su código debe consistir en una sola llamada a la createBotfunción. Nada más. Código de muestra:

createBot({
    ontick: function(environment) {
        return new Promise((resolve, reject)=>{
            this.move(0);//example
            resolve();//please call this when you are done
        });
    },
    onmessage: function(data, from, fromBot) {
        console.log("onMessage: " + this.name + " from " + this.team + " got message ", data, " from " + from + ", on team " + fromTeam);
        this.sendMessage(["bot", "otherbot"], "team", "some data");
    },
    team: "red",//your team
    name: "rmyteamname",//team name must begin with the first letter of your team's name
    onkill: function(){
        //say goodbye
    }
});

(Usted es libre de copiar y pegar esto. Simplemente modifíquelo para su equipo, etc.)

Métodos

  • ontick(environment)

    Llamado cuando es tu turno. Debe devolver un Promiseque se resuelva en 1 segundo o menos o se ignorará. Esto es por razones de rendimiento y tiene el agradable efecto secundario de no colgar la pestaña.

    this (cuando está en ontick)

    • landMines Cuantas minas terrestres te quedan. Cuantas más muertes tengas, más minas terrestres obtendrás.Por cada 2 bots que matas, obtienes 1 mina terrestre más. También obtienes 1 para comenzar.
    • direction La dirección que estás mirando.
    • storage Almacenamiento que persiste entre llamadas a onTickyonMessage . Un objeto vacío al inicio. Modifique para cualquier propósito, pero asegúrese de que sea una matriz u objeto siempre para asegurarse de que persista correctamente.
    • move(num) Moverse a la posición especificada. No hace nada si no es válido. Ver arriba para más detalles.
    • rotate(num) Girar a la posición especificada. No hace nada si no es válido. Ver arriba para más detalles.
    • kill() Mata al jugador al que te enfrentas, si existe y no está en tu equipo. Ver arriba para más detalles.
    • bomb() Mata a cualquiera en los 9 cuadrados que te rodean, incluido tú mismo.
    • landMine(num) Coloca una mina terrestre donde estás y luego se mueve a la posición especificada. No hace nada si no es válido numo no le queda ninguno. Ver arriba para más detalles.
    • dig() ¡nuevo! Devuelve una serie de información sobre las minas terrestres en un área de 5x5 centrada a tu alrededor. Ver arriba para más detalles.
    • sendMessage(recipients, team, data) recipientspuede ser un solo bot (cadena), una matriz de bot o undefined/ null. Es a quién le gustaría enviar el mensaje. teames una cadena del equipo al que le gustaría enviar el mensaje. Use "*"para enviar un mensaje a todos. dataes cualquier cosa que se pueda pasar a una función JS. Se envía a los destinatarios. Si se trata de un objeto o matriz, se pasa por referencia , de modo que usted y el (los) destinatario (s) pueden guardarlo en ellos storagey cualquier modificación en el objeto afecta las copias de ambos bot. Tenga en cuenta que los receptores que se encuentran en cualquiera de la lista de los robots, el robot exacta especificada en la cadena, o un bot en el equipo que ha especificado, se obtendrá el mensaje.

environment

En el primer tic

  • x: La posición x de tu jugador
  • y: La posición y de tu jugador
  • gridWidth: El ancho de la cuadrícula (en celdas)
  • gridHeight: La altura de la cuadrícula (en celdas)

    En todas las garrapatas

  • aroundMe: Una variedad de jugadores y minas terrestres. Los jugadores son objetos que se parecen {name: "bot name", team: "bot team"}, y las minas terrestres lo son {team: "team of bot who placed mine"}. Los índices de la matriz:

    0 es la parte superior izquierda, 1 es la parte superior central, 2 es la parte superior derecha, 3 es la parte central derecha, 4 es la parte central izquierda, 5 es la parte inferior izquierda, 6 es la parte inferior central y 7 es la parte inferior derecha.

    Tenga en cuenta que las minas terrestres colocadas en una marca diferente a la actual no se mostrarán.

    aroundMe ejemplo:

    Digamos que esta es la cuadrícula (usted es rojo):

    Una cuadrícula de 9x9, con azul claro en la parte superior izquierda, una "M" gris en la parte superior derecha, rojo en la parte central, amarillo en la parte central izquierda y una "M" roja en la parte inferior izquierda.

    Tu aroundMese verá así:

[
    {name: "bexamplebluebot", team: "blue"},
    undefined,//sparse array, nothing in index 1
    undefined,//there is technically a landmine here, but it wasn't placed this tick, so it is not shown
    undefined,//nothing in 3
    {name: "yexampleyellowbot", team: "yellow"},
    {team: "red"},//this is a landmine, you can tell is not a bot because it has no name. mines have the team name of the player they were placed by. This mine was placed this tick, otherwise you couldn't see it
    //nothing else after index 5, so the array's length is 5.
]

Los índices de la matriz se explican aquí:

0 es la parte superior izquierda, 1 es la parte superior central, 2 es la parte superior derecha, 3 es la parte central derecha, 4 es la parte central izquierda, 5 es la parte inferior izquierda, 6 es la parte inferior central y 7 es la parte inferior derecha.

Su bot efectivamente ve esto:

Un cuadro azul claro en la esquina superior izquierda con un número negro 0 en él, un cuadro amarillo en el borde izquierdo con un número negro 4 en él y una "M" roja en la esquina inferior izquierda con un 5 negro en él.

  • onmessage(data, fromBot, fromTeam)

    this (cuando está en un mensaje)

    • sendMessage(recipients, team, data) Función estándar de envío de mensajes.
    • storage Almacenaje estándar.

    dataLos datos enviados por el remitente. fromPlayerEl jugador desde el que se envió el mensaje. fromTeamEl equipo desde el que se envió el mensaje.

  • onkill()

    this (cuando en onkill)

    • sendMessage(recipients, team, data) Función estándar de envío de mensajes.

Convenientes matrices globales (constantes):

threeByThree:

[
    [0, 1, 2],
    [3, undefined, 4],
    [5, 6, 7]
]

Útil para pasar datos a la función de movimiento, así como para interpretar aroundMe. Véase más arriba.

fiveByFive :

[
    [0, 1, 2, 3, 4],
    [5, 6, 7, 8, 9],
    [10, 11, undefined, 12, 13],
    [14, 15, 16, 17, 18],
    [19, 20, 21, 22, 23]
]

Útil para la this.dig()función en elontick controlador.

¡Pruébalo!

El controlador se ejecutará desde mi máquina en host local por razones de rendimiento, pero puede usar CodePen para probar su bot.

Tenga en cuenta que debe pegar su código en la consola y presionar Enter antes de hacer clic en Ejecutar. Puedes pegar tantos bots como quieras. Los "Bots de prueba" son ejemplos para que los pruebes. Si puedes vencerlos o empatarlos a todos, tienes al menos un bot decente.

Envíos

Reglas

Reglas (aplicadas por el controlador)

  • Tu principal ontick código no debe tomar más de 1 segundo. No queremos rondas que duren para siempre. Si su código tarda> 1 segundo, se detendrá.
  • Si intenta realizar más de 1 acción por turno, o realiza una acción no válida (p. Ej. this.move(-1) o te mueves hacia un muro), será ignorado.
  • Más puede venir pronto ...

Reglas (aplicadas por mí, pueden resultar en DQ)

  • No escriba variables globales (la lectura está bien ).
  • Su código debe funcionar en Nodejs (en caso de que el controlador esté portado a Nodejs), entonces JSON.parse(...)está bien, pero alert()no lo está.
  • No se le permite llamar createBotni interferir con el controlador de ninguna manera .
  • No use el código de otra persona sin permiso y cambios significativos. No hay copybots.
  • Por favor, no hay escapatorias!
  • Más puede venir pronto ...

Mis bots

Aquí hay algunos bots:

Este bot elige aleatoriamente una acción. Bueno, es un azar ponderado, pero sigue siendo bastante aleatorio. Si puedes matar a este bot (eventualmente se suicidará, eso no cuenta), entonces tienes al menos un bot decente. ¡Publícalo y mira lo que sucede!

Mis bots tienen un nombre que comienza con "x" y un equipo de "ninguno". Puede utilizar parte de este código, pero realice al menos alguna modificación. Si no puede molestarse al menos en modificar un número, no ganará.

Formateando su envío

Por favor use este formato:

# rmyamazingbot

    createBot({
        ontick: function(environment) {
            return new Promise((resolve, reject)=>{
                this.move(0);//example
                resolve();//please call this when you are done
            });
        },
        onmessage: function(data, fromTeam, fromBot) {
            console.log("onMessage: " + this.name + " from " + this.team + " got message ", data, " from " + from + ", on team " + fromTeam);
            this.sendMessage(["bot", "otherbot"], "team", "some data");
        },
        team: "red",//your team
        name: "rmyteamname",//team name must begin with the first letter of your team's name
        onkill: function(){
            //say goodbye
        }
    });

Long, but cool explanation...

¿Solicitudes de funciones, errores, preguntas, etc.?

¡Comenta abajo! Verifique si ya hay un comentario con eso. Si ya hay uno, vótelo.

¿Quieres hablar con tu equipo?

Usa las salas de chat para rojo y azul .

Idioma

Actualmente, solo se admite JS y algo que se compila a JS, pero si conoce una forma de hacer que otros idiomas funcionen con Nodejs, me encantaría portar el controlador a Nodejs.

Notas finales

Ideas de estrategia

¡Ayuda a tu equipo! Crear un bot diseñado para ayudar a otro bot y trabajar juntos. Esta estrategia funcionó bien para Red vs. Blue - Pixel Team Battlebots

Buscadores de representantes

Aceptaré la respuesta más votada en el equipo ganador. Tenga en cuenta que las respuestas anteriores tienden a obtener más votos, pero es más probable que sus debilidades sean encontradas y explotadas.

Además, si responde pronto, puede obtener la recompensa de +100.

programador 5000
fuente
1
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
Dennis
¿Puedo hacer más de un bots? (lo siento, sé que la conversación se ha movido, solo estoy chateado, así que sí)
Matthew Roh
@SIGSEGV sí, pero alguien más debe publicarlo. Puedes publicar un bot y darle el código de otro a alguien de tu equipo, pero no puedes publicar dos veces.
programador
Sobre el posicionamiento, ¿dónde está la celda indexada [0, 0], es la celda superior izquierda? Además, ¿los mensajes consumen tu acción (por turno)? Gracias.
Thrax
@Thrax sí, y no. Incluso puede enviar mensajes en respuesta a un mensaje.
programador

Respuestas:

7

xscared (no competidor)

createBot({
    ontick: function(environment) {
        var reverse = [0, 1, 2, 3, 4, 5, 6, 7].reverse();
        return new Promise((resolve, reject)=>{
            (this.aroundMe || []).forEach((item,idx)=>{
                this.move(reverse[idx]);
                return resolve();
            });
            this.move(~~(Math.random() * 8));
            return resolve();
        });
    },
    onmessage: function() {
    },
    team: "none",
    name: "xscared",
    onkill: function(){
    }
});

Muy asustado de la gente. Se aleja de la primera persona (o mina) que ve. De lo contrario, se mueve al azar. Tenga en cuenta que esto no está compitiendo, solo un ejemplo. ¡Intenta vencerlo!

programador 5000
fuente
6

copia de seguridad, un bot azul

Como se advirtió en el chat, nunca escribí nada en JavaScript en mi vida, así que si encuentras algún error, ¡dímelo! (Gracias a @ programmer5000 por ayudarme con él).
El concepto de este bot es que se comunica con otros bots del mismo equipo y les envía su posición junto con un mapa de las minas que encontró. Intenta unirse al bot azul más cercano (si uno envía sus datos de posición [dados como una matriz [x, y]]), y permanece cerca de él (de espaldas lo máximo posible), matando a los bots rojos que se acercan o mirando adelante para minas.

createBot({
    team: 'blue',
    name: 'backup',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            //if (typeof this.x != "undefined") this.storage['position'] = [this.x, this.y];
            if (typeof environment.x != "undefined") this.storage['position'] = [environment.x, environment.y]; //Modified according to @WasteD
            if (typeof this.storage['map'] == "undefined") { //Create empty map
                var map = [[]];
                //for(i=0;i<this.gridHeight;i++) map[i]=[];
                for(i=0;i<environment.gridHeight;i++) map[i]=[]; //Modified according to @WasteD
                this.storage['map'] = map;
            }
            var blue = []
            var red = []
            var x = this.storage['position'][0];
            var y = this.storage['position'][1];
            var dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1]
            var dy = [1, 1, 1, 0, 0, 0, -1, -1, -1]
            (this.aroundMe || []).forEach((item, idx) => { // Update map and list positions of surrounding blues and reds
                if (item && item.team == 'red' && typeof item.name != "undefined") red += idx;
                if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx[idx]][y+dy[idx]] = 'M';
                if (item && item.team == 'blue' && typeof item.name != "undefined") blue += idx;
            });
            this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']}); //Send to buddies my position and the map
            if (red.indexOf([1, 4, 6, 3][this.direction]) > -1) this.kill() ; //If red guy is in front of
            else if (red.indexOf([1,4,6,3]) > -1) this.rotate(red.indexOf([1,4,6,3])); //If red guy is next but not in front of
            else if (blue.indexOf(3) > -1){ //If blue buddy on the left
                if (blue.indexOf(4) > -1){ //If another one is on the right
                    if (blue.indexOf(1) > -1 && this.direction != 2) this.rotate(2); //...and a third one at the top
                    else var digging = this.dig();
                    }
                else if (this.direction != 1) this.rotate(1);
                else var digging = this.dig();
            }
            else if (blue.indexOf(1) > -1){
                if (blue.indexOf(6) > -1 && this.direction != 3) this.rotate(3);
                else if (this.direction != 2) this.rotate(2);
                else var digging = this.dig();
            }
            else if (blue.indexOf(4) > -1){
                if (this.direction != 3) this.rotate(3);
                else var digging = this.dig();
            }
            else if (blue.indexOf(6) > -1 && this.direction != 0) this.rotate(0);
            else if (blue.indexOf([0,2]) > -1){ //If no blue next to me but one in diagonal, move next
                this.move(1);
                this.storage['position'][1] = y+1; //Update position
            }
            else if (blue.indexOf([5,7]) > -1){
                this.move(6);
                this.storage['position'][1] = y-1;
            }
            else if (typeof this.storage['other_blue'] != "undefined"){ //Check if buddies said where they were, try to go near the closest one
                var dmin = 99999;
                var pos = []
                (this.storage['other_blue'] || {}).forEach((item, idx) => {
                    var d = Math.sqrt(Math.pow(item['position'][0]-x,2) + Math.pow(item['position'][1]-y,2));
                    if (d < dmin){
                        dmin = d;
                        pos = item['position'];
                        }
                });
                if (pos[0]-x > 0){
                    this.move(4);
                    this.storage['position'][0] = x+1
                }
                else if (pos[0] < 0){
                    this.move(3);
                    this.storage['position'][0] = x-1
                }
                else if (pos[1] > 0){
                    this.move(1);
                    this.storage['position'][1] = y+1
                }
                else{
                    this.move(6);
                    this.storage['position'][1] = y-1
                }
            }
            else var digging = this.dig();
            if (typeof digging != "undefined"){ //Check out surroundings if dig() was played and update the map accordingly
                var dx2 = [-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2];
                var dy2 = [2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2];
                (digging || []).forEach((item, idx) => {
                    //if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M';
                    if (item) this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M'; //previously misread what dig() returned
                });
            }
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {
        if (typeof data['position'] != "undefined" && fromTeam == 'blue') { //If position sent by a blue bot
            if (typeof this.storage['other_blue'] == "undefined") this.storage['other_blue'] = [];
            for (i in this.storage['other_blue']){
                var found = false;
                if ('name' in i){
                    if (i['name'] == fromBot){
                        i['position'] = data['position'];
                        found = true; //Update if position already known from previous ticks
                        }
                }
            }
            if (!found) this.storage['other_blue'] += {'position':data['position'], 'name':fromBot}; //Add position if previously unknown
            this.sendMessage(fromBot, undefined, "roger.");
        }
    },
    onkill: function() {this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']});}
});
plannapus
fuente
Hola, te importa si también ingreso esto, pero (con un nombre diferente) también estoy en azul
Christopher
@ Christopher No, no me importa, pero eso sería un poco más interesante para ti y para el equipo si haces uno al menos un poco diferente (al menos para complementar los 2 bots que ya existen).
plannapus
Lo haré. Lo cambiaré
Christopher
Si trato de ejecutar su bot en codepen, no funciona porque lo está usando, this.xetc., pero ¿está environment.xo estoy equivocado?
WasteD
@WasteD como dije, no conozco Javascript en absoluto, por lo que es posible. Pero si es el caso, entonces supongo que también debería ser environment.gridHeighty environment.aroundMe. En cuyo caso, los otros bots tampoco deberían funcionar ya que lo usan this.aroundMe.
plannapus
5

Azul, azul, mi mundo es azul

createBot({
    team: 'blue',
    name: 'blue-blue-my-world-is-blue',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            var red = 0;
            // See who's around me
            (this.aroundMe || []).forEach((item, idx) => {
                if (item && item.team == 'red') red++;
            });
            // If surrounded, take one for the team
            if (red >= 6) this.bomb();
            else {
                // Translate direction into position
                var kill = [1, 4, 6, 3][this.direction];
                // Random values
                var move = Math.floor(Math.random() * 8);
                var nsew = Math.floor(Math.random() * 4);
                // Lay a landmine if possible
                if (this.landMines) this.landMine(move);
                // Kill if someone is in the way
                else if (this.aroundMe && this.aroundMe[kill] && this.aroundMe[kill].team == 'red' && this.aroundMe[kill].name) this.kill();
                else {
                    // Move somewhere if already in the requested direction
                    if (nsew == this.direction) this.move(move);
                    // Otherwise just rotate to the requested direction
                    else this.rotate(nsew);
                }
            }
            resolve();
        });
    },
    onmessage: function(data, from, fromBot) {},
    onkill: function() {}
});

En su mayoría aleatorio, pero bombardeará si está rodeado, y favorece comprobar y matar en movimiento.


fuente
¡Inteligente! Buena esa.
programmer5000
3
Escucha, aquí hay una historia sobre un pequeño hombre que vive en un mundo azul.
Matthew Roh
3

Bombardero relajado

Este bot busca un lugar con al menos 1 celda libre en cada lado y luego planta una mina. Acampa en él hasta que se acerca un enemigo. Cuando alguien se acerca, dará un paso adelante y atrás en su mina para atraer al otro robot. También rotará y matará si es necesario. Cuando no le quede ninguna mina, buscará refugio en la esquina superior izquierda de espaldas a la pared y tomará represalias si es amenazado.

No hay equipo especial aquí, aparte de transmitir su posición a su equipo con selfpalabras clave.

createBot({
    team: 'red',
    name: 'relaxed-bomber',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            if (typeof this.storage['dropped'] == "undefined") {
                this.storage['dropped'] = false;
                this.storage['covered'] = false;
                this.storage['baited'] = false;
            }
            if (typeof environment.x != "undefined" && typeof environment.y != "undefined") {
                this.storage['pos'] = [environment.x, environment.y];
            }
            if (typeof environment.gridWidth != "undefined" && typeof environment.gridHeight != "undefined") {
                this.storage['grid'] = [environment.gridWidth, environment.gridHeight];
            }
            var x = this.storage['pos'][0];
            var y = this.storage['pos'][1];
            var x0 = this.storage['grid'][0];
            var y0 = this.storage['grid'][1];
            var source = [1, 4, 6, 3];
            var dest = [6, 3, 1, 4];
            var rot = [0, 1, 2, 3];
            var movex = [-1, 0, 1, -1, 1, -1, 0, 1];
            var movey = [-1, -1, -1, 0, 0, 1, 1, 1];
            var action = false;
            if (this.landMines > 0) { 
                var move = [false, false, false, false];
                var moveIndex = -1;
                if (x <= 0) { move[1] = true; }
                if (x >= x0 - 1) { move[3] = true; }
                if (y <= 0) { move[2] = true; }
                if (y >= y0 - 1) { move[0] = true; }    
                if (move[0] && !move[1] && !move[2] && move[3]) { moveIndex = 0; }
                if (move[0] && !move[1] && !move[2] && !move[3]) { moveIndex = 1; }
                if (move[0] && move[1] && !move[2] && !move[3]) { moveIndex = 2; }
                if (!move[0] && !move[1] && !move[2] && move[3]) { moveIndex = 3; }
                if (!move[0] && move[1] && !move[2] && !move[3]) { moveIndex = 4; }
                if (!move[0] && !move[1] && move[2] && move[3]) { moveIndex = 5; }
                if (!move[0] && !move[1] && move[2] && !move[3]) { moveIndex = 6; }
                if (!move[0] && move[1] && move[2] && !move[3]) { moveIndex = 7; }  
                if (moveIndex >= 0) {
                    this.storage['pos'] = [ x + movex[moveIndex], y + movey[moveIndex]];
                    this.move(moveIndex);
                } else {
                    this.storage['dropped'] = true;
                    this.storage['covered'] = false;
                    this.landMine(1);
                }
            } else {
                if (this.storage['dropped']) {
                    this.storage['dropped'] = false;
                    this.storage['covered'] = true;
                    this.storage['pos'] = [ x + movex[6], y + movey[6]];
                    this.move(6);
                } else if (this.storage['covered']) {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            this.storage['covered'] = false;
                            this.storage['baited'] = true;
                            this.storage['mine'] = this.storage['pos'].slice();
                            this.storage['reverse'] = source[dest[i]];
                            this.storage['pos'] = [ x + movex[dest[i]], y + movey[dest[i]]];
                            this.move(dest[i]);
                            action = true;
                        }
                    }
                    if (!action) {
                        this.dig();
                    }
                } else if (this.storage['baited']) {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            if (this.direction == rot[source[i]]) {
                                this.kill();
                                this.storage['baited'] = false;
                                action = true;
                            } else {
                                this.rotate(rot[source[i]]);
                                action = true;
                            }
                        }
                    }
                    if (!action) {
                        if (this.storage['mine'][0] == this.storage['pos'][0] && this.storage['mine'][1] == this.storage['pos'][1]) {
                            this.storage['pos'] = [ x + movex[this.storage['reverse']], y + movey[this.storage['reverse']]];
                            this.move(this.storage['reverse']);
                            this.storage['reverse'] = source[this.storage['reverse']];
                        } else {
                            this.storage['pos'] = [ x + movex[this.storage['reverse']], y + movey[this.storage['reverse']]];
                            this.move(this.storage['reverse']);
                            this.storage['reverse'] = dest[this.storage['reverse']];
                        }
                    }
                } else {
                    for (var i = 0; i < source.length; i++) {
                        if (typeof environment.aroundMe[source[i]] != "undefined" && typeof environment.aroundMe[source[i]].team != "undefined" && environment.aroundMe[source[i]].team == "blue" && typeof environment.aroundMe[source[i]].name != "undefined") {
                            if (this.direction == rot[source[i]]) {
                                this.kill();
                                this.storage['baited'] = false;
                                action = true;
                            } else {
                                this.rotate(rot[source[i]]);
                                action = true;
                            }
                        }
                    }
                    if (!action) {
                        if (x > 0 && y > 0) {
                            this.storage['pos'] = [ x + movex[0], y + movey[0]];
                            this.move(0);
                        } else if (x > 0 && y == 0) {
                            this.storage['pos'] = [ x + movex[3], y + movey[3]];
                            this.move(3);
                        } else if (x == 0 && y > 0) {
                            this.storage['pos'] = [ x + movex[1], y + movey[1]];
                            this.move(1);
                        } else {
                            this.rotate(1);
                        }
                    }
                }
            }
            this.sendMessage(undefined, "red", {'self': this.storage['pos'] });
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {},
    onkill: function() {}
});
Thrax
fuente
En que equipo estas?
programador
@ programmer5000 Dado que los nombres de los bots tienen que comenzar con la letra del equipo, creo que soy Team Red :)
Thrax
Buen bot! Le sugiero que también transmita lo que le rodea a su equipo.
programador
1

Copia de seguridad 1 otro bot azul (olvidé hacer esto antes)

createBot({
    team: 'blue',
    name: 'backup1',
    ontick: function(environment) {
        return new Promise((resolve, reject) => {
            //if (typeof this.x != "undefined") this.storage['position'] = [this.x, this.y];
            if (typeof environment.x != "undefined") this.storage['position'] = [environment.x, environment.y]; //Modified according to @WasteD
            if (typeof this.storage['map'] == "undefined") { //Create empty map
                var map = [[]];
                //for(i=0;i<this.gridHeight;i++) map[i]=[];
                for(i=0;i<environment.gridHeight;i++) map[i]=[]; //Modified according to @WasteD
                this.storage['map'] = map;
            }
            var blue = []
            var red = []
            var x = this.storage['position'][0];
            var y = this.storage['position'][1];
            var dx = [-1, 0, 1, -1, 0, 1, -1, 0, 1]
            var dy = [1, 1, 1, 0, 0, 0, -1, -1, -1]
            (this.aroundMe || []).forEach((item, idx) => { // Update map and list positions of surrounding blues and reds
                if (item && item.team == 'red' && typeof item.name != "undefined") red += idx;
                if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx[idx]][y+dy[idx]] = 'M';
                if (item && item.team == 'blue' && typeof item.name != "undefined") blue += idx;
            });
            this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']}); //Send to buddies my position and the map
            if (red.indexOf([1, 4, 6, 3][this.direction]) > -1) this.kill() ; //If red guy is in front of
            else if (red.indexOf([1,4,6,3]) > -1) this.rotate(red.indexOf([1,4,6,3])); //If red guy is next but not in front of
            else if (blue.indexOf(3) > -1){ //If blue buddy on the left
                if (blue.indexOf(4) > -1){ //If another one is on the right
                    if (blue.indexOf(1) > -1 && this.direction != 2) this.rotate(2); //...and a third one at the top
                    else var digging = this.dig();
                    }
                else if (this.direction != 1) this.rotate(1);
                else var digging = this.dig();
            }
            else if (blue.indexOf(1) > -1){
                if (blue.indexOf(6) > -1 && this.direction != 3) this.rotate(3);
                else if (this.direction != 2) this.rotate(2);
                else var digging = this.dig();
            }
            else if (blue.indexOf(4) > -1){
                if (this.direction != 3) this.rotate(3);
                else var digging = this.dig();
            }
            else if (blue.indexOf(6) > -1 && this.direction != 0) this.rotate(0);
            else if (blue.indexOf([0,2]) > -1){ //If no blue next to me but one in diagonal, move next
                this.move(1);
                this.storage['position'][1] = y+1; //Update position
            }
            else if (blue.indexOf([5,7]) > -1){
                this.move(6);
                this.storage['position'][1] = y-1;
            }
            else if (typeof this.storage['other_blue'] != "undefined"){ //Check if buddies said where they were, try to go near the closest one
                var dmin = 99999;
                var pos = []
                (this.storage['other_blue'] || {}).forEach((item, idx) => {
                    var d = Math.sqrt(Math.pow(item['position'][0]-x,2) + Math.pow(item['position'][1]-y,2));
                    if (d < dmin){
                        dmin = d;
                        pos = item['position'];
                        }
                });
                if (pos[0]-x > 0){
                    this.move(4);
                    this.storage['position'][0] = x+1
                }
                else if (pos[0] < 0){
                    this.move(3);
                    this.storage['position'][0] = x-1
                }
                else if (pos[1] > 0){
                    this.move(1);
                    this.storage['position'][1] = y+1
                }
                else{
                    this.move(6);
                    this.storage['position'][1] = y-1
                }
            }
            else var digging = this.dig();
            if (typeof digging != "undefined"){ //Check out surroundings if dig() was played and update the map accordingly
                var dx2 = [-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,0,1,2];
                var dy2 = [2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2];
                (digging || []).forEach((item, idx) => {
                    //if (item && item.team == 'red' && typeof item.name == "undefined") this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M';
                    if (item) this.storage['map'][x+dx2[idx]][y+dy2[idx]] = 'M'; //previously misread what dig() returned
                });
            }
            resolve();
        });
    },
    onmessage: function(data, fromTeam, fromBot) {
        if (typeof data['position'] != "undefined" && fromTeam == 'blue') { //If position sent by a blue bot
            if (typeof this.storage['other_blue'] == "undefined") this.storage['other_blue'] = [];
            for (i in this.storage['other_blue']){
                var found = false;
                if ('name' in i){
                    if (i['name'] == fromBot){
                        i['position'] = data['position'];
                        found = true; //Update if position already known from previous ticks
                        }
                }
            }
            if (!found) this.storage['other_blue'] += {'position':data['position'], 'name':fromBot}; //Add position if previously unknown
            this.sendMessage(fromBot, undefined, "roger.");
        }
    },
    onkill: function() {this.sendMessage(undefined, "blue", {"position": this.storage['position'], 'map': this.storage['map']});}
});
Christopher
fuente
1

Luchador azul

createBot({
  team: "blue",
  name: "blue-fighter",
  ontick: function(environment) {
    return new Promise((resolve, reject)=>{
      let map = environment.aroundMe;
      let sides = [1, 4, 6, 3];
      let facing = sides[this.direction];
      let isTeam = (team,a) => a && a.team === team;
      let isRed = (a)=>isTeam("red",a);
      let isBlue = (a)=>isTeam("blue",a);
      let randomSquare = ()=>Math.floor(Math.random()*8);
      let redNum = map.filter(isRed).length;
      let blueNum =  map.filter(isBlue).length;
      if(redNum > blueNum && redNum > 2){
        this.bomb();
      }else if(isRed(map[facing])){
        this.kill();
      }else if(sides.includes(map.findIndex(isRed))){
        this.rotate(sides.indexOf(map.findIndex(isRed)));
      }else if(Math.random() < 0.5 && this.landMines > 0){
        this.landMine(randomSquare());
      }else{            
        this.move(randomSquare());
      }
      resolve();
    });
  },
  onmessage: function(data, from, fromBot) {},
  onkill: function(){}
});

El luchador azul se mueve y las minas terrestres al azar y gira hacia los jugadores rojos. Si los bloques circundantes tienen más rojo que azul, bombardea. Si se enfrenta a un jugador rojo, lo mata.

SuperStormer
fuente