Complicated caseiro Game odds de dados, AnyDice ou Troll fórmula ajuda necessária

6

Estou jogando um jogo caseiro e ele usa um sistema um pouco complicado em relação ao treinamento.

Ele funciona rolar 1d10 + bônus contra um número alvo variável, menos "headway". O Headway é obtido se você não conseguir atingir o número alvo modificado, e quanto é determinado rolando um dado específico determinado por quão bom você é nesse assunto. O "progresso" é cumulativo, incidentalmente, e é perdido após o sucesso.

Assim, por exemplo, treinando uma habilidade específica, o número alvo pode ser 10, você tem um bônus de 1 e um dado inicial 1d3. Você ganha um 5 no 1d10, para um total de 6, falhando o teste. Você então rola o 1d3 e ganha um 1. Na próxima vez que treinar essa habilidade, 1d10 + 1 exigiria um teste de 9 para o sucesso (o avanço +1 o levará a 10). Se você falhar, você rola novamente e recebe um 3, o que significa que na próxima vez que você rolar, você só precisa de um teste de 6 (você agora tem um avanço de 1 + 3).

Qual fórmula seria necessária para que possamos determinar as chances de sucesso de vários testes desse tipo?

    
por BFldyq 19.08.2014 / 09:27

3 respostas

ANYDICE NÃO PODE RESOLVER ESTE PROBLEMA

Eu tentei o programa abaixo, mas ele não funcionou corretamente, as chances de que ele retorne não estão corretas. Eu executei meu próprio programa com 1 milhão de iterações e obtive os seguintes resultados:

Você pode executar o programa aqui: link

Minha tentativa anterior de correção é aqui Mas os resultados não estão corretos.

set "maximum function depth" to 30
TARGET: 10
NUM_OF_ROLLS: 1
BONUS: 1
function: traintarget of TT:n with roll R:n rollnumber N:n {
  if R>=TT {result: N}
  else {
    NUM_OF_ROLLS: N + 1
    TARGET: TT - 1d3
    result: [traintarget of TARGET with roll R rollnumber NUM_OF_ROLLS] 
  }
}

output [traintarget of TARGET with roll (1d10+BONUS) rollnumber NUM_OF_ROLLS] named "Number of Rolls to Reach Target"
    
19.08.2014 / 10:30

Eu simplesmente não consegui fazê-lo funcionar no AnyDice, então aqui está um script do Python 3 que calcula o número de tentativas iteration times e produz os resultados em uma boa tabela. É muito mais lento que a resposta AnyDice do GMNoob e os resultados não coincidem.

from math import sqrt
import random

bonus = 1
iterations = 10000000

def d(x): return random.randint(1,x)

results = [0]*(10-bonus)
for i in range(iterations):
    target = 10
    tries = 1
    success = False
    while not success:
        success = (d(10)+bonus>=target)
        if success:
            break
        else:
            tries+=1
            target-=d(3)
    results[tries-1]+=1

average = sum([results[i]*(i+1) for i in range(len(results))])/iterations
deviation = sqrt(sum([results[i]*(i-average)**2 for i in range(len(results))])/(iterations-1))

print("Average: {:.3f}+-{:.3f}".format(average,deviation))
print("Number of Tries | "+" | ".join([str(x).rjust(6) for x in range(1,1+len(results))]))
print("Chance          | "+" | ".join([str(round(x/iterations*100,3)).rjust(6) for x in results]))

Experimente on-line em Ideone .

Eu corri com 10000000 iterações na minha máquina, com os seguintes resultados:

Average: 2.532+-1.509
Number of Tries |      1 |      2 |      3 |      4 |      5 |      6 |      7 |      8 |      9
Chance          | 19.997 | 32.006 | 28.262 | 14.904 |  4.198 |  0.591 |  0.042 |  0.001 |    0.0
    
19.08.2014 / 11:59

Aqui está uma rotina Python mais rápida que fornece resultados exatos (até os limites de precisão numérica, de qualquer forma):

# Target number and initial bonus + headway:
target = 10
bonus = 1
headway = 0

# Die sizes:
attempt_die = 10  # 1d10
headway_die = 3   # 1d3


# print header:
print "target: {0}, bonus {1:+d}, initial headway {2}".format(
    target, bonus, headway)
print "rolling 1d{0} for success, 1d{1} for headway".format(
    attempt_die, headway_die)

# initial headway distribution:
distribution = [0.0] * (max(target - bonus, headway) + 1)
distribution[headway] = 1.0

def clamp(probability):
    return min(1, max(0, probability))

cumulative = 0.0  # total success probability so far
expected = 0.0  # expected number of attempts needed

for attempt in xrange(1, 1 + max(1, target - bonus - headway)):
    success = 0.0  # total success probability for this attempt

    # loop through possible current headway values (in reversed order,
    # to avoid having to copy the distribution list):
    for curr_hw in reversed(xrange(len(distribution))):
        headway_prob = distribution[curr_hw]
        if headway_prob == 0: continue

        # probability of rolling below the target:
        failure_prob = clamp(float(target - bonus - curr_hw - 1) / attempt_die)
        success += headway_prob * (1 - failure_prob)

        # if the initial roll fails, increment headway (if headway exceeds
        # target - bonus, set it to that value so that next roll will
        # automatically succeed):
        distribution[curr_hw] = 0
        for roll in xrange(1, 1 + headway_die):
            new_hw = min(curr_hw + roll, len(distribution) - 1)
            distribution[new_hw] += failure_prob * headway_prob / headway_die

    cumulative += success
    expected += success * attempt
    print "success on attempt {0:2d}:".format(attempt), \
        "{0:9.5f}%".format(success * 100), \
        "(cumulative {0:9.5f}%)".format(cumulative * 100)

    # print "headway:", ", ".join(
    #     "{0}: {1:g}%".format(hw, 100 * distribution[hw]) \
    #     for hw in range(len(distribution))
    # )

print "expected number of attempts needed =", expected

Aqui está a saída para target = 10 , bonus = 1 e headway = 0 :

target: 10, bonus +1, initial headway 0
rolling 1d10 for success, 1d3 for headway
success on attempt  1:  20.00000% (cumulative  20.00000%)
success on attempt  2:  32.00000% (cumulative  52.00000%)
success on attempt  3:  28.26667% (cumulative  80.26667%)
success on attempt  4:  14.90370% (cumulative  95.17037%)
success on attempt  5:   4.19664% (cumulative  99.36701%)
success on attempt  6:   0.58975% (cumulative  99.95677%)
success on attempt  7:   0.04180% (cumulative  99.99857%)
success on attempt  8:   0.00142% (cumulative  99.99998%)
success on attempt  9:   0.00002% (cumulative 100.00000%)
expected number of attempts needed = 2.53240636049

Esse código funciona mantendo as probabilidades de todos os possíveis valores de headway atuais no array distribution e atualizando-os com base nas probabilidades dos vários resultados possíveis dos testes de dados.

Se desejar, o código acima pode ser feito para gerar a distribuição de diferentes valores de headway após cada tentativa, descomprometendo a instrução print extra no final do loop externo. (Note que esta não é, estritamente falando, uma distribuição de probabilidade adequada, pois não inclui a probabilidade de que o treinamento já tenha sido bem sucedido. Assim, para tentativas posteriores, as probabilidades de headway somarão um valor estritamente menor que 100%, embora adicionando a probabilidade de sucesso cumulativo irá corrigir isso.)

    
19.08.2014 / 17:08

Tags