UNA VENTANA AL MUNDO DE LA PASIÓN CIENTÍFICA

La ciencia de los videojuegos: IA(II)


Texto escrito por Víctor Buendía Ruiz-Azuaga

En la entrada anterior estuvimos hablando de por qué es importante un buen diseño en inteligencia artificial (IA), y estuvimos comentando sobre la importancia que tienen los grafos, tanto para mover entidades por un mapa como para conseguir que el ordenador reconociera en qué punto se encuentra la partida.

Sin embargo, llegamos a la conclusión de que había tareas que no podíamos solucionar con grafos, o que tenía un resultado poco convincente. Entre ellas, el movimiento coordinado de una agrupación de unidades, cómo conseguir que las unidades se movieran de forma convincente en grandes espacios abiertos o la relación entre la inteligencia individual de cada unidad con una macro-inteligencia que sea capaz de dominar la partida a nivel global.

En esta entrada vamos a hablar sobre movimientos coordinados y otras formas de mover a nuestras unidades en el mapa, que pueden ser usadas en combinación con los grafos para darle más realismo.

Campos escalares y campos vectoriales

Si la entrada anterior empleó los grafos, un objeto que empleado comúnmente en matemáticas, en este caso vamos a hablar de una de las herramientas favoritas de los físicos: los campos. Primero entenderemos de forma intuitiva qué es un campo y después veremos por qué es útil a la hora de diseñar una IA con movimientos coordenados.

Primero comencemos con el concepto de campo. Un campo es simplemente coger cada punto del espacio que queramos y asignarle un valor. El valor, aunque intuitivamente pensamos en un número, puede ser en general cualquier otro objeto matemático a nuestro gusto. Sin embargo, a nosotros nos bastan con dos clases de campos:

  • Campos escalares: a cada punto del espacio le corresponde un numerito. Por ejemplo, tenemos una habitación vacía y ponemos una estufa en medio. Está claro que no se calentará toda la habitación a la vez. Irá calentándose poco a poco, primero lo que está más cerquita de la estufa. En cada punto de la habitación, por tanto, hay un valor de temperatura diferente. Es un campo escalar de temperaturas
Ilustración 1: Un ejemplo de campo escalar. Podría indicar la temperatura en una habitación, siendo los sitios en rojo más calientes y los azules más fríos

Ilustración 1: Un ejemplo de campo escalar. Podría indicar la temperatura en una habitación, siendo los sitios en rojo más calientes y los azules más fríos

 

  • Campos vectoriales: a cada punto del espacio le corresponde un vector, es decir, una flechita que marca una dirección y una intensidad. Por ejemplo, un mapa del tiempo donde ponga hacia dónde va el viento. Generalmente la intensidad se dibuja con los tamaños de las flechas o poniéndoles colores. Este será un campo vectorial de velocidades.
Ilustración 2: Campo vectorial. Si fuera un mapa de viento, esto representaría a una especie de borrasca o torbellino. Es más intenso en el centro, donde las flechas son más grandes.

Ilustración 2: Campo vectorial. Si fuera un mapa de viento, esto representaría a una especie de borrasca o torbellino. Es más intenso en el centro, donde las flechas son más grandes.

Hay una gran cantidad de herramientas matemáticas dedicadas en exclusiva a analizar campos. En los campos escalares, por ejemplo, puede calcularse en qué dirección va variando el campo. En nuestro ejemplo de la estufa los cálculos nos dirían que la temperatura aumenta cuando nos acercamos a la estufa. En los campos vectoriales pueden averiguarse cosas como el flujo de aire que pasa por una superficie, si se producen torbellinos…

Las teorías de campos son excepcionalmente útiles en física. Hay campos para todo: campo gravitatorio, campo electromagnético, campos de velocidad, campos de temperatura, ¡hasta campos cuánticos! Por tanto hablamos de una teoría que tiene ya sus años y está bien trillada por físicos y matemáticos.

Movimiento con campos

Ahora bien, ¿y esto para qué nos sirve en la IA?  Tiene unos usos bastante interesantes, pero vamos a ir primero al más básico. Sirve para moverse por el mundo, dándole prioridad a unas zonas u otras.

