Equipe da colina!

27

Esse desafio foi inspirado no excelente desafio de @HelkaHomba : Red vs. Blue-Pixel Team Battlebots . Esse desafio foi provavelmente o melhor que eu já vi neste site. Sempre.

Meu desafio ainda é muito diferente, mas @HelkaHomba merece crédito pela inspiração.

visão global

Esta é uma equipe que seu time vence tendo todos os jogadores vivos no seu time. Em outras palavras, a última equipe em pé vence. Os sorteios serão refeitos.

Você está em um quadro. Você conhece sua posição no primeiro turno (marque 0). Você também sabe quem está na área ao seu redor:

Um único quadrado vermelho em uma grade 9x9, cercado por glóbulos brancos.

Nesse caso, você está sozinho (ou é o que você pensa) com ninguém ao seu redor. Você pode ver os itens ao redor no primeiro argumento para o seuontick manipulador. Mais sobre a API posteriormente.

Seu time

Sua equipe é determinada pelo seu ID de usuário. Para descobrir isso, clique na foto do seu perfil:

Minha foto do perfil

Em seguida, encontre seu ID de usuário na barra de endereço:

É entre / users / e / yourusername

Se for estranho, você está no time azul.

Se é par, você está no time vermelho.

Você é bem-vindo nos círculos desenhados à mão.

O seu nome (bot)

O nome do seu bot começa com a primeira letra do seu time ("r" ou "b"). Deve corresponder ao regex /^(r|b)[A-Za-z_-]$/. Fora isso, você pode escolher o nome do seu bot. Por favor, não use um já existente.

Iniciando

Os jogadores vermelhos começarão perto do topo do mapa e o azul começará perto do fundo. Você recebe informações especiais sobre o primeiro tick (turn) no environmentparâmetro para oontick função. Eu recomendo armazenar isso. Veja a API para detalhes.

Na sua vez

A ordem dos turnos é aleatória inicialmente, mas permanece a mesma.

Ativar ações

Você pode executar apenas uma ação por turno.

  • Mover

    Quando você deseja mudar, você chama this.move(num)a API. numé a célula para a qual você deseja mover:

    0 é superior esquerdo, 1 é superior central, 2 é superior direito, 3 é meio direito, 4 é meio esquerdo, 5 é inferior esquerdo, 6 é inferior central e 7 é inferior direito.

    Os locais relativos dos números para os quais você pode mover são armazenados na constante global threeByThree:

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

Se você se mover contra uma parede ou outro jogador, nada acontece.

  • Rodar

    Para girar, você liga this.rotate(num). Num é a direção que você deseja girar:

    0 é superior, 1 é correto, 2 é baixo e 3 é deixado

    A rotação é absoluta.

  • Mate

    Se outro jogador (de outro time) estiver na célula que você está enfrentando, você pode ligar this.kill()e matá-lo. Se não houver ninguém lá ou eles estiverem no seu time, isso não fará nada. Exemplo:

    Mesmos números acima, a célula 0 é verde, a 1 é azul, a 2 é laranja e a 3 é amarela

    Se você está ligado 0, você pode matar o verde. Se você está no 1, pode matar o azul. Se você tiver 2, pode matar a laranja. Se você tiver 3, você pode matar o amarelo.

  • Bombear

    Bombardear mata todos os jogadores, incluindo você e colegas de equipe nos 9 quadrados ao seu redor. Exemplo:

    Há uma grade 9x9 com "x" s em cada célula.

    Por que você iria querer fazer isso? Kamikaze . Se houver mais jogadores fora do seu time nas 9 células ao seu redor do que no seu time, você pode considerar o ataque. (Sugiro que você notifique seus camaradas primeiro!)

  • Coloque uma mina terrestre

    Isso cria um quadrado da morte para outras pessoas que não fazem parte do seu time. Quando você coloca uma mina terrestre, você também se move para não pisar nela. Você chama this.landMine(num)onde num é o quadrado para o qual deseja ir. Exemplo:

    Um único quadrado vermelho em uma grade 9x9, cercado por glóbulos brancos.

    Então você chama this.landMine(4):

    [Uma grade 9x9, com um "M" vermelho no meio e uma célula vermelha no meio à direita.

    Veja que "M"? É uma mina terrestre. Outros podem ver ... por enquanto. Qualquer pessoa, mesmo aqueles que não fazem parte do seu time, pode ver uma mina terrestre no tique-taque em que é colocado. Mas depois que o carrapato acabou, ninguém, nem você pode vê-lo. Mas ele explodirá assim que um inimigo passar por cima dele. Exemplo:

    Duas grades 9x9, uma célula azul no meio à esquerda no primeiro, um "M" vermelho no meio do primeiro, um "x" vermelho no meio do segundo e uma seta entre eles.

    Azul mudou-se em sua mina terrestre e BOOM! Você acabou de matar outra vez.

    A cada 2 mortes que você recebe (de mortes diretas ou minas terrestres), você recebe 1 mina extra. Você também recebe um no início.

  • Escavação

    Ao cavar, você procura por minas terrestres em uma área 5x5 centralizada ao seu redor. Isso não mostra a equipe do bot que colocou a mina terrestre. (Lembre-se de que você não pode ser morto por uma mina colocada por alguém da sua equipe.) Por exemplo, se essa era a grade ao seu redor:

    Então, o valor de retorno de this.dig()seria:

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

Os índices da matriz são iniciados no canto superior esquerdo, indo para a direita e depois para baixo, sem incluir você:

Existem 23 no total e suas localizações relativas são armazenadas na 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]
]

