Actualmente estoy lidiando con un sistema de combate multijugador donde el daño infligido por los jugadores siempre se multiplica por un factor aleatorio entre 0.8 y 1.2.
En teoría, un RNG verdaderamente aleatorio puede producir el mismo número muchas veces (ver el dilema de Tetris ). Esto podría resultar en una partida en la que el jugador siempre está haciendo un daño muy alto, mientras que el otro siempre hace un daño muy bajo.
¿Qué puedo hacer para asegurarme de que esto no suceda? ¿Son algunos RNG mejores que otros para evitar la repetición?
algorithm
multiplayer
random
Usuario no encontrado
fuente
fuente
Respuestas:
Puede resolverlo de la misma manera que lo hace Tetris, haciendo una lista preestablecida de resultados de daño y barajando.
Digamos que sabes que el jugador causará daños de 0.8x a 1.2x con una distribución lineal. Tome la lista [0.8, 0.9, 1.0, 1.1, 1.2]. Al azar , se obtiene, por ejemplo, [1.2, 1.0, 0.8, 0.9, 1.1].
La primera vez que el jugador inflige daño, inflige 1.2x. Entonces 1x. Luego, etc., a 1.1x. Solo cuando la matriz está vacía, debe generar y barajar una nueva matriz.
En la práctica, es probable que desee hacer esto en más de 4 matrices a la vez (por ejemplo, comience con [0.8,0.8,0.8,0.8,0.9,0.9,0.9,0.9, ...]). De lo contrario, el período de la secuencia es lo suficientemente bajo como para que los jugadores puedan determinar si su próximo golpe es "bueno" o no. (Aunque eso también puede agregar más estrategia al combate, como en la tabla Hoimi de Dragon Quest IX , que la gente descubrió cómo investigar mirando los números de curación y los ajustes hasta que se garantice una caída rara).
fuente
De hecho, escribí un código para hacer esto . La esencia de esto es usar estadísticas para corregir rayas desafortunadas. La forma en que puede hacer esto es hacer un seguimiento de cuántas veces se ha producido el evento y utilizarlo para sesgar el número generado por el PRNG.
En primer lugar, ¿cómo hacemos un seguimiento del porcentaje de eventos? La manera ingenua de hacer esto sería mantener todos los números generados en la memoria y promediarlos: lo que funcionaría pero es terriblemente ineficiente. Después de pensar un poco, se me ocurrió lo siguiente (que es básicamente un promedio móvil acumulativo ).
Tome las siguientes muestras de PRNG (donde procesamos si la muestra es> = 0.5):
Tenga en cuenta que cada valor contribuye a 1/5 del resultado final. Miremos de otra manera:
Observe que
0
contribuye al 50% del valor y1
contribuye al 50% del valor. Tomado un poco más lejos:Ahora los primeros valores aportan el 66% del valor y el último 33%. Básicamente podemos destilar esto al siguiente proceso:
Ahora necesitamos sesgar el resultado del valor muestreado del PRNG, porque vamos por un porcentaje de probabilidad aquí, las cosas son mucho más fáciles (en comparación con, por ejemplo, cantidades aleatorias de daño en un RTS). Esto va a ser difícil de explicar porque "se me ocurrió". Si el promedio es más bajo, significa que debemos aumentar las posibilidades de que ocurra el evento y viceversa. Entonces algunos ejemplos
Ahora, lo que se me ocurrió 'es que en el primer ejemplo, el 83% era solo "0.5 de 0.6" (en otras palabras, "0.5 de 0.5 más 0.1"). En términos de eventos aleatorios, eso significa:
Entonces, para generar un evento, básicamente usarías el siguiente código:
Y por lo tanto, obtienes el código que puse en la esencia. Estoy bastante seguro de que todo esto se puede usar en el escenario de caso de daño aleatorio, pero no me he tomado el tiempo para resolverlo.
Descargo de responsabilidad: se trata de estadísticas nacionales, no tengo educación en el campo. Sin embargo, mis pruebas unitarias sí pasan.
fuente
samples
en su valor máximo (en este caso, 100) desde el principio. De esa manera, el RNG no necesita 99 iteraciones para estabilizarse. De cualquier manera, la única desventaja que puedo ver con este método es que no garantiza la equidad, simplemente garantiza un promedio constante.total = (average / 2) + desired
.Lo que está pidiendo es en realidad lo contrario de la mayoría de los PRNG, una distribución no lineal. Simplemente coloque algún tipo de lógica de rendimientos decrecientes en sus reglas, suponiendo que todo sobre 1.0x sea un "golpe crítico" de algún tipo, solo diga que cada ronda sus posibilidades de obtener un crítico aumentan en X, hasta que obtenga uno en en qué punto se restablecen a Y. Luego haces dos tiradas cada ronda, una para determinar el crítico o no, y luego otra para la magnitud real.
fuente
Sid Meier tuvo un excelente discurso en GDC 2010 sobre este tema y los juegos de Civilization. Intentaré encontrar y pegar el enlace más tarde. En esencia, la aleatoriedad percibida no es lo mismo que la aleatoriedad verdadera. Para que las cosas se sientan justas, debe analizar los resultados anteriores y prestar atención a la psicología de los jugadores.
Evite las rachas de mala suerte a toda costa (si los dos turnos anteriores fueron desafortunados, el próximo debe garantizar que tenga suerte). El jugador debe ser siempre más afortunado que el oponente AI.
fuente
Use un sesgo cambiante
La distribución general estará sesgada por la siguiente fórmula:
Tome este número y escale adecuadamente al rango deseado.
Cada vez que un jugador ruede favorablemente, resta del sesgo. Cada vez que el jugador ruede desfavorablemente, agregue al sesgo. La cantidad modificada podría ser escalada según cuán (des) favorable sea la tirada o podría ser una cantidad fija (o una combinación). Deberá ajustar valores específicos para adaptarse a la sensación que busca.
fuente