Por ejemplo, podemos hacer un campo escalar que represente cuánto nos interesa movernos hacia un sitio. Por supuesto, hasta el momento no parece que cambie nada: yo podría también construir un grafo, con puntuaciones sobre qué sitios interesan más o menos, y trabajar sobre él. Pero el hecho de emplear un campo en lugar de un grafo tiene una serie de ventajas muy interesantes:

  1. El movimiento es continuo, sin huecos: recordemos, en espacios abiertos nuestros grafos adolecían del problema de que dejaban “huecos” por donde nuestro personaje no pasaba. Y rellenarlos implicaba aumentar el número de nodos y, por tanto, el tiempo de procesamiento. Con un campo, esto no ocurre: cada punto del espacio tiene un valor numérico.
  2. Velocidad de cómputo: para grandes espacios abiertos con pequeños obstáculos, el resultado es mucho más rápido, para ir entre dos puntos A y B. Con el grafo, tengo que ejecutar un algoritmo que resuelva la mejor ruta, que puede ser algo complicado o largo. Con el campo, lo que hago es simplemente es mirar qué valores toma el campo alrededor mío y moverme hacia la dirección en la cual me interese más (hacia el más caliente o el más frío, por ejemplo, si hacemos la analogía con un campo de temperaturas). La ruta se va creando conforme me voy moviendo.
  3. Esto último tiene una ventaja más, y es que el campo puede ser dinámico: yo puedo cambiar valores del campo en tiempo real, y mi IA reaccionará de forma inmediata: no hay que recalcular rutas.

Estas ventajas son especialmente buenas en juegos en los que hay que moverse en grandes espacios abiertos, donde los problemas de los grafos son bastante evidentes.

Además, los objetos del escenario serán las propias fuentes del campo. Por ejemplo, en un juego de estrategia con dos equipos, rojo y azul. Los obstáculos del mapa crearán un campo repulsivo para que las unidades no lo atraviesen. En cuanto a las unidades, cuando el equipo rojo crea unidades, nos interesa que las unidades propias se repelan ligeramente entre ellas, para que no se acerquen demasiado. Sin embargo, lo que quiero es que las unidades enemigas me atraigan, para tratar de acercarme a ellas lo máximo posible. Si a esto le añadimos que las zonas con interés estratégico atraigan, ponderando bien cuánto atraen y repelen las diferentes partes tendremos de forma relativamente sencilla un juego en el cual las unidades buscan sitios de interés estratégico, no chocan con las paredes, evitan chocar entre sí, y buscan al enemigo.

Así a primera vista, al igual que ocurre con los grafos, parece que los campos son una solución realmente buena a nuestros problemas. Sin embargo, y al igual que ocurría antes, siguen teniendo algunos problemas respecto del movimiento. Uno de ellos es el problema de los extremos locales.  Una buena forma de visualizar un campo escalar, como el que estamos utilizando, en un videojuego 2D, plano, es como si la superficie en la cual el juego tiene lugar fuera una especie de tela, que puede doblarse, y formar montañas, valles y depresiones. Los sitios que atraen se hunden hacia abajo, y eso es lo que hace que las unidades “caigan” hacia adentro y vayan a donde queremos. La repulsión vendría dada en montes y colinas. Ahora bien, puede que, tal como se ha desarrollado la partida, el equipo azul haya construido su campamento de tal forma que haya creado una especie de pozo en nuestra tela, de modo que las unidades que caen en él, no pueden salir. Eso ya de por sí queda muy mal cuando un jugador observa que algunas unidades controladas por el ordenador han quedado atascadas; pero más aún cuando el pozo está justo en medio de una zona de paso,  y todas las unidades que pasan se han ido quedando dentro (sin motivo aparente para el jugador). Por supuesto, debido a la repulsión entre unidades esto puede tener un límite, pero en todo caso es un problema grave: quiere decir que pueden aparecer una especie de “agujeros negros” de unidades; y si lo queréis poner peor aún, se puede: ¡el jugador avispado podría darse cuenta de que es posible explotar esta particularidad para crear él mismo estos agujeros y despachar fácilmente a la IA!