Observe que escavação revela minas colocadas em carrapatos anteriores, ao contrário aroundMe .

Comunicação

Quando você quer falar com alguém, você liga this.sendMessage(recipients, team, data). Os dados podem ser o que você quiser, e você pode enviá-lo para quem quiser, até jogadores de outras equipes.Isso pode ser usado para enganar bots mal programados, mas todos os jogadores podem ver quem enviou uma mensagem e em qual time está.

Exemplo:

Envie algo para um bot chamado "redisbest":

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

Envie algo para um bot chamado "redisbest" e "blueiscool":

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

Envie algo para toda a equipe vermelha

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

Envie algo para todos

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

Envie algo para toda a equipe vermelha e um bot chamado "blueiscool":

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

API

Seu código deve consistir em uma única chamada para a createBotfunção. Nada mais. Código de amostra:

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

(Você pode copiar e colar isso. Basta modificá-lo para sua equipe etc.)

Métodos

  • ontick(environment)

    Chamado quando é a sua vez. É necessário retornar um Promiseque seja resolvido em 1 segundo ou menos ou será ignorado. Isso ocorre por razões de desempenho e tem o bom efeito colateral de não travar a guia.

    this (quando no modo ontick)

    • landMines Quantas minas terrestres você deixou. Quanto mais você mata, mais minas terrestres você recebe. Para cada 2 bots que você mata, você recebe mais 1 minas terrestres. Você também recebe 1 para começar.
    • direction A direção que você está enfrentando.
    • storage Armazenamento que persiste entre chamadas para onTicke onMessage. Um objeto vazio no início. Modifique para qualquer finalidade, mas verifique sempre se é uma matriz ou objeto para garantir que persista corretamente.
    • move(num) Mover para a posição especificada. Não faz nada se inválido. Veja acima para detalhes.
    • rotate(num) Gire para a posição especificada. Não faz nada se inválido. Veja acima para detalhes.
    • kill() Mata o jogador que você está enfrentando, se existir e não estiver no seu time. Veja acima para detalhes.
    • bomb() Mata qualquer um dos 9 quadrados ao seu redor, incluindo você.
    • landMine(num) Coloca uma mina terrestre onde você está e depois se move para a posição especificada. Não faz nada se inválido numou você não tem mais nada. Veja acima para detalhes.
    • dig() Novo! Retorna uma matriz de informações sobre as minas terrestres em uma área 5x5 centralizada em torno de você. Veja acima para detalhes.
    • sendMessage(recipients, team, data) recipientspode ser um único bot (string), uma matriz de bot ou undefined/ null. É quem você gostaria de enviar a mensagem. teamé uma sequência da equipe que você deseja enviar a mensagem. Use "*"para enviar uma mensagem para todos. dataé qualquer coisa que possa ser passada para uma função JS. É enviado para os destinatários. Se for um objeto ou matriz, é passado por referência , para que você e o (s) destinatário (s) possam salvá-lo em suas storagee quaisquer modificações no objeto afetam as cópias dos dois bot. Nota que os destinatários que estão em qualquer lista de bots, o bot exato especificado na cadeia, ou um bot na equipe que você especificou, ele irá receber a mensagem.

environment

