Algoritmo simulador de batallas

Iniciado por GeorgArming, 11 Agosto 2013, 04:00 AM

0 Miembros y 1 Visitante están viendo este tema.

GeorgArming

Hola foreros. Quiero crear un simulador de batallas antiguas (rollo romanos, cartagineses,...) en modo texto. Es decir, quiero hacer un programa que lea unos datos, simula la batalla y dé otros datos.

Los datos que leería serían básicamente unidades de uno y otro ejército (así como su forma física, motivación, estado de salud, munición, adaptabilidad a los diferentes terrenos, a qué tipo de unidades hacen más daño y a qué tipo de unidades son más vulnerables,...), la disposición de los ejércitos en el terreno, el terreno mismo, las condiciones climatológicas y la táctica elegida por cada bando (defensiva, ofensiva, atacar por los flancos,...).

El usuario debería poder organizar las tropas (en grupos de "unidades", por ejemplo, 1 unidad de caballería serían 50 soldados) por el terreno y decidir las posibles tácticas, si se debería contemplar la rendición, rotaciones,...

La batalla en sí misma había pensado en organizarla por casillas (por ejemplo,e l campo de batalla es un campo de 10x10 casillas) y "turnos", aunque el usuario sólo podría escoger la táctica al principio.

Al final, el programa devolvería el nuevo estado de los ejércitos, número de bajas, heridos, si huyó alguno de los equipos, si se ha tomado el terreno,...

Sinceramente, tengo muchas dudas. Lo he puesto aquí porque mis dudas son básicamente de programación general. He estado pensando en algún algoritmo, pero el tema de las casillas no lo domino. Y otro tema que me es muy difícil es el de las luchas en sí. Si se enfrentan dos unidades, se me ocurre evaluar las diferentes características y eso. El problema es generar estas luchas, porque se deberían dar en el caso que unidades enemigas se encuentren en casillas contiguas. Y ahí el problema es que podría haber más de dos.

La intención de este post es que entre todos escribamos un algoritmo para este simulador. Yo, que soy el autor del post y el mayor interesado, voy a trabajar mucho, pero seguro que aquí hay muchos cracks que saben hacerlo y les interesa o gente que simplemente está interesada en aprender.

Lo dicho, a ver si vamos posteando el algoritmo. Voy a mirar código de simuladores de ajedrez porque podría ser de ayuda. Yo iré poniendo mi algoritmo, entre todos vamos corrigiendo si os parece y añadiendo cosas.

Muchas gracias.

Saludos.

eferion

Las casillas van a ser cuadradas, triangulares, pentagonales, hexagonales, ... cada tipo de casilla tendrá sus implicaciones en el algoritmo. Lo más sencillo es que las casillas sean cuadradas, así se pueden encajar en una matriz sin aplicar transformaciones.

Suponiendo que las casillas sean cuadradas... vas a permitir ataques en diagonal o solo en vertical y horizontal ?? si solo permites en vertical y horizontal el código se podría simplificar.

En el caso de que se enfrenten dos unidades aquí tienes varias opciones:

* En general podrías empezar comparando la fuerza de uno con la defensa del otro... lanzar una tirada aleatoria y comprobar quien gana... el que gana o pierde vida o directamente desaparece.

* Hay unidades especializadas en acabar con otras ? esto le tendría que reportar un bonus a su fuerza o a su defensa ( las posibilidades son amplias ) antes de realizar la tirada del combate. Esto también podría ser aplicable a bonus negativos.

* Vas a tener en cuenta la moral de las tropas ?? o algún efecto beneficioso si atacan con unidades aliadas a su lado ?? Al final esto se puede traducir en modificar los bonus de ataque y defensa.

* El terreno va a influir en el combate ?? más bonus y malus para la defensa, el ataque e incluso el movimiento... algunas unidades podrían llegar a quedar atrapadas por el terreno o incluso no podrían traspasarlo... depende de ti.

* Se van a permitir ataques a distancia ?? estos ataques normalmente deberían ser especiales ya que la unidad que ataca no puede recibir daños.

Al final el combate se puede simplificar en calcular un modificador ( bonus/malus ) para la fuerza / defensa, aplicarlos a las unidades implicadas y realizar una tirada que determine quien gane... lo que pase después ya es otra cosa.

El movimiento de tropas puede ser algo tan sencillo como que las unidades avancen hacia el enemigo que tengan más cerca primero hacia adelante ( casilllas cuadradas ) y luego, si se puede, hacia los lados o puedes intentar currarte un poco la IA para que intente atacar a los puntos debiles del enemigo.

