作者godfat (godfat 真常)
看板Ruby
标题[心得] 骰子与骰子组
时间Wed Aug 9 23:34:10 2006
有在玩 D&D 的玩家一定知道所谓的 d20 系统…
也就是 20 面骰子的系统。不过说是 20 面骰子,
事实上还有各种其他面数的骰子:
http://www.wizards.com/d20modern/d20mdice/dice.htm
更有甚者,其实整个 WarCraft III 的普通攻击也是整个用骰子去做成的。
比方说,Human 的 Knight 的攻击力就是 2d5 + 25, 也就是五面骰丢两个,
然後再加上 25 成为最终伤害。如果我没记错的话,每升一次级,则是加上
一颗骰子。也就是 3 级的 Knight 是 5d5 + 25. 查查官方网站,
http://www.battle.net/war3/human/units/knight.shtml
一个没升级的 Knight 伤害平均是 31, (2+2*5)/2+25, 确实是 31,
满级的是 40, (5+5*5)/2+25, 确实是 40...
然後一个单位的伤害极限是 100d100 +... 好吧,那个 +... 不要管了,
总之这样伤害力就会是 100 ~ 10000, 一个很鬼扯的伤害范围
为了查证我的推测没错,还不小心发现官网有看起来很有趣的地图……
有空可以抓来试试看。不过当然以上都不是重点,只是想表述一下骰子
对於游戏的重要性。
重点在於,今天下午我开始试着用 Ruby 实作骰子系统。想要做到的就是
可以方便呼叫骰子,使用骰子。当然我知道这个东西很简单,所以我也只是
大概写写,然後稍微介绍一下我是怎麽写的…
目标使用介面是这样:
2.roll # 等同於 2d20 => 2 ~ 40
3.roll(4) # 等同於 3d4 => 3 ~ 12
dice = 6.dice # 储存 6d20 的骰子(s)
dice = 8.dice(4) # 储存 8d4 的骰子(s)
dice.roll # 摇出那骰子(s)
只有这样就太无趣了,来个结构比较复杂的骰子组,比方说 2d20 + 3d4 + 8d4
dice_set = DiceSet.new(2.dice, 3.dice(4), 8.dice(d))
dice_set.roll # 这就是… 2~40 + 3~12 + 8~32 共 13~84
更有甚者,使用 composite pattern...
another_dice_set = DiceSet.new(2.dice, dice_set)
现在上面这个 another_dice_set 变成 2d20 + 原本设定好的 dice_set
another_dice_set << 2.dice # 再追加 2d20
another_dice_set << DiceSet.new(dice_set, dice_set, 2.dice)
现在这个 another_dice_set 已经变成很疯狂的骰子组了,我懒得算了…
another_dice_set.roll # 掷出刚刚那疯狂的骰子组
实作很简单,相信看到这里的各位都已经知道怎麽写了,不过还是稍微
说明一下好了,也许还有在观望的读者也说不定?
由於 5.times 之类的东西让我惊艳,所以我决定把骰子也加到数字里面。
而这可以靠着 Ruby 动态扩充 class 来办到,所以现在要决定的是要扩充
到哪个 class 中? 5 的型别是 Fixnum, 不过野心可以大一点,加到 Numeric
感觉会比较爽,於是可以丢出这种诡异的骰子:-123.456.roll, 还有这种:
12972398574892734896769868686934059230491204821491.roll(Bignum)
当然意义是不大,不过这是爽度问题…反正也不是什麽正经程式 XD
class Numeric # 打开 Numeric 去扩充
def roll(faces = 20) # 没输入面数则预设 20 面(d20 中最常用)
return nil unless self > 0 && self.integer? &&
faces > 0 && faces.integer?
# 如果「面数」或「骰数」其中之一不是整数,或是负数,
# 则…说真的我也不知道这种骰子要怎麽骰,所以暂时传回 nil
# 表示目前还不知道这个骰子的意义是什麽?
result = 0 # 这是骰子丢出来的结果,先初始化为 0
1.step(self){ |i| result += rand(faces) + 1 }
# ok, 这行的意思是 |i| 由 1 开始跑,|i| 递增 1,
# 直到 self 这个数字为止(包含 self)
# self 的意思等同於 C++/Java 中的 this,
# 而这个东西指向的是:Numeric, 也就是 2.roll 的 "2"
# 所以 2.roll 的话,这里的 self 是 2, 1 开始跑,到 2 为止,
# 正好是跑两次,也就是丢两颗骰子,rand(N) 产生 0~N-1 的数字
# 所以骰子需要 +1 成为 1~N, 也就是这里的 1~20
result # 最後一行可以省略 return... 所以这等同於 return result
end
end
预知详情,下回分晓……今天杂事有点多 =.=
下回介绍 Dice, DiceSet, 还有我拿来测试的 TestDice
--
Hear me exalted spirits. Hear me, be you gods or devils, ye who hold
dominion here:
I am a wizard without a home. I am a wonderer seeking refuge.
Sacrifice
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 220.135.28.18
1F:推 jaiyalas:XD 08/09 23:55
2F:推 poga:推 XDD 08/10 00:03
3F:推 PsMonkey:看不懂也可以推吧? [逃] 08/10 00:09
4F:→ Schelfaniel:Ruby 外国文章说, 算是最容易学习的语言.. 08/10 01:31
5F:推 ogamenewbie:推一个, 其他还有高过低於的骰数等等 (笑) 08/10 07:15
6F:推 godfat:高低骰是什麽?@@ 其实我骰子不太熟 XD 不过似乎离题太多… 08/10 14:48
7F:推 PttHuge:相当不错的例子 :) 08/10 23:35