Sintaxe para um sistema de dados único no Anydice?

10
Eu tenho estudado e jogado com um monte de sistemas de dados estranhos por um tempo agora, e Anydice tem sido uma grande ajuda para entender os efeitos de probabilidade de diferentes sistemas. No entanto, encontrei uma que, apesar de divertida na prática, não consegui modelar no Anydice para entender melhor suas curvas.

Um exemplo de saída pode ser descrito como

Maior 2 de 2d6 e 3d8

no entanto Anydice não reconhece essa sintaxe. Eu encontrei uma pergunta semelhante de cerca de um ano atrás, com algumas ótimas respostas, mas essa pessoa estava apenas tentando encontrar o maior resultado único, enquanto eu preciso dos dois maiores resultados de um conjunto de dados irregulares.

O sistema é uma combinação de rolagem e manter dados de passos, com dados de passos para atributos e número de dados rolados, sempre mantendo 2, para habilidades. Atributos aumentam de forma irregular, então a piscina é composta apenas de d6, uma mistura de d6 e d8, ou apenas d8. No caso de um pool misto, cada tipo de dado ocupa metade dele, arredondando em favor do dado maior se a sua piscina for ímpar.

Eu posso descobrir como fazer o loop das variáveis, embora eu possa encontrar uma maneira de organizar essas variáveis.

    
por Narrator 07.12.2016 / 22:55

4 respostas

Na verdade, é muito simples implementar em AnyDice :

function: highest N:n of A:s and B:s {
  result: {1..N} @ [sort {A, B}]
}

function: lowest N:n of A:s and B:s {
  LEN: #A + #B
  result: {LEN-N+1 .. LEN} @ [sort {A, B}]
}

Essas funções pressupõem que você não alterou a ordem de classificação, que é maior para o menor por padrão. Se você revertê-lo, a função "mais alta" começará a retornar os rolos mais baixos e vice-versa.

Você também pode modificar facilmente essas funções para lidar com mais de dois tipos de dados, como em:

function: highest N:n of A:s and B:s and C:s {
  result: {1..N} @ [sort {A, B, C}]
}

function: lowest N:n of A:s and B:s and C:s {
  LEN: #A + #B + #C
  result: {LEN-N+1 .. LEN} @ [sort {A, B, C}]
}

Agora, para as más notícias: essas funções podem ficar muito lentas para grandes conjuntos de dados, porque eles enumeram todos os possíveis rolos por força bruta. O built-in "maior / menor N de DICE " funções são otimizadas usando matemática inteligente para executar muito rapidamente, mesmo para um grande número de dados, mas estes não são. Se você tentar calcular algo como [highest 2 of 10d6 and 10d8] usando essas funções, você quase certamente receberá um erro de tempo limite.

Além disso, é importante notar que, assim como os built-ins, essas funções retornam um dado single que descreve a soma do maior / menor N valores. Assim, por exemplo, [highest 1 of [highest 2 of 1d6 and 1d8]] não é o mesmo de [highest 1 of 1d6 and 1d8] ! Tanto quanto sei, na verdade combinando, e. um d6 e um d8 em um único conjunto de dados no AnyDice simplesmente não são possíveis; você pode ter dados tendenciosos representando qualquer distribuição de probabilidade que você queira, e você pode ter conjuntos de vários dados idênticos , mas você não pode ter diferentes tipos de dados no mesmo conjunto.

No lado positivo, diferentemente dos internos, essas funções funcionam "como esperado" também para entradas de sequência: por exemplo, [highest 2 of {1,2} and {3,4}] retorna 7 = 3 + 4 conforme o esperado, não 10 = 1 + 2 + 3 + 4 como o correspondente [highest 2 of {1,2,3,4}] embutido seria (!). (Isso acontece porque os built-ins são definidos para usar um dado como entrada, não uma sequência e, assim, AnyDice converterá automaticamente uma sequência em um dado somando seus valores antes que a função o veja. Eu meio que considero isso um bug no AnyDice, mesmo que seja tecnicamente funcionando exatamente como documentado.)

    
17.12.2016 / 20:01

