bcdice 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -3
  3. data/README.md +1 -1
  4. data/i18n/MagicaLogia/zh_hans.yml +564 -0
  5. data/i18n/StellarKnights/ja_jp.yml +2 -0
  6. data/i18n/StellarKnights/ko_kr.yml +498 -0
  7. data/i18n/zh_hans.yml +7 -0
  8. data/lib/bcdice/command/parsed.rb +11 -3
  9. data/lib/bcdice/command/parser.rb +179 -100
  10. data/lib/bcdice/common_command/barabara_dice/node.rb +2 -2
  11. data/lib/bcdice/common_command/barabara_dice/result.rb +6 -0
  12. data/lib/bcdice/game_system.rb +3 -0
  13. data/lib/bcdice/game_system/Amadeus.rb +110 -93
  14. data/lib/bcdice/game_system/AnimaAnimus.rb +15 -8
  15. data/lib/bcdice/game_system/BattleTech.rb +109 -28
  16. data/lib/bcdice/game_system/BeastBindTrinity.rb +28 -12
  17. data/lib/bcdice/game_system/BlindMythos.rb +38 -37
  18. data/lib/bcdice/game_system/CodeLayerd.rb +39 -39
  19. data/lib/bcdice/game_system/ColossalHunter.rb +34 -47
  20. data/lib/bcdice/game_system/DeadlineHeroes.rb +9 -8
  21. data/lib/bcdice/game_system/DoubleCross.rb +2 -0
  22. data/lib/bcdice/game_system/Emoklore.rb +22 -17
  23. data/lib/bcdice/game_system/FutariSousa.rb +12 -10
  24. data/lib/bcdice/game_system/GardenOrder.rb +11 -6
  25. data/lib/bcdice/game_system/KemonoNoMori.rb +25 -38
  26. data/lib/bcdice/game_system/KurayamiCrying.rb +86 -0
  27. data/lib/bcdice/game_system/LiveraDoll.rb +254 -304
  28. data/lib/bcdice/game_system/LogHorizon.rb +10 -7
  29. data/lib/bcdice/game_system/MagicaLogia_SimplifiedChinese.rb +66 -0
  30. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +2 -1
  31. data/lib/bcdice/game_system/Nechronica.rb +57 -91
  32. data/lib/bcdice/game_system/NinjaSlayer.rb +2 -3
  33. data/lib/bcdice/game_system/SRS.rb +17 -16
  34. data/lib/bcdice/game_system/SamsaraBallad.rb +38 -11
  35. data/lib/bcdice/game_system/Satasupe.rb +31 -31
  36. data/lib/bcdice/game_system/ScreamHighSchool.rb +3 -3
  37. data/lib/bcdice/game_system/Skynauts.rb +101 -140
  38. data/lib/bcdice/game_system/StarryDolls.rb +318 -0
  39. data/lib/bcdice/game_system/SteamPunkers.rb +11 -6
  40. data/lib/bcdice/game_system/StellarKnights.rb +28 -12
  41. data/lib/bcdice/game_system/StellarKnights_Korean.rb +79 -0
  42. data/lib/bcdice/game_system/TokumeiTenkousei.rb +4 -3
  43. data/lib/bcdice/game_system/TrinitySeven.rb +275 -276
  44. data/lib/bcdice/game_system/Utakaze.rb +52 -47
  45. data/lib/bcdice/game_system/Yggdrasill.rb +1 -1
  46. data/lib/bcdice/game_system/ZettaiReido.rb +20 -25
  47. data/lib/bcdice/version.rb +1 -1
  48. metadata +8 -2
@@ -128,27 +128,30 @@ module BCDice
128
128
  dice_total = dice_list.sum()
129
129
  total = dice_total + parsed.modify_number
130
130
 
