2 votes

Utilisation d'instructions if/else imbriquées dans Anydice

J'essaie de déterminer les probabilités de dégâts d'un sort DOT qui oblige la cible à effectuer un jet de sauvegarde à chaque tour pour voir si elle se débarrasse de ses effets. Pour ce faire, j'utilise un tas de if / else chacun avec les dégâts pour un certain nombre de tours, mais pour une raison quelconque, il n'aime pas le formatage :

A: 1d20
B: 1d20
C: 1d20
D: 1d20
E: 1d20
F: 1d20
G: 1d20
H: 1d20
I: 1d20
J: 1d20
if A < 19 {
 if B < 19 {
  if C < 19 {
   if D < 19 {
    if E < 19 {
     if F < 19 {
      if G < 19 {
       if H < 19 {
        if I < 19 {
         if J < 19 {
          output 12d8 + 40d8
         }
         else {
          output 12d8 + 36d8
         }
        else {
         output 12d8 + 32d8
        }
       else {
        output 12d8 + 28d8
       }
      else {
       output 12d8 + 24d8
      }
     else {
      output 12d8 + 20d8
     }
    else {
     output 12d8 + 16d8
    }
   else {
    output 12d8 + 12d8
   }
  else {
   output 12d8 + 8d8
  }
 else {
  output 12d8 + 4d8
 }
else {
 output 12d8
}

Voici le enlace Si quelqu'un peut me dire ce que je fais mal, ce serait formidable.

5voto

trjh Points 11

Toroid a expliqué comment corriger les erreurs dans votre code. Voici comment le simplifier et l'améliorer.

Le mot magique ici est récursivité . En fait, vous voulez écrire une fonction comme celle-ci :

function: damage on following turns {
  result: (d20 < 19) * (4d8 + [damage on following turns])
}

Puis utilisez-le comme suit :

output 12d8 + [damage on following turns]

Aujourd'hui, si vous le faites Vous verrez une courbe à l'aspect étrange avec deux pics et un avertissement :

La profondeur maximale de la fonction a été dépassée, les résultats sont tronqués.

C'est une caractéristique délibérée d'AnyDice : la fonction que j'ai écrite s'appelle elle-même, et continuerait à le faire encore et encore si AnyDice ne la forçait pas à s'arrêter après (par défaut) 10 appels imbriqués. En gros, cela équivaut à forcer l'effet à se terminer après au plus 10 tours, que la cible réussisse sa sauvegarde ou non.

Il s'avère cependant qu'avec un DC de 19, la probabilité que la cible ne réussisse pas la sauvegarde en 10 tours est significative, ce qui signifie que la troncature modifie les résultats que nous obtenons. Heureusement, nous pouvons augmenter la limite en ajoutant quelque chose comme la ligne suivante avant la ligne de commande output déclaration :

set "maximum function depth" to 20

Avec ce réglage nous voyons toujours un deuxième pic dans le graphique, mais il est beaucoup plus petit maintenant, et les dégâts moyens sont sensiblement plus élevés (169,30 CV au lieu de 159,51 CV).

Nous pouvons même modifier la profondeur de récursion maximale au cours du programme afin de représenter les résultats obtenus avec différents paramètres dans un seul graphique, comme par exemple ceci :

loop MAXDEPTH over {10, 20, 30, 40, 50} {
  set "maximum function depth" to MAXDEPTH
  output 12d8 + [damage on following turns] named "max [MAXDEPTH] turns"
}

Les graphiques résultants ressemble à ceci :

AnyDice screenshot


Ps. Mathématiquement, le nombre de tours jusqu'à ce qu'une sauvegarde soit réussie est de réparti géométriquement . Sa valeur moyenne est donc \$ \frac1p -1\$ donde \$p = \frac {21- \mathrm {DC}}{20}\$ est la probabilité de réussite de la sauvegarde. Pour un DC de 19, cela signifie que \$p = \frac {2}{20} = \frac {1}{10}\$ et donc le nombre moyen de tours jusqu'à ce qu'une sauvegarde réussisse est de \$ \frac1p - 1 = 10 - 1 = 9\$ .

Nous pouvons donc calculer les dégâts moyens exacts du sort comme étant les dégâts initiaux moyens ( \$12 \times 4.5 = 54\$ HP pour 12d8) plus les dégâts moyens par tour ( \$4 \times 4.5 = 18\$ HP pour 4d8) multiplié par le nombre moyen de tours jusqu'à la sauvegarde ( \$9\$ comme calculé ci-dessus), pour un total de \$54 + 9 \times 18 = 216\$ HP de dégâts en moyenne. Il s'agit du même nombre moyen qu'AnyDice retournera (approximativement) si vous augmentez la profondeur de récursion maximale à un nombre suffisamment grand (comme, par exemple, 99).

Bien sûr, il faut noter qu'une partie de ces dégâts moyens ne sera infligée qu'au cours d'un très grand nombre de tours, et seulement si la cible est malchanceuse et continue de rater ses sauvegardes (et a suffisamment de PV pour absorber tous ces dégâts). Si vous prévoyez par exemple d'utiliser ce sort dans un combat qui se terminera probablement en peu de tours, les valeurs de dégâts tronquées obtenues en utilisant une profondeur de récursion maximale plus faible peuvent en fait mieux refléter les attentes réalistes du jeu.

3voto

Kyle Pollard Points 257

Le problème avec votre if / else est que vous ne parvenez pas à fermer l'espace de travail. if avant chaque bloc else . Prenons un exemple plus petit :

if I < 19 {
    if J < 19 {
        ...
    }
    else {
        ...
    }
else {
    ...
}

nous pouvons voir que le premier if n'est pas fermée avant que l'instruction else . Vous pouvez remédier à ce problème en introduisant un } avant chaque else . Dans le petit exemple, il s'agirait de :

if I < 19 {
    if J < 19 {
        output 12d8 + 40d8
    }
    else {
        output 12d8 + 36d8
    }
}
else {
    output 12d8 + 32d8
}

Dans l'exemple complet, il s'agit de

A: 1d20
B: 1d20
C: 1d20
D: 1d20
E: 1d20
F: 1d20
G: 1d20
H: 1d20
I: 1d20
J: 1d20
if A < 19 {
 if B < 19 {
  if C < 19 {
   if D < 19 {
    if E < 19 {
     if F < 19 {
      if G < 19 {
       if H < 19 {
        if I < 19 {
         if J < 19 {
          output 12d8 + 40d8
         }
         else {
          output 12d8 + 36d8
         }
        } 
        else {
         output 12d8 + 32d8
        }
       } 
       else {
        output 12d8 + 28d8
       }
      } 
      else {
       output 12d8 + 24d8
      }
     } 
     else {
      output 12d8 + 20d8
     }
    } 
    else {
     output 12d8 + 16d8
    }
   } 
   else {
    output 12d8 + 12d8
   }
  } 
  else {
   output 12d8 + 8d8
  }
 } 
 else {
  output 12d8 + 4d8
 }
} 
else {
 output 12d8
}

Ce nouveau programme donne un message d'erreur différent mais résout votre problème de syntaxe. Le nouveau message d'erreur est le suivant :

calculation error
Boolean values can only be numbers, but you provided "d{?}".
Depending on what you want, you might need to create a function.

Orientations pour cette nouvelle erreur après la if / else La syntaxe a été corrigée et peut être consultée à l'adresse suivante Comment puis-je exécuter un code dépendant de la valeur d'un dé dans AnyDice ?

AlleGamers.com

AlleGamers est une communauté de gamers qui cherche à élargir la connaissance des jeux vidéo.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X