Si alguna vez has jugado Spacewar! , sabes que fue un juego divertido. Si no lo ha hecho, sepa esto: fue (y es) uno de los primeros y más importantes juegos de computadora. ¡Y sigue siendo divertido! El clon en el que crecí es este , que es, aparentemente y desafortunadamente, solo para Windows. ¡Entonces lo recreé!
El KotH está alojado aquí: PPCG - Spacewar! Rey de la colina . Te animo a que juegues como humano contra al menos otro bot para tener una idea de cómo funciona el juego.
El juego
- Un cuadro es de 30 milisegundos (por lo tanto, alrededor de 33 cuadros por segundo).
- El campo tiene 800 píxeles de ancho y 600 píxeles de alto.
- El campo es toroidal, lo que significa que las naves espaciales y los misiles que se mueven fuera del campo reaparecen en el lado opuesto.
- Hay dos naves espaciales, roja y azul.
- El rojo se posiciona en x = 50 y aleatorio y entre 50, (altura del campo - 50) píxeles.
- El azul se posiciona en x = (ancho del campo - 50) y aleatorio y entre 50, (altura del campo - 50) píxeles.
- Ambas caras x = (ancho del campo) / 2.
- Los controles disponibles son:
- Gire a la izquierda - 5 grados por cuadro en sentido antihorario.
- Gire a la derecha: 5 grados por cuadro en sentido horario.
- Misil de fuego: viaja a 10 píxeles adicionales por cuadro, además de la velocidad de la nave, en la dirección en que apuntaba la nave.
- Camión de bomberos: acelera la nave espacial a 0,30 píxeles por cuadro en la dirección en que apunta la nave espacial.
- Salto en el hiperespacio: se teletransporta a algunas coordenadas aleatorias en el campo, con un 25% de posibilidades de explotar. Estas coordenadas aleatorias pueden estar encima del sol.
- La velocidad máxima para los barcos es de 15 píxeles por cuadro bajo la potencia del motor y 40 píxeles por cuadro cuando aumenta la gravedad.
- Al viajar a más de 15 píxeles por cuadro, el empuje del motor solo puede cambiar de dirección o reducir la velocidad.
- En cuanto a los misiles:
- Los misiles viajan en línea recta.
- Los misiles pueden dispararse a una velocidad máxima de 1 por 0.1 segundos.
- Los misiles tienen una vida útil de 2.25 segundos.
- Los barcos tienen un máximo de 20 misiles cada uno.
- Los misiles son partículas puntuales internamente.
- Hay un sol en el centro que es extremadamente peligroso para su barco. El más mínimo contacto es fatal. Este sol también destruye misiles.
- El sol tiene gravedad. La aceleración resultante es 5000 / (distancia ^ 2) píxeles / cuadro ^ 2, donde la distancia es en píxeles. Las naves espaciales y los misiles se ven afectados.
- Ambas naves tienen tres zonas de ataque: la nariz, el ala izquierda y el ala derecha.
- Un golpe en la nariz es la muerte instantánea.
- Un golpe en cualquier ala reduce la velocidad de giro de la nave espacial y la aceleración del motor a la mitad.
- Si se destruyen ambas alas, la nave espacial no se puede maniobrar y solo puede disparar misiles.
- Los barcos pueden chocar entre sí.
- Un impacto nariz-nariz es fatal para ambas naves.
- Un impacto en el ala de la nariz destruye el ala.
- Un impacto ala-ala destruye ambas alas.
- Las naves muertas son sólidas y congeladas hasta que explotan 1 segundo después.
- Después de que al menos una nave haya muerto, el campo se reinicia 3 segundos después. Hasta entonces, el sol y los misiles restantes siguen siendo peligrosos.
El juego original también tiene asteroides mortales e indestructibles, pero no los incluiré.
Las normas
- Su bot debe estar escrito en JavaScript.
- Su bot debe limitar su decisión a unos 10 milisegundos. Si noto un retraso constante debido a su bot , lo descalificaré y se lo haré saber para que pueda solucionarlo.
- Los bots tendrán acceso a lo siguiente:
- Ancho de campo y altura de campo
- Posición del sol y radio
- La posición, rotación, velocidad, forma, stock de misiles y estado dentro del hiperespacio de ambas naves
- La posición y la velocidad de todos los misiles.
- Cuando se le solicite, su bot debe devolver una lista de cadenas.
- Estas cadenas deben ser uno de los siguientes:
turn left
,turn right
,fire engine
,fire missile
,hyperspace
. Cualquier otra cadena será ignorada. - Si hay duplicados, solo se anotará el primero.
hyperspace
tiene prioridad sobre todos los demás.turn left
yturn right
al mismo tiempo no tendrá efecto.fire engine
no tendrá efecto si la nave solo tiene la nariz o está muerta.fire missile
no tendrá efecto si un misil fue disparado demasiado recientemente.
- Estas cadenas deben ser uno de los siguientes:
- En un cambio de lo habitual, su bot puede explotar el comportamiento de otros bots. Quiero alentar un metajuego.
- Los bots no pueden emular a otros bots. (Es decir, no leer la mente).
- Los bots no pueden establecer ninguna variable utilizada por el juego y el código de física. (Es decir, sin trampas).
Detalles de implementación del bot
Almacenaré su bot en su propio archivo JavaScript que se incluye automáticamente, con el nombre del archivo bot_<name>.js
. Por lo tanto, no ponga espacios o caracteres que interfieran con esto o con el nombramiento de una función en JavaScript. Esto se debe a que debe definir las siguientes funciones: <name>_setup(team)
y <name>_getActions(gameInfo, botVars)
. Más abajo en la página, existen áreas de texto para el robot de usuario , que puede editar para probar su código.
<name>_setup(team)
Esta función es para que usted defina las variables que desea persistir. team
será cualquiera "red"
o "blue"
. Esta función debe devolver un objeto. Defina variables así:
var vars = {};
vars['example'] = "example";
return vars;
Este vars
objeto se pasará a la otra función:
<name>_getActions(gameInfo, botVars)
botVars
es el objeto devuelto por <name>_setup(team)
. gameInfo
es un objeto que contiene las siguientes variables:
redScore
blueScore
timeLeft
fieldWidth
fieldHeight
sun_x
sun_y
sun_r //sun's radius
gravityStrength //acceleration in pixels/frame^2 at 1 pixel away from the sun's center
engineThrust //acceleration in pixels/frame^2
speedLimit //maximum speed under engine power
maxSpeed //maximum speed from gravity boosts
red_x
red_y
red_rot //rotation in degrees
red_xv //x velocity
red_yv //y velocity
red_shape //one of "full ship", "left wing", "right wing", "nose only"
red_missileStock //the number of missiles red has left
red_inHyperspace //true if red is in hyperspace
red_exploded //until red explodes, it is still solid and hazardous
red_alive
// likewise for blue //
numMissiles
missiles //this is a list of objects, each with the following variables
x
y
xv
yv
Su bot tiene acceso completo a estos. Estoy bastante seguro de que puede escribirles y no afectar las variables originales, pero no lo haga de todos modos. Una nota sobre las rotaciones: las naves apuntan en la dirección + y, hacia abajo, por lo que cualquier cosa que desee alinear con la nave debe compensarse 90 grados. Además, la rotación positiva es en sentido horario.
Esta función debe devolver una lista de cadenas, que representa las acciones de su bot. Por ejemplo, ["turn right","thrust"]
. Más detalles sobre esto están en la sección de Reglas .
Detalles adicionales
También puede hacer uso de lo siguiente:
LineIntersection(L1, L2)
L1 y L2 son matrices de dos elementos de matrices de dos elementos. Es decir, L1 := [[x1,y1],[x2,y2]]
y L2 := [[u1,v1],[u2,v2]]
. Esta función calcula la intersección de dos líneas y devuelve la siguiente: [[x,y], [a,b]]
. [x,y]
son las coordenadas del punto de intersección y [a,b]
son un par de relaciones que expresan qué tan lejos está el punto de intersección a lo largo de cada línea. Al igual que en, a = 0.25
significaría que el punto de intersección es una cuarta parte del camino de [x1,y1]
a [x2,y2]
, y lo mismo para b
. Si no hay intersección, se devuelve una matriz vacía.
window["shipShapes"]
var shipShapes = {
'full ship': [[-8,16],[0,-8],[8,16]],
'left wing': [[-8,16],[0,-8],[4,4],[0,8],[0,16]],
'right wing':[[-4,4],[0,-8],[8,16],[0,16],[0,8]],
'nose only': [[-4,4],[0,-8],[4,4],[0,8]]
};
Estas son las coordenadas de los polígonos de los barcos. Para facilitar la obtención de las coordenadas actuales, también puede usar ...
getShipCoords(<color>)
getShipCoords("red")
devolverá las coordenadas actuales de los vértices de la nave de Rojo, y de la misma manera para getShipCoords("blue")
Azul. Estas coordenadas están en una lista de este modo: [[x1,y1],[x2,y2],[x3,y3],...]
. Los polígonos están implícitamente cerrados, por lo que hay una línea entre el primer y el último par de coordenadas.
No puede acceder ni alterar ninguna otra variable o función en uso por el juego / sitio web. Y definitivamente no nombres tus funciones de la misma manera. No preveo que esto sea un problema, pero si su bot rompe el código del juego, esa es una posibilidad. No hay registro ni captura de excepciones.
Victorioso
- Cada emparejamiento de bots se jugará al menos 10 veces, en ambos sentidos. (Entonces, al menos 20 juegos en total).
- Trata de tener la mayor proporción de victorias / derrotas en general . Si su bot funciona muy bien contra otro bot, pero pierde contra los otros tres, eso no es tan bueno como ganar contra dos y perder contra dos (como regla general).
- Para cada bot, se calcularán las razones (victorias + 1) / (pérdidas + 1), luego se calculará la media y la desviación estándar de estas relaciones. Una media más alta tendrá prioridad, y en caso de que las medias estén dentro de 1 unidad entre sí, la varianza más baja tendrá prioridad.
- La puntuación comenzará en una semana a partir de hoy o después de tres días sin nuevas presentaciones. Esto es para que no tenga que repetir ningún emparejamiento de bots.
Sobre todo, ¡diviértete!
Clasificación (2016-01-08 05:15):
# Name Mean StdDev
1. Helios 13.625 6.852
2. EdgeCase 8.335 8.155
3. OpponentDodger 8.415 8.186
4. OrbitBot 5.110 6.294
5. SunAvoider 5.276 6.772
6. DangitBobby 3.320 4.423
7. SprayAndPray 3.118 4.642
8. Engineer 3.903 6.315
9. RighthandedSpasms 1.805 2.477
10. AttackAndComeBack 2.521 2.921
11. PanicAttack 2.622 3.102
12. FullSpeedAhead 2.058 3.295
13. UhhIDKWhatToCallThisBot 2.555 3.406
14. MissilesPlusScore 0.159 0.228
15. Hyper 0.236 0.332
16. RandUmmm 0.988 1.329
17. Kamikaze 0.781 1.793
Nota: Esto está sujeto a cambios a medida que corro más juegos. Además, el orden de los rangos 9-13 me molesta, por lo que puedo ajustar el método de puntuación para que coincida mejor con la intuición de cómo deben clasificarse.
(Las medias y las desviaciones estándar se redondearon a tres dígitos decimales. Además, Hyper
debería ser HYPER
pero eso estropea el resaltado.: P)
fuente
LineIntersection
a segmentos que no se cruzan devuelve una matriz vacía.Respuestas:
Helios
Este bot es el centro del universo, o al menos él cree que lo es. Lo primero que hace es corregir un error grave y colocarse en el centro del sistema de coordenadas. Luego gira cualquier cosa a su alrededor.
No le gusta el otro sol (falso), por lo tanto, trata de mantenerse alejado de él. Tampoco le gustan otros bots, por lo tanto, les dispara si está en una buena posición de disparo.
fuente
SunAvoider
Este solo trata de mantenerse alejado del sol. Lo hace bastante bien ... hasta que destruye una o ambas alas, por lo general, es solo cuestión de tiempo antes de que caiga.
fuente
Caso extremo
¡Vuela a toda velocidad lejos del sol hacia el borde del mapa! Cuando se encuentra apuntando hacia el sol, comenzará a disparar mientras se aleja para volver al borde. También ingresa al hiperespacio cuando está a punto de golpear el sol.
fuente
OrbitBot
Actualmente no tiene objetivos
ni evita colisiones. Intenta orbitar el sol.Editar: ahora entra en el hiperespacio cuando el impacto es inminente.
fuente
Espasmos diestros
El nombre es bastante descriptivo. Elige
turn right
con 0.5 probabilidad,fire engine
con 0.5 probabilidad yfire missile
con 0.8 probabilidad. Sorprendentemente difícil, principalmente porque es realmente impredecible.fuente
RandUmmm
Este desafío necesitaba un bot aleatorio. ¿Puntos de bonificación por golfiness?
fuente
Ingeniero
Le gusta usar el hiperespacio cuando está en peligro. Para ver su verdadero poder, abra la consola de su navegador y escriba
overideHyperspace = 0;
. Si olvida el punto y coma, obtendrá ASI para Navidad.fuente
Rociar y rezar
Dispara salvajemente en todas las direcciones. ¡No es muy efectivo!
fuente
Kamikaze
No es muy competitivo, ¡pero pensé que sería divertido! Simplemente vuela directamente hacia su oponente mientras dispara.
fuente
UhhIDKWhatToCallThisBot
Solo cosas al azar.
fuente
Oponente Dodger
LEJOS DE MI OPONENTE!
¡Gracias a user81655 por algún código!
fuente
Espía
La historia
El prototipo de este bot era un bot que tenía dos modos: modo loco y modo normal. Cuando estaba en modo loco, permaneció allí durante un número constante de tics. Había una probabilidad constante de entrar en modo loco. También se hiperespaciaba cuando estaba cerca del sol. En modo loco, apuntó al otro bot y disparó constantemente. En modo normal, voló lejos del otro bot, no disparando.
Ajusté ese prototipo para que estuviera en modo loco si y solo si el enemigo estaba lo suficientemente cerca. Entonces tuve una idea loca: ¿qué pasaría si solo se quedara en modo loco? Después de experimentar un poco (agregué hacer que el bot se disparara aleatoriamente cuando estaba en modo normal) me encontré con un nuevo bot que venció a todos los bot excepto a Helios. Este es mi código al final de este proceso, pero antes de limpiarlo.
Escribí todo mi bot en el área de texto KotH o el embellecedor JS. (Utilicé brevemente el editor Atom al limpiar, pero como dos líneas de código)
El bot
Este bot contiene una gran cantidad de código prestado de otros bots. Voltea el código de Kamikaze para huir del otro bot en lugar de correr hacia el otro bot y toma el código de EdgeCase para hiperespacio cuando está cerca del sol.
Su archienemigo es Helios. Siendo el extraño y largas conversaciones con un martini.
Se escapa del otro bot con un 70% de posibilidades de disparar un misil e hiperespacios cuando está cerca del sol. Tan sencillo como eso. Sí.
Editar: probé mi bot con el nuevo código y falla para cualquier otro bot. Estoy trabajando en arreglarlo. Acabo de confirmar que esto es solo para mi nuevo bot.
El código
El misceláneo
Nota: Podría haber roto algo al limpiar el código porque no probé el bot después de limpiar el código.
También es mucho, mucho, mucho mejor que todos mis otros bots: en realidad venció a cualquier otro bot, excepto Helios (editar) , SetCourseFor30Degrees y OrbitBot. Se vincula con SunAvoider.
Nota al margen: soy horrible en javascript, no sé por qué.
fuente
AttackAndComeBack
En lugar de girar, entra en la parte superior y sale en la parte inferior (regresa en la parte superior), disparando muy rápidamente. Generalmente evita el sol.
fuente
Máxima velocidad adelante
Siempre dispara tanto los motores como los misiles sin girar nunca. A veces dura sorprendentemente mucho antes de golpear el sol.
fuente
Ataque de pánico
Tiene una probabilidad del 50% de disparar y una probabilidad del 80% de girar a la izquierda; pero si no gira a la izquierda, girará a la derecha. Después de que se quede sin misiles, el tiempo eventualmente hará que se detenga debido al sol.
EDITAR: se agregó algo de lógica para no disparar cuando el enemigo está vivo porque podría ser asesinado por sus propios misiles.
fuente
DangitBobby
A Bobby Hill no le importa lo que otros piensen de él: está bastante contento de dar vueltas perezosamente por el campo y esperar pacientemente a que su oponente se quede sin fuerzas antes de golpear como una cobra "ronca".
"¡ESE ES MI MONEDERO! ¡NO TE CONOZCO!"
fuente
Francotirador
He estado jugando con la predicción durante un tiempo para crear un robot de francotirador que snipes a sus enemigos. Mi javascript es demasiado grande para caber en una respuesta, así que aquí hay un enlace, bot_Sniper .
fuente
SmartArrow
Como Arrow, pero inteligente
fuente
Kamikaze-
Tampoco está diseñado para ser competitivo. Solo por diversión. Se hiperespacia cuando está cerca del sol y persigue al jugador sin disparar balas. Es divertido ver a este robot perseguir una versión desarmada de Spy, pero desafortunadamente no puede tener más de un robot de usuario.
El'endia: alguna vez consideró agregar más de un robot de usuario;)
Solo tomé el código de Kamikaze + y me deshice de la parte de disparo de misiles.
fuente
MissilesPlusScore
Se me ocurrió una idea extraña que toma que el valor absoluto de la diferencia de los puntajes y utiliza una lista de movimientos de forma aleatoria en función del juego. Funciona bien contra bots con una estrategia, pero falla contra tormentas de misiles. También mi primer rey de la colina .
HIPER
¡¡¡HIPERSPACE ES FRESCO !!!!!!!!!!!!!!!!
Influencia coordinada
Basado en las coordenadas, sorprendentemente eficaz:
fuente
SetCourseFor30Degrees
No tengo idea de por qué el capitán es tan insistente en establecer la nave en un curso de 30 grados, pero bueno, como una humilde bandera, ¿a quién interrogarás? ¡Al menos te han dado permiso para evitar el sol! Y se te permite disparar los misiles ... simplemente no puedes apuntarlos ...
fuente
Flecha
Simplemente persigue a su enemigo, hiperespacio cuando está en peligro e inactivo cuando su enemigo está muerto.
fuente
Kamikaze +
No está diseñado para ser competitivo. Solo por diversión. Técnicamente, hace lo contrario de Spy: perseguir al jugador, hiperespacio cuando está cerca del sol, disparar misiles el 70% del tiempo. Solo quiero ver a KamikazePlus persiguiendo a Spy y Spy corriendo como un loco.
Básicamente solo tomé el código de Spy y volteé "izquierda" y "derecha".
fuente
overideHyperspace = 0;
; simplemente siguen desaparecidos cuando intentan enfrentarse el uno al otro.