131
+ result = result_text(dice_count, dice_list, total, parsed)
132
+
131
133
  sequence = [
132
134
  "(#{parsed})",
133
135
  "#{dice_total}[#{dice_list.join(',')}]#{Format.modifier(parsed.modify_number)}",
134
136
  total,
135
- result_text(dice_count, dice_list, total, parsed),
137
+ result.text,
136
138
  ].compact
137
139
 
138
- return sequence.join(" > ")
140
+ result.text = sequence.join(" > ")
141
+ result
139
142
  end
140
143
 
141
144
  def result_text(dice_count, dice_list, total, parsed)
142
145
  if dice_list.count(6) >= 2
143
- translate("LogHorizon.LH.critical")
146
+ Result.critical(translate("LogHorizon.LH.critical"))
144
147
  elsif dice_list.count(1) >= dice_count
145
- translate("LogHorizon.LH.fumble")
148
+ Result.fumble(translate("LogHorizon.LH.fumble"))
146
149
  elsif parsed.cmp_op.nil?
147
- nil
150
+ Result.new
148
151
  elsif total >= parsed.target_number
149
- translate('success')
152
+ Result.success(translate("success"))
150
153
  else
151
- translate('failure')
154
+ Result.failure(translate("failure"))
152
155
  end
153
156
  end
154
157
 
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/game_system/MagicaLogia"
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class MagicaLogia_SimplifiedChinese < MagicaLogia
8
+ # ゲームシステムの識別子
9
+ ID = "MagicaLogia:SimplifiedChinese"
10
+
11
+ # ゲームシステム名
12
+ NAME = "魔导书大战"
13
+
14
+ # ゲームシステム名の読みがな
15
+ SORT_KEY = "国際化:Simplified Chinese:魔导书大战"
16
+
17
+ # ダイスボットの使い方
18
+ HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
+ ・判定
20
+ 可以判定大成功/大失败/成功/失败
21
+ ・各种表
22
+ 经历表 BGT/初期锚点表 DAT/命运属性表 FAT
23
+ 愿望表 WIT/战利品表 PT
24
+ 时间流逝表 TPT/大判时间流逝表 TPTB
25
+ 事件表 AT
26
+ 大失败表 FT/变调表 WT
27
+ 命运转变表表 FCT
28
+  典型性灾厄 TCT/物理性灾厄 PCT/精神性灾厄 MCT/狂气性灾厄 ICT
29
+  社会性灾厄 SCT/超自然灾厄 XCT/不可思议的灾厄 WCT/喜剧性灾厄 CCT
30
+  魔法使的灾厄 MGCT
31
+ 场景表 ST/大判场景表 STB
32
+  极限环境 XEST/内心世界 IWST/魔法都市 MCST
33
+  死后世界 WDST/迷宫世界 LWST
34
+  魔法书架 MBST/魔法学院 MAST/克雷德塔 TCST
35
+  平行世界 PWST/终末世界 PAST/异世界酒吧 GBST
36
+  星影 SLST/旧图书馆 OLST
37
+ 世界法则追加表 WLAT/徘徊怪物表 WMT
38
+ 随机领域表 RCT
39
+ 随机特技表 RTT
40
+  星领域随机特技表 RTS, RTT1
41
+  兽领域随机特技表 RTB, RTT2
42
+  力领域随机特技表 RTF, RTT3
43
+  歌领域随机特技表 RTP, RTT4
44
+  梦领域随机特技表 RTD, RTT5
45
+  暗领域随机特技表 RTN, RTT6
46
+ 空白秘密表 BST
47
+  宿敌表 MIT/谋略表 MOT/因缘表 MAT
48
+  奇人表 MUT/力场表 MFT/同盟表 MLT
49
+ 落花表 FFT
50
+ 那之后表 FLT
51
+ ・可以使用D66
52
+ INFO_MESSAGE_TEXT
53
+
54
+ register_prefix_from_super_class()
55
+
56
+ def initialize(command)
57
+ super(command)
58
+
59
+ @locale = :zh_hans
60
+ end
61
+
62
+ SKILL_TABLE = translate_skill_table(:zh_hans)
63
+ TABLES = translate_tables(:zh_hans, SKILL_TABLE)
64
+ end
65
+ end
66
+ end
@@ -72,7 +72,8 @@ module BCDice
72
72
  'BUS', 'SHS', 'ASS', 'SUS', 'SCS', 'LAS', 'NES', 'COS', 'ENS', 'TOS',
