Je suis en train de créer un nouveau jeu simple sur mobile et j'ai passé plusieurs jours sur la partie suivante.
Pour simplifier, disons que j'ai deux combattants. Le seul attribut d'entre eux est l'attaque et la défense. Lors des premières attaques, la seule chose qui compte c'est l'attaque de lui et la défense de l'adversaire. Et vice versa.
Ils n'ont pas d'équipement, d'articles, d'endurance ou de santé. Juste attaque contre défense.
Exemple:
Combattant 1:
Attaque: 50, Défense: 35
Combattant 2:
Attaque 20, défense: 80
Le processus de combat ne sera qu'une seule attaque qui déterminera le vainqueur. Donc, pas d'attaques ou de rounds multiples. Je ne veux pas le rendre déterministe, mais ajouter une version légère d'inattendu. Un combattant avec une attaque plus faible pourra gagner un autre combattant avec une défense plus élevée (mais bien sûr pas à chaque fois)
Ma première idée a été de le rendre linéaire et d'appeler un générateur de nombres aléatoires uniforme.
If Random() < att1 / (att1 + def2) {
winner = fighter1
} else {
winner = fighter2
}
Exemple avec attaque 50 et défense 80, le combattant attaquant aura environ 38% à gagner. Cependant, il me semble que l'inattendu est trop loin et que les pires combattants gagneront beaucoup.
Je me demandais comment vous avez travaillé sur des situations similaires.
PS J'ai beaucoup cherché dans cette QnA et d'autres sources et j'ai trouvé des questions similaires mentionnées comme trop larges pour SE. Mais ceux-ci ont eu de nombreux attributs, armes, objets, classes, etc. qui pourraient compliquer les choses. Je pense que ma version est beaucoup plus simple pour l'adapter au style QnA de la SE.
Réponses:
Si vous voulez que vos résultats de combat soient plus prévisibles mais pas complètement déterministes, ayez un système best of n .
Répétez les
n
temps de combat (oùn
devrait être un nombre inégal) et déclarez le combattant vainqueur qui a gagné le plus souvent. Plus votre valeur est élevée,n
moins vous gagnez et perdez de surprises.Ce système ne fonctionne que dans le cas particulier où un combat est un simple résultat binaire de gagner ou de perdre. Lorsqu'un combat a des résultats plus complexes, comme lorsque le gagnant perd toujours des points de vie en fonction de la proximité de la victoire, cette approche ne fonctionne plus. Une solution plus générale consiste à changer la façon dont vous générez des nombres aléatoires. Lorsque vous générez plusieurs nombres aléatoires et que vous prenez ensuite la moyenne, les résultats se regrouperont près du centre de la plage et les résultats plus extrêmes seront plus rares. Par exemple:
aura une courbe de distribution comme celle-ci:
(photo gracieuseté de anydice - un outil vraiment utile pour concevoir des formules de mécanique de jeu qui impliquent le hasard, pas seulement pour les jeux de table)
Dans mon projet actuel, j'utilise une fonction d'assistance qui permet de définir une taille d'échantillon arbitraire:
la source
+
place de*
ou j'ai mal compris ce qu'il fait?C'est ce que j'ai utilisé pour déterminer le vainqueur d'une bataille dans mon applet Lords of Conquest Imitator. Dans ce jeu, similaire à votre situation, il n'y a qu'une valeur d'attaque et une valeur de défense. La probabilité que l'attaquant gagne est plus grande plus l'attaquant a de points et moins la défense a de points, avec des valeurs égales évaluant à 50% de chances de réussite de l'attaque.
Algorithme
Lancez une pièce au hasard.
1a. Têtes: la défense perd un point.
1b. Queues: les têtes perdent un point.
Si la défense et l'attaquant ont encore des points, revenez à l'étape 1.
Celui qui est à 0 point perd la bataille.
3a. Attaquant jusqu'à 0: l'attaque échoue.
3b. Défense jusqu'à 0: l'attaque réussit.
Je l'ai écrit en Java, mais il devrait être facilement traduisible dans d'autres langues.
Un exemple
Par exemple, disons que att = 2 et def = 2, juste pour s'assurer que la probabilité est de 50%.
La bataille sera décidée en un maximum de
n = att + def - 1
lancers de pièces, ou 3 dans cet exemple (c'est essentiellement le meilleur des 3 ici). Il y a 2 n combinaisons possibles de lancer de pièces. Ici, "W" signifie que l'attaquant a gagné le lancer de pièces et "L" signifie que l'attaquant a perdu le lancer de pièces.L'attaquant gagne dans 4/8, soit 50% des cas.
Les maths
Les probabilités mathématiques résultant de cet algorithme simple sont plus compliquées que l'algorithme lui-même.
Le nombre de combinaisons où il y a exactement x Ls est donné par la fonction de combinaison:
L'attaquant gagne lorsqu'il y a entre
0
etatt - 1
Ls. Le nombre de combinaisons gagnantes est égal à la somme des combinaisons de à0
traversatt - 1
, une distribution binomiale cumulative:La probabilité que l'attaquant gagne est w divisée par 2 n , une probabilité cumulée binomiale:
Voici le code en Java pour calculer cette probabilité d'arbitraire
att
et dedef
valeurs:Code de test:
Production:
Observations
Les probabilités sont
0.0
si l'attaquant a des0
points,1.0
si l'attaquant a des points mais la défense a des0
points,0.5
si les points sont égaux, moins que0.5
si l'attaquant a moins de points que la défense, et plus grand que0.5
si l'attaquant a plus de points que la défense .En prenant
att = 50
etdef = 80
, je devais passer àBigDecimal
s pour éviter un débordement, mais j'obtiens une probabilité d'environ 0,0040.Vous pouvez rapprocher la probabilité de 0,5 en modifiant la
att
valeur pour qu'elle soit la moyenne des valeursatt
etdef
. Att = 50, Def = 80 devient (65, 80), ce qui donne une probabilité de 0,1056.la source
Vous pouvez modifier l'attaque par un nombre aléatoire échantillonné à partir d'une distribution normale. De cette façon, la plupart du temps, le résultat sera ce que vous attendez, mais parfois une attaque plus élevée perdra contre une défense inférieure ou une attaque inférieure gagnera contre une défense plus élevée. La probabilité que cela se produise diminue à mesure que la différence entre l'attaque et la défense augmente.
La fonction
norm(x0, sigma)
renvoie un flottant échantillonné à partir d'une distribution normale centrée sur x0, avec un écart-type sigma. La plupart des langages de programmation fournissent une bibliothèque avec une telle fonction, mais si vous voulez la faire vous-même, jetez un œil à cette question . Vous devrez ajuster le sigma de telle sorte qu'il se sente bien, mais une valeur de 10-20 pourrait être un bon point de départ.Pour quelques valeurs sigma, la probabilité de victoire pour une donnée
att1 - def2
ressemble à ceci:la source