研发技能挑战


14

《龙与地下城》中,几乎所有事情都是由掷骰子决定的。通常,如果滚动大于或等于指定值,则您尝试做任何您想做的事情都会成功,否则会失败。最常见的是,使用20面模具(又名d20)进行滚动。

其他时候,使用技能挑战系统。它与上述简单系统相似,但是成功是由一个或多个玩家成功个人在失败一定次数之前进行一定次数的掷骰来决定的。例如,玩家可能试图用有限数量的锁扣来挑门上的多个锁。单独的成功掷骰表示成功摘取了其中一个锁,单独的失败掷骰表示破解了一个撬锁。总体而言,成功将意味着在打破所有锁扣之前成功摘取所有锁。

此外,某些卷可以是关键卷。在d20上,掷出1是严重失败,导致整个挑战立即失败(在上面的示例中,玩家可能会意外警告警卫)。掷出20是至关重要的成功,导致立即完成整个挑战(在上面的示例中,玩家可能会找到一组锁的钥匙,从而无需挑选它们)。在关键投掷的情况下,无论先前的成功与失败次数如何,挑战都将立即结束并确定结果。

在此挑战中,将给您带来难度,所需的成功次数以及挑战失败的失败次数。您必须模拟一个尝试挑战的玩家,然后输出结果。

输入值

3个整数,代表在单个掷骰中成功必须达到或超过的值,在挑战中成功所需的成功次数以及挑战失败的失败次数。输入的顺序和格式无关紧要,只要您指定要使用的顺序即可。难度将在1到20之间(包括1和20),成功和失败的次数将在1到100之间(包括1和100)。

输出量

d20掷骰的每个结果(按顺序排列的整数)和挑战的总体结果(真/假值)。格式无关紧要,只要单个结果是按顺序排列的,那么总体结果就可以在所有单个卷之前或之后出现(例如,您不能在卷中间输出整个结果),并且您可以指定要使用的输出格式并始终使用。

示例(括号中的值仅作说明,不包括在内):

输入:

12 5 3 (difficulty successes failures)

输出:

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)

输入:

15 2 3 (difficulty failures successes)

输出:

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

输入:

5 5 10 (successes failures difficulty)

输出:

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

输入:

3 10 3 (failures difficulty successes)

输出:

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

规则

  • 这是,因此以字节为单位的最短代码获胜
  • 您必须为每卷随机选择一个介于1到20(含)之间的整数值。每个值的选择概率应相等(或尽可能接近相等)。

@ BradGilbertb2gills the number of successes and failures will both be between 1 and 100, inclusive.因此,是的,单个失败有可能导致整个挑战失败。
Mego 2015年

我是否应该假设代表整体成功的真实价值始终必须是相同的真实价值?还是仅仅是失败的次数?
布拉德·吉尔伯特b2gills 2015年

@ BradGilbertb2gills它的真实值不必相同;我使用了Python答案中剩下的失败次数。
Mego 2015年

恩,我可能只是将其保留为返回一个布尔值,因为它只有一个字节,它有助于提高输出的可读性。
布拉德·吉尔伯特b2gills 2015年

@ BradGilbertb2gills可读性远不及得分重要。
Mego 2015年

Answers:


3

JavaScript,83 78 76 75字节

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

此代码递归地计算成功和失败的发生时间。当任一成功(s)或故障(f)已经递减计数到0,我们完成与所述true!ss0或的falsy值ff0

输出为正则表达式形式/^(-\d{1,2})+(0|true)$/(或更严格地说为/^(-[1-9]|-1[0-9]|-20)+(0|true)$/)。就是说,输入中有一个前导连字符,然后是由连字符划定的滚动值,最后是未从最终滚动定界的最终结果(0true)。但是,这仍然是明确的语法,因为始终可以区分出无效的结果和最终的结果:输出的最后一个字符(0e)始终表示结果,并且最终结果0始终与数字分开读取最后一卷。

样本输出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

说明:

该代码通过滚动负数 d20并使用负号作为分隔符来进行工作。

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

数负布尔表达式工作,因为truefalse被转换为10在数值上下文。在这种情况下,d>-r1卷筒是否失败以及0它是否是成功的。


4

Python,134个字节

感谢Pietu1998保存的字节

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

很简单,也许可以打更多的高尔夫球,但是我们需要一些东西来使它开始。在线尝试


您可以节省几个字节:将import更改为from random import*drop和drop random.,使用randint(1,20)代替randrange(20)+1,替换and *。您还可以将最终结果放在输出的开头,以节省空间。
PurkkaKoodari 2015年

3

Python 2中,123个 121字节

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

(此答案混合了空格和制表符,因此第一个缩进级别是单个空格,而第二个缩进级别是单个制表符。)

功能 f采用以下参数:

a,单个掷骰成功的阈值,

b,整体成功所需的成功次数,

c,即整体故障所需的故障数。

在每个压模辊上,一个bc两个减量(但不是两个都减)。只要两者都是积极的,它就会再次循环,除非出现严重失败或严重成功的情况。

假设没有关键的成功或失败,则当循环结束时bc将结束时为零,但不是同时结束。在这种情况下,该函数仅返回的当前值c,如果我们用尽所有失败,则零(Falsey),如果成功,则正数(Truthy)。

作为奖励,输出会告诉您还剩下多少个故障,这很不错,以防万一(例如)以后有更多锁可供选择。(除非它在严重失败或成功时终止,在这种情况下,输出将是布尔值而不是整数。)


3

,39字节

有人说他们想用高尔夫语言来解决。

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

我很确定这不会使用比问题新的语言功能。按以下顺序将输入作为命令行参数:难度,所需的成功,所需的失败。对于整体失败,输出为0;对于整体成功,输出为非零。在线尝试!

该方法是一种相当简单的“同时循环”策略,从其他解决方案中吸取了一两个技巧。这是带有注释,空格和一些额外输出的版本:

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

2

Ruby 2.2,75个字节

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}

基本的迭代解决方案。示例运行:

f[12, 5, 3]

可能输出:

11
17
8
14
7
false

您可以在此处看到它在IDEONE上运行。


让我非常嫉妒0虚假的语言!
Paul Prestidge 2015年

1

VBA 180字节

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

示例输出

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

输出的最后一个数字将为0for False1for True。每卷用换行符分隔。这使用内置于RNG rnd()中的VBA (众所周知)不是那么随机,但这应尽可能满足要求。

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

1

SpecBAS-165字节

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

输入内容应按难度,成功,失败顺序输入。

新版本的SpecBAS现在允许“?” 代替PRINT并消除了对LET变量分配之前,因此这是试用它们的好方法。

由于默认情况下数组是基于1的,因此如果掷骰失败,第6行将返回0/1,并添加1以更新正确的索引。


1

Perl 6的 101个   99字节

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

输入是一个可变数组,包含困难,成功和失败

输出是一个两个元素的列表,第一个元素是滚动值的列表,第二个元素是剩余的故障数。

用法:

# 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)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.