bcdice 3.5.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +29 -0
  3. data/i18n/FutariSousa/ja_jp.yml +705 -9
  4. data/i18n/KillDeathBusiness/ja_jp.yml +1 -1
  5. data/i18n/SwordWorld/ja_jp.yml +6 -0
  6. data/i18n/SwordWorld2_0/ja_jp.yml +37 -0
  7. data/i18n/SwordWorld2_5/ja_jp.yml +57 -0
  8. data/lib/bcdice/common_command/add_dice/node.rb +28 -4
  9. data/lib/bcdice/common_command/add_dice/parser.rb +149 -85
  10. data/lib/bcdice/dice_table/d66_parity_table.rb +8 -0
  11. data/lib/bcdice/game_system/Avandner.rb +1 -2
  12. data/lib/bcdice/game_system/Ayabito.rb +229 -0
  13. data/lib/bcdice/game_system/BattleTech.rb +1 -1
  14. data/lib/bcdice/game_system/CyberpunkRed.rb +135 -0
  15. data/lib/bcdice/game_system/DarkDaysDrive.rb +76 -41
  16. data/lib/bcdice/game_system/Elysion.rb +36 -20
  17. data/lib/bcdice/game_system/FutariSousa.rb +48 -4
  18. data/lib/bcdice/game_system/KemonoNoMori.rb +17 -17
  19. data/lib/bcdice/game_system/NeverCloud.rb +19 -8
  20. data/lib/bcdice/game_system/Shiranui.rb +145 -0
  21. data/lib/bcdice/game_system/ShuumatsuKikou.rb +298 -0
  22. data/lib/bcdice/game_system/StarryDolls.rb +318 -0
  23. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +18 -5
  24. data/lib/bcdice/game_system/SwordWorld.rb +6 -6
  25. data/lib/bcdice/game_system/SwordWorld2_0.rb +16 -39
  26. data/lib/bcdice/game_system/SwordWorld2_5.rb +3 -63
  27. data/lib/bcdice/game_system/VampireTheMasquerade5th.rb +29 -28
  28. data/lib/bcdice/game_system/cyberpunk_red/tables.rb +530 -0
  29. data/lib/bcdice/game_system/meikyu_kingdom/tables.rb +1 -1
  30. data/lib/bcdice/game_system/meikyu_kingdom_basic/table.rb +1 -1
  31. data/lib/bcdice/game_system/satasupe/tables.rb +1 -1
  32. data/lib/bcdice/game_system/sword_world/rating_options.rb +47 -0
  33. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +34 -82
  34. data/lib/bcdice/game_system/sword_world/rating_parser.rb +43 -53
  35. data/lib/bcdice/game_system/sword_world/transcendent_test.rb +14 -10
  36. data/lib/bcdice/game_system.rb +4 -0
  37. data/lib/bcdice/randomizer.rb +1 -1
  38. data/lib/bcdice/version.rb +1 -1
  39. metadata +11 -2
@@ -86,6 +86,7 @@ module BCDice
86
86
  return roll_tables(command, TABLES) if result.empty?
87
87
  end
88
88
 
89
+ return result if result.instance_of?(Result)
89
90
  return '' if result.empty?
90
91
 
91
92
  return "#{command} > #{result}"
@@ -158,16 +159,20 @@ module BCDice
158
159
  addTotal = base + modify
159
160
  total = diceTotal + addTotal
160
161
 
161
- result = ""
162
- result += "(2D6#{getValueString(base)}#{getValueString(modify)})"
163
- result += " #{diceTotal}[#{dice1},#{dice2}]#{getValueString(addTotal)} > #{total}"
162
+ result = Result.new
163
+ result.text = "EL"
164
+ result.text += base.to_s unless base.zero?
165
+ result.text += getValueString(modify) unless modify.zero?
166
+ result.text += " > "
167
+ result.text += "(2D6#{getValueString(base)}#{getValueString(modify)})"
168
+ result.text += " > #{diceTotal}[#{dice1},#{dice2}]#{getValueString(addTotal)} > #{total}"
164
169
 
165
170
  if dice1 == dice2
166
- result += getSpecialResult(dice1, total)
171
+ getSpecialResult(dice1, total, result)
167
172
  return result
168
173
  end
169
174
 
170
- result += getCheckResult(total)
175
+ result = getCheckResult(total, result)
171
176
 
172
177
  return result
