IA de combate realista para juegos 2D

imagen

Aunque Close Quarters es predominantemente un juego multijugador, los bots de IA complejos aún deben estar presentes para que los jugadores sigan jugando cuando su conexión a Internet es deficiente o no hay otros jugadores en línea. Además, los bots juegan un papel de apoyo importante en algunos modos de juego. Por lo tanto, deben comportarse de manera creíble y demostrar un conjunto de comportamientos complejos, que incluyen el uso de refugios, el uso de objetos en el momento adecuado, eludir los flancos, arrojar granadas y escapar de ellos.

Entorno y restricciones


El entorno de juego consiste en polígonos. La mayoría de los polígonos bloquean el movimiento, la visibilidad y el disparo, pero también hay polígonos "bajos" que solo bloquean el movimiento. El entorno está fuertemente cubierto de obstáculos y refugios.

La IA también está limitada por varios factores técnicos. El más importante de ellos: el servidor en el que se ejecutan los bots, cuando hay pocos jugadores en línea, debería funcionar rápidamente en un VPS económico con al menos diez bots. Además, la carga de la CPU debe permanecer lo suficientemente baja como para permitir múltiples instancias de servidor en el mismo VPS sin exceder el límite de la CPU y sin causar sanciones por parte del proveedor del servicio VPS.


Figura 1: entornos


Figura 2: vista desde la cara del jugador de los obstáculos que bloquean la vista (las áreas grises son invisibles para él)

Malla de navegación y visibilidad, búsqueda táctica de un camino.


Los bots usan una malla de navegación densa que consiste en puntos discretos. La malla se genera de la siguiente manera: primero, los polígonos que conforman el entorno se expanden y combinan . Se agregan nodos adicionales cerca de las esquinas, porque es muy probable que estos lugares sean lugares de refugio adecuados. El espacio de movimiento resultante se triangula para generar una malla.


Figura 3: malla de navegación

Dado que los bots deben realizar una búsqueda táctica de la ruta , la malla de navegación debe contener datos de visibilidad que nos permitan verificar rápidamente si el nodo contiene refugio del enemigo seleccionado. Por lo tanto, cada nodo contiene una matriz de 24 bytes, cada uno de los cuales representa una distancia aproximada calculada previamente entre el nodo y el obstáculo más cercano que bloquea el campo de visión en una determinada dirección.


Figura 4: Datos de visibilidad almacenados en el nodo (líneas azules). Cada línea representa un valor de un solo byte que define la visibilidad en una dirección determinada.

Gracias a estos datos, puede buscar los gráficos utilizando el algoritmo A *en la malla de navegación, en la que los nodos que se pueden abrir a enemigos conocidos reciben menor prioridad sin costosas comprobaciones de la línea de visión. Para verificar si cierto nodo está abierto al enemigo, determinamos la dirección y la distancia desde el nodo al enemigo, y luego verificamos si esta distancia es menor que la distancia almacenada en el elemento de matriz que está más cerca de esta dirección. Además, podemos verificar si el enemigo está mirando el nodo. Entonces podemos aplicar el factor de penalización al costo de moverse a través de nodos abiertos a los enemigos, y la ruta resultante tenderá a evitar tales nodos.

Los mismos datos de visibilidad, además de encontrar el camino entre dos puntos dados, pueden usarse para otras acciones "tácticas". Por ejemplo, el bot busca refugio realizando una búsqueda amplia y se detiene tan pronto como encuentra un sitio protegido. Las pruebas de línea de visión se utilizan para verificar que el sitio realmente proporcione refugio. Del mismo modo, podemos generar rutas de ataque desde los flancos buscando A * para el objetivo; Al mismo tiempo, se imponen altas multas a los nodos abiertos dentro del cono de tiro al blanco. La búsqueda se detiene tan pronto como alcanzamos un nudo abierto fuera de este cono de disparo. (Uno de los problemas con este enfoque es que los bots que están fuera de alcance constantemente intentan acercarse a la meta y, por lo tanto, parecen demasiado agresivos; esto probablemente se puede solucionar configurando la heurística A * de modo quepara que el bot no se mueva directamente al objetivo, sino a los nodos ubicados a una distancia seleccionada del objetivo).

Sentimientos y memoria de bots


Para que los bots se comporten de manera convincente, no deberían parecer tramposos. En otras palabras, la información con la que trabaja el bot debe ser similar a la información que posee el jugador. Por ejemplo, el enemigo detrás del obstáculo debe ser invisible para el bot tal como no es visible para el jugador.


Hay dos formas en que un jugador puede detectar la posición de un enemigo: puede ver al enemigo o escuchar cómo se mueve, dispara o realiza alguna otra acción.

Cada bot mantiene una lista de "hechos" conocidos sobre las posiciones y la dirección de la mirada de los enemigos. Sin actualizaciones, estos hechos se eliminan después de diez segundos. Un hecho relacionado con un enemigo específico se actualiza cuando el bot puede escuchar o ver a ese enemigo. Cuando un bot escucha a un enemigo, para simular incertidumbre, la posición del hecho correspondiente se desplaza de la posición verdadera del enemigo en una dirección y distancia aleatorias, dependiendo de qué tan cerca esté el bot (ver video, 1:28).


Figura 5: hechos (círculos rosados) en la memoria del bot

Árbol de comportamiento


