Aqui está uma simples solução "força bruta" do AnyDice para o seu problema:
function: brawl A:s vs B:s {
SA: A >= 1@B
SB: B >= 1@A
if SA = SB { result: (A > B) - (A < B) }
else { result: SA - SB }
}
function: set element I:n in SEQ:s to N:n {
NEW: {}
loop J over {1 .. #SEQ} {
if I = J { NEW: {NEW, N} }
else { NEW: {NEW, J@SEQ} }
}
result: NEW
}
function: brawl A:s vs B:s with optional swap {
AX: [sort [set element #A in A to 1@B]]
BX: [sort [set element 1 in B to #A@A]]
NOSWAP: [brawl A vs B]
SWAP: [brawl AX vs BX]
result: [highest of NOSWAP and SWAP]
}
output [brawl 3d6 vs 3d6 with optional swap] named "A vs B Damage"
A função [brawl A vs B]
faz exatamente a mesma coisa que no seu código original (mesmo que eu ajustei um pouco), enquanto a função de ajuda [set element I in SEQ to N]
é de esta resposta . A nova função [brawl A vs B with optional swap]
apenas chama a primeira função duas vezes, uma vez com o menor dado de A trocou com o maior dado de B e uma vez sem, e retorna o melhor resultado dos dois.
function: brawl A:s vs B:s with optional swap {
if #A@A >= 1@B {
result: [brawl A vs B]
}
AX: [sort [set element #A in A to 1@B]]
BX: [sort [set element 1 in B to #A@A]]
result: [brawl AX vs BX]
}
Como alternativa, aqui está um programa em Python que calcula a mesma coisa , usando (uma versão ligeiramente modificada) do gerador de conjuntos de dados de esta resposta :
# generate all possible sorted NdD rolls and their probabilities
# see http://en.wikipedia.org/wiki/Multinomial_distribution for the math
# original: https://rpg.stackexchange.com/questions/63120/anydice-help-ore-like-resolution/65440#65440
# (this version modified to return rolls as simple n-tuples of integers, sorted in descending order)
factorial = [1.0]
def dice_pool(n, d):
for i in range(len(factorial), n+1):
factorial.append(factorial[i-1] * i)
nom = factorial[n] / float(d)**n
for roll, den in _dice_pool(n, d):
yield roll, nom / den
def _dice_pool(n, d):
if d > 1:
for i in range(0, n+1):
highest = (d,) * i
for roll, den in _dice_pool(n-i, d-1):
yield highest + roll, den * factorial[i]
else:
yield (d,) * n, factorial[n]
def brawl_with_swap(rollA, rollB):
# optionally swap A's lowest roll with B's highest:
minA = rollA[-1]
maxB = rollB[0]
if minA < maxB:
rollA = sorted(rollA[:-1] + (maxB,), reverse=True)
rollB = sorted(rollB[1:] + (minA,), reverse=True)
# scoring:
scoreA = sum(x >= rollB[0] for x in rollA)
scoreB = sum(x >= rollA[0] for x in rollB)
if scoreA != scoreB:
return scoreA - scoreB
else:
return (rollA > rollB) - (rollA < rollB)
stats = {}
for rollA, probA in dice_pool(3,6):
for rollB, probB in dice_pool(3,6):
result = brawl_with_swap(rollA, rollB)
if result not in stats: stats[result] = 0.0
stats[result] += probA * probB
for result, prob in sorted(stats.items()):
print("%+2d:%8.4f%% %s" % (result, 100*prob, "#" * int(60*prob + 0.5)))
Ao contrário da simulação estocástica de A.B., este código calcula as probabilidades exatas (bem, exatas até a precisão do ponto flutuante, de qualquer forma) dos vários resultados diretamente, enumerando todos os possíveis lançamentos de dados e suas probabilidades, assim como o AnyDice. É um pouco mais rápido do que AnyDice, no entanto, com o caso 3D6 3D6 vs. tendo apenas cerca de 0,1 segundos e 4d6 vs. 4d6 tendo apenas 0,25 segundos na servidor TIO