173
178
  end
@@ -185,17 +190,25 @@ module BCDice
185
190
  return ""
186
191
  end
187
192
 
188
- def getCheckResult(total)
193
+ def getCheckResult(total, result)
189
194
  success = getSuccessRank(total)
190
195
 
191
- return " > 失敗" if success == 0
196
+ if success == 0
197
+ result.failure = true
198
+ result.text += " > 失敗"
199
+ return result
200
+ end
192
201
 
193
- return getSuccessResult(success)
202
+ return getSuccessResult(success, result)
194
203
  end
195
204
 
196
- def getSuccessResult(success)
197
- result = " > 成功度#{success}"
198
- result += " > 大成功 《アウル》2点獲得" if success >= SUCCESS_MAX
205
+ def getSuccessResult(success, result)
206
+ result.success = true
207
+ result.text += " > 成功度#{success}"
208
+ if success >= SUCCESS_MAX
209
+ result.critical = true
210
+ result.text += " > 大成功 《アウル》2点獲得"
211
+ end
199
212
 
200
213
  return result
201
214
  end
@@ -209,29 +222,32 @@ module BCDice
209
222
  return success
210
223
  end
211
224
 
212
- def getSpecialResult(number, total)
225
+ def getSpecialResult(number, total, result)
213
226
  debug("getSpecialResult", number)
214
227
 
215
228
  if number == 6
216
- return getCriticalResult
229
+ return getCriticalResult(result)
217
230
  end
218
231
 
219
- return getFambleResultText(number, total)
232
+ return getFambleResultText(number, total, result)
220
233
  end
221
234
 
222
- def getCriticalResult
223
- getSuccessResult(SUCCESS_MAX)
235
+ def getCriticalResult(result)
236
+ getSuccessResult(SUCCESS_MAX, result)
224
237
  end
225
238
 
226
- def getFambleResultText(number, total)
239
+ def getFambleResultText(number, total, result)
227
240
  debug("getFambleResultText number", number)
228
241
 
229
242
  if number == 1
230
- return " > 大失敗"
243
+ result.fumble = true
244
+ result.failure = true
245
+ result.text += " > 大失敗"
246
+ return result
231
247
  end
232
248
 
233
- result = getCheckResult(total)
234
- result += " / (#{number - 1}回目のアシストなら)大失敗"
249
+ result = getCheckResult(total, result)
250
+ result.text += " / (#{number - 1}回目のアシストなら)大失敗"
235
251
 
236
252
  debug("getFambleResultText result", result)
237
253
 
@@ -19,13 +19,25 @@ module BCDice
19
19
  助手用:【AS】…6面ダイスを2つ振って判定します。『有利』なら【3AS】、『不利』なら【1AS】を使います。
20
20
  ・各種表
21
21
  【調査時】
22
- 異常な癖決定表 SHRD
23
-  口から出る表 SHFM/強引な捜査表    SHBT/すっとぼけ表  SHPI
24
-  事件に夢中表 SHEG/パートナーと……表 SHWP/何かしている表 SHDS
25
-  奇想天外表  SHFT/急なひらめき表   SHIN/喜怒哀楽表   SHEM
22
+ 異常な癖決定表      SHRD/新・異常な癖決定表   SHND
23
+ 普通の?・異常な癖決定表 SHAD/ケイジ異常な癖決定表  SHKD
24
+  口から出る表    SHFM/強引な捜査表      SHBT/すっとぼけ表       SHPI
25
+  事件に夢中表    SHEG/パートナーと……表    SHWP/何かしている表      SHDS
26
+  奇想天外表     SHFT/急なひらめき表     SHIN/喜怒哀楽表        SHEM
27
+  人間エミュレート表 SHHE/人間エミュレート失敗表 SHHF/パートナーへのいたずら表 SHMP
28
+  思わせぶり表    SHSB/もどかしい表      SHFR/突然どうした表      SHIS
29
+  わがままを言う表  SHSE/普通に見える表     SHLM/嫉妬に狂う表       SHJS
30
+  傲慢な態度表    SHAR/比較的軽度なもの表   SHRM/ノータイム表       SHNT
31
+  捜査のやり方表   SHIM/貴族表         SHNO/説明しない表       SHNE
32
+  刑事としての癖表  SHHD
26
33
  イベント表
27
34
   現場にて  EVS/なぜ?  EVW/協力者と共に EVN
