4 votes

Mécanisme de pool de dés dés désavantageux/adversaire qui élimine les dés supérieurs à 1 du pool et y ajoute des 1.

Je travaille sur un système de pool de dés pour les compétences et les actions à utiliser dans un nouveau système.

Dans ce système, tout jet de 1 affectera négativement le résultat de la résolution d'une action utilisant un pool de dés.

Dans ce cas, j'essaie de modéliser la probabilité de chaque résultat lors d'un lancer de 2d4 avec 1d4 de désavantage/adversité en regardant le total des 2 plus hauts dés lancés (ce qui dans ce cas est la totalité des 2d4) après le calcul du désavantage.

Le désavantage est censé fonctionner de la manière suivante :

  • Tous les dés de désavantage qui obtiennent un 1 sont ajoutés à la réserve.
  • Tout dé de désavantage dont le résultat est supérieur à 1 retire du pool le dé le plus élevé de valeur égale ou inférieure si le dé en question est supérieur à 1 (le dé de désavantage lui-même n'est pas ajouté).

Edit : Quelques exemples de séquences ici, la séquence de dés principale est listée en premier puis le dé de désavantage.

  • 23, 1 -> 23 avec le 1 supplémentaire ajouté, le total des 2 premiers dés est de 5.
  • 23, 4 -> 4 élimine 3, il ne reste que 2.
  • 12, 2 -> 2 élimine 2, ne laissant qu'un seul.
  • 44, 4 -> 4 élimine un 4, laissant 4.
  • 24, 1 -> 24 avec le 1 supplémentaire ajouté, le total des 2 premiers dés est de 6

Comme il n'est pas possible de retirer des éléments des séquences, j'essaie de construire la séquence DISADVANTAGEPROCESSED tout en excluant les dés qui seraient retirés du pool afin que la fonction puisse ensuite retourner le total du nombre de dés demandé spécifié dans le paramètre POSTOOUTPUT calculé à partir de cette séquence.

J'ai travaillé sur un code similaire à celui ci-dessous pendant plusieurs jours et, bien que l'avantage (et le passage de la séquence de dés directement sans avantage ou désavantage) fonctionne, je n'obtiens toujours pas ce que je crois être les résultats corrects que j'ai obtenus en traçant manuellement les 64 résultats possibles.

Le mécanisme d'ajout des dés de désavantage qui obtiennent 1 au pool semble fonctionner, comme je l'ai déterminé en exécutant le code avec POSSTOOUTPUT réglé sur {3}.

J'ai l'impression de passer à côté de quelque chose d'évident et je vais continuer à travailler sur le sujet, mais toute idée ou conseil que vous pourriez me donner serait très apprécié.

LOWMAX: 1
DICESEQ: 2d4
ADVANTAGESEQ: {}
DISADVANTAGESEQ: 1d4
POSTOOUTPUT: {1..2}

function: POSITION:s DICEPARAM:s with ADVANTAGEPARAM:s advantage and DISADVANTAGEPARAM:s disadvantage
{
 ADVANTAGE: 0
 ADVANTAGEPROCESSED: {}
 DISADVANTAGEPROCESSED: {}

\ Other code omitted due to irrelevance \

 if DISADVANTAGEPARAM != {} & ADVANTAGEPARAM = {} \If there is only disadvantage \
 {

  loop Y over {1..#DISADVANTAGEPARAM}  \ Have also tried loop Y over DISADVANTAGEPARAM and not used the indexing \
  {
    REMOVED: 0 \ This flag is to be set when a die has been removed from the pool for the current disadvantage die in the sequence \
   loop X over {1..#DICEPARAM} \ Have also tried loop X over DICEPARAM, no different \
   {
  \ Have also tried without the whole loops and just gone with code like if DICEPARAM > DISADVANTAGEPARAM hoping that the mechanics of passing dice collections to the function as parameters that expect sequences will do the job, still no luck \
    if X@DICEPARAM>Y@DISADVANTAGEPARAM | X@DICEPARAM <=LOWMAX
    {
     DISADVANTAGEPROCESSED: {DISADVANTAGEPROCESSED, X@DICEPARAM}
    }

    if X@DICEPARAM <= Y@DISADVANTAGEPARAM
    {
     if !REMOVED
     {
      REMOVED: 1
     }
     else
     {
      DISADVANTAGEPROCESSED: {DISADVANTAGEPROCESSED, X@DICEPARAM}
     }
    }

    if Y@DISADVANTAGEPARAM <= LOWMAX
    {
     DISADVANTAGEPROCESSED: {DISADVANTAGEPROCESSED, Y@DISADVANTAGEPARAM}
    }

   }
  }

  COMBINED: [sort {DISADVANTAGEPROCESSED}]
  result: POSITION@COMBINED

  }

}

output [POSTOOUTPUT DICESEQ with ADVANTAGESEQ advantage and DISADVANTAGESEQ disadvantage] named "[DICESEQ] with [ADVANTAGESEQ] advantage and [DISADVANTAGESEQ] disadvantage"
```

4voto

trjh Points 11

Je suis d'accord, la manipulation des séquences intégrée à AnyDice craint un peu. On pourrait penser que quelque chose comme {1,3,5}@ROLL retournerait une séquence de trois éléments contenant les première, troisième et cinquième valeurs dans ROLL mais non, il renvoie en fait le somme de ces valeurs.

Cependant, nous pouvons toujours écrire une fonction pour faire ce que nous voulons :

function: select INDICES:s from SEQUENCE:s {
  RESULT: {}
  loop INDEX over INDICES {
    RESULT: {RESULT, INDEX@SEQUENCE}
  }
  result: RESULT
}

Maintenant, [select {1,3,5} from ROLL] fera en fait ce que nous voulions {1,3,5}@ROLL à faire, du moins tant que ROLL est une séquence.

(S'il s'agit d'un pool de dés, la fonction fonctionnera toujours techniquement, mais les résultats seront automatiquement additionnés en un nombre avant d'être rassemblés dans un dé, ce qui revient à faire la même chose que {1,3,5}@ROLL mais plus lentement).

En utilisant cette fonction d'aide pratique, nous pouvons ensuite écrire une fonction pour mettre en œuvre votre mécanisme d'élimination :

function: ROLL:s drop highest up to LIMIT:n unless EXCLUDE:s {
  \ assumes ROLL is sorted in descending order! \
  OFFSET: 1 + (ROLL > LIMIT) 
  if OFFSET > #ROLL | OFFSET@ROLL = EXCLUDE { result: ROLL }
  result: [select {1 .. OFFSET-1, OFFSET+1 .. #ROLL} from ROLL]
}

Notez l'astuce ici : en supposant que la séquence des valeurs obtenues est triée par ordre décroissant (comme AnyDice trie les pools de dés par défaut), nous pouvons trouver la position de la plus haute valeur inférieure ou égale à la limite dans la séquence simplement en comptant le nombre de valeurs dans la séquence qui sont supérieures à la limite et en ajoutant un.

Maintenant, nous sommes prêts à mettre en œuvre votre mécanique complète comme une fonction :

function: roll ROLL:s disadvantage DIS:s {
  POOL: [sort ROLL]
  loop D over DIS {
    if D > 1 { POOL: [POOL drop highest up to D unless 1] }
  }
  result: {1,2}@POOL
}

Voici l'ensemble du programme mis en place ainsi que quelques cas de test.

Notez que je trie de manière redondante l'entrée dans la fonction ci-dessus, juste au cas où. De cette façon, le code ne se comportera pas bizarrement si vous appelez accidentellement la fonction avec des données de test manuel mal triées. En particulier, j'ai rencontré ce problème moi-même lorsque j'ai testé le code avec vos exemples de cas, et j'ai décidé d'ajouter le tri pour réduire les risques d'erreur :

output [roll {2,3} disadvantage 1] named "2,3 with extra 1 added, total of first 2 dice is 5"
output [roll {2,3} disadvantage 4] named "4 knocks out 3, leaving only 2"
output [roll {1,2} disadvantage 2] named "2 knocks out 2, leaving only 1"
output [roll {4,4} disadvantage 4] named "4 knocks out one 4, leaving 4"
output [roll {2,4} disadvantage 1] named "2,4 with extra 1 added, total of first 2 dice is 6"

Screenshot of AnyDice test output

Et voici la distribution réelle des résultats avec 2-4 dés normaux et un dé de désavantage :

Screenshot of AnyDice output

(Le code lié ci-dessus calcule également les résultats pour les dés d'inconvénients 0 et 2, mais si vous les représentez graphiquement en une seule fois, le résultat n'est qu'un fouillis de lignes qui se croisent).


Ps. D'après votre question, je ne suis pas sûr à 100% que vous vouliez compter les uns comme faisant partie de la somme s'ils apparaissent parmi les deux premiers dés restants après l'application de la mécanique d'élimination. Si non, vous pouvez changer la dernière ligne de la fonction principale par ex :

POOL: [select {1,2} from POOL]
result: POOL - (POOL = 1)

Cela fonctionne en tronquant d'abord la séquence POOL à ses deux premiers éléments, puis en fait la somme et en soustrait le nombre de uns. Alternativement, nous pourrions écrire une autre fonction d'aide pour supprimer explicitement les uns de la séquence avant de l'additionner, par exemple comme ceci :

function: remove EXCLUDE:s from SEQUENCE:s {
  RESULT: {}
  loop VALUE over SEQUENCE {
    if VALUE = EXCLUDE { RESULT: {RESULT, VALUE} }
  }
  result: RESULT
}

et l'utiliser comme ceci dans la fonction principale :

result: {1,2}@[remove 1 from POOL]

Vous pouvez également vous intéresser à la distribution du nombre de "1" obtenus pour différentes tailles de dés, afin d'estimer le risque d'"effets négatifs" qu'ils déclenchent. Le problème ici est que, bien sûr, le nombre de "un" sera fortement lié à la somme des deux premiers lancers, et ce d'une manière assez compliquée.

Une façon de visualiser cette distribution combinée serait de tracer le graphique de la distribution conditionnelle du nombre de uns, étant donné que la somme des deux premiers rouleaux est \$N\$ pour chaque somme possible \$N\$ par exemple comme ceci :

function: count ones in ROLL:s disadvantage DIS:s if sum is TARGET:n {
  POOL: [sort ROLL]
  loop D over DIS {
    if D > 1 { POOL: [POOL drop highest up to D unless 1] }
  }
  SUM: {1,2}@POOL
  if SUM != TARGET { result: d{} } \ wrong sum, skip this result! \
  result: (ROLL = 1) + (DIS = 1)   \ else return total number of ones \
}

Voici un graphique du nombre moyen de uns pour chaque résultat possible avec deux dés normaux et un dé de désavantage, illustrant la complexité de la distribution :

Screenshot of AnyDice summary output

Sinon, vous pouvez essayer codage de la somme et du nombre de uns en un seul nombre de résultats. par exemple, comme ceci :

function: roll ROLL:s disadvantage DIS:s {
  POOL: [sort ROLL]
  loop D over DIS {
    if D > 1 { POOL: [POOL drop highest up to D unless 1] }
  }
  SUM: {1,2}@POOL
  ONES: (ROLL = 1) + (DIS = 1)
  result: 10*SUM + ONES
}

La ligne result: 10*SUM + ONES ajoute effectivement le nombre de uns comme chiffre supplémentaire après la somme, de sorte que, par exemple, un résultat de 42 signifie "les deux premiers dés font 4 après le KO, avec 2 uns au total".

Hélas, la sortie qui en résulte Bien qu'il soit très riche en informations, il ressemble à un fouillis lorsqu'il est tracé (puisqu'il s'agit essentiellement de réduire un graphique bidimensionnel à une seule dimension). Il est toujours possible d'exporter le résultat, par exemple dans une feuille de calcul, et de le représenter plus facilement.

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