Wyzwania dotyczące umiejętności D&D

14

W Dungeons & Dragons prawie o wszystkim decyduje rzut kostką. Zazwyczaj, jeśli rzut jest większy lub równy określonej wartości, próba zrobienia tego, co chcesz, kończy się powodzeniem, a w przeciwnym razie kończy się niepowodzeniem. Najczęściej do rzutu używana jest 20-stronna kostka (aka d20).

Innym razem stosuje się system wyzwań umiejętności. Jest podobny do prostego systemu opisanego powyżej, ale o sukcesie decyduje to, czy gracz (ci) odniesie sukces w poszczególnych rzutach określoną liczbę razy, zanim nie odniesie pewnej liczby porażek. Na przykład gracz (-y) może próbować wybrać wiele zamków do drzwi z ograniczoną liczbą wytrychów. Poszczególne udane rzuty oznaczają pomyślne wybranie jednego z zamków, a poszczególne nieudane rzuty oznaczają zerwanie wytrycha. Ogólny sukces oznaczałby pomyślne wybranie wszystkich zamków przed zerwaniem wszystkich wytrychów.

Ponadto niektóre rzuty mogą być rzutami krytycznymi. Na k20 rzut 1 jest krytyczną porażką, co powoduje natychmiastowe niepowodzenie całego wyzwania (w powyższym przykładzie gracz (y) może przypadkowo zaalarmować strażnika). Rzut 20 jest krytycznym sukcesem, skutkującym natychmiastowym zakończeniem całego wyzwania (w powyższym przykładzie gracz (gracze) mogą znaleźć zestaw kluczy do zamków, eliminując potrzebę ich wybierania). W przypadku rzutu krytycznego wyzwanie jest natychmiast kończone, a wynik decyduje, niezależnie od poprzedniej liczby sukcesów i porażek.

W tym wyzwaniu otrzymasz trudność, liczbę potrzebnych sukcesów i liczbę niepowodzeń, w których wyzwanie się nie powiodło. Musisz zasymulować gracza podejmującego wyzwanie i przedstawić wynik.

Wejście

3 liczby całkowite, reprezentujące wartość, która musi zostać osiągnięta lub przekroczona, aby odnieść sukces przy pojedynczym rzucie, liczbę sukcesów potrzebnych do odniesienia sukcesu w wyzwaniu oraz liczbę niepowodzeń, w których wyzwanie nie powiodło się. Kolejność i format danych wejściowych nie ma znaczenia, o ile określisz, jakiej kolejności będziesz używać. Poziom trudności będzie wynosił od 1 do 20 włącznie, a liczba sukcesów i porażek będzie wynosić od 1 do 100 włącznie.

Wynik

Wyniki każdego z rzutów d20 (liczby całkowite, w kolejności) oraz ogólny wynik wyzwania (wartość true / falsey). Format nie ma znaczenia, o ile poszczególne wyniki są w porządku, ogólny wynik pojawia się przed lub po wszystkich pojedynczych rolkach (na przykład nie można wyprowadzić ogólnego wyniku w środkowej części rolek) i określasz używany format wyjściowy i konsekwentnie go używasz.

Przykłady (wartości w nawiasach podano w celu wyjaśnienia i nie trzeba ich włączać):

Wejście:

12 5 3 (difficulty successes failures)

Wynik:

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)

Wejście:

15 2 3 (difficulty failures successes)

Wynik:

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

Wejście:

5 5 10 (successes failures difficulty)

Wynik:

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

Wejście:

3 10 3 (failures difficulty successes)

Wynik:

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

Zasady

  • To jest , więc wygrywa najkrótszy kod w bajtach
  • Musisz losowo wybrać wartość całkowitą od 1 do 20 (włącznie) dla każdego rzutu. Każda wartość powinna mieć jednakowe prawdopodobieństwo wyboru (lub tak bliska, jak to możliwe).
Mego
źródło
@ BradGilbertb2gills the number of successes and failures will both be between 1 and 100, inclusive.Tak, istnieje możliwość, że pojedyncza awaria zakończy się niepowodzeniem całego wyzwania.
Mego
Czy powinienem założyć, że prawdziwa wartość reprezentująca ogólny sukces musi zawsze mieć tę samą prawdziwą wartość? A może po prostu liczba pozostałych awarii?
Brad Gilbert b2gills,
@ BradGilbertb2gills Nie musi to być ta sama prawdziwa wartość; Używam liczby błędów pozostałych w mojej odpowiedzi w języku Python .
Mego
Ech, prawdopodobnie zostawię to jako zwracanie Boola, ponieważ jest to tylko jeden bajt, co pomaga poprawić czytelność danych wyjściowych.
Brad Gilbert b2gills,
@ BradGilbertb2gills Czytelność jest znacznie mniej ważna niż wynik.
Mego

Odpowiedzi:

3

JavaScript, 83 78 76 75 bajtów

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

Ten kod rekurencyjnie odlicza sukcesy i porażki. Kiedy odliczone są albo sukcesy ( s), albo porażki ( f) 0, kończymy truewartością !skiedy sjest 0lub wartością fałszu fkiedy fjest 0.

