Anuncios Google

Problema con la IA

Estoy creando un juego de las "Motos de luz". Manejas una moto que deja un rastro de color a su paso y tienes que intentar matar al otro (haciendo que se estrelle contra una pared).

 

El caso es que quiero crearle una IA, el problema esque siempre que llega a la esquina superior izquierda. Empieza a cabecear de forma rara hasta suicidarse (la amarilla es la maquina):

 

La funcion que gestiona los movimientos de la maquina es la siguiente:

 

void InteligenciaArtificial(Vehiculo &Jugador2)
{
 
     int color;
     int color2;
     bool Movido = false;
 
     // Si se choca en el eje X
 
     if (Jugador2.MovimientoX != 0) // Si se mueve en el eje x
     {
        color = getpixel(screen,Jugador2.X+50*Jugador2.MovimientoX, Jugador2.Y); // Comprobamos si hay algun obstaculo
 
        if ((color != 0)&& (color != palette_color[15]))
        {
 
           color = getpixel(screen,Jugador2.X, Jugador2.Y+50);
           color2= getpixel(screen,Jugador2.X, Jugador2.Y-50);
 
           if ((color!= 0)&& (color != palette_color[15])&& (color2 != 0)&& (color2!= palette_color[15]))
              Jugador2.MovimientoY = 1;
           else  
               Jugador2.MovimientoY = -1;
 
           Jugador2.MovimientoX = 0;
           Movido = true;
           // return;
        }
 
 
     }
 
     // Si se choca en el eje Y
 
     if ((Jugador2.MovimientoY != 0)&& (Movido == false))
     {
        color = getpixel(screen,Jugador2.X, Jugador2.Y+50*Jugador2.MovimientoY);
 
        if ((color != 0)&& (color != palette_color[15]))
        {
           color = getpixel(screen,Jugador2.X+50, Jugador2.Y);
           color2= getpixel(screen,Jugador2.X-50, Jugador2.Y);
 
           if ((color!= 0)&& (color != palette_color[15])&& (color2 != 0)&& (color2 != palette_color[15]))
              Jugador2.MovimientoX = 1;
           else
               Jugador2.MovimientoX = -1;
 
           Jugador2.MovimientoY = 0;
           Movido = true;
           //return;
        }
     }
 
 
}

 

La función GetPixel es una función de la librería gráfica que te devuelve el color de un determinado adyacente. Lo uso para determinar si el siguiente pixel es un obstaculo o solo parte del fondo.

 

Saludos!


Editado: El límite del ancho de las imágenes es de 500 pixeles, sobrepasar este límite puede descolocar la web e incumple las Normas de la Comunidad, antes de volver a postear por favor revíselas.| AORV


Anuncios Google

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

Ya he desarrollado el sistema

Ya he desarrollado el sistema de distancias:

 

int Obstaculo(Vehiculo Jugador2)
{
    int color = 0;
    int i = 0;
 
    do
    {
        i++;
        color = getpixel(screen,Jugador2.X+i*Jugador2.MovimientoX, Jugador2.Y+i*Jugador2.MovimientoY);
 
    } while ((color == 0) || (color == palette_color[15]));
 
    return i;
}

void InteligenciaArtificial(Vehiculo &Jugador2)
{
     int Longitud1 = 0;
     int Longitud2 = 0;
 
     bool Movido = false;
 
 
     // Si se choca en el eje X
 
     if (Jugador2.MovimientoX != 0) // Se mueve en el eje x
     {
 
        if (Obstaculo(Jugador2) < 30)
        {
              Jugador2.MovimientoX = 0;
              Jugador2.MovimientoY = 1;
              Longitud1 = Obstaculo(Jugador2);
              Jugador2.MovimientoY = -1;
              Longitud2 = Obstaculo(Jugador2);
 
              if (Longitud1 >= Longitud2)
                 Jugador2.MovimientoY = 1;
 
           // return;
        }
 
        Movido = true;
 
 
     }
 
     // Si se choca en el eje Y
 
     if ((Jugador2.MovimientoY != 0)&& (Movido == false))
     {
        if (Obstaculo(Jugador2) < 30)
        {
              Jugador2.MovimientoY = 0;                  
              Jugador2.MovimientoX = 1;
              Longitud1 = Obstaculo(Jugador2);
              Jugador2.MovimientoX = -1;
              Longitud2 = Obstaculo(Jugador2);
 
              if (Longitud1 >= Longitud2)
                 Jugador2.MovimientoX = 1;
 
           // return;
        }
     }
 
 
}

 

Funciona de maravilla (bueno quitando que lo unico que hace es dar vueltas al campo y que es muy pasiva xD). ¡Muchas gracias! ^^

Imagen de joserc87

Me alegro que funcione.

El siguiente paso, como en casi toda IA para juegos, es hacer una búsqueda recursiva del arbol de movimientos. Al final, aunque parezca raro, es un algoritmo minimax como podría ser la IA de un juego de ajedrez. En este link por ejemplo te explican una forma de hacerlo en Haskell (es un lenguaje un poco raro pero se entiende el algoritmo). Básicamente la idea es tomar como heurística el número de puntos que controla tu moto, es decir, los puntos a los que llegas antes que el enemigo. Por ejemplo, si tu controlas el 99% del tablero es porque, probablemente, el enemigo esté encerrado. Así que, aunque el algoritmo busque controlar el máximo del tablero, en realidad lo que va a parecer que hace es encerrar al otro.

Saludos.