El algoritmo de general de la batalla podría ser algo así:

* Mover tropas equipo 1
* Atacar equipo 1
* Mover tropas equipo 2
* Atacar equipo 2

Posteriormente si te ves con ganas podrías mejorarlo y que sea continuo... con tropas moviéndose mientras son atacadas y cosas así. ( Nota: esto no es tiempo real por mucho que algunos se empeñen )

Y finalmente te puedes plantear si alguno de los bandos puede rendirse en un momento dado en base al desarrollo de la batalla o si por contra se exige la destrucción total del enemigo.

La verdad es que dicho parecen cuatro tonterías que se programan en un par de horas... pero al final tiene bastante más curro.

GeorgArming

Cita de: eferion en 11 Agosto 2013, 13:34 PM
Las casillas van a ser cuadradas, triangulares, pentagonales, hexagonales, ... cada tipo de casilla tendrá sus implicaciones en el algoritmo. Lo más sencillo es que las casillas sean cuadradas, así se pueden encajar en una matriz sin aplicar transformaciones.

Suponiendo que las casillas sean cuadradas... vas a permitir ataques en diagonal o solo en vertical y horizontal ?? si solo permites en vertical y horizontal el código se podría simplificar.

En el caso de que se enfrenten dos unidades aquí tienes varias opciones:

* En general podrías empezar comparando la fuerza de uno con la defensa del otro... lanzar una tirada aleatoria y comprobar quien gana... el que gana o pierde vida o directamente desaparece.

* Hay unidades especializadas en acabar con otras ? esto le tendría que reportar un bonus a su fuerza o a su defensa ( las posibilidades son amplias ) antes de realizar la tirada del combate. Esto también podría ser aplicable a bonus negativos.

* Vas a tener en cuenta la moral de las tropas ?? o algún efecto beneficioso si atacan con unidades aliadas a su lado ?? Al final esto se puede traducir en modificar los bonus de ataque y defensa.

* El terreno va a influir en el combate ?? más bonus y malus para la defensa, el ataque e incluso el movimiento... algunas unidades podrían llegar a quedar atrapadas por el terreno o incluso no podrían traspasarlo... depende de ti.

* Se van a permitir ataques a distancia ?? estos ataques normalmente deberían ser especiales ya que la unidad que ataca no puede recibir daños.

Al final el combate se puede simplificar en calcular un modificador ( bonus/malus ) para la fuerza / defensa, aplicarlos a las unidades implicadas y realizar una tirada que determine quien gane... lo que pase después ya es otra cosa.

El movimiento de tropas puede ser algo tan sencillo como que las unidades avancen hacia el enemigo que tengan más cerca primero hacia adelante ( casilllas cuadradas ) y luego, si se puede, hacia los lados o puedes intentar currarte un poco la IA para que intente atacar a los puntos debiles del enemigo.

El algoritmo de general de la batalla podría ser algo así:

* Mover tropas equipo 1
* Atacar equipo 1
* Mover tropas equipo 2
* Atacar equipo 2

Posteriormente si te ves con ganas podrías mejorarlo y que sea continuo... con tropas moviéndose mientras son atacadas y cosas así. ( Nota: esto no es tiempo real por mucho que algunos se empeñen )

Y finalmente te puedes plantear si alguno de los bandos puede rendirse en un momento dado en base al desarrollo de la batalla o si por contra se exige la destrucción total del enemigo.

La verdad es que dicho parecen cuatro tonterías que se programan en un par de horas... pero al final tiene bastante más curro.

Gracias por tus sugerencias. Hay cosas que dices en las que ya había pensado, si te fijas en el post original (por ejemplo, lo del terreno). Otras no las había tenido en cuenta y están bien.

Hoy he estado todo el día dándole vueltas al tema del algoritmo. Las casillas, como dices, deben ser cuadradas, y lo del ataque en diagonal quizás sería mejor que sí pero entonces es más complejo. El tema es que quiero que haya ataque a distancia, y no tiene sentido que éste no puede hacerse en diagonal.

El juego está formado por casillas 10x10.

Lo mejor sería que todo el código fuese modular y que el runtime funcionase por turnos. He pensado eso:

Programa general

Leer datos (llamando a una función externa).
Iniciar el simulador general pasándole los datos leídos.
Devolver datos, guardándolos (llamando a una función externa).
Fin del programa.