Dane wyjściowe mają postać wyrażeń regularnych /^(-\d{1,2})+(0|true)$/(lub ściślej /^(-[1-9]|-1[0-9]|-20)+(0|true)$/). Oznacza to, że wejście ma wiodący łącznik, następnie wartości rzutu określone przez łączniki, a na końcu ostateczny wynik ( 0lub true), który nie jest wyznaczony z ostatniego rzutu. Jest to jednak nadal jednoznaczna gramatyka, ponieważ zawsze można rozróżnić wynik wykorzystania i rzut końcowy: ostatni znak wyniku (albo 0albo e) zawsze wskazuje wynik, a wynik końcowy 0zawsze odczytuje się oddzielnie od liczby (liczb) ostatniego rzutu.

Przykładowe dane wyjściowe dla 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

Wyjaśnienie:

Ten kod działa poprzez rzutowanie ujemnego d20 i (ab) przy użyciu znaków ujemnych jako ograniczników.

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)
      )
   ]

Wyrażenia numer-minus-logiczna pracy, bo truei falseodlewa się 1i 0w kontekście numerycznym. W takim przypadku d>-rbędzie, 1jeśli rzut jest porażką i 0jeśli był sukcesem.

apsillery
źródło
4

Python, 134 bajty

Dzięki Pietu1998 za zapisane bajty

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

Całkiem proste, prawdopodobnie można nieco bardziej zagrać w golfa, ale potrzebowaliśmy czegoś, aby to rozpocząć. Wypróbuj online .

Mego
źródło
Można zaoszczędzić kilka bajtów: zmienić przywozu do from random import*i upuść random., użycie randint(1,20)zamiast randrange(20)+1wymienić and z *. Możesz także umieścić wynik końcowy na początku wyjścia, oszczędzając miejsce.
PurkkaKoodari,
3

Python 2, 123 121 bajtów

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

(Ta odpowiedź miesza spacje i tabulatory , więc pierwszy poziom wcięcia to pojedyncza spacja, a drugi to pojedyncza tabulator.)

Funkcja fprzyjmuje następujące argumenty:

a, próg dla pojedynczego rzutu kostką liczony jako sukces,

b, liczba sukcesów potrzebnych do ogólnego sukcesu,

c, liczba awarii potrzebnych do ogólnej awarii.

Na każdym rzucie rzuć albo balbo cjest zmniejszany (ale nie oba). Dopóki oba są dodatnie, pętla ponownie, z wyjątkiem krytycznej awarii lub krytycznego sukcesu.

Zakładając brak krytycznych sukcesów lub niepowodzeń, kiedy kończy się pętla albo bczy cbędzie zero, ale nie jednocześnie. W takim przypadku funkcja zwraca tylko bieżącą wartość c, która wynosi zero (Falsey), jeśli wyczerpiemy wszystkie nasze awarie, i dodatnia (Prawda), jeśli nam się uda.

Jako bonus, dane wyjściowe informują o tym, ile błędów pozostało, co jest miłe w przypadku, gdy (powiedzmy) więcej blokad do wyboru później. (Chyba że zakończy się krytycznym niepowodzeniem lub sukcesem, w którym to przypadku wyjście będzie wartością logiczną zamiast int.)

Mathmandan
źródło
3

Pip , 39 bajtów

Ktoś powiedział, że chce znaleźć rozwiązanie w języku golfowym.

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

Jestem prawie pewien, że nie używa żadnych funkcji językowych nowszych niż pytanie. Pobiera dane jako argumenty wiersza poleceń w następującej kolejności: trudność, wymagane sukcesy, wymagane niepowodzenia. Wyjście 0 dla ogólnego niepowodzenia lub niezerowe dla ogólnego sukcesu. Wypróbuj online!

Podejście to jest dość prostą strategią pętli podczas, z jedną lub dwiema sztuczkami zaczerpniętymi z innych rozwiązań. Oto wersja z komentarzami, białymi znakami i dodatkowymi danymi wyjściowymi:

; 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
źródło
2

Ruby 2.2, 75 bajtów

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}

Podstawowe iteracyjne rozwiązanie. Przykładowy przebieg:

f[12, 5, 3]

Moc wyjściowa:

11
17
8
14
7
false

Można zobaczyć go w ruchu na IDEONE tutaj .

Paul Prestidge
źródło
Sprawia, że ​​jestem naprawdę zazdrosna o języki, w których 0 to falsey!
Paul Prestidge,
1

VBA 180 bajtów

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

Przykładowy wynik

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

Ostatnia cyfra wyjściem będzie 0dla Falselub 1za True. Każdy rzut jest oddzielony nową linią. Korzysta z VBA wbudowanego w RNG, rnd()który jest znany z tego, że nie jest tak przypadkowy , ale powinno to najlepiej spełniać wymagania.

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
źródło
1

SpecBAS - 165 bajtów

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

Dane wejściowe należy wprowadzać według poziomu trudności, sukcesów, awarii.

Nowa wersja SpecBAS umożliwia teraz „?” zamiast PRINTi eliminuje potrzebę LETprzed przypisywaniem zmiennych, więc był to dobry sposób na ich wypróbowanie.

Ponieważ tablice są domyślnie oparte na 1, linia 6 zwraca 0/1, jeśli rzut przewyższa trudność i dodaje 1, aby zaktualizować właściwy indeks.

Brian
źródło
1

Perl 6 ,  101   99 bajtów

->$/ {(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
}

Dane wejściowe to zmienna tablica zawierająca trudność, sukcesy i niepowodzenia

Dane wyjściowe to lista dwóch elementów, pierwszy element to lista walcowanych wartości, drugi element to liczba pozostałych awarii.

Stosowanie:

# 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
źródło