Baseado em Tim e respostas iniciais de Trish , eu construí este monstruosidade , que, como a maioria dos meus programas, faz uso pesado do casting / reificação de parâmetros AnyDice para lidar com o processo tedioso de construir e usar dados com funções:

function: X:n upper D:n {
  Y: X / 2
  result: YdD
}
\Dissimilar sizes\
function: X:n smaller D:n {
  Y: X / 2
  Z: X - Y
  E: D - 2
  result: ZdE
}
\Same size, other half\
function: X:n lower D:n {
  Y: X / 2
  Z: X - Y
  result: ZdD
}
function: highest N:n of B:s and L:s {
  J: 1
  K: 1
  SUM: 0
  loop I over {1..N} {
    BC: J@B
    LC: K@L
    if BC >= LC {
      SUM: SUM + BC
      J: J + 1
    }
    else {
      SUM: SUM + LC
      K: K + 1
    }
  }
  result: SUM
}

\Skill is in integral die sizes, smaller better, which are split 
   around odd sizes to make pairs of dissimilar even-sided groups \
function: highest N:n of P:n skill S:n {
  if S / 2 = 0 {
    SFINAL: S
    B: [P lower SFINAL]
  }
  else {
    SFINAL: S + 1
    B: [P smaller SFINAL]
  }
  A: [P upper SFINAL]
  result: [highest N of A and B]
}
output [2 upper 8] + [2 smaller 8] named "1d6 + 1d8, basically"
output [highest 1 of [2 upper 8] and [2 smaller 8]] named "highest 1 of 1d6 and 1d8"
output [highest 1 of 2 skill 7] named "highest 1, pool 2, skill 7"
output [highest 1 of 2d8] named "highest 1 of 2d8"
output [highest 2 of [3 upper 8] and [3 smaller 8]] named "highest 2 of 1d6 and 2d8"
output [highest 2 of 3 skill 7] named "highest 2, pool 3, skill 7"
output [highest 2 of 3 skill 8] named "highest 2, pool 3, skill 8"
output [highest 2 of 5 skill 7] named "highest 2, pool 5, skill 7"

As declarações output dão uma ideia do seu uso, juntamente com os casos de teste para mostrar vários rolos que este código faz e não corresponde. Para uso geral, você deve usar [highest N of P skill S] . Passe o número que você deseja manter, o tamanho do pool (total, de ambos os tamanhos juntos) e a habilidade . "Habilidade" significa o tamanho médio do dado do seu grupo, o qual pode ser um número ímpar e, nesse caso, ser classificado para ter metade do total (arredondado) usando o próximo dado maior e parcial e o restante usando o próximo dado menor e uniforme. Então, uma habilidade de 9 torna-se um pool que é aproximadamente metade de d10s e o restante de d8s. (Não é feita nenhuma tentativa para impedir que você use tamanhos malucos, por exemplo, 2d14 + 3d16, mas a matemática confirma se você deseja rolar esses dados estranhos de qualquer maneira.)

Verificar os resultados significa crescer com o aumento do pool e os tamanhos mantidos, o que é esperado; os limites são mantidos nos dados disponíveis (assim, [highest 2 of 3 skill 7] acaba usando o d8 e um dos d6s na maior parte do tempo, mas não tem o segundo d8 por perto), mas são tão grandes quanto o número de dados rolados do dado maior tamanho do dado. E visualmente, os picos tendem a exibir a característica de "ajuntamento" dos melhores arranjos de N, junto com a inclinação de poços de moldes diferentes. Então eu acredito que isso está correto.

    
08.12.2016 / 09:56

AVISO: APENAS UMA (boa) APROXIMAÇÃO!

.

Número de chances

Depois de brincar com qualquer dado por várias horas e passar por um resultado totalmente falso, finalmente consegui o código a seguir . Ele informa com que frequência cada número ocorre na combinação de dados:

DONE:d6
NONE:2
DTWO:d8
NTWO:3

function: run{
result: (NONE d (DONE =NUMBER)+ NTWO d (DTWO=NUMBER))
}

loop NUMBER over {1..[maximum of DTWO]}{
output [run] named "[NUMBER]s on [NONE][DONE]+[NTWO][DTWO]"
}

Contando

No entanto, isso ainda não é contado e não é amigável para o usuário. Então, mais violinos resultaram nisso:

