Estoy en el proceso de crear un nuevo juego simple en dispositivos móviles y he pasado varios días en la siguiente parte.
Por simplicidad, digamos que tengo dos luchadores. El único atributo de ellos es Ataque y Defensa. Cuando los primeros ataques, lo único que importa es el ataque de él y la defensa del oponente. Y viceversa.
No tienen equipo, artículos, resistencia o salud. Solo ataque vs defensa.
Ejemplo:
Luchador 1:
Ataque: 50, Defensa: 35
Luchador 2:
Ataque 20, Defensa: 80
El proceso de lucha será solo un ataque que determinará el ganador. Por lo tanto, no hay múltiples ataques o rondas. No quiero que sea determinista, pero agregue una versión ligera de inesperado. Un luchador con un ataque más bajo podrá ganar a otro luchador con una defensa más alta (pero, por supuesto, no siempre)
Mi primera idea fue hacerlo lineal y llamar a un generador uniforme de números aleatorios.
If Random() < att1 / (att1 + def2) {
winner = fighter1
} else {
winner = fighter2
}
Ejemplo con ataque 50 y defensa 80, el luchador atacante tendrá alrededor del 38% para ganar. Sin embargo, me parece que lo inesperado está demasiado lejos y que los peores peleadores ganarán mucho.
Me preguntaba cómo has trabajado en situaciones similares.
PD. Busqué mucho en este QnA y en otras fuentes y encontré preguntas similares mencionadas como demasiado amplias para SE. Pero esos han tenido muchos atributos, armas, artículos, clases, etc. que podrían hacerlo demasiado complicado. Creo que mi versión es mucho más simple para encajar en el estilo QnA del SE.
Respuestas:
Si desea que los resultados de su pelea sean más predecibles pero no completamente deterministas, tenga lo mejor de n sistema.
Repita los
n
tiempos de pelea (donden
debería haber un número desigual) y declare al combatiente el ganador que ganó con más frecuencia. Cuanto mayor sea su valor porn
menos sorpresas, ganará y perderá.Este sistema solo funciona en el caso especial donde una pelea es un simple resultado binario de ganar o perder. Cuando un combate tiene resultados más complejos, como cuando el ganador todavía pierde algunos puntos de golpe dependiendo de cuán cerca estuvo la victoria, este enfoque ya no funciona. Una solución más general es cambiar la forma de generar números aleatorios. Cuando genera múltiples números aleatorios y luego toma el promedio, los resultados se agruparán cerca del centro del rango y los resultados más extremos serán más raros. Por ejemplo:
tendrá una curva de distribución como esta:
(Imagen cortesía de anydice : una herramienta realmente útil para diseñar fórmulas mecánicas de juego que implican aleatoriedad, no solo para juegos de mesa)
En mi proyecto actual estoy usando una función auxiliar que permite establecer un tamaño de muestra arbitrario:
fuente
+
lugar de*
o no entendí lo que hace?Esto es lo que solía determinar el ganador de una batalla en mi applet Imitator de Lords of Conquest. En este juego, similar a tu situación, solo hay un valor de ataque y un valor de defensa. La probabilidad de que el atacante gane es mayor cuantos más puntos tenga el atacante, y menos puntos tenga la defensa, con valores iguales que evalúan un 50% de probabilidad de que el ataque tenga éxito.
Algoritmo
Lanza una moneda al azar.
1a. Jefes: la defensa pierde un punto.
1b. Colas: las cabezas pierden un punto.
Si tanto la defensa como el atacante aún tienen puntos, regrese al paso 1.
Quien tenga 0 puntos pierde la batalla.
3a. Atacante hasta 0: el ataque falla.
3b. Defensa hasta 0: el ataque tiene éxito.
Lo escribí en Java, pero debería ser fácilmente traducible a otros idiomas.
Un ejemplo
Por ejemplo, supongamos que att = 2 y def = 2, solo para asegurarse de que la probabilidad sea del 50%.
La batalla se decidirá en un máximo de
n = att + def - 1
lanzamientos de monedas, o 3 en este ejemplo (es esencialmente el mejor de 3 aquí). Hay 2 n combinaciones posibles de lanzamientos de monedas. Aquí, "W" significa que el atacante ganó el lanzamiento de la moneda, y "L" significa que el atacante perdió el lanzamiento de la moneda.El atacante gana en 4/8, o 50% de los casos.
Las matemáticas
Las probabilidades matemáticas que surgen de este algoritmo simple son más complicadas que el algoritmo mismo.
El número de combinaciones donde exactamente x Ls viene dado por la función de combinación:
El atacante gana cuando hay entre
0
yatt - 1
Ls. El número de combinaciones ganadoras es igual a la suma de combinaciones de a0
travésatt - 1
, una distribución binomial acumulativa:La probabilidad de que el atacante ganadora es w divide por 2 n , una probabilidad acumulativa binomial:
Aquí está el código en Java para calcular esta probabilidad para valores arbitrarios
att
ydef
:Código de prueba:
Salida:
Observaciones
Las probabilidades son
0.0
si el atacante tiene0
puntos,1.0
si el atacante tiene puntos pero la defensa tiene0
puntos,0.5
si los puntos son iguales, menos que0.5
si el atacante tiene menos puntos que la defensa, y mayores que0.5
si el atacante tiene más puntos que la defensa .Tomando
att = 50
ydef = 80
, necesitaba cambiar aBigDecimal
s para evitar el desbordamiento, pero tengo una probabilidad de aproximadamente 0.0040.Puede acercar la probabilidad a 0,5 cambiando el
att
valor para que sea el promedio de los valoresatt
ydef
. Att = 50, Def = 80 se convierte en (65, 80), lo que arroja una probabilidad de 0.1056.fuente
Puede modificar el ataque mediante un número aleatorio muestreado de una distribución normal. De esta manera, la mayoría de las veces el resultado será el esperado, pero ocasionalmente un ataque más alto perderá contra una defensa más baja o un ataque más bajo ganará contra una defensa más alta. La probabilidad de que esto ocurra será menor a medida que aumente la diferencia entre ataque y defensa.
La función
norm(x0, sigma)
devuelve un flotador muestreado de una distribución normal centrada en x0, con desviación estándar sigma. La mayoría de los lenguajes de programación proporcionan una biblioteca con dicha función, pero si desea hacerlo usted mismo, eche un vistazo a esta pregunta . Tendría que ajustar sigma de modo que 'se sienta bien', pero un valor de 10-20 podría ser un buen lugar para comenzar.Para algunos valores sigma, la probabilidad de victoria para un dado se
att1 - def2
ve así:fuente