28
35
   向こうから EVC/VS容疑者 EVV
36
+  閉鎖空間  EVE
37
+  探偵のみ捜査 EVD/助手のみ捜査   EVA/観光捜査  EVT
38
+  思わぬヒント EVH/実験をしてみよう EVX/ゲスト捜査 EVG
39
+  ケイジ聞き込み捜査    EVQ/ケイジ大規模捜査      EVM/こっそり情報の受け渡し EVP
40
+  同僚たちと一緒に捜査する EVO/頻染みの店シチュエーション EVF/ハードBデカアクション EVB
29
41
  調査の障害表 OBT  変調表 ACT  目撃者表 EWT  迷宮入り表 WMT
30
42
  【設定時】
31
43
  背景表
@@ -111,6 +123,9 @@ module BCDice
111
123
  def translate_tables(locale)
112
124
  {
113
125
  "SHRD" => DiceTable::Table.from_i18n("FutariSousa.table.SHRD", locale),
126
+ "SHND" => DiceTable::Table.from_i18n("FutariSousa.table.SHND", locale),
127
+ "SHAD" => DiceTable::Table.from_i18n("FutariSousa.table.SHAD", locale),
128
+ "SHKD" => DiceTable::Table.from_i18n("FutariSousa.table.SHKD", locale),
114
129
  "SHFM" => DiceTable::Table.from_i18n("FutariSousa.table.SHFM", locale),
115
130
  "SHBT" => DiceTable::Table.from_i18n("FutariSousa.table.SHBT", locale),
116
131
  "SHPI" => DiceTable::Table.from_i18n("FutariSousa.table.SHPI", locale),
@@ -120,11 +135,40 @@ module BCDice
120
135
  "SHFT" => DiceTable::Table.from_i18n("FutariSousa.table.SHFT", locale),
121
136
  "SHIN" => DiceTable::Table.from_i18n("FutariSousa.table.SHIN", locale),
122
137
  "SHEM" => DiceTable::Table.from_i18n("FutariSousa.table.SHEM", locale),
138
+ "SHHE" => DiceTable::Table.from_i18n("FutariSousa.table.SHHE", locale),
139
+ "SHHF" => DiceTable::Table.from_i18n("FutariSousa.table.SHHF", locale),
140
+ "SHMP" => DiceTable::Table.from_i18n("FutariSousa.table.SHMP", locale),
141
+ "SHSB" => DiceTable::Table.from_i18n("FutariSousa.table.SHSB", locale),
142
+ "SHFR" => DiceTable::Table.from_i18n("FutariSousa.table.SHFR", locale),
143
+ "SHIS" => DiceTable::Table.from_i18n("FutariSousa.table.SHIS", locale),
144
+ "SHSE" => DiceTable::Table.from_i18n("FutariSousa.table.SHSE", locale),
145
+ "SHLM" => DiceTable::Table.from_i18n("FutariSousa.table.SHLM", locale),
146
+ "SHJS" => DiceTable::Table.from_i18n("FutariSousa.table.SHJS", locale),
147
+ "SHAR" => DiceTable::Table.from_i18n("FutariSousa.table.SHAR", locale),
148
+ "SHRM" => DiceTable::Table.from_i18n("FutariSousa.table.SHRM", locale),
149
+ "SHNT" => DiceTable::Table.from_i18n("FutariSousa.table.SHNT", locale),
150
+ "SHIM" => DiceTable::Table.from_i18n("FutariSousa.table.SHIM", locale),
151
+ "SHNO" => DiceTable::Table.from_i18n("FutariSousa.table.SHNO", locale),
152
+ "SHNE" => DiceTable::Table.from_i18n("FutariSousa.table.SHNE", locale),
153
+ "SHHD" => DiceTable::Table.from_i18n("FutariSousa.table.SHHD", locale),
123
154
  "EVS" => DiceTable::Table.from_i18n("FutariSousa.table.EVS", locale),
124
155
  "EVW" => DiceTable::Table.from_i18n("FutariSousa.table.EVW", locale),
125
156
  "EVN" => DiceTable::Table.from_i18n("FutariSousa.table.EVN", locale),
126
157
  "EVC" => DiceTable::Table.from_i18n("FutariSousa.table.EVC", locale),
127
158
  "EVV" => DiceTable::Table.from_i18n("FutariSousa.table.EVV", locale),
159
+ "EVE" => DiceTable::Table.from_i18n("FutariSousa.table.EVE", locale),
160
+ "EVD" => DiceTable::Table.from_i18n("FutariSousa.table.EVD", locale),
161
+ "EVA" => DiceTable::Table.from_i18n("FutariSousa.table.EVA", locale),
162
+ "EVT" => DiceTable::Table.from_i18n("FutariSousa.table.EVT", locale),
163
+ "EVH" => DiceTable::Table.from_i18n("FutariSousa.table.EVH", locale),
164
+ "EVX" => DiceTable::Table.from_i18n("FutariSousa.table.EVX", locale),
165
+ "EVG" => DiceTable::Table.from_i18n("FutariSousa.table.EVG", locale),
166
+ "EVQ" => DiceTable::Table.from_i18n("FutariSousa.table.EVQ", locale),
167
+ "EVM" => DiceTable::Table.from_i18n("FutariSousa.table.EVM", locale),
168
+ "EVP" => DiceTable::Table.from_i18n("FutariSousa.table.EVP", locale),
169
+ "EVO" => DiceTable::Table.from_i18n("FutariSousa.table.EVO", locale),
170
+ "EVF" => DiceTable::Table.from_i18n("FutariSousa.table.EVF", locale),
171
+ "EVB" => DiceTable::Table.from_i18n("FutariSousa.table.EVB", locale),
128
172
  "OBT" => DiceTable::D66Table.from_i18n("FutariSousa.table.OBT", locale),
129
173
  "ACT" => DiceTable::Table.from_i18n("FutariSousa.table.ACT", locale),
130
174
  "EWT" => DiceTable::Table.from_i18n("FutariSousa.table.EWT", locale),
@@ -17,27 +17,27 @@ module BCDice
17
17
 
18
18
  # ダイスボットの使い方
19
19
  HELP_MESSAGE = <<~MESSAGETEXT
20
- ・行為判定(成功度自動算出): KAx[±y]
20
+ ・行為判定(成功度自動算出)(P119): KAx[±y]
21
21
  ・継続判定(成功度+1固定): KCx[±y]
22
22
  x=目標値
23
23
  y=目標値への修正(任意) x+y-z のように複数指定可能
24
24
  例1)KA7+3 → 目標値7にプラス3の修正を加えた行為判定
