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 rei-da-colina 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:
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:
Em seguida, encontre seu ID de usuário na barra de endereço:
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 environment
parâ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: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: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: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:
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:Então você chama
this.landMine(4)
: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:
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 createBot
funçã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
Promise
que 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 paraonTick
eonMessage
. 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álidonum
ou 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)
recipients
pode ser um único bot (string), uma matriz de bot ouundefined
/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 suasstorage
e 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 jogadory
: Posição y do seu jogadorgridWidth
: 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: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):
Você
aroundMe
ficará 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:
Seu bot vê efetivamente isso:
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.
data
Os dados enviados pelo remetente.fromPlayer
O jogador do qual a mensagem foi enviada.fromTeam
A 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, masalert()
não está. - Você não tem permissão para ligar
createBot
ou 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.