En una versión anterior de Close Quarters, AI usó STRIPS, una solución popularizada por FEAR en 2005. En STRIPS, la relación entre diferentes comportamientos de IA no está predefinida por el programador. En cambio, cada comportamiento contiene una lista de precondiciones y resultados binarios. Cada bot tiene un estado del problema en el mundo y usa la búsqueda en el gráfico A * para encontrar la secuencia de comportamientos para lograrlo. Esta solución funcionó bien, pero sentí que era demasiado compleja para mi aplicación y más adecuada para la IA, que necesitaba desarrollar planes complejos que involucraran muchos comportamientos diferentes. En la mayoría de los casos, ya sabía las circunstancias bajo las cuales el bot tenía que realizar este o aquel comportamiento, por lo que usar A * para este algoritmo era un desperdicio innecesario de recursos de la CPU.

Por lo tanto, los bots ahora usan un árbol de decisión y un comportamiento simples. En cada medida, el bot rodea el árbol, comenzando desde la raíz, hasta que alcanza el comportamiento. Si este comportamiento es el mismo que ya se realizó, entonces el bot continúa este comportamiento. Si no, el bot inicia el comportamiento y comienza a ejecutarlo.

Algunos comportamientos pueden "bloquear", es decir, evitar que el bot atraviese repetidamente el árbol hasta que se cumpla una determinada condición. Esto es útil, por ejemplo, para garantizar que los bots se cubran antes de decidir atacar. Además, los comportamientos pueden "anularse" entre sí, lo que obliga al bot a volver a omitir el árbol y reiniciar el comportamiento. Esto es útil, por ejemplo, cuando un bot escapa de una granada y aparece otra granada que compromete las posiciones de escape seleccionadas.


Figura 6: El árbol de decisión y comportamiento actualmente en uso

Algunos comportamientos secundarios están codificados dentro de otros comportamientos más generales. Por ejemplo, si un bot intenta atacar a un enemigo y descubre que el enemigo no está en la posición esperada, entonces asume dónde puede estar el enemigo ahora y calcula una nueva ruta de ataque sin abandonar el comportamiento de ataque.

Distribución de la carga


No es necesario actualizar cada bot en cada cuadro de física, es decir, 40 veces por segundo. Para reducir los costos de CPU, cada bot "piensa" solo 20 veces por segundo (este número se puede reducir si es necesario). Por lo tanto, solo la mitad de los bots se actualizan en cada ciclo de física.

Trabajar con granadas


Un problema grave fue el uso significativo de granadas por los bots. Trabajar con granadas es mucho más difícil que disparar, porque las granadas pueden volar desde las paredes, tienen un radio de destrucción y tiempo para lanzar. Afortunadamente, no se requiere que los bots usen granadas perfectamente, suficiente persuasión.

La solución tradicional a este problema es calcular previamente las rutas de las granadas en los nodos de navegación , pero cuando se implementa, se agregan unos segundos al tiempo de carga de cada mapa, lo que contradice mi objetivo: Close Quarters debería lanzar a los jugadores a la batalla en cuestión de segundos después de comenzar el juego.

Por lo tanto, los bots están buscando oportunidades para usar granadas, calculando los caminos de las granadas sobre la marcha. En cada ciclo, el bot atacante verifica varias trayectorias posibles en una dirección dada dentro de los 60 grados de la dirección del objetivo seleccionado. Si una granada lanzada a lo largo de un camino probado puede matar al objetivo y el objetivo está fuera del alcance, el bot arroja una granada. La dirección marcada se repite en cada reloj AI.


Figura 7: direcciones verificadas por el bot durante un segundo (líneas de color rosa pálido) y trayectorias probadas (círculos azules) a lo largo de la dirección seleccionada en la medida actual (línea de color rosa brillante).

Es decir, los bots usan granadas siempre que sea posible y no se mueven a una posición específica para lanzar una granada. Sin embargo, el camino elegido por el bot para atacar al enemigo es a menudo un camino sensible desde el cual lanzar una granada.

Un inconveniente significativo de dicho sistema es que, debido al número limitado de direcciones controladas, los bots pierden la oportunidad de lanzar granadas para que reboten en pequeños obstáculos. Más notablemente, esto está al lado de las puertas, donde los bots generalmente no reconocen la posibilidad de usar una granada. Este problema se puede resolver probando varias direcciones en un cuadro y, por lo tanto, reduciendo el ángulo entre la dirección que se verifica y la siguiente.

Movimiento hacia un comportamiento más humano


Tal problema se hace evidente rápidamente: los bots son demasiado rápidos para apretar el gatillo, porque es muy difícil derrotarlos en una batalla uno a uno. El tiempo promedio de reacción humana a los estímulos visuales es de 250 milisegundos, pero a 20 latidos por segundo, ¡el tiempo máximo de reacción del robot es de solo 50 milisegundos!

Para resolver este problema, agregué deliberadamente un retraso entre el momento en que el bot tiene la oportunidad de disparar y el disparo en sí, para que su tiempo de reacción sea comparable al tiempo de reacción de una persona.

Futuras mejoras


Los sistemas presentados anteriormente proporcionan una IA fundamental fuerte, pero no brindan oportunidades para mejoras importantes. Por ejemplo, ahora el pensamiento espacial del robot está limitado por su entorno inmediato, por lo tanto, aunque el robot generalmente trata de evitar al enemigo desde el flanco, a menudo pierde rutas de flanqueo alrededor de grandes obstáculos. Además, los bots solo conocen aproximadamente la presencia de compañeros de equipo, por lo que a veces se acumulan en un solo lugar, en lugar de dividirse y evitar los flancos.

All Articles