D&D Skill Challenges

14

En Dungeons & Dragons , casi todo se decide tirando un dado. Por lo general, si la tirada es mayor o igual que un valor específico, su intento de hacer lo que quisiera tiene éxito y, de lo contrario, falla. Más comúnmente, un dado de 20 lados (también conocido como d20) se usa para tirar.

Otras veces, se utiliza el sistema de desafío de habilidad. Es similar al sistema simple descrito anteriormente, pero el éxito está determinado por si el jugador (s) tiene éxito o no tira una determinada cantidad de veces antes de fallar una determinada cantidad de veces. Por ejemplo, los jugadores pueden estar intentando abrir múltiples cerraduras en una puerta con un número limitado de cerraduras. Los lanzamientos exitosos individuales representan la elección exitosa de una de las cerraduras, y los lanzamientos fallidos individuales representan romper una cerradura. El éxito general significaría seleccionar con éxito todas las cerraduras antes de romper todas las cerraduras.

Además, ciertos rollos pueden ser rollos críticos. En un d20, sacar un 1 es una falla crítica, lo que resulta en la falla inmediata de todo el desafío (en el ejemplo anterior, los jugadores pueden alertar accidentalmente a un guardia). Lanzar un 20 es un éxito crítico, lo que resulta en el éxito inmediato de todo el desafío (en el ejemplo anterior, los jugadores pueden encontrar un conjunto de llaves para las cerraduras, eliminando la necesidad de elegirlas). En el caso de una tirada crítica, el desafío termina inmediatamente y se decide el resultado, independientemente del número anterior de éxitos y fracasos.

En este desafío, se le dará una dificultad, el número de éxitos necesarios y el número de fracasos en los que se falla el desafío. Debes simular a un jugador que intenta el desafío y generar el resultado.

Entrada

3 enteros, que representan el valor que debe cumplirse o superarse para tener éxito en una tirada individual, la cantidad de éxitos necesarios para tener éxito en el desafío y la cantidad de fallas en las que el desafío falla. El orden y el formato de las entradas no importan, siempre que especifique el orden que utilizará. La dificultad estará entre 1 y 20, inclusive, y el número de éxitos y fracasos estará entre 1 y 100, inclusive.

Salida

Los resultados de cada una de las tiradas de d20 (enteros, en orden), y el resultado general del desafío (un valor verdadero / falso). El formato no importa, siempre y cuando los resultados individuales estén en orden, el resultado general viene antes o después de todos los rollos individuales (por ejemplo, no puede generar el resultado general en el medio de los rollos), y usted especifica qué formato de salida usa y lo usa de manera consistente.

Ejemplos (los valores entre paréntesis son para explicación y no necesitan ser incluidos):

Entrada:

12 5 3 (difficulty successes failures)

Salida:

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)

Salida:

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

Entrada:

5 5 10 (successes failures difficulty)

Salida:

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

Entrada:

3 10 3 (failures difficulty successes)

Salida:

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

Reglas

  • Este es el , por lo que gana el código más corto en bytes
  • Debe elegir aleatoriamente un valor entero entre 1 y 20 (inclusive) para cada rollo. Cada valor debe tener la misma probabilidad de ser elegido (o lo más parecido posible a igual).
Mego
fuente
@ BradGilbertb2gills the number of successes and failures will both be between 1 and 100, inclusive.Entonces, sí, existe la posibilidad de que una sola falla resulte en el fracaso de todo el desafío.
Mego
¿Debo suponer que el valor verdadero que representa el éxito general siempre tiene que ser el mismo valor verdadero? ¿O podría ser la cantidad de fallas que quedan?
Brad Gilbert b2gills
@ BradGilbertb2gills No tiene que ser el mismo valor verdadero; Uso la cantidad de fallas que quedan en mi respuesta de Python .
Mego
Ehh, probablemente lo dejaré como si devolviera un Bool, ya que es solo un byte y ayuda a mejorar la legibilidad de la salida.
Brad Gilbert b2gills
@ BradGilbertb2gills La legibilidad es mucho menos importante que la puntuación.
Mego

Respuestas:

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)

Este código cuenta recursivamente los éxitos y fracasos a medida que ocurren. Cuando los éxitos ( s) o los fracasos ( f) han regresado 0, terminamos con el truevalor !swhen sis 0o con el valor falso de fwhen fis 0.