Un problema de este calibre tiene una gran cantidad de desventajas. Por supuesto, esto se puede evitar con un diseño de niveles y mapas adecuado, así como incluir diferentes tipos de procesamiento. Por ejemplo, el movimiento de unidades a gran escala podría hacerse con grafos. Podríamos definir diferentes zonas, a grosso modo, y ordenar a las unidades que se muevan siguiendo los grafos. Para hacer movimientos a pequeña escala, sin embargo, usaremos los campos, de modo que las unidades se muevan de una forma más independiente en espacios abiertos. Esto solucionará en buena medida problemas de grandes agujeros negros.

Un detalle más es el hecho de que hemos empleado campos escalares para realizar nuestro ejemplo. Podríamos emplear también campos vectoriales, los cuales indican también direcciones. Estos parecen a primera vista más restrictivos que los anteriores, ya que también señalan la dirección en la que una unidad ha de moverse. Sin embargo, el caso es que para nuestros fines ambos campos son muy muy parecidos, ya que podemos pasar de uno a otro. Como hemos dicho antes, lo que hacemos cuando movemos una unidad es observar el campo alrededor, y movernos hacia el sitio que nos convenga más (es decir, el que tenga pendiente hacia abajo, siguiendo el ejemplo de la tela). Ahora bien, haciendo esto, suponiendo que ponemos una unidad en cada punto posible del campo y viendo hacia dónde iría, podemos asignarle un campo de flechas, vectorial. Si usamos este nuevo campo para dirigir a nuestras unidades, será exactamente equivalente al anterior. Por ese motivo, a la hora de programar se emplea el escalar, que es más sencillo.

Además, los campos tienen una serie de aplicaciones curiosas e imaginativas para la inteligencia artificial. A modo de ejemplo, la forma que tiene el juego Supreme Commander 2 de mover las tropas en formación cuando se encuentra con otras tropas en dirección contraria. Como se puede ver en este vídeo, los ejércitos se comportan como si fueran un fluido que está bordeando un obstáculo. Esto permite a las tropas moverse sin estorbarse entre ellas y mantener siempre su formación.

Por supuesto, desde el punto de vista del análisis, este movimiento es el de un fluido, como el agua, y se estudia con campos. Ahora, puede que se haya programado mediante campos, o puede que no: a veces, para esta clase de movimientos coordenados hay una opción mucho más fácil de programar, con unos resultados, cuando menos, sorprendentes.

Steering Behaviors

La traducción del término es algo compleja, y se trata básicamente de una serie de comportamientos que sirven para que una entidad se mueva de forma autónoma en un escenario. Frente a los campos, lo que hacen los steering behaviors es simplemente modificar la velocidad de la entidad o unidad (como si algo la empujara) según lo que haya en su entorno. Aplicadas de forma inteligente, estas fuerzas permiten comportamientos la mar de curiosos que sirven para que nuestros bichejos se muevan por el muevo como si fueran inteligentes de verdad.  Incluyen algunas como:

  • Llegar/evitar: una fuerza atractiva o repulsiva para acercar o alejar de un sitio, según se quiera. Esta funciona exactamente igual que un campo.
  • Perseguir/evadir: igual que el anterior, la diferencia es que este suele emplearse con un objetivo en movimiento. Además, la fuerza tira no hacia donde está ahora nuestro objetivo, sino hacia donde estará dentro de poco tiempo (basándonos en su velocidad actual). A pesar de su simplicidad, el resultado es que parece realmente que la IA nos persigue o nos evade de una forma inteligente.
  • Seguir al líder: las entidades siguen a una entidad que consideramos líder. Si, además, le añadimos que evadan al líder ligeramente, se consigue un efecto muy bonito que permite que este se dé la vuelta, se aparte todo el mundo educadamente, y luego continúen siguiéndolo.
  • Evitar obstáculos o seguir paredes: con las fuerzas tratando siempre de empujar hacia fuera de la pared o manteniéndolas paralelas, se puede conseguir que eviten obstáculos o que sigan pegados a la pared.
  • Hacer cola: sí, parece increíble, pero simplemente con algunas fuerzas puede conseguirse que muchas entidades “hagan cola” para pasar por una puerta estrecha y lo hagan de una en una y ordenadamente. Muy útil para juegos tipo Call of Duty, cuando hace falta entrar a un edificio.
  • Seguir una ruta: puede seguirse una ruta, que tal vez ha sido previamente calculada con grafos. La ventaja de seguir una ruta usando esta técnica es que no hay por qué pasar exactamente por el nodo, sino que la entidad lo hace de forma más natural. También pueden seguirse de esta forma campos vectoriales.