DONE:d6
NONE:2
DTWO:d8
NTWO:3

function: run{
COUNTER:0
loop RUNS over {1..AMMOUNT}{
COUNTER: COUNTER+ (NONE d (DONE =NUMBER)+ NTWO d (DTWO=NUMBER))=RUNS
}
result: COUNTER
}

loop AMMOUNT over {1..2}{
loop NUMBER over {1..[maximum of DTWO]}{
output [run] named "[AMMOUNT] times [NUMBER] on [NONE][DONE]+[NTWO][DTWO]"
 }}

Isso , pelo menos, nos diz quantos desses casos são 1 ou 2 deles. Nós não temos interesse em casos em que 3 ou mais de um determinado resultado aparecem, já que esses extras terão que ser ignorados. Ainda assim, isso só nos dá as probabilidades simples "uma ou duas vezes" e "duas vezes a mesma", não as probabilidades para os dois mais altos do conjunto.

Agora, isso não está claro ainda.

Sequenciamento

Mas aqui as sequências são úteis: Anydice pode fazer sequências, então podemos fazer uma sequência de NdX e MdY, que é uma única string contendo todos esses números. Ele lida quase como um dado, mas não é um.

DONE:d6
NONE:2
DTWO:d8
NTWO:3

output {DONE:NONE,DTWO:NTWO} named "1,2,3,4,5,6,1,2,3,4,5,6,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8"

Obtendo soluções seqüenciadas

Esta sequência não pode ser usada como um dado como é, devemos transformá-lo em um. Para fazer isso, nós fingimos que é uma super-face N-die (onde N comprimento da seqüência), que é rotulado da mesma maneira que a seqüência, então no nosso exemplo 5x1, 5x2, ..., 5x6, 3x7, 3x8. A parte fácil é que precisamos apenas adicionar um "d" na frente da sequência e obter um dado.

Para obter o resultado final do maior resultado de dois em um set, precisamos apenas lançar um número desses superdices imaginários igual ao número total de dados reais que mergulhamos no dado envolvido.

DONE:d6
NONE:2
DTWO:d8
NTWO:3

output [highest 2 of (NONE+NTWO)d{DONE:NONE,DTWO:NTWO}]

Para o caso de teste NONE: 0, com qualquer NTWO, ele mantém o resultado correto, então aqui estamos, fechando no alongamento em casa! Isso ainda tem alguns erros: para NONE: 1 NTOW: 1 o código permite 15 e 16, o que não deveria ser. Esse caso é na verdade o maior de 1d6 e 1d8, sempre tendo os dois. Não podemos ter 2d6 e 1d8 a partir da premissa. Para 2d6 nós recorremos ao simples caso de manter ambos, então precisamos verificar alguns casos separadamente para corrigir os resultados.

Análise de casos

Diferenciação de casos para NTWO = 0, 1 e mais corrige os resultados com falha nas regiões baixas:

DONE:d6
NONE:2
DTWO:d8
NTWO:0

function: run{
if (NTWO>1){result: [highest 2 of (NONE+NTWO)d{DONE:NONE,DTWO:NTWO}]}
if (NTWO=1){result: [highest 1 of d6]+[highest 1 of d8]}
if (NTWO=0){result: [highest 2 of 2d6]}
}

output [run]

Palavras finais

A solução oferece, na melhor das hipóteses, uma boa aproximação, mas, como Ilmari apontou:

[Y]ou're effectively defining a hybrid die that behaves like a d6 with probability N1/(N1+N2) and like a d8 with probability N2/(N1+N2), and then making N1+N2 independent rolls of that die. Thus, while the dice pool you're rolling will have an average of N1 d6's and N2 d8's, you also end up counting cases where the composition of the pool differs from the average

    
08.12.2016 / 08:17

EDIT: Depois de ler o comentário de Trish sobre como o dado precisa ser rolado com a mesma freqüência que há dados na piscina, fiquei imaginando se o seguinte realmente funcionaria:

output [highest 2 of 5d{d6, d6, d8, d8, d8}]

Parece que esta pode ser a maneira mais simples de fazer isso? Eu tenho uma boa curva com esta terceira tentativa.

    
08.12.2016 / 06:45