La salida es de la forma de expresión regular /^(-\d{1,2})+(0|true)$/(o, más estrictamente /^(-[1-9]|-1[0-9]|-20)+(0|true)$/). Es decir, la entrada tiene un guión inicial, luego los valores del rollo delineados por guiones, y finalmente el resultado final ( 0o true), que no está delineado del rollo final. Sin embargo, esto sigue siendo una gramática inequívoca porque el resultado de utilmate y la tirada final siempre se pueden distinguir: el último carácter de la salida (ya sea 0o e) siempre es indicativo del resultado, y una final 0siempre se lee por separado del número (s) del rollo final.

Resultados de muestra 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

Explicación:

Este código funciona rodando un d20 negativo y (ab) usando los signos 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)
      )
   ]

Las expresiones booleanas de número menos funcionan porque trueyfalse se convierten en 1y 0en un contexto numérico. En este caso, d>-rserá 1si el lanzamiento es un fracaso y 0si fue un éxito.

apsillers
fuente
4

Python, 134 bytes

Gracias Pietu1998 por los bytes guardados

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

Bastante simple, probablemente se pueda jugar un poco más, pero necesitábamos algo para comenzar. Pruébalo en línea .

Mego
fuente
Puede guardar un par de bytes: cambie la importación from random import*y suelte random., use en randint(1,20)lugar de randrange(20)+1, reemplace and con *. También puede poner el resultado final al comienzo de la salida, ahorrando espacio.
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 respuesta mezcla espacios y pestañas , por lo que el primer nivel de sangría es un solo espacio, mientras que el segundo es una sola pestaña).

La función f toma los siguientes argumentos:

a, el umbral para que una tirada de dado individual cuente como un éxito,

b, la cantidad de éxitos necesarios para el éxito general,

c, la cantidad de fallas necesarias para la falla general.

En cada tirada del dado, bo cse disminuye (pero no ambos). Mientras ambos sean positivos, se repite nuevamente, excepto en el caso de falla crítica o éxito crítico.

Suponiendo que no haya éxitos o fracasos críticos, cuando el ciclo finalice bo csea ​​cero, pero no ambos. En ese caso, la función solo devuelve el valor actual de c, que es cero (Falsey) si agotamos todas nuestras fallas, y positivo (Verdad) si lo logramos.

Como beneficio adicional, la salida le indica cuántas fallas le quedan, lo cual es bueno en caso de que (digamos) más cerraduras para elegir más tarde. (A menos que termine en una falla crítica o éxito, en cuyo caso el resultado será un booleano en lugar de un int.)

Mathmandan
fuente
3

Pip , 39 bytes

Alguien dijo que quería ver una solución en un lenguaje de golf.

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

Estoy bastante seguro de que esto no usa ninguna función de idioma más nueva que la pregunta. Toma datos como argumentos de línea de comandos en este orden: dificultad, se requieren éxitos, se requieren fallas. Salidas 0 para falla general o no cero para éxito general.Pruébalo en línea!

El enfoque es una estrategia bastante sencilla de bucle while, con un truco o dos tomados de otras soluciones. Aquí hay una versión con comentarios, espacios en blanco y algunos resultados adicionales:

; 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
fuente
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}

Solución iterativa básica. Ejemplo de ejecución:

f[12, 5, 3]

Podría salida:

11
17
8
14
7
false

Puedes verlo ejecutándose en IDEONE aquí .

Paul Prestidge
fuente
Me pone realmente celoso de langues donde 0 es 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

Salida de ejemplo

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

El último dígito de salida será un 0para Falseo un 1para True. Cada rollo está separado por una nueva línea. Esto utiliza VBA integrado en RNG, rnd()que es conocido por no ser tan aleatorio , pero esto debe cumplir los requisitos lo mejor posible.

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
fuente
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")

La entrada debe ingresarse en orden de dificultad, éxitos, fracasos.

La nueva versión de SpecBAS ahora permite "?" en lugar de PRINTy elimina la necesidad de hacer LETfrente a las asignaciones variables, por lo que esta fue una buena manera de probarlas.

Como las matrices están basadas en 1 de manera predeterminada, la línea 6 devuelve 0/1 si la tirada supera la dificultad y agrega 1 para actualizar el índice correcto.

Brian
fuente
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
}

La entrada es una matriz mutable que contiene dificultades, éxitos y fracasos.

La salida es una lista de dos elementos, el primer elemento es una lista de los valores acumulados, el segundo elemento es el número de fallas 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
fuente