El lector curioso puede que encuentre divertida la página de Craig Reynolds, creador de estos steering behaviors, http://www.red3d.com/cwr/steer/. En ella hay demostraciones Java de cómo funciona cada uno de ellos, y puede comprobarse cómo funcionan. La ventaja que tienen los steering behaviors es que, como se puede ver, incluyen toda clase de acciones y además se pueden compatibilizar con los grafos o los campos con facilidad. Otra cosa, muy importante, es que se pueden añadir varias fuerzas a la misma entidad, y después ponderarlas para darle prioridad a unas u otras según la situación.  Así, se puede seguir una ruta, evitando colisiones con entidades vecinas, y siguiendo una pared siempre que sea posible.

Esto da lugar a mecanismos que permiten movimientos de grupo. Incluso, con unas fuerzas un poco más sutiles podemos conseguir movimientos de grupo muy realistas. Para empezar, la entidad detecta a otras entidades cercanas y se forma un grupo. Después, hay que añadir, a las fuerzas que tengan, estas tres:

  • Cohesión: sobre la entidad actúa una fuerza que atrae hacia lo que sería el “centro de masas” del grupo. Así evitamos que el grupo se disperse.
  • Alineación: orientamos la entidad que sea hacia donde está mirando el resto del grupo, de media.
  • Finalmente, evitar choques con otros miembros del grupo mediante repulsión.

Nuevamente, la ventaja de estos algoritmos es su sencillez: son muy fáciles de programar, consumen muy pocos recursos, funcionan muy bien en espacios abiertos, y el movimiento que generan es suave, realista y agradable para el jugador. Por supuesto, también tienen desventajas: la ponderación de las fuerzas es complicada, y cuando hay muchas afectando a una misma entidad pueden ser un problema. Por otro, al igual que los campos, en estos algoritmos la entidad no sabe absolutamente nada del terreno o la ruta que seguirá en un futuro, simplemente es arrastrada por la fuerza. Esto lleva en ocasiones a momentos en los cuales nuestra entidad se queda atascada, nuevamente como en el “pozo” del caso de los campos. Con los steering behaviors suele suceder con cierta frecuencia con los obstáculos, puesto que para aquellos que tienen formas complicadas a veces pueden llevar al atasco de las entidades.

Como último comentario, estos steering behaviors no se emplean solamente para los videojuegos: en ocasiones se emplean también para estudiar cómo se comportan animales reales, como pájaros en formación o bancos de peces, ya que el movimiento es muy similar. Por tanto, se usan en física interdisciplinar para explicar algunos de los comportamientos más básicos de estos animales.

Conclusiones

Hoy hemos visto que hay más herramientas para mover a una unidad por un mapa de forma inteligente; con los grafos, solucionamos el problema de que la unidad vaya de A hasta B por la mejor ruta posible. Con los campos, podemos movernos libremente por el espacio. Y empleando los steering behaviors podemos realizar incluso más cosas para conseguir que nuestras unidades se muevan por el mapa total naturalidad, incluso manteniendo formaciones o cuando el espacio está lleno de unidades moviéndose.

Sin embargo, aunque ya dominamos bien la cuestión de movernos, aún queda un “detalle”. ¿A dónde nos movemos? ¿Qué tenemos que hacer? ¿Qué estrategia seguimos? ¿Vamos ganando o perdiendo? Es decir, vale,  sabemos a dónde mandar nuestras unidades, sabemos que ellas solas pueden moverse de forma independiente, pero nos falta una mente pensante que domine todo eso. En la siguiente (¡y última!) entrega de IA, hablaremos cuáles son las estrategias básicas para construir un pequeño cerebro capaz de tomar decisiones.

Leave a Reply

Your email address will not be published. Required fields are marked *