25
25
  例2)KC6 → 目標値6の継続判定
26
- ・罠動作判定: CTR
27
- 罠ごとに1D12を振る。12が出た場合は罠が動作し、獲物がその効果を受ける
26
+ ・罠動作チェック+獲物表(P163): CTR
27
+ 罠ごとに1D12を振り、12が出た場合には生き物が罠を動作させ、その影響を受けている。
28
28
  ・各種表
29
- ・大失敗表: FT
30
- ・能力値ランダム決定表: RST
31
- ・ランダム所要時間表: RTT
32
- ・ランダム消耗表: RET
33
- ・ランダム天気表: RWT
34
- ・ランダム天気持続表: RWDT
35
- ・ランダム遮蔽物表(屋外): ROMT
36
- ・ランダム遮蔽物表(屋内): RIMT
37
- ・逃走体験表: EET
38
- ・食材採集表: GFT
39
- ・水採集表: GWT
40
- ・白の魔石効果表: WST
29
+ ・大失敗表(P120): FT
30
+ ・能力値ランダム決定表(P121): RST
31
+ ・ランダム所要時間表(P122): RTT
32
+ ・ランダム消耗表(P122): RET
33
+ ・ランダム天気表(P128): RWT
34
+ ・ランダム天気持続表(P128): RWDT
35
+ ・ランダム遮蔽物表(屋外)(P140): ROMT
36
+ ・ランダム遮蔽物表(屋内)(P140): RIMT
37
+ ・逃走体験表(P144): EET
38
+ ・食材採集表(P157): GFT
39
+ ・水採集表(P157): GWT
40
+ ・白の魔石効果表(P186): WST
41
41
  MESSAGETEXT
42
42
 
43
43
  def eval_game_system_specific_command(command)
@@ -106,9 +106,9 @@ module BCDice
106
106
  [1..3, '【余裕】が3点減少する(最低0まで)'],
107
107
  [4..5, 'ランダムな荷物1個が落ちて行方不明になる(大失敗したエリアのアイテム調査で見つけることが可能)'],