EDIT: He encontrado un link que te explica un poco mejor el algoritmo. No lo he leido, pero creo que viene a ser lo mismo, solo que más explicado y sin código. Además tienes el Armagetron Advanced, que es opensource, así que le puedes echar un ojo a su IA. Por cierto, si no estás acostumbrado a los algoritmos de búsqueda te recomiendo que antes te metas en wikipedia (por ejemplo) y le eches un ojo a algoritmos de búsqueda (recursividad, algoritmo de fuerza bruta, algoritmo minimax, poda alfa-beta, etc etc) porque sino te va a ser más dificil entenderlo todo.


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Imagen de joserc87

Normal.

Es normal que te haga eso, ya que si x<50 && y<50 tiene obstáculos tanto en x como en y, asi que va intentando esquivarlos pero siempre igual: girar a la izquierda, luego a la derecha, luego a la izquierda... La solución más simple es que el giro sea aleatorio:

void InteligenciaArtificial(Vehiculo &Jugador2)
{
     int color;
     int color2;
     bool Movido = false;
 
     // Si se choca en el eje X
     if (Jugador2.MovimientoX != 0) // Si se mueve en el eje x
     {
        color = getpixel(screen,Jugador2.X+50*Jugador2.MovimientoX, Jugador2.Y); // Comprobamos si hay algun obstaculo
 
        if ((color != 0)&& (color != palette_color[15]))
        {
 
           float aleat = rand ();
           if (aleat>=0.5)
              Jugador2.MovimientoY = 1;
           else  
               Jugador2.MovimientoY = -1;
           Jugador2.MovimientoX = 0;
           Movido = true;
           // return;
        }
     }
 
     // Si se choca en el eje Y
 
     if ((Jugador2.MovimientoY != 0)&& (Movido == false))
     {
        color = getpixel(screen,Jugador2.X, Jugador2.Y+50*Jugador2.MovimientoY);
 
        if ((color != 0)&& (color != palette_color[15]))
        {
           float aleat = rand ();
           if (aleat>=0.5)
              Jugador2.MovimientoX = 1;
           else  
               Jugador2.MovimientoX = -1;
           Jugador2.MovimientoY = 0;
           Movido = true;
           // return;
        }
     }
 
 
}

Es una solución más tonta que la que intentas hacer pero debería funcionar. Ahora bien, yo cambiaría el valor de 50 por algo un poco más pequeño.

Si quieres una solución más inteligente, debes comenzar por implementar una función del tipo:

int Obstaculo (Vehiculo &jugador){
  ...
}

Que te devuelva, para la posición y dirección del jugador, la distancia a la que está el siguiente obstáculo en píxeles. Esto es solo un simple if y un par de for pero te facilitará las cosas. Así, en la función de InteligenciaArtificial puedes usarla para saber si hay un obstáculo (Obstaculo(jugador)<50), y si lo hay, en qué dirección tendrías que moverte (la dirección que minimice la función Obstáculo).

Por supuesto, no llegaría a ser inteligente ni mucho menos, pero con eso ya tienes para empezar.

Saludos y pregunta si no entiendes algo.


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Más que tonta, es un poco

Más que tonta, es un poco chapucera no? xD

 

He probado tu solución palabra por palabra (bueno, en vez de hacer un aleatorio con floats lo he hecho con enteros). Siempre hace lo mismo:

 

Sale, llega al primer obstaculo y va hacia arriba. Llega a la esquina de arriba y da MEDIA VUELTA. Es decir, gira dos veces a la derecha y hace un cambio de sentido. Repite el mismo procedimiento en la esquina inferior izquierda. Cuando llega a la inferior derecha, vuelve a subir y muere.

 

Lo curioso es que los numeros son aleatorios, luego no debería seguir ese patrón... Los aleatorios deberían funcionar creo yo:

srand(time(0));
int numero = rand() % 10+1;
           if (numero > 5)
                // Tal y tal
 

 

Mirare la solución de las distancias, cuando la tenga te la digo.

 

PD: El numero 50 es para hacer las pruebas (para ver las maniobras con más antelación).


Editado: El límite del ancho de las imágenes es de 500 pixeles, sobrepasar este límite puede descolocar la web e incumple las Normas de la Comunidad, antes de volver a postear por favor revíselas.| AORV

Imagen de joserc87

Por curiosidad.

Ya que tienes la otra solución da igual, pero en el código he cometido un error ya que no miro en la posición x-50 ni y-50. Por ejemplo, si va en la dirección x, se mira el punto x+50, y:

if (Jugador2.MovimientoX != 0) // Si se mueve en el eje x
     {
        color = getpixel(screen,Jugador2.X+50*Jugador2.MovimientoX, Jugador2.Y);

Pero que pasa si va en sentido contrario? Creo que es por eso por lo que se da la vuelta, a no ser que te hayas dado cuenta y lo hayas arreglado. En cualquier caso, la otra solución es mejor así que da igual :)


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Si va en sentido contrario,

Si va en sentido contrario, Jugador2.MovimientoX será -1. Y por tanto será x-50 :)

PD: Miro los links y te contesto a lo otro : P

Imagen de joserc87

Tienes razón.

La primera vez sí que vi la multiplicación, pero ayer estaba algo empanado xD.

En fin, si tienes algún problema con el algoritmo avisa :)


Be pointer my friend...

Dennis Ritchie. Padre de C y cocreador de UNIX.

R.I.P.

 

Imagen de Guillermo_Cornielle

Pienso

Que la variable "movido = true" deberia de ir al principio del bloque de la instruccion deñ bloque if..else, ya que es cuando el jugador empieza a moverse, pero sobre tu error, La verdad es que yo no se nada, pero parece que elerror ha de estar dentro del bloque del movimeinto Y.

De todas formas, eso opino.


Manual del Perfecto Votante Para un voto libre y justo!.

TheGCProjects

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.