No primeiro tick

  • x: Posição x do seu jogador
  • y: Posição y do seu jogador
  • gridWidth: A largura da grade (em células)
  • gridHeight: A altura da grade (em células)

    Em todos os ticks

  • aroundMe: Uma variedade de jogadores e minas terrestres. Os jogadores são objetos que parecem {name: "bot name", team: "bot team"}e as minas terrestres são {team: "team of bot who placed mine"}. Os índices da matriz:

    0 é superior esquerdo, 1 é superior central, 2 é superior direito, 3 é meio direito, 4 é meio esquerdo, 5 é inferior esquerdo, 6 é inferior central e 7 é inferior direito.

    Observe que as minas terrestres colocadas em um carrapato diferente do atual não serão mostradas.

    aroundMe exemplo:

    Digamos que esta é a grade (você é vermelho):

    Uma grade 9x9, com azul claro no canto superior esquerdo, um "M" cinza no canto superior direito, vermelho no meio, amarelo no meio esquerdo e um "M" vermelho no canto inferior esquerdo.

    Você aroundMeficará assim:

[
    {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.
]

Os índices da matriz são explicados aqui:

0 é superior esquerdo, 1 é superior central, 2 é superior direito, 3 é meio direito, 4 é meio esquerdo, 5 é inferior esquerdo, 6 é inferior central e 7 é inferior direito.

Seu bot vê efetivamente isso:

Uma caixa azul clara no canto superior esquerdo com um número preto 0, uma caixa amarela na borda esquerda com um número preto 4 e um "M" vermelho no canto inferior esquerdo com um 5 preto.

  • onmessage(data, fromBot, fromTeam)

    this (quando em uma mensagem)

    • sendMessage(recipients, team, data) Função de envio de mensagem padrão.
    • storage Armazenamento padrão.

    dataOs dados enviados pelo remetente. fromPlayerO jogador do qual a mensagem foi enviada. fromTeamA equipe da qual a mensagem foi enviada.

  • onkill()

    this (quando em morte)

    • sendMessage(recipients, team, data) Função de envio de mensagem padrão.

Matrizes globais convenientes (constantes):

threeByThree:

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

Útil para passar dados para a função de movimentação e também para interpretar aroundMe. Veja acima.

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 a this.dig()função noontick manipulador.

Experimente!

O controlador será executado em minha máquina no host local por razões de desempenho, mas você pode usar o CodePen para testar seu bot.

Observe que você deve colar seu código no console e pressionar Enter antes de clicar em executar. Você pode colar quantos bots desejar. Os "Bot de teste" são exemplos para você testar. Se você pode vencer ou amarrar todos eles, você tem pelo menos um bot decente.

Submissões

Regras

Regras (aplicadas pelo controlador)

  • Seu principal ontick código não deve demorar mais de 1 segundo. Não queremos que as rodadas durem para sempre. Se o seu código demorar> 1 segundo, ele será interrompido.
  • Se você tentar executar mais de uma ação por turno ou executar uma ação inválida (por exemplo, this.move(-1) ou mover-se contra uma parede), ela será ignorada.
  • Mais podem vir em breve ...

Regras (aplicadas por mim, podem resultar em DQ)

  • Não escreva variáveis ​​globais (a leitura é boa ).
  • Seu código deve funcionar no Nodejs (caso o controlador seja portado para o Nodejs), tudo JSON.parse(...)bem, mas alert()não está.
  • Você não tem permissão para ligar createBotou interferir com o controlador de forma alguma .
  • Não use o código de outra pessoa sem permissão e alterações significativas. Sem copybots.
  • Por favor, sem brechas!
  • Mais podem vir em breve ...

Meus bots

Aqui estão alguns bots:

Este bot escolhe aleatoriamente uma ação. Bem, é uma aleatória ponderada, mas ainda bem aleatória. Se você pode matar esse bot (ele acabará se matando, isso não conta), então você tem pelo menos um bot decente. Publique e veja o que acontece!

Meus bots têm um nome que começa com "x" e uma equipe de "nenhum". Você pode usar parte desse código, mas faça pelo menos algumas modificações. Se você não pode se incomodar em pelo menos ajustar um número, não ganhará.

Formatando seu envio

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...

Solicitações de recursos, bugs, perguntas, etc?

Comente abaixo! Por favor, verifique se já existe um comentário sobre isso. Se já houver um, faça um voto positivo.

Quer conversar com sua equipe?

Use as salas de chat para vermelho e azul .

Língua

Atualmente, apenas JS e algo que compila para JS são suportados, mas se você souber uma maneira de fazer com que outros idiomas funcionem com o Nodejs, ficaria feliz em portar o controlador para o Nodejs.

Notas finais

Idéias de estratégia

Ajude sua equipe! Criando um bot projetado para ajudar outro bot e trabalhar em conjunto. Essa estratégia funcionou bem para Red vs. Blue - Pixel Team Battlebots

Requerentes de representantes

Aceitarei a resposta mais votada na equipe vencedora. Lembre-se de que as respostas anteriores tendem a receber mais votos, mas é mais provável que suas fraquezas sejam encontradas e exploradas.

Além disso, se você responder em breve, poderá receber +100 de recompensa.

programmer5000
fonte
1
Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Dennis
Posso fazer mais de um bots? (desculpe, eu sei que a conversa foi movida, eu só estou chatbanned então sim)
Matthew Roh
@SIGSEGV sim, mas alguém deve publicá-lo. Você pode postar um bot e fornecer o código de outro a alguém da sua equipe, mas não pode postar duas vezes.
Programmer5000 #
Sobre o posicionamento, onde está a célula indexada [0, 0], é a célula superior esquerda? Além disso, as mensagens consomem sua ação (por turno)? Obrigado.
Thrax
@ Thrax sim e não. Você pode até enviar uma mensagem em resposta a uma mensagem.
Programmer5000 #

Respostas:

7

xscared (não concorrente)

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

Muito medo de pessoas. Afasta-se da primeira pessoa (ou minas terrestres) que vê. Caso contrário, ele se move aleatoriamente. Observe que isso não está competindo, apenas um exemplo. Tente vencê-lo!

programmer5000
fonte
6

backup, um bot azul

Conforme avisado no bate-papo, nunca escrevi nada em javascript na minha vida; portanto, se você encontrar algum erro, diga-me! (Obrigado a @ programmer5000 por já me ajudar com isso)
O conceito desse bot é que ele se comunica com outros bots da mesma equipe e envia sua posição junto com um mapa das minas que encontrou. Ele tenta se juntar ao bot azul mais próximo (se alguém enviar seus dados de posição [dados como uma matriz [x, y]]) e permanecer próximo (com as costas o máximo possível), matando os bots vermelhos ou procurando à frente 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
fonte
Hey Você se importa se eu também entram isso, mas (com nome diferente) Estou também no azul
Christopher
@ Christopher Não, eu não me importo, mas isso seria um pouco mais interessante para você e para a equipe, se você fizer um pelo menos um pouco diferente (pelo menos para complementar os 2 bots que já existem).
plannapus
Vai fazer isso. Vou mudar isso
Christopher
Se eu tentar executar seu bot no codepen, ele não funcionará porque você está usando this.xetc., mas está environment.xou estou errado?
desperdiçado
@ WasteD como eu disse, não sei Javascript, então é possível. Mas se for o caso, acho que também deveria ser environment.gridHeighte environment.aroundMe? Nesse caso, os outros bots também não devem funcionar, pois usam this.aroundMe.
Plannapus
5

Azul, azul, meu mundo é 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() {}
});

