{"id":52118,"date":"2019-11-01T00:00:00","date_gmt":"2019-10-31T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih"},"modified":"2020-02-18T13:59:47","modified_gmt":"2020-02-18T10:59:47","slug":"kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","status":"publish","type":"post","link":"https:\/\/prohoster.info\/es\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","title":{"rendered":"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/9e57175b233a104e0df98383b374eded.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEncontr\u00e9 un material interesante sobre inteligencia artificial en los juegos. Con explicaciones b\u00e1sicas sobre la IA mediante ejemplos simples, y adem\u00e1s, incluye muchas herramientas y m\u00e9todos \u00fatiles para su desarrollo y dise\u00f1o. Tambi\u00e9n hay informaci\u00f3n sobre c\u00f3mo, d\u00f3nde y cu\u00e1ndo usarlos.<\/p>\n<p>La mayor\u00eda de los ejemplos est\u00e1n escritos en pseudoc\u00f3digo, por lo que no se requieren profundos conocimientos de programaci\u00f3n. M\u00e1s abajo hay 35 p\u00e1ginas de texto con im\u00e1genes y gifs, as\u00ed que prep\u00e1rense.<\/p>\n<p>UPD. Lo siento, pero ya hice mi propia traducci\u00f3n de este art\u00edculo en Habrahabr. <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/users\/PatientZero\/\">PatientZero<\/a><\/noindex>. Se puede leer su versi\u00f3n <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/420219\/\">aqu\u00ed<\/a><\/noindex>, pero por alguna raz\u00f3n el art\u00edculo me pas\u00f3 desapercibido (utilic\u00e9 la b\u00fasqueda, pero algo sali\u00f3 mal). Y como escribo en un blog dedicado al desarrollo de videojuegos, decid\u00ed dejar mi propia traducci\u00f3n para mis suscriptores (algunos puntos los he presentado de manera diferente, y otros los he omitado intencionadamente por recomendaci\u00f3n de los desarrolladores).<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>\u00bfQu\u00e9 es la IA?<\/h2>\n<p>\nLa IA en los juegos se centra en las acciones que debe realizar un objeto, en funci\u00f3n de las condiciones en las que se encuentra. Esto generalmente se llama gesti\u00f3n de \"agentes inteligentes\", donde el agente puede ser un personaje del juego, un veh\u00edculo, un bot, o a veces algo m\u00e1s abstracto: un grupo entero de entidades o incluso una civilizaci\u00f3n. En cada caso, es una entidad que debe percibir su entorno, tomar decisiones basadas en ello y actuar en consecuencia. Esto se conoce como el ciclo Sense\/Think\/Act (Sentir\/Pensar\/Actuar):<\/p>\n<ul>\n<li>Sense: el agente encuentra o recibe informaci\u00f3n sobre cosas en su entorno que pueden influir en su comportamiento (amenazas cercanas, objetos para recoger, lugares interesantes para investigar).<\/li>\n<li>Think: el agente decide c\u00f3mo reaccionar (considera si es lo suficientemente seguro recoger objetos o si primero debe luchar\/esconderse).<\/li>\n<li>Act: el agente lleva a cabo acciones para realizar la decisi\u00f3n anterior (comienza a moverse hacia el enemigo o el objeto).<\/li>\n<li>\u2026ahora la situaci\u00f3n ha cambiado debido a las acciones de los personajes, por lo que el ciclo se repite con nuevos datos.<\/li>\n<\/ul>\n<p>\nLa IA, por lo general, se concentra en la parte de Sense del ciclo. Por ejemplo, los coches aut\u00f3nomos capturan im\u00e1genes de la carretera, combinan estas con datos de radar y lidar, y los interpretan. Normalmente, esto lo hace el aprendizaje autom\u00e1tico, que procesa los datos entrantes y les da significado, extrayendo informaci\u00f3n sem\u00e1ntica del tipo \"hay otro coche a 20 yardas enfrente de ti\". Estos son los llamados problemas de clasificaci\u00f3n.<\/p>\n<p>Los juegos no necesitan un sistema complicado para extraer informaci\u00f3n, ya que gran parte de los datos ya es parte integral del mismo. No es necesario ejecutar algoritmos de reconocimiento de im\u00e1genes para determinar si hay un enemigo adelante; el juego ya lo sabe y transmite esa informaci\u00f3n directamente en el proceso de toma de decisiones. Por lo tanto, la parte del ciclo Sense es a menudo mucho m\u00e1s simple que Think y Act.<\/p>\n<h2>Limitaciones de la IA en los juegos<\/h2>\n<p>\nLa IA tiene una serie de limitaciones que deben ser respetadas:<\/p>\n<ul>\n<li>La IA no necesita ser entrenada de antemano, como lo har\u00eda un algoritmo de aprendizaje autom\u00e1tico. No tiene sentido escribir una red neuronal durante el desarrollo para observar a decenas de miles de jugadores y estudiar la mejor forma de jugar contra ellos. \u00bfPor qu\u00e9? Porque el juego no ha sido lanzado y no hay jugadores.<\/li>\n<li>El juego debe entretener y desafiar, por lo que los agentes no deben encontrar el mejor enfoque contra los humanos.<\/li>\n<li>Los agentes deben parecer realistas para que los jugadores sientan que est\u00e1n jugando contra personas reales. El programa AlphaGo super\u00f3 al humano, pero los movimientos seleccionados estaban muy alejados de la comprensi\u00f3n tradicional del juego. Si el juego imita a un oponente humano, esa sensaci\u00f3n no deber\u00eda existir. El algoritmo debe modificarse para que tome decisiones plausibles en lugar de perfectas.<\/li>\n<li>La IA debe operar en tiempo real. Esto significa que el algoritmo no puede monopolizar el uso del procesador durante largos per\u00edodos para tomar decisiones. Incluso 10 milisegundos para esto es demasiado tiempo, porque la mayor\u00eda de los juegos necesitan entre 16 y 33 milisegundos para procesar todo y pasar al siguiente fotograma gr\u00e1fico.<\/li>\n<li>Es ideal que al menos parte del sistema sea controlada por datos, para que los \"no programadores\" puedan hacer cambios y para que las correcciones ocurran m\u00e1s r\u00e1pidamente.<\/li>\n<\/ul>\n<p>\nConsideremos enfoques de IA que abordan todo el ciclo Sense\/Think\/Act.<\/p>\n<h3>Toma de decisiones b\u00e1sicas<\/h3>\n<p>\nComencemos con el juego m\u00e1s simple: Pong. Objetivo: mover la paleta (paddle) para que la pelota rebote en ella y no pase de largo. Es como el tenis, donde pierdes si no golpeas la pelota. Aqu\u00ed la IA tiene una tarea relativamente sencilla: decidir en qu\u00e9 direcci\u00f3n mover la paleta.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/e1935d657b9f090bf60c365c21e8f92b.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<\/p>\n<h3>Operadores condicionales<\/h3>\n<p>\nPara la IA en Pong, la soluci\u00f3n m\u00e1s obvia es siempre intentar mantener la paleta debajo de la pelota.<\/p>\n<p>Un algoritmo simple para esto, escrito en pseudoc\u00f3digo:<\/p>\n<p><i>cada fotograma\/actualizaci\u00f3n mientras el juego est\u00e9 en funcionamiento:<br \/>\nsi la pelota est\u00e1 a la izquierda de la paleta:<br \/>\n mover la paleta a la izquierda<br \/>\nsi no, si la pelota est\u00e1 a la derecha de la paleta:<br \/>\n mover la paleta a la derecha<\/i><\/p>\n<p>Si la paleta se mueve a la misma velocidad que la pelota, entonces este es el algoritmo ideal para la IA en Pong. No hay necesidad de complicar las cosas si hay pocos datos y acciones posibles para el agente.<\/p>\n<p>Este enfoque es tan simple que todo el ciclo Sense\/Think\/Act es apenas perceptible. Pero existe:<\/p>\n<ul>\n<li>La parte Sense se encuentra en dos operadores if. El juego sabe d\u00f3nde est\u00e1 la pelota y d\u00f3nde est\u00e1 la paleta, por lo que la IA consulta esa informaci\u00f3n. <\/li>\n<li>La parte Think tambi\u00e9n consiste en dos operadores if. Ellos encapsulan dos decisiones, que en este caso son mutuamente excluyentes. Como resultado, se selecciona una de tres acciones: mover la paleta a la izquierda, moverla a la derecha o no hacer nada si ya est\u00e1 en la posici\u00f3n correcta.<\/li>\n<li>La parte Act se encuentra en los operadores Mover Paleta a la Izquierda y Mover Paleta a la Derecha. Dependiendo del dise\u00f1o del juego, pueden mover la paleta instant\u00e1neamente o a una velocidad determinada. <\/li>\n<\/ul>\n<p>\nEste tipo de enfoques se llama reactivos: hay un conjunto simple de reglas (en este caso, los operadores if en el c\u00f3digo) que reaccionan al estado actual del mundo y act\u00faan.<\/p>\n<h3>\u00c1rbol de decisiones<\/h3>\n<p>\nEl ejemplo del juego Pong equivale en realidad al concepto formal de IA llamado \u00e1rbol de decisiones. El algoritmo lo atraviesa para llegar a la \"hoja\": una decisi\u00f3n sobre qu\u00e9 acci\u00f3n tomar.<\/p>\n<p>Hagamos un diagrama de flujo del \u00e1rbol de decisiones para el algoritmo de nuestra paleta:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/d3b7290ba93144967cd849416cd5eef3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCada parte del \u00e1rbol se llama nodo (node) \u2014 la IA utiliza la teor\u00eda de grafos para describir estas estructuras. Hay dos tipos de nodos:<\/p>\n<ul>\n<li>Nodos de decisi\u00f3n: elegir entre dos alternativas bas\u00e1ndose en la verificaci\u00f3n de alguna condici\u00f3n, donde cada alternativa se presenta como un nodo separado.<\/li>\n<li>Nodos terminales: acci\u00f3n a ejecutar, que representa la decisi\u00f3n final.<\/li>\n<\/ul>\n<p>\nEl algoritmo comienza con el primer nodo (la \"ra\u00edz\" del \u00e1rbol). Este toma una decisi\u00f3n sobre qu\u00e9 nodo hijo visitar o realiza una acci\u00f3n almacenada en el nodo y se completa.<\/p>\n<p>\u00bfCu\u00e1l es la ventaja, si el \u00e1rbol de decisiones realiza el mismo trabajo que los operadores if en la secci\u00f3n anterior? Aqu\u00ed hay un sistema com\u00fan donde cada decisi\u00f3n tiene solo una condici\u00f3n y dos resultados posibles. Esto permite al desarrollador crear inteligencia artificial a partir de datos que representan decisiones en el \u00e1rbol, evitando su codificaci\u00f3n r\u00edgida. Imagin\u00e9moslo en forma de tabla:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/6875293a60ff9d0efa26fb5e1aa4b21c.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn el lado del c\u00f3digo, tendr\u00e1s un sistema para leer las filas. Crea un nodo para cada una de ellas, conecta la l\u00f3gica de toma de decisiones basada en la segunda columna y los nodos hijos basados en la tercera y cuarta columna. A\u00fan necesitar\u00e1s programar las condiciones y acciones, pero ahora la estructura del juego ser\u00e1 m\u00e1s compleja. En ella a\u00f1adir\u00e1s decisiones y acciones adicionales, y luego configurar\u00e1s toda la IA simplemente editando un archivo de texto que define el \u00e1rbol. Luego, pasas el archivo al dise\u00f1ador de juegos, quien podr\u00e1 modificar el comportamiento sin recompilar el juego ni cambiar el c\u00f3digo.<\/p>\n<p>Los \u00e1rboles de decisiones son muy \u00fatiles cuando se construyen autom\u00e1ticamente a partir de un gran conjunto de ejemplos (por ejemplo, utilizando el algoritmo ID3). Esto los convierte en una herramienta eficiente y de alto rendimiento para clasificar situaciones basadas en los datos obtenidos. Sin embargo, salimos del \u00e1mbito de un simple sistema para la selecci\u00f3n de acciones por parte de los agentes.<\/p>\n<h3>Escenarios<\/h3>\n<p>\nHemos discutido el sistema del \u00e1rbol de decisiones que utilizaba condiciones y acciones predefinidas. La persona que dise\u00f1a la IA puede organizar el \u00e1rbol como desee, pero todav\u00eda debe depender del programador que lo codific\u00f3. \u00bfQu\u00e9 pasar\u00eda si pudi\u00e9ramos darle al dise\u00f1ador herramientas para crear sus propias condiciones o acciones?<\/p>\n<p>Para que el programador no tenga que escribir c\u00f3digo para las condiciones Is Ball Left Of Paddle e Is Ball Right Of Paddle, puede crear un sistema en el que el dise\u00f1ador escriba las condiciones para verificar esos valores. Entonces, los datos del \u00e1rbol de decisiones se ver\u00edan as\u00ed:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/8e77f7c3410d097e8b7d8e1209355cc6.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn esencia, es lo mismo que en la primera tabla, pero las soluciones internas tienen su propio c\u00f3digo, algo similar a la parte condicional de un operador if. En el c\u00f3digo, esto se leer\u00eda en la segunda columna para los nodos de decisi\u00f3n, pero en lugar de buscar una condici\u00f3n espec\u00edfica para ejecutar (\u00bfEst\u00e1 la bola a la izquierda de la paleta?), eval\u00faa la expresi\u00f3n condicional y devuelve verdadero o falso seg\u00fan corresponda. Esto se hace usando un lenguaje de scripting como Lua o Angelscript, permitiendo al desarrollador trabajar con objetos en su juego (bola y paleta) y crear variables que ser\u00e1n accesibles en el script (bola.posici\u00f3n). Adem\u00e1s, el lenguaje de scripting es m\u00e1s simple que C++. No requiere un proceso completo de compilaci\u00f3n, lo que lo hace ideal para ajustes r\u00e1pidos en la l\u00f3gica del juego y permite a los<\/p>\n<p>programadores\" crear las funciones necesarias por s\u00ed mismos.<\/p>\n<p>Se puede ir a\u00fan m\u00e1s lejos y escribir completamente el \u00e1rbol de decisiones en el lenguaje de scripting. Este ser\u00eda un c\u00f3digo compuesto de operadores condicionales programados de manera fija (hardcoded), pero estar\u00edan en archivos de script externos, es decir, podr\u00edan ser modificados sin recompilar todo el programa. A menudo es posible cambiar el archivo de script en tiempo real durante el juego, para probar r\u00e1pidamente diferentes reacciones de la IA.<\/p>\n<h3>Reacci\u00f3n a eventos<\/h3>\n<p>\nLos ejemplos anteriores son perfectos para Pong. Ejecutan continuamente el ciclo Sensar\/Pensar\/Actuar y act\u00faan seg\u00fan el \u00faltimo estado del mundo. Pero en juegos m\u00e1s complejos, es necesario reaccionar a eventos individuales, en lugar de evaluar todo de una vez. Pong, en tal caso, ya no es un buen ejemplo. Tomemos otro. <\/p>\n<p>Imagina un shooter en el que los enemigos permanecen inm\u00f3viles hasta que detectan al jugador, tras lo cual act\u00faan dependiendo de su \u201cespecializaci\u00f3n\u201d: algunos correr\u00e1n para \u201catacar\u201d, otros atacar\u00e1n desde lejos. Esta sigue siendo una base de sistema reactivo: \u201csi se ve al jugador, haz algo\u201d, pero se puede dividir l\u00f3gicamente en el evento Jugador Visto (jugador detectado) y la reacci\u00f3n (selecciona una respuesta y ejec\u00fatala).<\/p>\n<p>Esto nos lleva de vuelta al ciclo Sensar\/Pensar\/Actuar. Podemos codificar la parte de Sensar, que revisar\u00e1 en cada cuadro si la IA ve al jugador. Si no, no pasa nada, pero si lo ve, se crea un evento Jugador Visto. El c\u00f3digo tendr\u00e1 una secci\u00f3n separada que dir\u00e1: \u00abcuando se produzca el evento Jugador Visto, haz\u00bb, donde  ser\u00e1 la respuesta que necesitas para dirigirte a las partes Pensar y Actuar. As\u00ed, configurar\u00e1s las reacciones al evento Jugador Visto: para un personaje que carga, ser\u00e1 CargarYAtacar, y para un francotirador, EsconderYDisparar. Estas conexiones se pueden crear en un archivo de datos para una edici\u00f3n r\u00e1pida sin necesidad de recompilar. Y aqu\u00ed tambi\u00e9n se puede usar un lenguaje de scripts.<\/p>\n<h2>Tomar decisiones complejas<\/h2>\n<p>\nAunque los sistemas de reacciones simples son muy efectivos, hay muchas situaciones en las que no son suficientes. A veces es necesario tomar diferentes decisiones basadas en lo que el agente est\u00e1 haciendo en ese momento, pero representarlo como una condici\u00f3n es dif\u00edcil. A veces hay demasiadas condiciones para representarlas de manera efectiva en un \u00e1rbol de decisiones o un script. A veces es necesario evaluar de antemano c\u00f3mo cambiar\u00e1 la situaci\u00f3n antes de tomar una decisi\u00f3n sobre el siguiente paso. Para abordar estos problemas se requieren enfoques m\u00e1s complejos.<\/p>\n<h3>M\u00e1quina de estados finitos<\/h3>\n<p>\nUna m\u00e1quina de estados finitos o FSM (m\u00e1quina de estados finitos) es una forma de decir que nuestro agente se encuentra actualmente en uno de varios estados posibles, y que puede pasar de un estado a otro. Hay un n\u00famero definido de tales estados, de ah\u00ed el nombre. El mejor ejemplo de la vida real es un sem\u00e1foro. En diferentes lugares hay diferentes secuencias de luces, pero el principio es el mismo: cada estado representa algo (detenerse, ir, etc.). El sem\u00e1foro solo est\u00e1 en un estado en cualquier momento dado y cambia de uno a otro basado en reglas simples.<\/p>\n<p>Con los NPC en los juegos, la historia es similar. Tomemos como ejemplo un guardia con los siguientes estados:<\/p>\n<ul>\n<li>Patrullando (Patrolling).<\/li>\n<li>Atacando (Attacking).<\/li>\n<li>Huyendo (Fleeing).<\/li>\n<\/ul>\n<p>\nY con estas condiciones para cambiar su estado:<\/p>\n<ul>\n<li>Si el guardia ve a un enemigo, ataca.<\/li>\n<li>Si el guardia ataca, pero ya no ve al enemigo, vuelve a patrullar.<\/li>\n<li>Si el guardia ataca, pero est\u00e1 gravemente herido, huye.<\/li>\n<\/ul>\n<p>\nTambi\u00e9n se pueden escribir operadores if con variables de estado del guardia y diversas comprobaciones: si hay enemigos cercanos, cu\u00e1l es el nivel de salud del NPC, etc. Agreguemos algunos estados m\u00e1s:<\/p>\n<ul>\n<li>Inactividad (Idling) \u2014 entre patrullas.<\/li>\n<li>B\u00fasqueda (Searching) \u2014 cuando un enemigo avistado se ha ocultado.<\/li>\n<li>Pedir ayuda (Finding Help) \u2014 cuando un enemigo es detectado, pero es demasiado fuerte para luchar solo.<\/li>\n<\/ul>\n<p>\nLas opciones para cada uno est\u00e1n limitadas; por ejemplo, el guardia no buscar\u00e1 al enemigo oculto si tiene poca salud.<\/p>\n<p>Al final, una gran lista de &laquo;si &lt;x \u0438 y, \u043d\u043e \u043d\u0435 z&gt;, entonces &lt;p&gt;&raquo; puede volverse demasiado extensa, por lo que es necesario formalizar un m&eacute;todo que nos permita mantener en mente los estados y las transiciones entre ellos. Para hacer esto, consideraremos todos los estados y bajo cada estado anotaremos en una lista todas las transiciones a otros estados, junto con las condiciones necesarias para ellas.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/ba4c401aa20de3d22d2478cba5a4b1ec.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEsta es una tabla de transiciones de estados: una forma compleja de representar una FSM. Dibujemos un diagrama y obtendremos una visi\u00f3n completa de c\u00f3mo cambia el comportamiento del NPC.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/b4182359983cf573872dacc575af13dc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEl diagrama refleja la esencia de la toma de decisiones para este agente basada en la situaci\u00f3n actual. Adem\u00e1s, cada flecha muestra una transici\u00f3n entre estados si la condici\u00f3n al lado de ella es verdadera.<\/p>\n<p>En cada actualizaci\u00f3n verificamos el estado actual del agente, revisamos la lista de transiciones y si se cumplen las condiciones para la transici\u00f3n, asume un nuevo estado. Por ejemplo, cada frame se verifica si el temporizador de 10 segundos ha expirado, y si es as\u00ed, el guardia pasa de Idling a Patrolling. De la misma manera, el estado Attacking verifica la salud del agente; si es baja, pasa al estado Fleeing.<\/p>\n<p>Esto es el manejo de transiciones entre estados, pero \u00bfqu\u00e9 pasa con el comportamiento relacionado con los propios estados? En cuanto a la implementaci\u00f3n del comportamiento real para un estado espec\u00edfico, generalmente hay dos tipos de \"ganchos\" donde asignamos acciones a la FSM:<\/p>\n<ul>\n<li>Acciones que realizamos peri\u00f3dicamente para el estado actual.<\/li>\n<li>Acciones que emprendemos al transitar de un estado a otro.<\/li>\n<\/ul>\n<p>\nEjemplos del primer tipo. El estado Patrolling mover\u00e1 al agente por la ruta de patrulla en cada frame. El estado Attacking intentar\u00e1 iniciar un ataque o cambiar a un estado en el que esto sea posible en cada frame.<\/p>\n<p>Para el segundo tipo, consideremos la transici\u00f3n: \"si el enemigo es visible y el enemigo es demasiado fuerte, entonces pasar al estado Finding Help.\" El agente debe elegir a d\u00f3nde ir en busca de ayuda y guardar esta informaci\u00f3n para que el estado Finding Help sepa a d\u00f3nde acudir. Una vez que se encuentra ayuda, el agente regresa al estado Attacking. En ese momento, querr\u00e1 informar a su aliado sobre la amenaza, por lo que puede surgir la acci\u00f3n NotifyFriendOfThreat.<\/p>\n<p>Una vez m\u00e1s, podemos ver este sistema a trav\u00e9s del ciclo Sense\/Think\/Act. Sense se manifiesta en los datos utilizados por la l\u00f3gica de transici\u00f3n. Think son las transiciones disponibles en cada estado. Y Act se lleva a cabo a trav\u00e9s de las acciones que se realizan peri\u00f3dicamente dentro del estado o durante las transiciones entre estados.<\/p>\n<p>A veces, la encuesta continua de las condiciones de transici\u00f3n puede ser costosa. Por ejemplo, si cada agente realiza c\u00e1lculos complejos en cada fotograma para determinar si ve enemigos y entender si puede pasar del estado Patrolling a Attacking, podr\u00eda consumir mucho tiempo de CPU. <\/p>\n<p>Los cambios importantes en el estado del mundo pueden considerarse eventos que se manejar\u00e1n a medida que ocurran. En lugar de que la FSM verifique en cada fotograma la condici\u00f3n de transici\u00f3n \"\u00bfpuede mi agente ver al jugador?\", se puede configurar un sistema separado para realizar las verificaciones con menos frecuencia (por ejemplo, 5 veces por segundo). Y el resultado ser\u00eda emitir Player Seen cuando la verificaci\u00f3n pasa. <\/p>\n<p>Esto se pasa a la FSM, que ahora debe pasar a la condici\u00f3n de evento Player Seen recibido y responder adecuadamente. El comportamiento final es el mismo, excepto por una casi imperceptible demora antes de la respuesta. Sin embargo, el rendimiento ha mejorado como resultado de separar parte de Sense en una parte independiente del programa.<\/p>\n<h3>M\u00e1quina de estados finitos jer\u00e1rquica<\/h3>\n<p>\nSin embargo, trabajar con grandes FSM no siempre es conveniente. Si quisi\u00e9ramos ampliar el estado de ataque, reemplaz\u00e1ndolo por MeleeAttacking (cuerpo a cuerpo) y RangedAttacking (a distancia), tendr\u00edamos que cambiar las transiciones de todos los dem\u00e1s estados que conducen al estado Attacking (tanto actuales como futuros).<\/p>\n<p>Seguramente habr\u00e1s notado que en nuestro ejemplo hay muchas transiciones duplicadas. La mayor\u00eda de las transiciones en estado de Idling son id\u00e9nticas a las transiciones en estado de Patrolling. Ser\u00eda ideal no repetirnos, especialmente si a\u00f1adimos m\u00e1s estados similares. Tiene sentido agrupar Idling y Patrolling bajo una etiqueta com\u00fan de \"no combativa\", donde solo hay un conjunto com\u00fan de transiciones a los estados de combate. Si consideramos esta etiqueta como un estado, Idling y Patrolling se convertir\u00edan en subestados. Ejemplo de uso de una tabla de transiciones separada para un nuevo subestado no combatiente:<\/p>\n<p><i>Estados principales:<\/i><br \/>\n<img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/d86dd918acbe81b9bf22c2fb34aecee3.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\n<i>Estado fuera de combate:<\/i><br \/>\n<img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/9d5bc2053010a32c5f68d7f0192c04ed.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nY en forma de diagrama:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/0ccf95ecafa9ce2a6ea5b5b9833ddc4f.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEste es el mismo sistema, pero con un nuevo estado no combatiente que incluye Idling y Patrolling. Con cada estado conteniendo un FSM con subestados (y estos subestados, a su vez, contienen sus propios FSM \u2014 y as\u00ed sucesivamente tantas veces como necesites), obtenemos una M\u00e1quina de Estados Finitos Jer\u00e1rquica o HFSM (m\u00e1quina de estados finitos jer\u00e1rquica). Al agrupar el estado no combatiente, hemos eliminado un mont\u00f3n de transiciones redundantes. Lo mismo podemos hacer para cualquier nuevo estado con transiciones comunes. Por ejemplo, si en el futuro ampliamos el estado Attacking a los estados MeleeAttacking y MissileAttacking, estos ser\u00e1n subestados que transicionan entre s\u00ed en funci\u00f3n de la distancia al enemigo y la disponibilidad de municiones. Como resultado, los modelos de comportamiento complejos y los submodelos de comportamiento se pueden representar con un m\u00ednimo de transiciones duplicadas.<\/p>\n<h3>\u00c1rbol de comportamientos<\/h3>\n<p>\nCon HFSM se crean combinaciones complejas de comportamientos de manera sencilla. Sin embargo, hay una peque\u00f1a dificultad, ya que la toma de decisiones en forma de reglas de transici\u00f3n est\u00e1 fuertemente vinculada al estado actual. Y en muchos juegos, esto es justo lo que se necesita. Un uso meticuloso de la jerarqu\u00eda de estados puede reducir la cantidad de repeticiones en las transiciones. Pero a veces se requieren reglas que funcionen independientemente del estado en el que te encuentres o que se apliquen casi en cualquier estado. Por ejemplo, si la salud del agente cae al 25%, querr\u00e1s que huya independientemente de si ha estado en combate, ocioso o conversando; tendr\u00e1s que a\u00f1adir esta condici\u00f3n en cada estado. Y si tu dise\u00f1ador quiere m\u00e1s tarde cambiar el umbral de baja salud del 25% al 10%, tendr\u00e1s que lidiar con ello nuevamente.<\/p>\n<p>Idealmente, para esta situaci\u00f3n se necesita un sistema en el que las decisiones sobre 'qu\u00e9 estado adoptar' est\u00e9n fuera de los propios estados, de modo que los cambios se realicen solo en un lugar sin alterar las condiciones de transici\u00f3n. Aqu\u00ed es donde aparecen los \u00e1rboles de comportamiento.<\/p>\n<p>Existen varias formas de implementarlos, pero la esencia para todos es aproximadamente la misma y se asemeja a un \u00e1rbol de decisiones: el algoritmo comienza desde un nodo 'ra\u00edz', y en el \u00e1rbol hay nodos que representan decisiones o acciones. Sin embargo, hay algunas diferencias clave:<\/p>\n<ul>\n<li>Ahora los nodos devuelven uno de tres valores: Succeeded (si la tarea se complet\u00f3), Failed (si no se puede iniciar) o Running (si todav\u00eda est\u00e1 en ejecuci\u00f3n y no hay un resultado final).<\/li>\n<li>Ya no hay nodos de decisi\u00f3n para elegir entre dos alternativas. En su lugar, hay nodos Decorator, que tienen un solo nodo hijo. Si tienen \u00e9xito, ejecutan su \u00fanico nodo hijo.<\/li>\n<li>Los nodos que realizan acciones devuelven el valor Running para indicar que las acciones est\u00e1n en curso.<\/li>\n<\/ul>\n<p>\nEste peque\u00f1o conjunto de nodos se puede combinar para crear una gran cantidad de modelos de comportamiento complejos. Imaginemos el HFSM de un guardia del ejemplo anterior como un \u00e1rbol de comportamiento:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/5eaa5c725e4ada8285f16f95bb206d53.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nCon esta estructura, no deber\u00eda haber una transici\u00f3n expl\u00edcita de los estados Idling\/Patrolling al estado Attacking o a cualquier otro. Si el enemigo es visible y la salud del personaje es baja, la ejecuci\u00f3n se detendr\u00e1 en el nodo Fleeing, sin importar qu\u00e9 nodo estaba ejecutando anteriormente: Patrolling, Idling, Attacking o cualquiera otro.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/e1c1dcc2055174aa7cfa846364b1709a.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nLos \u00e1rboles de comportamiento son complejos: hay muchas maneras de construirlos, y encontrar la combinaci\u00f3n adecuada de decoradores y nodos compuestos puede ser problem\u00e1tico. Tambi\u00e9n hay preguntas sobre con qu\u00e9 frecuencia se debe revisar el \u00e1rbol: \u00bfqueremos revisarlo en cada parte o solo cuando cambia una de las condiciones? \u00bfC\u00f3mo almacenar el estado relacionado con los nodos: c\u00f3mo saber cu\u00e1ndo estuvimos en estado Idling durante 10 segundos o c\u00f3mo saber qu\u00e9 nodos se ejecutaron la \u00faltima vez para manejar correctamente la secuencia?<\/p>\n<p>Es por eso que existen muchas implementaciones. Por ejemplo, en algunos sistemas, los nodos decoradores han sido reemplazados por decoradores integrados. Estos reeval\u00faan el \u00e1rbol cuando las condiciones del decorador cambian, ayudan a conectar nodos y proporcionan actualizaciones peri\u00f3dicas.<\/p>\n<h3>Sistema basado en utilidad<\/h3>\n<p>\nAlgunos juegos tienen una variedad de mec\u00e1nicas diferentes. Es deseable que obtengan todas las ventajas de las reglas de transici\u00f3n simples y generales, pero no necesariamente en forma de un \u00e1rbol completo de comportamiento. En lugar de tener un conjunto claro de elecciones o un \u00e1rbol de acciones posibles, es m\u00e1s sencillo estudiar todas las acciones y elegir la m\u00e1s adecuada en ese momento.<\/p>\n<p>Un sistema basado en utilidad ayudar\u00e1 en esto. Es un sistema donde el agente tiene m\u00faltiples acciones y \u00e9l mismo elige cu\u00e1l realizar, bas\u00e1ndose en la utilidad relativa de cada una. Donde la utilidad es una medida arbitraria de cu\u00e1n importante o deseable es ejecutar esa acci\u00f3n para el agente. <\/p>\n<p>La utilidad calculada de una acci\u00f3n, basada en el estado actual y el entorno, puede ser verificada por el agente y puede elegir el estado alternativo m\u00e1s adecuado en cualquier momento. Esto es similar a un FSM, salvo que las transiciones se determinan por la evaluaci\u00f3n de cada estado potencial, incluyendo el actual. Tenga en cuenta que elegimos la acci\u00f3n m\u00e1s \u00fatil para la transici\u00f3n (o nos quedamos si ya la hemos ejecutado). Para mayor variedad, esto puede ser una elecci\u00f3n ponderada, pero aleatoria de una peque\u00f1a lista.<\/p>\n<p>El sistema asigna un rango arbitrario de valores de utilidad, por ejemplo, de 0 (totalmente indeseable) a 100 (completamente deseable). Cada acci\u00f3n tiene un conjunto de par\u00e1metros que influyen en el c\u00e1lculo de este valor. Volviendo a nuestro ejemplo del guardia:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/085fb2c197bde93d78455d18e63c9c25.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nLas transiciones entre acciones son ambiguas: cualquier estado puede seguir a cualquier otro. Las prioridades de las acciones est\u00e1n en los valores de utilidad devueltos. Si un enemigo es visible y este enemigo es fuerte, mientras que la salud del personaje es baja, tanto Fleeing como FindingHelp devolver\u00e1n altos valores no nulos. Sin embargo, FindingHelp siempre ser\u00e1 m\u00e1s alto. De esta manera, las acciones no relacionadas con el combate nunca devuelven m\u00e1s de 50, por lo que siempre ser\u00e1n inferiores a las de combate. Esto debe tenerse en cuenta al crear acciones y calcular su utilidad.<\/p>\n<p>En nuestro ejemplo, las acciones devuelven ya sea un valor constante fijo o uno de dos valores fijos. Un sistema m\u00e1s realista sugiere devolver una evaluaci\u00f3n de un rango continuo de valores. Por ejemplo, la acci\u00f3n de Huida devuelve valores de utilidad m\u00e1s altos si la salud del agente es baja, mientras que la acci\u00f3n de Ataque devuelve valores m\u00e1s bajos si el enemigo es demasiado fuerte. Debido a esto, la acci\u00f3n de Huida tiene prioridad sobre el Ataque en cualquier situaci\u00f3n en que el agente sienta que no tiene suficiente salud para vencer al oponente. Esto permite cambiar las prioridades de las acciones bas\u00e1ndose en una serie de criterios, lo que hace que este enfoque sea m\u00e1s flexible y variable que un \u00e1rbol de comportamiento o FSM.<\/p>\n<p>Cada acci\u00f3n tiene muchas condiciones para calcular el programa. Estas se pueden escribir en un lenguaje de scripting o como una serie de f\u00f3rmulas matem\u00e1ticas. En The Sims, que modela la rutina diaria de un personaje, se a\u00f1ade un nivel adicional de c\u00e1lculos: el agente recibe una serie de 'motivaciones' que afectan las evaluaciones de utilidad. Si el personaje tiene hambre, con el tiempo tendr\u00e1 a\u00fan m\u00e1s hambre, y el resultado de utilidad de la acci\u00f3n ComerComida aumentar\u00e1 hasta que el personaje la realice, reduciendo su nivel de hambre y devolviendo el valor de ComerComida a cero. <\/p>\n<p>La idea de elegir acciones basadas en un sistema de puntuaci\u00f3n es bastante simple, por lo que un sistema basado en la utilidad se puede utilizar como parte de los procesos de toma de decisiones de IA, y no como un reemplazo completo. Un \u00e1rbol de decisiones puede solicitar la evaluaci\u00f3n de utilidad de dos nodos hijos y elegir el de mayor puntuaci\u00f3n. De manera similar, un \u00e1rbol de comportamiento puede tener un nodo compuesto de Utilidad para evaluar la utilidad de las acciones y decidir cu\u00e1l elemento hijo ejecutar.<\/p>\n<h2>Movimiento y navegaci\u00f3n<\/h2>\n<p>\nEn los ejemplos anteriores ten\u00edamos una plataforma que mov\u00edamos hacia la izquierda o hacia la derecha, y un guardi\u00e1n que patrullaba o atacaba. Pero, \u00bfc\u00f3mo manejamos el movimiento del agente durante un per\u00edodo de tiempo determinado? \u00bfC\u00f3mo establecemos la velocidad, c\u00f3mo evitamos obst\u00e1culos y c\u00f3mo planificamos una ruta si llegar al destino es m\u00e1s complicado que simplemente moverse en l\u00ednea recta? Vamos a analizarlo.<\/p>\n<h3>Gesti\u00f3n<\/h3>\n<p>\nEn la etapa inicial, asumiremos que cada agente tiene un valor de velocidad que incluye qu\u00e9 tan r\u00e1pido se mueve y en qu\u00e9 direcci\u00f3n. Puede medirse en metros por segundo, kil\u00f3metros por hora, p\u00edxeles por segundo, etc. Recordando el ciclo Sensar\/Pensar\/Actuar, podemos imaginar que la parte de Pensar elige la velocidad y la parte de Actuar aplica esta velocidad al agente. Normalmente, en los juegos hay un sistema f\u00edsico que realiza esta tarea por usted, evaluando el valor de velocidad de cada objeto y ajust\u00e1ndolo. Por lo tanto, se puede dejar que la IA tenga una sola tarea: decidir qu\u00e9 velocidad debe tener el agente. Si se sabe d\u00f3nde debe estar el agente, se debe mover en la direcci\u00f3n correcta a la velocidad establecida. Una ecuaci\u00f3n muy trivial:<\/p>\n<p><i>desired_travel = destination_position \u2013 agent_position<\/i><\/p>\n<p>Imagina un mundo 2D. El agente se encuentra en el punto (-2,-2), el destino est\u00e1 en alguna parte al noreste en el punto (30, 20), y la ruta necesaria para que el agente llegue all\u00ed es (32, 22). Supongamos que estas posiciones se miden en metros; si tomamos la velocidad del agente como 5 metros por segundo, entonces escalaremos nuestro vector de movimiento y obtendremos una velocidad de aproximadamente (4.12, 2.83). Con estos par\u00e1metros, el agente llegar\u00eda a su destino en casi 8 segundos.<\/p>\n<p>Los valores se pueden recalcular en cualquier momento. Si el agente est\u00e1 a mitad de camino hacia el objetivo, el movimiento ser\u00eda la mitad de la longitud, pero como la velocidad m\u00e1xima del agente es de 5 m\/s (lo decidimos anteriormente), la velocidad ser\u00e1 la misma. Esto tambi\u00e9n funciona para objetivos en movimiento, permitiendo al agente realizar peque\u00f1os ajustes a medida que se mueven.<\/p>\n<p>Pero queremos m\u00e1s variabilidad; por ejemplo, aumentar la velocidad lentamente para simular un personaje que pasa de estar de pie a correr. Lo mismo se puede hacer al final antes de detenerse. Estas caracter\u00edsticas se conocen como comportamientos de direcci\u00f3n, cada uno de los cuales tiene nombres espec\u00edficos: Buscar (Seek), Huir (Flee), Llegada (Arrival), etc. La idea es que las fuerzas de aceleraci\u00f3n pueden aplicarse a la velocidad del agente, bas\u00e1ndose en la comparaci\u00f3n de la posici\u00f3n del agente y su velocidad actual con respecto al destino, para utilizar diferentes m\u00e9todos de movimiento hacia el objetivo.<\/p>\n<p>Cada comportamiento tiene un objetivo ligeramente diferente. Seek y Arrival son formas de mover al agente hacia un destino. Obstacle Avoidance (evitaci\u00f3n de obst\u00e1culos) y Separation (separaci\u00f3n) ajustan el movimiento del agente para sortear obst\u00e1culos en su camino hacia el objetivo. Alignment (alineaci\u00f3n) y Cohesion (cohesi\u00f3n) mantienen a los agentes juntos durante su movimiento. Cualquier n\u00famero de diferentes comportamientos de direcci\u00f3n puede sumarse para obtener un solo vector que considere todos los factores. Un agente utiliza los comportamientos Arrival, Separation y Obstacle Avoidance para mantenerse alejado de las paredes y otros agentes. Este enfoque funciona bien en espacios abiertos sin detalles adicionales. <\/p>\n<p>En condiciones m\u00e1s dif\u00edciles, la combinaci\u00f3n de diferentes comportamientos funciona peor; por ejemplo, un agente puede quedar atrapado en una pared debido al conflicto entre Arrival y Obstacle Avoidance. Por lo tanto, se deben considerar opciones que sean m\u00e1s complejas que simplemente sumar todos los valores. Una forma de hacerlo es, en lugar de sumar los resultados de cada comportamiento, considerar el movimiento en diferentes direcciones y elegir la mejor opci\u00f3n. <\/p>\n<p>Sin embargo, en un entorno complejo con callejones sin salida y decisiones sobre hacia d\u00f3nde ir, necesitaremos algo a\u00fan m\u00e1s avanzado.<\/p>\n<h3>B\u00fasqueda de caminos<\/h3>\n<p>\nLos comportamientos de direcci\u00f3n son ideales para movimientos simples en espacios abiertos (un campo de f\u00fatbol o una arena), donde ir de A a B es un camino directo con peque\u00f1as desviaciones alrededor de obst\u00e1culos. Para rutas m\u00e1s complejas, necesitamos pathfinding (b\u00fasqueda de caminos), que es una forma de explorar el mundo y tomar decisiones sobre la ruta a seguir.<\/p>\n<p>La forma m\u00e1s simple es superponer una cuadr\u00edcula sobre cada celda adyacente al agente y evaluar en cu\u00e1les se permite moverse. Si alguna de ellas es un destino, siga desde all\u00ed la ruta de cada celda a la anterior hasta que llegue al inicio. Esa es la ruta. De lo contrario, repita el proceso con las celdas m\u00e1s cercanas hasta que encuentre el destino o se agoten las celdas (lo que indica que no hay ruta posible). Esto se conoce formalmente como B\u00fasqueda en Amplitud o BFS (Breadth-First Search). En cada paso, mira en todas las direcciones (de ah\u00ed lo de amplitud). El espacio de b\u00fasqueda se asemeja a un frente de ola que se desplaza hasta alcanzar el lugar buscado: el \u00e1rea de b\u00fasqueda se expande en cada paso hasta que se alcanza el punto final, despu\u00e9s de lo cual se puede rastrear el camino de vuelta al inicio.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/d367e62bc53033b05388538649853a41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nComo resultado, obtendr\u00e1 una lista de celdas a trav\u00e9s de las cuales se compone la ruta necesaria. Este es el camino (de ah\u00ed el t\u00e9rmino pathfinding) \u2014 una lista de lugares que el agente visitar\u00e1 al dirigirse al destino.<\/p>\n<p>Dado que conocemos la posici\u00f3n de cada celda en el mundo, se pueden usar comportamientos de direcci\u00f3n para moverse por el camino \u2014 de nodo 1 a nodo 2, luego de nodo 2 a nodo 3, y as\u00ed sucesivamente. La opci\u00f3n m\u00e1s simple es dirigirse al centro de la siguiente celda, pero es a\u00fan mejor detenerse a mitad de arista entre la celda actual y la siguiente. Esto permitir\u00e1 al agente recortar esquinas en giros cerrados.<\/p>\n<p>El algoritmo BFS tiene desventajas: explora tantas celdas en la direcci\u00f3n \"incorrecta\" como en la \"correcta\". Aqu\u00ed es donde aparece un algoritmo m\u00e1s sofisticado llamado A* (A estrella). Funciona de manera similar, pero en lugar de explorar ciegamente las celdas vecinas (luego las vecinas de las vecinas, y as\u00ed sucesivamente), recopila nodos en una lista y los organiza de tal manera que el siguiente nodo a investigar siempre sea el que conducir\u00e1 al camino m\u00e1s corto. Los nodos se ordenan en funci\u00f3n de una heur\u00edstica que toma en cuenta dos cosas: el \"costo\" de la ruta hipot\u00e9tica hacia la celda deseada (incluyendo cualquier costo de movimiento) y una estimaci\u00f3n de qu\u00e9 tan lejos est\u00e1 esa celda del destino (dirigiendo la b\u00fasqueda en la direcci\u00f3n correcta).<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/1cab4f53fa5af6b31d352c7bcf453d7e.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEn este ejemplo se muestra que el agente explora un cuadrado a la vez, eligiendo cada vez el vecino que es m\u00e1s prometedor. El camino resultante es el mismo que en el BFS, pero se consideraron menos cuadrados en el proceso, lo que tiene un gran impacto en el rendimiento del juego.<\/p>\n<h3>Movimiento sin rejilla<\/h3>\n<p>\nPero la mayor\u00eda de los juegos no est\u00e1n dispuestos en rejilla, y a menudo no se puede hacer sin comprometer el realismo. Se requieren compromisos. \u00bfQu\u00e9 tama\u00f1o deber\u00edan tener los cuadrados? Si son demasiado grandes, no podr\u00e1n representar correctamente pasillos o giros peque\u00f1os; si son demasiado peque\u00f1os, habr\u00e1 demasiados cuadrados para buscar, lo que finalmente tomar\u00e1 mucho tiempo.<\/p>\n<p>Lo primero que hay que entender es que la rejilla nos da un gr\u00e1fico de nodos interconectados. Los algoritmos A* y BFS trabajan en gr\u00e1ficos y no se preocupan en absoluto por nuestra rejilla. Podr\u00edamos colocar nodos en cualquier lugar del mundo del juego: siempre que haya conexi\u00f3n entre dos nodos conectados, as\u00ed como entre el punto de inicio y el de destino y al menos uno de los nodos, el algoritmo funcionar\u00e1 tan bien como antes. Esto se conoce a menudo como un sistema de puntos de referencia (waypoint), ya que cada nodo representa una posici\u00f3n significativa en el mundo que puede ser parte de cualquiera de varios caminos hipot\u00e9ticos.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/d87e9d4bb2a2fc713d32abc158506eaa.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ejemplo 1: un nodo en cada cuadrado. La b\u00fasqueda comienza desde el nodo en el que se encuentra el agente y termina en el nodo del cuadrado requerido.<\/i><\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/b535a5db805efdc427d7c5724b866982.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<i>Ejemplo 2: un conjunto m\u00e1s peque\u00f1o de nodos (puntos de referencia). La b\u00fasqueda comienza en el cuadrado con el agente, pasa por el n\u00famero necesario de nodos y luego contin\u00faa hasta el destino.<\/i><\/p>\n<p>Este es un sistema bastante flexible y potente. Pero se necesita cierta precauci\u00f3n en las decisiones sobre d\u00f3nde y c\u00f3mo colocar el waypoint, de lo contrario, los agentes pueden simplemente no ver el punto m\u00e1s cercano y no podr\u00e1n comenzar el camino. Ser\u00eda m\u00e1s sencillo si pudi\u00e9ramos colocar autom\u00e1ticamente los puntos de referencia en funci\u00f3n de la geometr\u00eda del mundo.<\/p>\n<p>Aqu\u00ed es donde entra en juego el navigation mesh o navmesh (rejilla de navegaci\u00f3n). Esta es generalmente una rejilla 2D de tri\u00e1ngulos que se superpone a la geometr\u00eda del mundo, en todas partes donde se permite que el agente camine. Cada uno de los tri\u00e1ngulos de la rejilla se convierte en un nodo en el gr\u00e1fico y tiene hasta tres tri\u00e1ngulos adyacentes que se convierten en nodos vecinos en el gr\u00e1fico. <\/p>\n<p>Esta imagen es un ejemplo del motor Unity: ha analizado la geometr\u00eda del mundo y ha creado un navmesh (en la captura de pantalla de color azul claro). Cada pol\u00edgono en el navmesh es un \u00e1rea donde un agente puede estar de pie o moverse de un pol\u00edgono a otro. En este ejemplo, los pol\u00edgonos son m\u00e1s peque\u00f1os que los pisos en los que se encuentran, para tener en cuenta los tama\u00f1os del agente que sobresalen de su posici\u00f3n nominal.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/845705ba7b9a9d469203aedf7942da41.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nPodemos buscar una ruta a trav\u00e9s de esta cuadr\u00edcula, utilizando nuevamente el algoritmo A*. Esto nos dar\u00e1 una ruta pr\u00e1cticamente ideal en el mundo, que tiene en cuenta toda la geometr\u00eda y, al mismo tiempo, no requiere nodos adicionales ni la creaci\u00f3n de puntos de referencia.<\/p>\n<p>La b\u00fasqueda de caminos es un tema demasiado extenso que no se puede cubrir en una sola secci\u00f3n de un art\u00edculo. Si desea estudiarlo m\u00e1s a fondo, puede hacerlo a trav\u00e9s del <noindex><a rel=\"nofollow\" href=\"https:\/\/www.redblobgames.com\/pathfinding\/a-star\/introduction.html\">sitio de Amit Patel<\/a><\/noindex>.<\/p>\n<h2>Planificaci\u00f3n<\/h2>\n<p>\nCon la b\u00fasqueda de caminos, hemos visto que a veces no es suficiente simplemente elegir una direcci\u00f3n y avanzar: debemos elegir una ruta y realizar varios giros para llegar a nuestro destino. Podemos generalizar esta idea: alcanzar un objetivo no es solo el siguiente paso, sino toda una secuencia, donde a veces es necesario mirar hacia adelante algunos pasos para saber cu\u00e1l debe ser el primero. Esto se llama planificaci\u00f3n. La b\u00fasqueda de caminos puede considerarse como uno de los varios complementos de la planificaci\u00f3n. Desde el punto de vista de nuestro ciclo Sentir\/Pensar\/Actuar, es donde la parte Pensar planifica varias partes Actuar para el futuro.<\/p>\n<p>Tomemos como ejemplo el juego de cartas Magic: The Gathering. Nosotros jugamos primero con esta mano de cartas:<\/p>\n<ul>\n<li>Pantano \u2014 proporciona 1 man\u00e1 negro (carta de tierra).<\/li>\n<li>Bosque \u2014 proporciona 1 man\u00e1 verde (carta de tierra).<\/li>\n<li>Mago Fugitivo \u2014 requiere 1 man\u00e1 azul para invocarse.<\/li>\n<li>M\u00edstico Elfo \u2014 requiere 1 man\u00e1 verde para invocarse.<\/li>\n<\/ul>\n<p>\nIgnoramos las otras tres cartas para simplificar. Seg\u00fan las reglas, al jugador se le permite jugar 1 carta de tierra por turno, puede 'tapar' esta carta para extraer man\u00e1 de ella y luego usar hechizos (incluyendo invocar criaturas) seg\u00fan la cantidad de man\u00e1. En esta situaci\u00f3n, el jugador sabe que debe jugar Bosque, 'tapar' 1 man\u00e1 verde y luego invocar M\u00edstico Elfo. Pero, \u00bfc\u00f3mo puede adivinar esto la IA del juego?<\/p>\n<h3>Planificaci\u00f3n simple<\/h3>\n<p>\nEl enfoque trivial es probar cada acci\u00f3n por turno hasta que no queden opciones disponibles. Al mirar las cartas, la IA ve que puede jugar Swamp. Y lo juega. \u00bfQuedan otras acciones en este turno? No puede invocar ni a Elvish Mystic ni a Fugitive Wizard, ya que requieren mana verde y azul respectivamente, y Swamp solo proporciona mana negra. Ya no podr\u00e1 jugar Forest porque ya jug\u00f3 Swamp. Por lo tanto, la IA del juego actu\u00f3 de acuerdo con las reglas, pero lo hizo mal. Se puede mejorar.<\/p>\n<p>La planificaci\u00f3n puede encontrar una lista de acciones que llevan el juego al estado deseado. As\u00ed como cada cuadrado en el camino tiene vecinos (en pathfinding), cada acci\u00f3n en el plan tambi\u00e9n tiene vecinos o sucesores. Podemos buscar estas acciones y las subsiguientes hasta que alcancemos el estado deseado.<\/p>\n<p>En nuestro ejemplo, el resultado deseado es \u00abinvocar una criatura, si es posible\u00bb. Al comienzo del turno, solo vemos dos acciones posibles permitidas por las reglas del juego:<\/p>\n<p><i>1. Jugar Swamp (resultado: Swamp en juego)<br \/>\n2. Jugar Forest (resultado: Forest en juego)<\/i><\/p>\n<p>Cada acci\u00f3n tomadas puede conducir a acciones adicionales y cerrar otras, nuevamente dependiendo de las reglas del juego. Imagina que jugamos Swamp; esto eliminar\u00e1 Swamp como siguiente paso (ya lo hemos jugado), y tambi\u00e9n eliminar\u00e1 Forest (porque seg\u00fan las reglas solo se puede jugar una carta de tierra por turno). Despu\u00e9s, la IA a\u00f1ade como siguiente paso \u2013 obtener 1 mana negra, porque no hay otras opciones. Si avanza y elige Tap the Swamp, obtendr\u00e1 1 unidad de mana negra y no podr\u00e1 hacer nada con ella.<\/p>\n<p><i>1. Jugar Swamp (resultado: Swamp en juego)<br \/>\n 1.1 \u00abTapiar\u00bb Swamp (resultado: Swamp \u00abtapada\u00bb, +1 unidad de mana negra)<br \/>\n No hay acciones disponibles \u2013 FIN<br \/>\n2. Jugar Forest (resultado: Forest en juego)<\/i><\/p>\n<p>La lista de acciones es corta, nos hemos estancado. Repetimos el proceso para la siguiente acci\u00f3n. Jugamos Forest, desbloqueamos la acci\u00f3n \u00abobtener 1 mana verde\u00bb, que a su vez abrir\u00e1 una tercera acci\u00f3n: invocar a Elvish Mystic.<\/p>\n<p><i>1. Jugar Swamp (resultado: Swamp en juego)<br \/>\n 1.1 \u00abTapiar\u00bb Swamp (resultado: Swamp \u00abtapada\u00bb, +1 unidad de mana negra)<br \/>\n No hay acciones disponibles \u2013 FIN<br \/>\n2. Jugar Forest (resultado: Forest en juego)<br \/>\n 2.1 \u00abTapiar\u00bb Forest (resultado: Forest \u00abtapada\u00bb, +1 unidad de mana verde)<br \/>\n 2.1.1 Invocar a Elvish Mystic (resultado: Elvish Mystic en juego, -1 unidad de mana verde)<br \/>\n No hay acciones disponibles \u2013 FIN<\/i><\/p>\n<p>Finalmente, hemos explorado todas las acciones posibles y encontramos un plan para invocar una criatura.<\/p>\n<p>Este es un ejemplo muy simplificado. Es preferible elegir el mejor plan posible en lugar de cualquiera que cumpla con ciertos criterios. Por lo general, se pueden evaluar los planes potenciales en funci\u00f3n del resultado final o el beneficio total de su ejecuci\u00f3n. Puedes asignarte 1 punto por jugar una carta de tierra y 3 puntos por invocar una criatura. Jugar un Swamp te dar\u00eda 1 punto. Y jugar un Forest \u2192 Tap the Forest \u2192 invocar un Elvish Mystic te dar\u00eda 4 puntos de inmediato. <\/p>\n<p>As\u00ed es como funciona la planificaci\u00f3n en Magic: The Gathering, pero esta misma l\u00f3gica se aplica en otras situaciones. Por ejemplo, mover un pe\u00f3n para hacer espacio para el movimiento de un alfil en el ajedrez. O esconderse detr\u00e1s de una pared para disparar de forma segura en XCOM. En general, ya entiendes la idea.<\/p>\n<h3>Planificaci\u00f3n mejorada<\/h3>\n<p>\nA veces hay demasiadas acciones potenciales para considerar cada posible opci\u00f3n. Volviendo al ejemplo de Magic: The Gathering: supongamos que en el juego tienes varias cartas de tierra y criaturas en la mano; el n\u00famero de combinaciones posibles de movimientos puede contarse por decenas. Hay varias soluciones al problema.<\/p>\n<p>La primera forma es el backwards chaining (cadena inversa). En lugar de probar todas las combinaciones, es mejor comenzar con el resultado final y tratar de encontrar una ruta directa. En lugar de ir del \u00e1rbol ra\u00edz a una hoja espec\u00edfica, nos movemos en la direcci\u00f3n opuesta: de la hoja a la ra\u00edz. Este m\u00e9todo es m\u00e1s simple y r\u00e1pido.<\/p>\n<p>Si el oponente tiene 1 punto de salud, podemos encontrar un plan para \"infligir 1 o m\u00e1s puntos de da\u00f1o\". Para lograr esto, es necesario cumplir con una serie de condiciones: <\/p>\n<p>1. El da\u00f1o puede ser infligido por un hechizo: debe estar en la mano.<br \/>\n2. Para jugar el hechizo, se necesita man\u00e1.<br \/>\n3. Para obtener man\u00e1, es necesario jugar una carta de tierra.<br \/>\n4. Para jugar una carta de tierra, debe estar en la mano.<\/p>\n<p>Otro m\u00e9todo es el best-first search (b\u00fasqueda de mejor primero). En lugar de probar todos los caminos, elegimos el m\u00e1s apropiado. A menudo, este m\u00e9todo proporciona un plan \u00f3ptimo sin costos innecesarios en la b\u00fasqueda. A* es una forma de b\u00fasqueda de mejor primero: al explorar las rutas m\u00e1s prometedoras desde el principio, ya puede encontrar el mejor camino sin necesidad de verificar otras opciones.<\/p>\n<p>Una opci\u00f3n interesante y cada vez m\u00e1s popular de b\u00fasqueda best-first es la B\u00fasqueda por \u00c1rbol de Monte Carlo. En lugar de adivinar qu\u00e9 planes son mejores que otros al elegir cada acci\u00f3n subsiguiente, el algoritmo selecciona sucesores aleatorios en cada paso, hasta alcanzar el final (cuando el plan conduce a una victoria o derrota). Luego, el resultado final se utiliza para incrementar o disminuir la evaluaci\u00f3n del \"peso\" de las opciones anteriores. Repitiendo este proceso varias veces, el algoritmo proporciona una buena evaluaci\u00f3n de cu\u00e1l es el mejor siguiente paso, incluso si la situaci\u00f3n cambia (si el oponente toma medidas para obstaculizar al jugador). <\/p>\n<p>En el relato sobre planificaci\u00f3n en juegos, no se puede pasar por alto el Goal-Oriented Action Planning o GOAP (planificaci\u00f3n de acciones orientada a objetivos). Este es un m\u00e9todo ampliamente utilizado y debatido, pero adem\u00e1s de algunos detalles distintivos, es esencialmente un m\u00e9todo de encadenamiento inverso del que hablamos anteriormente. Si la tarea es \"destruir al jugador\", y el jugador est\u00e1 detr\u00e1s de una cobertura, el plan puede ser: destr\u00fayelo con una granada \u2192 cons\u00edguela \u2192 l\u00e1nzala.<\/p>\n<p>Generalmente hay m\u00faltiples objetivos, cada uno con su prioridad. Si el objetivo de m\u00e1s alta prioridad no se puede cumplir (ninguna combinaci\u00f3n de acciones crea el plan \"destruir al jugador\" porque el jugador no es visible), la IA regresar\u00e1 a los objetivos de menor prioridad.<\/p>\n<h2>Aprendizaje y adaptaci\u00f3n<\/h2>\n<p>\nYa hemos mencionado que la IA de los juegos generalmente no utiliza aprendizaje autom\u00e1tico, porque no se adapta bien para controlar agentes en tiempo real. Pero eso no significa que no se pueda tomar prestado algo de este campo. Queremos que un oponente en un shooter sea capaz de aprender algo. Por ejemplo, conocer las mejores posiciones en el mapa. O un oponente en un juego de lucha que bloqueara los combos m\u00e1s utilizados por el jugador, motiv\u00e1ndolo a usar otros. As\u00ed que el aprendizaje autom\u00e1tico en tales situaciones puede ser muy \u00fatil.<\/p>\n<h3>Estad\u00edsticas y probabilidades<\/h3>\n<p>\nAntes de entrar en ejemplos complejos, evaluemos hasta d\u00f3nde podemos llegar, tomando algunas medidas simples y utiliz\u00e1ndolas para tomar decisiones. Por ejemplo, la estrategia en tiempo real \u2014 \u00bfc\u00f3mo podemos determinar si un jugador puede comenzar un ataque en los primeros minutos del juego y qu\u00e9 defensa preparar contra eso? Podemos estudiar la experiencia previa del jugador para entender cu\u00e1l podr\u00eda ser su reacci\u00f3n futura. Empezaremos por reconocer que no contamos con esos datos iniciales, pero podemos recopilarlos: cada vez que la IA juega contra un humano, puede registrar el tiempo del primer ataque. Despu\u00e9s de varias sesiones, obtendremos un promedio del tiempo en que el jugador atacar\u00e1 en el futuro.<\/p>\n<p>Los promedios tambi\u00e9n tienen un problema: si un jugador ha 'rushado' 20 veces y ha jugado despacio 20 veces, los valores necesarios estar\u00e1n en alg\u00fan lugar del medio, lo cual no nos dar\u00e1 informaci\u00f3n \u00fatil. Una soluci\u00f3n es limitar los datos de entrada \u2014 se pueden considerar solo los \u00faltimos 20 casos.<\/p>\n<p>Un enfoque similar se utiliza al evaluar la probabilidad de ciertas acciones, asumiendo que las preferencias pasadas del jugador ser\u00e1n las mismas en el futuro. Si un jugador nos ataca cinco veces con un bola de fuego, dos veces con un rayo y una vez cuerpo a cuerpo, es evidente que prefiere la bola de fuego. Extrapolamos y vemos la probabilidad de uso de diferentes armas: bola de fuego = 62.5%, rayo = 25% y cuerpo a cuerpo = 12.5%. Nuestra IA de juego necesita prepararse para defenderse del fuego.<\/p>\n<p>Otro m\u00e9todo interesante es utilizar el Clasificador Bayesiano Naive (naive Bayes classifier) para estudiar grandes vol\u00famenes de datos de entrada y clasificar la situaci\u00f3n, de modo que la IA reaccione de manera adecuada. Los clasificadores bayesianos son m\u00e1s conocidos por su uso en filtros de spam de correo electr\u00f3nico. All\u00ed investigan las palabras, las comparan con d\u00f3nde han aparecido anteriormente (en spam o no) y sacan conclusiones sobre los correos entrantes. Podemos hacer lo mismo incluso con una menor cantidad de datos de entrada. Bas\u00e1ndonos en toda la informaci\u00f3n \u00fatil que ve la IA (por ejemplo, qu\u00e9 unidades enemigas han sido creadas, o qu\u00e9 hechizos est\u00e1n utilizando, o qu\u00e9 tecnolog\u00edas han investigado), y el resultado final (guerra o paz, 'rushar' o defenderse, etc.) \u2014 elegiremos el comportamiento adecuado para la IA.<\/p>\n<p>Todos estos m\u00e9todos de aprendizaje son suficientes, pero es preferible utilizarlos bas\u00e1ndose en datos de pruebas. La IA aprender\u00e1 a adaptarse a las diferentes estrategias que hayan usado tus testers de juego. Una IA que se adapta al jugador despu\u00e9s del lanzamiento puede volverse demasiado predecible o, por el contrario, demasiado dif\u00edcil de vencer.<\/p>\n<h3>Adaptaci\u00f3n basada en valores<\/h3>\n<p>\nTeniendo en cuenta el contenido de nuestro mundo de juego y sus reglas, podemos modificar el conjunto de valores que impactan las decisiones, en lugar de utilizar \u00fanicamente los datos de entrada. Lo hacemos as\u00ed:<\/p>\n<ul>\n<li>Permite que la IA recopile datos sobre el estado del mundo y eventos clave durante el juego (como se indic\u00f3 anteriormente).<\/li>\n<li>Cambiaremos algunos valores importantes (value) bas\u00e1ndonos en estos datos.<\/li>\n<li>Implementaremos nuestras decisiones, basadas en el procesamiento o evaluaci\u00f3n de estos valores.<\/li>\n<\/ul>\n<p>\nPor ejemplo, un agente tiene varias habitaciones para elegir en un mapa de un juego de disparos en primera persona. Cada habitaci\u00f3n tiene su propio value, que determina cu\u00e1n deseable es para visitar. La IA elige al azar a qu\u00e9 habitaci\u00f3n ir, bas\u00e1ndose en el value. Luego, el agente recuerda en qu\u00e9 habitaci\u00f3n fue asesinado y reduce su value (la probabilidad de que regrese all\u00ed). De manera similar en la situaci\u00f3n opuesta: si el agente destruye a muchos oponentes, el value de la habitaci\u00f3n aumenta.<\/p>\n<h3>Modelo de Markov<\/h3>\n<p>\n\u00bfQu\u00e9 pasar\u00eda si utilizamos los datos recopilados para hacer pron\u00f3sticos? Si recordamos cada habitaci\u00f3n donde vemos al jugador durante un periodo de tiempo determinado, podremos predecir a qu\u00e9 habitaci\u00f3n puede moverse el jugador. Al rastrear y registrar los movimientos del jugador entre habitaciones (values), podemos hacer predicciones.<\/p>\n<p>Tomemos tres habitaciones: roja, verde y azul. Y tambi\u00e9n las observaciones que registramos mientras observ\u00e1bamos una sesi\u00f3n de juego:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/6e90a365b72a176c36c9a14213baaafc.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nLa cantidad de observaciones para cada habitaci\u00f3n es casi igual; a\u00fan no sabemos d\u00f3nde hacer un buen lugar para una emboscada. La recopilaci\u00f3n de estad\u00edsticas tambi\u00e9n se complica con el respawn de los jugadores, que aparecen uniformemente en todo el mapa. Pero los datos de la siguiente habitaci\u00f3n a la que entran despu\u00e9s de aparecer en el mapa ya son \u00fatiles.<\/p>\n<p>Es evidente que la sala verde satisface a los jugadores; la mayor\u00eda de las personas que est\u00e1n en la sala roja la eligen, y el 50% de estas se queda all\u00ed. Por el contrario, la sala azul no es popular, casi no recibe visitas, y si hay visitas, son breves. <\/p>\n<p>Pero los datos nos dicen algo m\u00e1s importante: cuando un jugador se encuentra en la sala azul, la siguiente sala en la que probablemente lo veremos ser\u00e1 la roja, y no la verde. A pesar de que la sala verde es m\u00e1s popular que la roja, la situaci\u00f3n cambia si el jugador est\u00e1 en la sala azul. El siguiente estado (es decir, la sala a la que el jugador se trasladar\u00e1) depende del estado anterior (es decir, la sala en la que se encuentra actualmente el jugador). Gracias al estudio de las dependencias, podremos hacer pron\u00f3sticos m\u00e1s precisos que si simplemente cont\u00e1ramos las observaciones de manera independiente entre s\u00ed.<\/p>\n<p>Predecir el estado futuro basado en los datos del estado pasado se llama modelo de Markov, y tales ejemplos (con las salas) se denominan cadenas de Markov. Dado que los modelos representan la probabilidad de cambios entre estados sucesivos, se visualizan como FSMs con probabilidades en cada transici\u00f3n. Anteriormente, utilizamos FSM para representar el estado comportamental en el que se encontraba el agente, pero este concepto se aplica a cualquier estado, independientemente de si est\u00e1 relacionado con el agente o no. En este caso, los estados representan la sala que ocupa el agente:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/edb32dff7a3298b19c3fa4d66f48e9f4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nEsta es una forma sencilla de representar la probabilidad relativa de cambios de estado, dando al IA la capacidad de predecir el siguiente estado. Se puede prever varios pasos hacia adelante.<\/p>\n<p>Si el jugador est\u00e1 en la sala verde, hay un 50% de probabilidad de que permanezca all\u00ed en la siguiente observaci\u00f3n. Pero, \u00bfcu\u00e1l es la probabilidad de que todav\u00eda est\u00e9 all\u00ed incluso despu\u00e9s de eso? No solo hay una probabilidad de que el jugador haya permanecido en la sala verde despu\u00e9s de dos observaciones, sino tambi\u00e9n una probabilidad de que se haya ido y regresado. Aqu\u00ed hay una nueva tabla considerando los nuevos datos:<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/f87afff68b066a879661e37f68654ae2.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n <br \/>\nDe ella se desprende que la probabilidad de ver al jugador en la sala verde despu\u00e9s de dos observaciones ser\u00e1 del 51%: 21% de que provenga de la sala roja, 5% de que el jugador haya visitado la sala azul entre ellas, y 25% de que el jugador no haya salido de la sala verde en absoluto.<\/p>\n<p>La tabla es una herramienta visual simple; el proceso solo requiere multiplicar probabilidades en cada paso. Esto significa que puedes mirar lejos en el futuro con una salvedad: suponemos que la probabilidad de entrar a una habitaci\u00f3n depende completamente de la habitaci\u00f3n actual. Esto se llama propiedad de Markov (Markov Property): el estado futuro depende solo del presente. Pero no es 100% preciso. Los jugadores pueden alterar decisiones bas\u00e1ndose en otros factores: nivel de salud o cantidad de municiones. Dado que no fijamos estos valores, nuestras predicciones ser\u00e1n menos precisas.<\/p>\n<h3>N-Grams<\/h3>\n<p>\n\u00bfY qu\u00e9 hay del ejemplo con la pelea y la predicci\u00f3n de los combos de un jugador? \u00a1Lo mismo! Pero en lugar de un solo estado o evento, exploraremos secuencias enteras que componen el golpe de combo.<\/p>\n<p>Una de las formas de hacerlo es almacenar cada entrada (por ejemplo, Kick, Punch o Block) en un b\u00fafer y registrar todo el b\u00fafer como un evento. As\u00ed, el jugador presiona repetidamente Kick, Kick, Punch para realizar el ataque SuperDeathFist, el sistema de IA almacena todas las entradas en el b\u00fafer y recuerda las \u00faltimas tres utilizadas en cada paso.<\/p>\n<p><img decoding=\"async\" alt=\"C\u00f3mo crear una IA para juegos: gu\u00eda para principiantes\" src=\"\/wp-content\/uploads\/2019\/11\/9a95226ae155dca5e45a66d4440f3cd4.jpeg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n(Las l\u00edneas en negrita indican cu\u00e1ndo el jugador inicia el ataque SuperDeathFist.)<\/p>\n<p>La IA ver\u00e1 todas las combinaciones cuando el jugador elija Kick, seguido de otro Kick, y luego notar\u00e1 que la siguiente entrada siempre es Punch. Esto permitir\u00e1 al agente predecir el combo SuperDeathFist y bloquearlo, si es posible.<\/p>\n<p>Estas secuencias de eventos se llaman N-gramas (N-grams), donde N es la cantidad de elementos almacenados. En el ejemplo anterior, fue un 3-grama (trigrama), lo que significa: las dos primeras entradas se utilizan para predecir la tercera. De manera correspondiente, en un 5-grama, las primeras cuatro entradas predicen la quinta y as\u00ed sucesivamente.<\/p>\n<p>El desarrollador debe elegir cuidadosamente el tama\u00f1o de los N-gramas. Un n\u00famero menor de N requiere menos memoria, pero tambi\u00e9n almacena menos historia. Por ejemplo, un 2-grama (bigram) registrar\u00e1 Kick, Kick o Kick, Punch, pero no podr\u00e1 almacenar Kick, Kick, Punch, por lo que la IA no reaccionar\u00e1 al combo SuperDeathFist.<\/p>\n<p>Por otro lado, n\u00fameros m\u00e1s grandes requieren m\u00e1s memoria y la IA tendr\u00e1 m\u00e1s dificultad para aprender, ya que habr\u00e1 muchas m\u00e1s combinaciones posibles. Si tienes tres entradas posibles: Kick, Punch o Block, y usamos un 10-grama, obtendremos alrededor de 60,000 combinaciones diferentes.<\/p>\n<p>El modelo de bigramas es una cadena de Markov simple: cada par \"estado anterior\/estado actual\" es un bigrama, y puedes predecir el segundo estado en funci\u00f3n del primero. Los trigramas y n-gramas m\u00e1s grandes tambi\u00e9n se pueden considerar como cadenas de Markov, donde todos los elementos (excepto el \u00faltimo en el n-grama) forman el primer estado, y el \u00faltimo elemento es el segundo. Un ejemplo relacionado con la lucha muestra la probabilidad de transici\u00f3n del estado Kick y Kick al estado Kick y Punch. Al considerar varios registros de la historia de entrada como una unidad, esencialmente transformamos la secuencia de entrada en parte de un estado total. Esto nos proporciona la propiedad de Markov, permiti\u00e9ndonos usar cadenas de Markov para predecir la siguiente entrada y adivinar qu\u00e9 movimiento de combo ser\u00e1 el siguiente.<\/p>\n<h2>Conclusi\u00f3n<\/h2>\n<p>\nHablamos sobre las herramientas y enfoques m\u00e1s comunes en el desarrollo de inteligencia artificial. Tambi\u00e9n discutimos situaciones en las que deben aplicarse y d\u00f3nde son especialmente \u00fatiles. <\/p>\n<p>Esto deber\u00eda ser suficiente para comprender lo b\u00e1sico en IA de videojuegos. Pero, por supuesto, esto est\u00e1 lejos de ser todos los m\u00e9todos. Menos populares, pero igual de efectivos, son:<\/p>\n<ul>\n<li>algoritmos de optimizaci\u00f3n, incluidos el ascenso de monta\u00f1a, el descenso de gradiente y los algoritmos gen\u00e9ticos<\/li>\n<li>algoritmos de b\u00fasqueda\/planificaci\u00f3n competitiva (minimax y poda alpha-beta)<\/li>\n<li>m\u00e9todos de clasificaci\u00f3n (perceptrones, redes neuronales y m\u00e1quinas de soporte vectorial)<\/li>\n<li>sistemas para el procesamiento de la percepci\u00f3n y la memoria de los agentes<\/li>\n<li>enfoques arquitect\u00f3nicos para IA (sistemas h\u00edbridos, subconjuntos de arquitecturas y otras formas de superposici\u00f3n de sistemas de IA)<\/li>\n<li>herramientas de animaci\u00f3n (planificaci\u00f3n y coordinaci\u00f3n del movimiento)<\/li>\n<li>factores de rendimiento (nivel de detalle, algoritmos anytime y timeslicing)<\/li>\n<\/ul>\n<p>\nRecursos en l\u00ednea sobre el tema:<\/p>\n<p>1. En GameDev.net hay <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gamedev.net\/articles\/programming\/artificial-intelligence\/\">una secci\u00f3n con art\u00edculos y tutoriales sobre IA<\/a><\/noindex>, as\u00ed como <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gamedev.net\/forums\/forum\/6-artificial-intelligence\/\">foro<\/a><\/noindex>.<br \/>\n2. <noindex><a rel=\"nofollow\" href=\"http:\/\/aigamedev.com\/\">AiGameDev.com<\/a><\/noindex> contiene numerosas presentaciones y art\u00edculos sobre una amplia gama de temas relacionados con el desarrollo de IA en videojuegos.<br \/>\n3. <noindex><a rel=\"nofollow\" href=\"https:\/\/www.gdcvault.com\/\">The GDC Vault<\/a><\/noindex> incluye temas de la cumbre GDC AI, muchos de los cuales est\u00e1n disponibles de forma gratuita.<br \/>\n4. Tambi\u00e9n se pueden encontrar materiales \u00fatiles en el sitio <noindex><a rel=\"nofollow\" href=\"http:\/\/gameai.com\/\">AI Game Programmers Guild<\/a><\/noindex>.<br \/>\n5. Tommy Thompson, investigador de IA y desarrollador de juegos, hace videos en el canal de YouTube <noindex><a rel=\"nofollow\" href=\"https:\/\/www.youtube.com\/user\/tthompso\">AI and Games<\/a><\/noindex> con explicaciones y estudios de IA en videojuegos comerciales.<\/p>\n<p>Libros sobre el tema:<\/p>\n<p>1. La serie de libros Game AI Pro consiste en colecciones de art\u00edculos breves que explican c\u00f3mo implementar funciones espec\u00edficas o resolver problemas concretos.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"http:\/\/go.gamedev.net\/?id=13722X707581&amp;xs=1&amp;isjs=1&amp;url=https%3A%2F%2Famzn.to%2F2KGoB8n&amp;xguid=f8ad586e5984991508efff4754027dbd&amp;xuuid=305451ecead59d76ca830fded0aab276&amp;xsessid=6ccb8b9fa3f10b478b65f7ed703a447b&amp;xcreo=0&amp;xed=0&amp;sref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F%3Fdo%3Dedit%26d%3D1%26id%3D4942%26csrfKey%3D7015c6d2c5c643e87baa74f8e5d2c094&amp;pref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F&amp;xtz=420&amp;jv=13.7.1&amp;bv=2.5.1\">Game AI Pro: Sabidur\u00eda Colectada de Profesionales de IA en Juegos<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"http:\/\/go.gamedev.net\/?id=13722X707581&amp;xs=1&amp;isjs=1&amp;url=https%3A%2F%2Famzn.to%2F2KFKyoe&amp;xguid=f8ad586e5984991508efff4754027dbd&amp;xuuid=305451ecead59d76ca830fded0aab276&amp;xsessid=6ccb8b9fa3f10b478b65f7ed703a447b&amp;xcreo=0&amp;xed=0&amp;sref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F%3Fdo%3Dedit%26d%3D1%26id%3D4942%26csrfKey%3D7015c6d2c5c643e87baa74f8e5d2c094&amp;pref=https%3A%2F%2Fwww.gamedev.net%2Farticles%2Fprogramming%2Fartificial-intelligence%2Fthe-total-beginners-guide-to-game-ai-r4942%2F&amp;xtz=420&amp;jv=13.7.1&amp;bv=2.5.1\">Game AI Pro 2: Sabidur\u00eda Colectada de Profesionales de IA en Juegos<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2KF4irS\">Game AI Pro 3: Sabidur\u00eda Colectada de Profesionales de IA en Juegos<\/a><\/noindex><\/p>\n<p>2. La serie AI Game Programming Wisdom es el predecesor de la serie Game AI Pro. Presenta m\u00e9todos m\u00e1s antiguos, pero casi todos son relevantes incluso hoy.<\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2ARFhKx\">AI Game Programming Wisdom 1<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2Mkv4eh\">AI Game Programming Wisdom 2<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2nnuYEh\">AI Game Programming Wisdom 3<\/a><\/noindex><br \/>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2ARFEEV\">AI Game Programming Wisdom 4<\/a><\/noindex><\/p>\n<p>3. <noindex><a rel=\"nofollow\" href=\"https:\/\/amzn.to\/2AWKuRh\">Inteligencia Artificial: Un Enfoque Moderno<\/a><\/noindex> \u2014 es uno de los textos b\u00e1sicos para todos aquellos que quieran entender el campo general de la inteligencia artificial. Este libro no trata sobre el desarrollo de juegos \u2014 ense\u00f1a los fundamentos b\u00e1sicos de la IA.<br \/>\n<br \/>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/pixonic\/blog\/428892\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431 \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u043b\u043b\u0435\u043a\u0442\u0435 \u0432 \u0438\u0433\u0440\u0430\u0445. \u0421 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u0438\u0435\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0432\u0435\u0449\u0435\u0439 \u043f\u0440\u043e \u0418\u0418 \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445, \u0430 \u0435\u0449\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0435\u0433\u043e \u0443\u0434\u043e\u0431\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041a\u0430\u043a, \u0433\u0434\u0435 \u0438 \u043a\u043e\u0433\u0434\u0430 \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u2014 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c. \u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043e\u0434\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0433\u043b\u0443\u0431\u043e\u043a\u0438\u0435 \u0437\u043d\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c 35 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-52118","post","type-post","status-publish","format-standard","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0418\u0418: \u0433\u0430\u0439\u0434 \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/es\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T10:59:47+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47C\u00f3mo crear IA de juegos: gu\u00eda para principiantes | ProHoster","description":"Me encontr\u00e9 con un material interesante sobre.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0418\u0418: \u0433\u0430\u0439\u0434 \u0434\u043b\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0449\u0438\u0445 | ProHoster","og:description":"\u041d\u0430\u0442\u043a\u043d\u0443\u043b\u0441\u044f \u043d\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043e\u0431.","og:url":"https:\/\/prohoster.info\/es\/blog\/news\/kak-sozdat-igrovoj-ii-gajd-dlya-nachinayushhih","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T21:00:00+00:00","article:modified_time":"2020-02-18T10:59:47+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"52118","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 02:32:21","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 20:49:49","updated":"2026-01-24 02:32:21","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/52118","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=52118"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/52118\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=52118"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=52118"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=52118"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}