Desafios de D&D

14

Dentro Dungeons & Dragons , quase tudo é decidido rolando um dado. Normalmente, se a rolagem for maior ou igual a um valor especificado, sua tentativa de fazer o que você deseja fazer será bem-sucedida e falhará de outra forma. Geralmente, um dado de 20 lados (também conhecido como d20) é usado para rolar.

Outras vezes, o sistema de desafio de habilidades é usado. É semelhante ao sistema simples descrito acima, mas o sucesso é determinado pelo fato de o (s) jogador (es) ter sucesso ou não um indivíduo rola um certo número de vezes antes de falhar um certo número de vezes. Por exemplo, o (s) jogador (es) pode estar tentando abrir várias fechaduras em uma porta com um número limitado de fechaduras. Os rolos individuais bem-sucedidos representam a escolha bem-sucedida de um dos bloqueios, e os rolos individuais com falha representam a quebra de um palpite. O sucesso geral significaria selecionar com êxito todos os bloqueios antes de quebrar todos os bloqueios.

Além disso, certos rolos podem ser críticos. Em um d20, rolar 1 é uma falha crítica, resultando na falha imediata de todo o desafio (no exemplo acima, os jogadores podem alertar acidentalmente um guarda). Rolar 20 é um sucesso crítico, resultando no sucesso imediato de todo o desafio (no exemplo acima, o (s) jogador (es) pode encontrar um conjunto de chaves para os bloqueios, eliminando a necessidade de buscá-los). No caso de um teste crítico, o desafio termina imediatamente e o resultado é decidido, independentemente do número anterior de sucessos e falhas.

Nesse desafio, você terá uma dificuldade, o número de sucessos necessários e o número de falhas nas quais o desafio falhou. Você deve simular um jogador que tenta o desafio e gerar o resultado.

Entrada

3 números inteiros, representando o valor que deve ser atendido ou excedido para ter sucesso em um teste individual, o número de sucessos necessários para ter sucesso no desafio e o número de falhas nas quais o desafio falhou. A ordem e o formato das entradas não importa, desde que você especifique qual ordem será usada. A dificuldade será entre 1 e 20, inclusive, e o número de sucessos e falhas será entre 1 e 100, inclusive.

Resultado

Os resultados de cada um dos rolos d20 (números inteiros, em ordem) e o resultado geral do desafio (um valor de verdade / falsey). O formato não importa, desde que os resultados individuais estejam em ordem, o resultado geral ocorre antes ou depois de todos os rolos individuais (você não pode exibir o resultado geral no meio dos rolos, por exemplo) e você especifica qual formato de saída você usa e o usa de forma consistente.

Exemplos (os valores entre parênteses são explicativos e não precisam ser incluídos):

Entrada:

12 5 3 (difficulty successes failures)

Resultado:

15 (success, 1-0)
10 (failure, 1-1)
5  (failure, 1-2)
16 (success, 2-2)
12 (success, 3-2)
15 (success, 4-2)
19 (success, 5-2)
True (overall success)

Entrada:

15 2 3 (difficulty failures successes)

Resultado:

0  (overall failure)
15 (success, 1-0)
12 (failure, 1-1)
13 (failure, 1-2)

Entrada:

5 5 10 (successes failures difficulty)

Resultado:

11 (success, 1-0)
5  (failure, 1-1)
20 (critical success)
1  (overall success)

Entrada:

3 10 3 (failures difficulty successes)

Resultado:

12 (success, 1-0)
11 (success, 2-0)
1  (critical failure)
False (overall failure)

Regras

  • Isso é , então o código mais curto em bytes ganha
  • Você deve escolher aleatoriamente um valor inteiro entre 1 e 20 (inclusive) para cada rolo. Cada valor deve ter uma probabilidade igual de ser escolhido (ou o mais próximo possível da igual).
Mego
fonte
@ BradGilbertb2gills the number of successes and failures will both be between 1 and 100, inclusive.Então, sim, existe a possibilidade de uma única falha resultar na falha de todo o desafio.
Mego
Devo assumir que o valor verdadeiro que representa o sucesso geral sempre deve ser o mesmo valor verdadeiro? Ou poderia ser apenas o número de falhas restantes?
Brad Gilbert b2gills
@ BradGilbertb2gills Não precisa ser o mesmo valor verdadeiro; Eu uso o número de falhas restantes na minha resposta em Python .
Mego
Ehh, provavelmente vou deixá-lo retornando um Bool, pois esse é apenas um byte, e isso ajuda a melhorar a legibilidade da saída.
Brad Gilbert b2gills
@ BradGilbertb2gills A legibilidade é muito menos importante que a pontuação.
Mego

Respostas:

3

JavaScript, 83 78 76 75 bytes

F=(d,f,s)=>!s||f&&(r=~(Math.random()*20))+""+F(d,~r&&f-(k=d>-r),r+20&&s-!k)

Esse código recursivamente conta sucessos e falhas à medida que ocorrem. Quando sucessos ( s) ou falhas ( f) são contados 0, terminamos com o truevalor !squando sé 0ou com o valor falso de fquando fé 0.