Principalmente aleatório, mas bombardeará se estiver cercado e favorece checar e matar por se mover.


fonte
Inteligente! Agradável.
programmer5000
3
Ouve, aqui está uma história, sobre um rapaz que vive em um mundo azul.
Matthew Roh
3

Bombardeiro relaxado

Esse bot procura um local com pelo menos 1 célula livre de cada lado e depois planta uma mina. Ele acampa nele até que um inimigo se aproxime. Quando alguém se aproxima, ele vai e volta na mina para atrair o outro bot. Ele também girará e matará, se necessário. Quando ele não tiver mais nenhuma mina, ele buscará refúgio no canto superior esquerdo, de costas para a parede, e retaliará se estiver ameaçado.

Nenhuma jogada de equipe especial aqui, além de transmitir sua posição para sua equipe com a selfpalavra - chave.

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
fonte
Em qual time você está?
Programmer5000 #
@ programmer5000 Desde os nomes dos bots tem que começar com a letra da equipe, eu acho que eu sou Equipe Red :)
Thrax
Bom bot! Sugiro que você também transmita o que está ao seu redor para sua equipe.
Programmer5000 #
1

Faça backup de outro bot azul (esqueceu de fazer isso 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
fonte
1

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

O lutador azul se move e minas terrestres aleatoriamente e gira em direção aos jogadores vermelhos. Se os blocos ao redor tiverem mais vermelho que azul, ele será bombardeado. Se estiver enfrentando um jogador vermelho, ele o mata.

SuperStormer
fonte