73
73
  'ABUS', 'ASHS', 'AASS', 'ASUS', 'ASCS', 'ALAS', 'ANES', 'ACOS', 'AENS', 'ATOS',
74
74
  'SE', 'ARN', 'WEN', 'NEN', 'CEN', 'SEN', 'OEN',
75
- 'DFT'
75
+ 'DFT',
76
+ 'PNT', 'MLT'
76
77
  )
77
78
 
78
79
  def initialize(command)
@@ -17,10 +17,10 @@ module BCDice
17
17
  # ダイスボットの使い方
18
18
  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
19
19
  ・判定 (nNC+m)
20
-  ダイス数n、修正値mで判定ロールを行います。
20
+  ダイス数n、修正値mで判定ロールを行います(省略=1)
21
21
   ダイス数が2以上の時のパーツ破損数も表示します。
22
22
  ・攻撃判定 (nNA+m)
23
-  ダイス数n、修正値mで攻撃判定ロールを行います。
23
+  ダイス数n、修正値mで攻撃判定ロールを行います(省略=1)
24
24
   命中部位とダイス数が2以上の時のパーツ破損数も表示します。
25
25
 
26
26
 
@@ -37,126 +37,92 @@ module BCDice
37
37
  @default_target_number = 6 # 目標値が空欄の時の目標値
38
38
  end
39
39
 