A saída é da forma de expressão regular /^(-\d{1,2})+(0|true)$/(ou, mais estritamente /^(-[1-9]|-1[0-9]|-20)+(0|true)$/). Ou seja, a entrada possui um hífen inicial, depois os valores do rolo delineados por hífens e, finalmente, o resultado final ( 0ou true), que não é delineado do rolo final. No entanto, essa ainda é uma gramática inequívoca porque o resultado útil e a rolagem final sempre podem ser distinguidos: o último caractere da saída (um 0ou e) é sempre indicativo do resultado, e uma final 0é sempre lida separadamente do (s) número (s) do rolo final.

Resultados de amostra para F(11,3,4):

-3-14-12-16-16true  // normal success
-2-12-20true        // critical success
-20true             // first-roll critical success
-18-2-8-14-18-90    // normal failure
-18-12-10           // critical failure
-10                 // first-roll critical failure
-4-16-4-100         // normal failure where last roll is a 10

Explicação:

Esse código funciona rolando um d20 negativo e (ab) usando os sinais negativos como delimitadores.

F=(d,f,s)=>    // define function F(difficulty, fails, successes)

!s||   // if zero more successes needed, return true
f &&   // if zero more failures needed, return 0

    (r=~(Math.random()*20)  // add negative d20 to output, store in `r`
    +""+                    // string concatenation
    F(                      // recursive call to F with changed fail/success
       d,                   //   pass along d      
       ~r                   //   if r is -1, zero more fails needed
          &&f-              //   otherwise, reduce fails needed by
              (k=d>-r),     //   the boolean `d>-r` (and store in k)
       r+20                 //   if r is -20, zero more successes needed
           &&s-!k           //   otherwise, reduce successes needed by
                            //   the opposite of `k` (which indicates a fail)
      )
   ]

As expressões número-menos-booleano funcionam porque truee falsesão convertidas para 1e 0em um contexto numérico. Nesse caso, d>-rserá 1se o teste for uma falha e 0se foi um sucesso.

apsillers
fonte
4

Python, 134 bytes

Obrigado Pietu1998 pelos bytes salvos

from random import*
def g(a,b,c):
 s,z=[],[c,b]
 while z[0]*z[1]:d=randint(1,20);z[a<d]-=[1,z[a<d]][d in[1,20]];s+=[d]
 return[z[0]]+s

Muito simples, provavelmente pode ser jogado um pouco mais, mas precisávamos de algo para começar. Experimente online .

Mego
fonte
Você pode salvar alguns bytes: altere a importação para from random import*e solte random., use em randint(1,20)vez de randrange(20)+1, substitua and por *. Você também pode colocar o resultado final no início da saída, economizando espaço.
PurkkaKoodari
3

Python 2, 123 121 bytes

from random import*
def f(a,b,c):
 while c*b:
    r=randint(1,20);print r;c-=r<a;b-=r>=a
    if r in[1,20]:return r>9
 return c

(Esta resposta combina espaços e tabulações , portanto, o primeiro nível de recuo é um espaço único, enquanto o segundo é uma única guia.)

A função f aceita os seguintes argumentos:

a, o limite para um dado individual contar como um sucesso,

b, o número de sucessos necessários para o sucesso geral,

c, o número de falhas necessárias para a falha geral.

Em cada rolo de dado, bou cé diminuído (mas não ambos). Desde que ambos sejam positivos, ele volta a repetir, exceto no caso de falha crítica ou sucesso crítico.

Assumindo que não haja sucessos ou falhas críticas, quando o loop termina um bou cserá zero, mas não ambos. Nesse caso, a função retorna o valor atual de c, que é zero (Falsey) se esgotarmos todas as nossas falhas e positivo (Truthy) se tivermos sucesso.

Como bônus, a saída mostra quantas falhas você teve, o que é bom caso haja (digamos) mais bloqueios para escolher mais tarde. (A menos que seja finalizado com uma falha ou êxito crítico, nesse caso a saída será um booleano em vez de um int.)

mathmandan
fonte
3

Pip , 39 bytes

Alguém disse que queria ver uma solução em um idioma de golfe.

Wc&b{Pd:1+RR20d<a?--c--bc*:d>1b*:d<20}c

Tenho certeza de que isso não usa nenhum recurso de idioma mais recente que a pergunta. Recebe entrada como argumentos da linha de comando nesta ordem: dificuldade, sucessos necessários, falhas necessárias. Saídas 0 para falha geral ou diferente de zero para êxito geral.Experimente online!

A abordagem é uma estratégia bastante direta, com um ou dois truques retirados de outras soluções. Aqui está uma versão com comentários, espaço em branco e alguma saída extra:

; a,b,c are initialized to the cmdline args
; a = difficulty (roll >=a succeeds, roll <a fails)
; b = required successes to succeed the task
; c = required failures to fail the task
; d = single die roll