108
108
  [6..7, 'ランダムな荷物1個が破壊される'],
109
- [8..9, 'ランダム天気表を使用し、結果をターンの終了まで適用する'],
109
+ [8..9, 'ランダム天気表(RWT)を使用し、結果をターンの終了まで適用する'],
110
110
  [10, 'ランダムな準備している小道具1個が破壊される'],
111
- [11, '着想している防具が破壊される'],
111
+ [11, '着装している防具が破壊される'],
112
112
  [12, '準備している武器が破壊される'],
113
113
  ]
114
114
  ),
@@ -19,6 +19,8 @@ module BCDice
19
19
 
20
20
  # ダイスボットの使い方
21
21
  HELP_MESSAGE = <<~MESSAGETEXT
22
+ ・LIST のコマンドを入力して、ルールの解説・2D6表、一覧の表示
23
+
22
24
  ・判定(xNC±y>=z)
23
25
   xD6の判定を行います。ファンブル、クリティカルの場合、その旨を出力します。
24
26
   x:振るダイスの数。
@@ -27,7 +29,6 @@ module BCDice
27
29
   ダイスの出目ふたつが6ならクリティカル(自動成功)
28
30
   ダイスの出目すべてが1ならファンブル(自動失敗)
29
31
   例) 2NC+2>=5 1NC
30
- ・ルール詳細、表の一覧(LIST)
31
32
  MESSAGETEXT
32
33
 
33
34
  def eval_game_system_specific_command(command)
@@ -37,6 +38,8 @@ module BCDice
37
38
  return TEXTS[command].chomp
38
39
  elsif TABLES.key?(command)
39
40
  return roll_tables(command, TABLES)
41
+ elsif ALIAS_TEXTS.key?(command)
42
+ return TEXTS[ALIAS_TEXTS[command]].chomp
40
43
  else
41
44
  return nil
42
45
  end
@@ -88,23 +91,27 @@ module BCDice
88
91
  ・キャラ作成アプリ:https://nctrpg.com/bloomi
89
92
 
90
93
  ・判定(xD6±y>=z)
94
+
95
+ ()内のコマンドを入力して詳細を表示。
96
+
91
97
  2D6(CHAR1) ・所属表(2D6またはRoC。基本ルール書籍版P33)
92
- 2D6(CHRA2) ・趣味表(2D6またはRoC。基本ルール書籍版P38)
98
+ 2D6(CHAR2) ・趣味表(2D6またはRoC。基本ルール書籍版P38)
93
99
  2D6(CHAR3) ・リビド武装形状表(2D6またはRoC。基本ルール書籍版P39)
94
100
  2D6(NAYA1) 悩みの詳細表・愛/Love:得意方向(正面)(2D6またはRoC。基本ルール書籍版P49)
95
101
  2D6(NAYA2) 悩みの詳細表・体/Figure:得意方向(正面)(2D6またはRoC。基本ルール書籍版P49)
96
102
  2D6(NAYA3) 悩みの詳細表・才/Talent:得意方向(背面)(2D6またはRoC。基本ルール書籍版P49)
97
103
  2D6(NAYA4) 悩みの詳細表・絆/Bonds:得意方向(側面)(2D6またはRoC。基本ルール書籍版P49)
98
104
  2D6(NAYA5) 悩みの詳細表・住/Home:得意方向(側面)(2D6またはRoC。基本ルール書籍版P49)
99
- 各種RoC表はコマンドの最後にアルファベットのLを付けることにより一覧表示が可能
100
105
 
101
- (LIKE) LIKE(基本ルール書籍版P60)
106
+ 各種2D6:RoC表はコマンドの最後にアルファベットのLを付けて一覧表示が可能(例:NAYA5→NAYA5L)
107
+
108
+ (LIKE1) LIKE(基本ルール書籍版P60)
102
109
  (RESE1) リサーチカード(基本ルール書籍版P63)
103
110
  (RESE2) インタビュー(基本ルール書籍版P62)
104
111
  (RESE3) パイルドライヴ(基本ルール書籍版P64)
105
112
  (RESE4) [決意]と[使命](基本ルール書籍版P61)
106
113
 
107
- (ARTS) リビドアーツのデータ項目(基本ルール書籍版P40)
114
+ (ARTS1) リビドアーツのデータ項目(基本ルール書籍版P40)
108
115
  (STAT1) SSリスト(基本ルール書籍版P41)