Simulador general

Determinar los valores de las variables globales (clima, tipo de terreno, cuál de los dos ejércitos tiene la iniciativa, tácticas elegidas por cada ejército,...) según los datos leídos.
Crear las 100 casillas de la siguiente forma: se determina el tipo de terreno según los datos leídos con un 0% de azar O según el tipo de terreno general se generan aleatoriamente las diferentes casillas (por ejemplo, si es en una zona alemana, debería haber 75% de terreno de bosque, 5% de agua,...).
Crear instancias unidades partiendo de la clase Unidad y completando los atributos según los datos leídos (velocidad, motivación, estado físico, número total de efectivos de la unidad, defensa cuerpo a cuerpo, ataque cuerpo a cuerpo, defensa a distancia, unidades que se le dan bien para luchar, unidades que se le dan mal, terrenos que se le dan bien, climas que se le dan bien,...).
Ubicar las unidades en los sitios especificados por los datos leídos (aquí puede devolver error si se han puesto las unidades en sitios inválidos: fuera del "campo propio", encima de otra unidad ya colocada o en casillas ocupadas por agua,...).
Iniciar bucle de combate (con un máximo de 100 turnos) {
  Si estamos en el primer turno {
    Se avanzan una a una las unidades del ejército con iniciativa (obviamente, la caballería avanza más casillas por turno que la infantería pesada).
    Según la táctica elegida por el ejército sin iniciativa, las unidades avanzan o no.
  }
  Si no estamos en el primer turno {
  Las unidades del ejército con iniciativa avanzan según la táctica, disciplina, estado físico, situación de combate y del terreno y motivación que tengan.
  Si en alguna casilla se produce situación de choque (se encuentran en casillas contiguas unidades enemigas entre si o alguna unidad con ataque a distancia está a dos casillas de una unidad enemiga) {
  Se inicia el simulador concreto pasándole como datos las casillas de lucha y las unidades que participan.
  }
  Las unidades del ejército sin iniciativa avanzan según la táctica, disciplina, estado físico, situación de combate (si una unidad no está en combate y ha pasado de la mitad del campo, se dirigirá hacia unidades enemigas, preferentemente hacia las más cercanas) y del terreno y motivación que tengan.
  Si en alguna casilla se produce situación de choque (se encuentran en casillas contiguas unidades enemigas entre si o alguna unidad con ataque a distancia está a dos casillas de una unidad enemiga) {
  Se inicia el simulador concreto pasándole como datos las casillas de lucha y las unidades que participan.
  }
}


Simulador concreto


Si uno de los dos bandos está solamente formado por una unidad con ataque a distancia y el otro no está solamente formado por unidades de ataque a distancia {
  Las unidades dentro del combate sin ataque a distancia atacadas por unidades con ataque a distancia se dirigen hacia la unidad que les está atacando a distancia o deciden ponerse a salvo, según circunstancias de la partida (táctica, motivación,...).
}
Se cuentan los turnos de combate.
Atacan las unidades con iniciativa y ataque a distancia.
Se efectúan los daños: según capacidad de ataque, defensa, clima,...
Atacan las unidades sin iniciativa pero con ataque a distancia.
Se efectúan los daños: según capacidad de ataque, defensa, clima,...
Atacan las unidades con iniciativa cuerpo a cuerpo.
Se efectúan los daños: según capacidad de ataque, defensa, clima,...
Atacan las unidades sin iniciativa cuerpo a cuerpo.
Se efectúan los daños: según capacidad de ataque, defensa, clima,...
Si se llevan 3 turnos consecutivos en los que un equipo de los dos consigue más bajas {
  La unidad que está perdiendo se ve forzada a retroceder.
  Si no puede retroceder (porque está acorralada, dificultades del terreno,...) {
    Desbonificación (le baja mucho más el estado físico, motivación,...).
  Se pone el contador de turnos a 0.
}
Sino {
  Según táctica, moral y motivación, una unidad puede decidir (o no) retroceder.
}


¿Qué os parece? ¿Está bien? ¿No? ¿Le falta algo (general)? Si está bien, podríamos pasar a concretar más el algoritmo, poniéndolo ya con pseudocódigo y pasando argumentos, con funciones y variables,...

xustyx

Realmente quieres hacer un simulador o quieres aplicarle jugabilidad, por que estaría muy chulo la verdad. Mezcla de Warcraft 3, AoE, en tablero.

Si realmente quereis ir haciendo algo podriamos definir ya con listas los atributos básicos de las unidades, y luego los secundarios. ¿Que os parece? Así ya podemos generar una classe básica de donde hereden todo los otros tipos de unidades y ponernos a trabajar xDD.

GeorgArming

Cita de: xustyx en 11 Agosto 2013, 19:50 PM
Realmente quieres hacer un simulador o quieres aplicarle jugabilidad, por que estaría muy chulo la verdad. Mezcla de Warcraft 3, AoE, en tablero.

Si realmente quereis ir haciendo algo podriamos definir ya con listas los atributos básicos de las unidades, y luego los secundarios. ¿Que os parece? Así ya podemos generar una classe básica de donde hereden todo los otros tipos de unidades y ponernos a trabajar xDD.

Yo hablo de él como simulador, pero sí, tenemos que aplicarle jugabilidad. La idea sería que el simulador sería el backend, y luego sería fácil añadir un frontend y podríamos hacer un buen juego online masivo (o lo que queramos).

Qué te parecen los algoritmos que he puesto?

Como dices podemos ya ir añadiendo los atributos de las unidades para tener la clase. Me parece muy bien.

xustyx

Creo que hay que bajar un poco el nivel que requiere tantas condicionesy ir poco a poco.

Por ejemplo lo de simular una batalla lo veo más como la lucha entre dos IA, y crear una IA no es tan complicado en este caso, simplemente puedes hacer que la máquina calcule todos los posibles movimientos con todas sus tropas y haga una estadistica de cual movimiento es el que mas le rinde, y si quieres subirle en nivel, puedes hacer que calcule uno, dos o tres turnos antes de mover, claro esta, que contra mas turnos analice, las posibilidades crecen exponencialmente pero también la IA puede realizar mejores movimientos... aunque no siempre realice el mejor ya que en sus simulaciones puede que gane pero luego cuando mueve y se vuelve a simular realmente la lucha, puede que un "RANDOM" le page mal esa vez :D

Por todo lo demas, lo veo bien pero yo me decantaría por atributos más usados: Vida, armadura, ataque, (velocidad de ataque)* etc...
Luego lo del clima y el terreno se podría arreglar como Auras.

GeorgArming

Cita de: xustyx en 11 Agosto 2013, 22:59 PM
Creo que hay que bajar un poco el nivel que requiere tantas condicionesy ir poco a poco.

Por ejemplo lo de simular una batalla lo veo más como la lucha entre dos IA, y crear una IA no es tan complicado en este caso, simplemente puedes hacer que la máquina calcule todos los posibles movimientos con todas sus tropas y haga una estadistica de cual movimiento es el que mas le rinde, y si quieres subirle en nivel, puedes hacer que calcule uno, dos o tres turnos antes de mover, claro esta, que contra mas turnos analice, las posibilidades crecen exponencialmente pero también la IA puede realizar mejores movimientos... aunque no siempre realice el mejor ya que en sus simulaciones puede que gane pero luego cuando mueve y se vuelve a simular realmente la lucha, puede que un "RANDOM" le page mal esa vez :D

Por todo lo demas, lo veo bien pero yo me decantaría por atributos más usados: Vida, armadura, ataque, (velocidad de ataque)* etc...
Luego lo del clima y el terreno se podría arreglar como Auras.

Me parece bien, pero lo de la IA yo lo implementaría después de haber hecho la "base" del simulador. Por ejemplo, propongo esta clase:

Clase unidad
Atributos:
-ID de la unidad.
-Tipo general de unidad (caballería, infantería,...).
-Tipo concreto de unidad (Unidad de caballería pesada,...).
-Nombre de la unidad (Unidad de caballería pesada II,...).
-Número de efectivos.
-Heridos.
-Motivación.
-Estado físico.
-Clima favorable.
-Clima perjuficial.
-Terreno favorable.
-Terreno perjudicial.
-Capacidad de ataque cuerpo a cuerpo.
-Capacidad de defensa cuerpo a cuerpo.
-Capacidad de ataque a distancia.
-Capacidad de defensa a distancia.
-Disciplina táctica (como más elevada, más probable es que una unidad cumpla las órdenes y que lo haga bien).
-Velocidad (en casillas/turno  :D).
-Tipo general de unidad que se le da bien (la caballería tiene bonificación contra la infantería en general).
-Tipo concreto de unidad que se le da bien.
-Tipo general de unidad que se le da mal.
-Tipo concreto de unidad que se la da mal.
-Nutrición.
-Capacidad de resistencia.


De momento se me ocurre esto. ¿Qué os parece? Saludos.

za.asi

#7
También se podría añadir los factores que alteran la moral:
- resultados ultimas 5 batallas
- clima + terreno +/-
- situación relativa en el ejercito propio y enemigo
- ...


Ademas se podría ir subiendo la dificultad:
- primera batalla la IA calcula un turno de antelacion
- segundo dos
- tercera tres


Se puede buscar manera de atravesar obstáculos:
- se tarda un turno en talar una casilla de bosque y otro mas en construir un balsa

Si se implementa el aumento progresivo de dificultad se puede aumentar el nivel de las unidades supervivientes aumentando sus características (ataque, defensa, velocidad...) o la moral

Sobretodo creo que es importante agregar el factor random a los combates, teniendo en cuenta las habilidades de las unidades.

GeorgArming

#8
Cita de: za.asi en 12 Agosto 2013, 00:18 AM
Tambien se podria añadir los factores que alteran la moral:
- resultados ultimas 5 batallas
- clima + terreno +/-
- situacion relativa en el ejercito propio y enemigo
- ...

Ademas se podria ir subiendo la dificultad:
- primera batalla la IA calcula un turno de antelacion
- segund dos
- tercera tres

Se puede buscar manera de atravesar obstaculos:
- se tarda un turno en talar una casilla de bosque y otro mas en construir un balsa

Si se implementa el aumento progresivo de dificultad se puede aumentar el nivel de las unidades superviientes aumentando sus caracterusticas ( ataque, defensa, velocidad...) o la moral

Sobretodo creo que es importante agregar el factor random a los combates, teniendo en cuenta lS habilidades de las unidades.

Gracias por tus sugerencias. Estaría bien lo de la IA pero primero tenemos que crear la base.

En cuanto a la motivación, también le podría afectar si el general está en la batalla o no, cómo los trata el general, resultados como has dicho,... Lo detallaremos del todo cuando pongamos el pseudocódigo. Lo vamos poniendo ya?

Lo de tardar más o menos según el terreno está bien. Esto lo deberíamos meter en el objeto Casilla. Lo de la balsa no lo veo porque en medio de una batalla no es muy realista, pero por ejemplo atravesar zonas pantanosas reduciría la velocidad un tanto por ciento.

En cuanto al factor random, sí, es muy importante. Lo que debería hacer el simulador es calcular probabilidades teniendo en cuenta los factores que hemos dicho, y luego si por ejemplo sale un 70% que pase una cosa, el simulador randomiza y si sale 90 será que no pasará y si sale 60 sí pasará.

xustyx

#9
Cita de: GeorgArming en 12 Agosto 2013, 00:28 AM
En cuanto al factor random, sí, es muy importante. Lo que debería hacer el simulador es calcular probabilidades teniendo en cuenta los factores que hemos dicho, y luego si por ejemplo sale un 70% que pase una cosa, el simulador randomiza y si sale 90 será que no pasará y si sale 60 sí pasará.

Este metodo lo utilizaria para aplicarlo a la IA, en cuanto a los combates concretos, yo me decantaria por simular la lucha realmente y olvidarno de estadisticas XD, así aun sería mas aleatorio.

Me refiero a que si calculamos la ventaja que tiene un contrincante VS otro, se puede deducir facilmente quien ganara, por ejemplo uno tiene un 60% de ganar (se tira un dado del 1 al 10, si cae entre el 1 y el 6 gana, si no pierde), bueno, pues este metodo me parece fantastico para la IA, pero cuando una unidad decide atacar yo simularia realmente el combate en el turno.

Por otra parte tenemos que definir bastante bien los atributos principales y los secundarios...

Para mi los principales son los contables, y los secundarios son incontables, los atributos secundarios incrementan en % atributos principales, mientras que por otro lado tambien tenemos otra clase de condiciones que se aplican como auras despues de realizar los calculos anteriores.

Una vez hecho esto se simula las dos unidades golpeandose, utilizando randoms para ver si una unidad mete "Critico, esquiva, cae un trueno y despista al otro XDDDDD etc etc..." creo que es mejor aplicar un random a cada golpe así la suerte decidirá, aunque uno de primeras tenga más posibilidades de ganar, nunca se sabe, y bueno el combate acaba cuando uno de los dos se queda sin Vida.

Que os parece???