40
- private
41
-
42
- def replace_text(string)
43
- string = string.gsub(/(\d+)NC(10)?([+\-][+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[0]" }
44
- string = string.gsub(/(\d+)NC(10)?/i) { "#{Regexp.last_match(1)}R10[0]" }
45
- string = string.gsub(/(\d+)NA(10)?([+\-][+\-\d]+)/i) { "#{Regexp.last_match(1)}R10#{Regexp.last_match(3)}[1]" }
46
- string = string.gsub(/(\d+)NA(10)?/i) { "#{Regexp.last_match(1)}R10[1]" }
47
-
48
- return string
40
+ def eval_game_system_specific_command(command)
41
+ roll_tables(command, self.class::TABLES) || nechronica_check(command)
49
42
  end
50
43
 
51
- public
44
+ def result_nd10(total, _dice_total, value_list, cmp_op, target)
45
+ # 後方互換を維持するため、1d10>=nを目標値nの1NCとして処理
46
+ if value_list.count != 1 || cmp_op != :>= || target.nil? || target == "?"
47
+ return nil
48
+ end
52
49
 
53
- def eval_game_system_specific_command(command)
54
- return roll_tables(command, self.class::TABLES) || nechronica_check(command)
50
+ result_nechronica([total], target)
55
51
  end
56
52
 
57
53
  private
58
54
 
59
- def result_nd10(total, _dice_total, dice_list, cmp_op, target) # ゲーム別成功度判定(nD10)
60
- return Result.nothing if target == '?'
61
- return nil unless cmp_op == :>=
62
-
63
- if total >= 11
64
- Result.critical(translate("Nechronica.critical"))
65
- elsif total >= target
66
- Result.success(translate("success"))
67
- elsif dice_list.count { |i| i <= 1 } == 0
55
+ def result_nechronica(value_list, target)
56
+ if value_list.max >= target
57
+ if value_list.max >= 11
58
+ Result.critical(translate("Nechronica.critical"))
59
+ else
60
+ Result.success(translate("success"))
61
+ end
62
+ elsif value_list.count { |i| i <= 1 } == 0
68
63
  Result.failure(translate("failure"))
69
- elsif dice_list.size > 1
70
- fumble = translate("Nechronica.fumble")
64
+ elsif value_list.size > 1
71
65
  break_all_parts = translate("Nechronica.break_all_parts")
66
+ fumble = translate("Nechronica.fumble")
72
67
  Result.fumble("#{fumble} > #{break_all_parts}")
73
68
  else
74
69
  Result.fumble(translate("Nechronica.fumble"))
75
70
  end
76
71
  end
77
72
 
78
- def result_nd10_text(total, dice_list, target)
79
- text = result_nd10(total, 0, dice_list, :>=, target)&.text
73
+ # Rコマンドの後方互換を維持する
74
+ def r_backward_compatibility(command)
75
+ m = command.match(/^(\d)?R10([+\-\d]+)?(\[(\d+)\])?$/)
76
+ return command unless m
80
77
 
81
- if text.nil?
82
- ""
78
+ if m[4] == "1"
79
+ "#{m[1]}NA#{m[2]}"
83
80
  else
84
- "#{text}"
81
+ "#{m[1]}NC#{m[2]}"
85
82
  end
86
83
  end
87
84
 
88
- def nechronica_check(string)
89
- string = replace_text(string)
90
- debug("nechronica_check string", string)
91
-
92
- unless /(^|\s)S?((\d+)[rR]10([+\-\d]+)?(\[(\d+)\])?)(\s|$)/i =~ string
93
- return nil
94
- end
95
-
96
- string = Regexp.last_match(2)
85
+ def nechronica_check(command)
86
+ command = r_backward_compatibility(command)
87
+ # 歴史的経緯で10を受理する
88
+ cmd = Command::Parser.new(/N[CA](10)?/, round_type: round_type)
89
+ .enable_prefix_number.parse(command)
90
+ return nil unless cmd
97
91
 
98
- dice_n = 1
99
- dice_n = Regexp.last_match(3).to_i if Regexp.last_match(3)
92
+ dice_count = [1, cmd.prefix_number.to_i].max
93
+ modify_number = cmd.modify_number || 0
100
94
 
101
- battleMode = Regexp.last_match(6).to_i
95
+ dice = @randomizer.roll_barabara(dice_count, 10).sort
96
+ dice_mod = dice.map { |i| i + modify_number }
97
+ total = dice_mod.max
102
98
 
103
- modText = Regexp.last_match(4)
104
- mod = ArithmeticEvaluator.eval(modText)
99
+ na = get_hit_location(total) if cmd.command.start_with?("NA")
105
100
 
106
- # 0=判定モード, 1=戦闘モード
107
- isBattleMode = (battleMode == 1)
108
- debug("nechronica_check string", string)
109
- debug("isBattleMode", isBattleMode)
101
+ result = result_nechronica(dice_mod, 6)
110
102
 
111
- diff = 6
103
+ sequence = [
104
+ "(#{cmd})",
105
+ "[#{dice.join(',')}]#{Format.modifier(modify_number)}",
106
+ "#{total}[#{dice_mod.join(',')}]",
107
+ result.text,
108
+ na,
109
+ ].compact
112
110
 
113
- dice = @randomizer.roll_barabara(dice_n, 10).sort
114
- n_max = dice.max
115
-
116
- total_n = n_max + mod
117
-
118
- output = "(#{string}) > [#{dice.join(',')}]"
119
- if mod < 0
120
- output += mod.to_s
121
- elsif mod > 0
122
- output += "+#{mod}"
123
- end
124
-
125
- dice.map! { |i| i + mod }
126
-
127
- dice_str = dice.join(",")
128
- output += " > #{total_n}[#{dice_str}]"
129
-
130
- output += result_nd10_text(total_n, dice, diff)
131
-
132
- if isBattleMode
133
- hit_loc = getHitLocation(total_n)
134
- if hit_loc != '1'
135
- output += " > #{hit_loc}"
136
- end
137
- end
138
-
139
- return output
111
+ result.text = sequence.join(" > ")
112
+ return result
140
113
  end
141
114
 
142
- def getHitLocation(dice)
143
- output = '1'
144
-
145
- debug("getHitLocation dice", dice)
146
- return output if dice <= 5
115
+ def get_hit_location(value)
116
+ return nil if value <= 5
147
117
 
148
118
  table = translate("Nechronica.hit_location.table")
149
- index = dice - 6
119
+ text = table[(value - 6).clamp(0, 5)]
150
120
 
151
- addDamage = ""
152
- if dice > 10
153
- index = 5
154
- addDamage = translate("Nechronica.hit_location.additional_damage", damage: dice - 10)
121
+ if value > 10
122
+ text + translate("Nechronica.hit_location.additional_damage", damage: value - 10)
123
+ else
124
+ text
155
125
  end
156
-
157
- output = table[index] + addDamage
158
-
159
- return output
160
126
  end
161
127
 
162
128
  class << self
@@ -173,7 +139,7 @@ module BCDice
173
139
 
174
140
  TABLES = translate_tables(:ja_jp)
175
141
 
176
- register_prefix('\d+NC', '\d+NA', '\d+R10', TABLES.keys)
142
+ register_prefix('\d?NC', '\d?NA', '\dR10', TABLES.keys)
177
143
  end
178
144
  end
179
145
  end
@@ -176,8 +176,7 @@ module BCDice
176
176
  command = bRollCommand(at.num, at.difficulty)
177
177
  roll_result = BCDice::CommonCommand::BarabaraDice.eval(command, self, @randomizer)
178
178
 
179
- values = roll_result.rands.map { |v, _| v }
180
- num_of_max_values = values.count(6)
179
+ num_of_max_values = roll_result.last_dice_list.count(6)
181
180
 
182
181
  parts = [roll_result.text]
183
182
 
@@ -195,7 +194,7 @@ module BCDice
195
194
  command = bRollCommand(el.num, el.difficulty)
196
195
  roll_result = BCDice::CommonCommand::BarabaraDice.eval(command, self, @randomizer)
197
196
 
198
- values = roll_result.rands.map { |v, _| v }
197
+ values = roll_result.last_dice_list
199
198
  num_of_max_values = values.count(6)
200
199
  sum_of_true_values = values.count { |v| v >= el.difficulty }
201
200
 
@@ -219,7 +219,7 @@ module BCDice
219
219
 
220
220
  # 固有のダイスロールコマンドを実行する
221
221
  # @param [String] command 入力されたコマンド
222
- # @return [String, nil] ダイスロールコマンドの実行結果
222
+ # @return [Result, nil] ダイスロールコマンドの実行結果
223
223
  def eval_game_system_specific_command(command)
224
224
  alias_replaced_with_2d6 = replace_alias_for_srs_roll_with_2d6(command)
225
225
 
@@ -297,7 +297,7 @@ module BCDice
297
297
 
298
298
  # 成功判定を実行する
299
299
  # @param [SRSRollNode] srs_roll 成功判定ノード
300
- # @return [String] 成功判定結果
300
+ # @return [Result] 成功判定結果
301
301
  def execute_srs_roll(srs_roll)
302
302
  dice_list = @randomizer.roll_barabara(2, 6)
303
303
  dice_list.sort! if @sort_add_dice
@@ -307,35 +307,36 @@ module BCDice
307
307
 
308
308
  modified_sum = sum + srs_roll.modifier
309
309
 
310
+ result = compare_result(srs_roll, sum, modified_sum)
311
+
310
312
  parts = [
311
313
  "(#{srs_roll})",
312
314
  "#{sum}[#{dice_str}]#{Format.modifier(srs_roll.modifier)}",
313
315
  modified_sum,
314
- compare_result(srs_roll, sum, modified_sum)
316
+ result.text
315
317
  ]
316
318
 
317
- return parts.compact.join(' > ')
319
+ result.text = parts.compact.join(' > ')
320
+ result
318
321
  end
319
322
 
320
323
  # ダイスロール結果を目標値、クリティカル値、ファンブル値と比較する
321
324
  # @param [SRSRollNode] srs_roll 成功判定ノード
322
325
  # @param [Integer] sum 出目の合計
323
326
  # @param [Integer] modified_sum 修正後の値
324
- # @return [String, nil] 比較結果
327
+ # @return [Result] 比較結果
325
328
  def compare_result(srs_roll, sum, modified_sum)
326
329
  if sum >= srs_roll.critical_value
327
- return '自動成功'
328
- end
329
-
330
- if sum <= srs_roll.fumble_value
331
- return '自動失敗'
332
- end
333
-
334
- if srs_roll.target_value
335
- return modified_sum >= srs_roll.target_value ? '成功' : '失敗'
330
+ Result.critical("自動成功")
331
+ elsif sum <= srs_roll.fumble_value
332
+ Result.fumble("自動失敗")
333
+ elsif srs_roll.target_value.nil?
334
+ Result.new
335
+ elsif modified_sum >= srs_roll.target_value
336
+ Result.success("成功")
337
+ else
338
+ Result.failure("失敗")
336
339
  end
337
-
338
- return nil
339
340
  end
340
341
  end
341
342
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'bcdice/base'
4
+
3
5
  module BCDice
4
6
  module GameSystem
5
7
  class SamsaraBallad < Base
@@ -59,38 +61,63 @@ module BCDice
59
61
  total = 100 if total == 0
60
62
  end
61
63
 
62
- cmp_result = compare(total, cmd)
64
+ result = compare(total, cmd)
65
+
66
+ result_str =
67
+ if result.failure?
68
+ "失敗"
69
+ elsif result.success?
70
+ "成功"
71
+ end
72
+
73
+ additional_str =
74
+ if result.fumble?
75
+ "ファンブル"
76
+ elsif result.critical?
77
+ "クリティカル"
78
+ end
63
79
 
64
80
  sequence = [
65
81
  "(D100#{cmd.cmp_op}#{cmd.target_number})",
66
82
  places_text,
67
83
  total.to_s,
68
- cmp_result,
84
+ result_str,
85
+ additional_str,
69
86
  ].compact
70
87
 
71
- return sequence.join(" > ")
88
+ result.text = sequence.join(" > ")
89
+
90
+ return result
72
91
  end
73
92
 
74
93
  private
75
94
 
76
- # @return [String]
77
- # @return [nil]
95
+ # @return [Result]
78
96
  def compare(total, cmd)
79
97
  if [:<=, :<].include?(cmd.cmp_op)
80
98
  if !total.send(cmd.cmp_op, cmd.target_number)
81
- "失敗"
99
+ Result.failure(nil)
82
100
  elsif fumble_?(total, cmd.fumble)
83
- "ファンブル"
101
+ Result.new.tap do |r|
102
+ r.success = true
103
+ r.fumble = true
104
+ end
84
105
  elsif critical_?(total, cmd.critical)
85
- "クリティカル"
106
+ Result.critical(nil)
86
107
  else
87
- "成功"
108
+ Result.success(nil)
88
109
  end
89
110
  elsif fumble_?(total, cmd.fumble)
90
111
  # ファンブル優先
91
- "ファンブル"
112
+ Result.new.tap do |r|
113
+ r.fumble = true
114
+ end
92
115
  elsif critical_?(total, cmd.critical)
93
- "クリティカル"
116
+ Result.new.tap do |r|
117
+ r.critical = true
118
+ end
119
+ else
120
+ Result.new
94
121
  end
95
122
  end
96
123