109
116
  (STAT2) LSリスト(基本ルール書籍版P411)
110
117
  (ACTI1) タイミング:サブアクション(基本ルール書籍版P422)
@@ -132,7 +139,7 @@ module BCDice
132
139
  (MINI5) ねばくらミニでのスペシャルアーツ(ねばくらミニ書籍版P13)
133
140
  (MINI6) ねばくらミニでのポータルとサーヴァント(ねばくらミニ書籍版P14)
134
141
  TEXT
135
- 'LIKE' => <<~TEXT,
142
+ 'LIKE1' => <<~TEXT,
136
143
  LIKE(基本ルール書籍版P60)
137
144
  ・全ての参加者(PLやGMや見学者)はセッション中にPCやGMのロールプレイや行動に、
138
145
   共感や称賛や琴線に触れた時[LIKE:~]と言ってその内容と共に記述して蓄積して行く。
@@ -167,7 +174,7 @@ module BCDice
167
174
  ・これとは別にGMは[LIKE]の合計点を5で割った値を[使命]言う単位(最大5点)とする。
168
175
   [決意]と[使命]は[Pコトノハ][Sコトノハ][ワード]の単語ごとに割り振られ、これらの単語を使用したロールプレイを推奨する。
169
176
  TEXT
170
- 'ARTS' => <<~TEXT,
177
+ 'ARTS1' => <<~TEXT,
171
178
  リビドアーツのデータ項目(基本ルール書籍版P40)
172
179
  ・射程:起点から『ぴったり』に、何Sq離れたキャラクターを対象に取れるかを示す。射程0は自身のみのことである。
173
180
  ・威力:そのアーツを使用した結果に対象に及ぼす数値を示す。ダイスロールを含む場合「威力ロール」と呼ぶ。
@@ -602,8 +609,12 @@ module BCDice
602
609
  ),
603
610
  }.freeze
604
611
 
612
+ ALIAS_TEXTS = {
613
+ "ARTS" => "ARTS1",
614
+ }.freeze
615
+
605
616
  # ダイスボットで使用するコマンドを配列で列挙する
606
- register_prefix('\d+NC', '\d+D6?([\+\-\d]*)>=\d+', TEXTS.keys, TABLES.keys)
617
+ register_prefix('\d+NC', '\d+D6?([\+\-\d]*)>=\d+', TEXTS.keys, TABLES.keys, ALIAS_TEXTS.keys)
607
618
  end
608
619
  end
609
620
  end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Shiranui < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Shiranui'
