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 rey de la colina 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:
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 ontick
controlador. 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:
Luego encuentre su ID de usuario en la barra de direcciones:
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 environment
parámetro para la ontick
funció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.num
es la celda a la que te gustaría mover: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: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: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:
¿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:Entonces llamas
this.landMine(4)
:¿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:
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 createBot
funció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
Promise
que 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 aonTick
yonMessage
. 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álidonum
o 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)
recipients
puede ser un solo bot (cadena), una matriz de bot oundefined
/null
. Es a quién le gustaría enviar el mensaje.team
es una cadena del equipo al que le gustaría enviar el mensaje. Use"*"
para enviar un mensaje a todos.data
es 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 ellosstorage
y 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 jugadory
: La posición y de tu jugadorgridWidth
: 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: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):
Tu
aroundMe
se 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í:
Su bot efectivamente ve esto:
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.
data
Los datos enviados por el remitente.fromPlayer
El jugador desde el que se envió el mensaje.fromTeam
El 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, peroalert()
no lo está. - No se le permite llamar
createBot
ni 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.