; Loop while c and b are both nonzero:
W c&b {
 ; d gets 1+randrange(20); output it
 O d:1+RR20
 ; If d<a, decrement req'd failures, else decrement req'd successes
 d<a ? --c --b
 ; Verbose output for the ungolfed version
 P " (" . (d=1|d=20 ? "critical " "") . (d<a ? "failure" "success") . ")"
 ; If d=1, req'd failures is * by 0 (becomes 0), else * by 1 (unchanged)
 c *: d>1
 ; If d=20, req'd successes is * by 0 (becomes 0), else * by 1 (unchanged)
 b *: d<20
}
; c, remaining failures, is the output: 0 if overall failure, nonzero if overall success
c . " (overall " . (c ? "success" "failure") . ")"
DLosc
fonte
2

Ruby 2.2, 75 bytes

f=->(v,s,f){p(r=rand(20)+1)<2?f=0:r>19?s=0:r<v ?f-=1:s-=1while s*f>0
p s<1}

Solução iterativa básica. Exemplo de execução:

f[12, 5, 3]

Pode saída:

11
17
8
14
7
false

Você pode vê-lo em execução no IDEONE aqui .

Paul Prestidge
fonte
Me deixa com muita inveja das línguas onde 0 é falsey!
Paul Prestidge
1

VBA 180 bytes

Sub P(d,s,f):k=1
Do While x<s And v<f:r=Int(20*Rnd()+1)
If r=20 Then x=s
If r=1 Then v=f
If r>=d Then: x=x+1: Else: v=v+1
Debug.Print r:Loop:If v>=f Then k=0
Debug.Print k:End Sub

Saída de exemplo

P 12,5,3
 18 
 2 
 19 
 8 
 11 
 0 

O último dígito da saída será um 0para Falseou um 1para True. Cada rolo é separado por uma nova linha. Isso usa o VBA incorporado no RNG, rnd()conhecido por não ser tão aleatório , mas isso deve atender aos requisitos da melhor maneira possível.

Sub P(d,s,f)
k=1
Do While x<s And v<f               'Keep Rolling while Current Successes and Failures are less then the Maximum Allowed
r=Int(20*Rnd()+1)                'Creates a Randomish Number between 1 and 20
If r=20 Then x=s                   'Checks for Crit Success
If r=1 Then v=f                    'Checks for Crit Failure
If r>=d Then: x=x+1: Else: v=v+1   'Increments Current Success or Fails
Debug.Print r                      'Prints (Could us MSGBOX, it is shorter)
Loop
If v>=f Then k=0                   'Checks & Changes Total Outcome to False
Debug.Print k                      'Prints (Could us MSGBOX, it is shorter)
End Sub
JimmyJazzx
fonte
1

SpecBAS - 165 bytes

1 INPUT d,s,f
2 DIM p(2)
3 DO 
4 r=1+INT(RND*20): ?r
5 IF r IN [1,20] THEN EXIT 
6 INC p((r>=d)+1)
7 LOOP UNTIL p(1)>=f OR p(2)>=s
8  ?IIF$(r=1 OR p(1)>=f,"fail","success")

A entrada deve ser inserida em ordem de dificuldade, sucessos, falhas.

A nova versão do SpecBAS agora permite "?" em vez de PRINTe remove a necessidade LETde atribuições de variáveis, portanto, essa foi uma boa maneira de testá-las.

Como as matrizes são baseadas em 1 por padrão, a linha 6 retorna 0/1 se a rolagem superar a dificuldade e adiciona 1 para atualizar o índice correto.

Brian
fonte
1

Perl 6 ,  101   99 bytes

->$/ {(1..20).roll(*).map({$1*$2||last;$2-=$0>$_;$2=0 when 1;$1-=$_>=$0;$1=0 when 20;$_}).eager,$2}
# 101 bytes
->$/ {
  (1..20).roll(*).map({  # roll an infinite sequence, and map over them
    $1*$2||last;         # stop if either counter is 0
    $2-=$0>$_;           # decrement failure counter when a failure
    $2=0 when 1;         # set failure counter to 0  when a critical failure
    $1-=$_>=$0;          # decrement success counter when a success
    $1=0 when 20;        # set success counter to 0  when a critical success
    $_                   # the rolled value
  }).eager,$2            # the value of failure counter
}

Input é um array mutável que contém dificuldades, sucessos, falhas

A saída é uma lista de dois elementos, o primeiro elemento é uma lista dos valores acumulados, o segundo elemento é o número de falhas restantes.

Uso:

# give it a name for ease of use
my &code = {...}

for ^10 { say code [12, 5, 3] }
((14 4 15 5 5) 0)
((17 4 16 12 3 8) 0)
((2 14 14 7 14 19 19) 1)
((3 12 13 15 10 1) 0)
((3 17 16 10 11) 0)
((18 11 18 4 6) 0)
((15 13 1) 0)
((13 15 8 2 8) 0)
((16 17 8 10 11) 0)
((9 20) 2)
Brad Gilbert b2gills
fonte