8
+
9
+ # ゲームシステム名
10
+ NAME = '不知火'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'しらぬい'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~HELP
17
+ ■∞D66ダイスロール
18
+ 「 ∞D66 」または「 ID66 」
19
+ ( ID は Infinite D の略です)
20
+
21
+ □行動力や攻撃力の指定
22
+ 「 x+∞D66 」または「 x+ID66 」
23
+ ( x は行動力や攻撃力)
24
+
25
+ □鬼火の使用について
26
+ 鬼火を使用する∞D66は、ダイスボットでサポートしていません。
27
+
28
+ ■おみくじを引く
29
+ OMKJ
30
+ HELP
31
+
32
+ INFINITE_D66_ROLL_REG = /^((\d+)\+)?(∞|I)D66$/i.freeze
33
+ register_prefix('(\d+\+)?(∞|I)D66')
34
+
35
+ def initialize(command)
36
+ super(command)
37
+
38
+ @sort_barabara_dice = true
39
+ end
40
+
41
+ def eval_game_system_specific_command(command)
42
+ if (m = INFINITE_D66_ROLL_REG.match(command))
43
+ fixed_score = m[1]&.to_i
44
+ roll_infinite_d66(fixed_score)
45
+ else
46
+ roll_tables(command, TABLES)
47
+ end
48
+ end
49
+
50
+ def roll_infinite_d66(fixed_score)
51
+ steps = []
52
+
53
+ while steps.empty? || steps.last.to_continue_diceroll?
54
+ # 個別の出目をあつかうので、 roll_d66 ではなく roll_barabara を使う
55
+ dices = @randomizer.roll_barabara(2, 6).sort
56
+
57
+ steps << InifiniteD66Step.new(dices)
58
+ end
59
+
60
+ is_failure = steps.first.score.zero? # 「しくじり」か?
61
+ total = is_failure ? 0 : steps.sum(&:score) + fixed_score.to_i
62
+
63
+ result_text = "(#{self.class.make_command_text(fixed_score)})"
64
+ result_text += " > " + steps.map(&:to_s).join(' > ')
65
+ if is_failure
66
+ result_text += " > しくじり"
67
+ else
68
+ result_text += " > " + self.class.score_expression_text(steps, fixed_score) if steps.size > 1 || !fixed_score.nil?
69
+ result_text += " > " + total.to_s
70
+ end
71
+
72
+ Result.new(result_text).tap do |r|
73
+ r.critical = steps.size > 1
74
+ r.failure = is_failure
75
+ r.fumble = is_failure
76
+ end
77
+ end
78
+
79
+ def self.make_command_text(fixed_score)
80
+ fixed_score.nil? ? "∞D66" : "#{fixed_score}+∞D66"
81
+ end
82
+
83
+ def self.score_expression_text(steps, fixed_score)
84
+ text = steps.map(&:score).join('+')
85
+ text = "#{fixed_score}+(#{text})" unless fixed_score.nil?
86
+ text
87
+ end
88
+
89
+ class InifiniteD66Step
90
+ def initialize(dices)
91
+ @dices = dices.dup.freeze
92
+ end
93
+
94
+ def score
95
+ if repdigit?
96
+ # ゾロ目の場合
97
+
98
+ digit = @dices.first
99
+
100
+ if digit == 1
101
+ # 1 のゾロ目なら 0 となる
102
+ 0
103
+ else
104
+ # 1 以外のゾロ目なら、数字の 10 倍となる
105
+ digit * 10
106
+ end
107
+ else
108
+ # ゾロ目でない場合は、 D66 様式で値を算出する
109
+ @dices[0] * 10 + @dices[1]
110
+ end
111
+ end
112
+
113
+ def repdigit?
114
+ @dices[0] == @dices[1]
115
+ end
116
+
117
+ # ダイスロールを継続する必要があるか?
118
+ def to_continue_diceroll?
119
+ repdigit? && @dices[0] != 1
120
+ end
121
+
122
+ def to_s
123
+ "[#{@dices[0]},#{@dices[1]}]"
124
+ end
125
+ end
126
+
127
+ TABLES = {
128
+ "OMKJ" => DiceTable::Table.new(
129
+ "おみくじ",
130
+ "1D6",
131
+ [
132
+ "大凶[御利益1]――このみくじにあたる人は、凶運から逃れることができぬ者なり。まさに凶運にその身をゆだねてこそ、浮かぶ瀬もあれ。……これより上演中に演者が振る[∞D66]で初めて⚀⚀が出たら、御利益を使っても振り直しができない。",
133
+ "凶[御利益2]――このみくじにあたる人は、吉兆を逃す定めにある。まさに、天の与うるを取らざれば反ってその咎めを受く。……これより上演中に演者が振る[∞D66]で初めて⚅⚅が出たら、強制的に1回の振り直しをする。",
134
+ "小吉[御利益3]――このみくじにあたる人は、神使の機嫌を損ねている。神使が何に怒り、何に苛立っているのかは、まさに神のみぞ知る。……神使の機嫌が突然、悪くなる。これより上演中に神使は何かと理由をつけてはシラヌイの前から立ち去ろうとする。",
135
+ "中吉[御利益4]――このみくじにあたる人は、神使の機嫌を良くすることを行った者なり。神使が何に喜び、なぜ機嫌が良いのか、まさに神のみぞ知る。……神使の機嫌がすこぶる良くなる。これより上演中に神使は上機嫌となり、シラヌイに何かにつけて話しかけてくれる。",
136
+ "吉[御利益5]――このみくじにあたる人は、悪運を幸運へと変える道を進む者なり。まさに禍福は糾える縄の如し。……これより上演中に演者が振る[∞D66]で初めて⚀⚀が出たら、御利益を消費することなく、1回の振り直しをする。",
137
+ "大吉[御利益6]――このみくじにあたる人は、思いもよらぬ幸運に巡り合う者なり。まさに、暗き道より出て、気づけば月の光あり。……これより上演中に演者が振る[∞D66]で1回だけ、サイコロの出目を⚅⚅に変えてよい。",
138
+ ]
139
+ ),
140
+ }.freeze
141
+
142
+ register_prefix(TABLES.keys)
143
+ end
144
+ end
145
+ end