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)
LineIntersection
a segmentos que no se cruzan devuelve una matriz vacía.