bcdice 3.4.0 → 3.5.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/i18n/BeginningIdol/ja_jp.yml +2806 -0
  4. data/i18n/BeginningIdol/ko_kr.yml +1400 -0
  5. data/i18n/KillDeathBusiness/ja_jp.yml +1 -1
  6. data/i18n/MagicaLogia/ja_jp.yml +1 -1
  7. data/i18n/MonotoneMuseum/ko_kr.yml +526 -53
  8. data/lib/bcdice/common_command/choice.rb +5 -1
  9. data/lib/bcdice/common_command/tally_dice/node.rb +135 -0
  10. data/lib/bcdice/common_command/tally_dice/parser.rb +302 -0
  11. data/lib/bcdice/common_command/tally_dice.rb +19 -0
  12. data/lib/bcdice/common_command.rb +2 -0
  13. data/lib/bcdice/dice_table/d66_table.rb +5 -1
  14. data/lib/bcdice/game_system/Aoharubaan.rb +91 -0
  15. data/lib/bcdice/game_system/AssaultEngine.rb +91 -0
  16. data/lib/bcdice/game_system/BadLife.rb +264 -289
  17. data/lib/bcdice/game_system/Bakenokawa.rb +244 -0
  18. data/lib/bcdice/game_system/BeginningIdol.rb +116 -2390
  19. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +10 -2312
  20. data/lib/bcdice/game_system/CastleInGray.rb +133 -0
  21. data/lib/bcdice/game_system/Cthulhu.rb +2 -2
  22. data/lib/bcdice/game_system/Cthulhu7th.rb +6 -6
  23. data/lib/bcdice/game_system/DoubleCross.rb +5 -0
  24. data/lib/bcdice/game_system/Emoklore.rb +1 -1
  25. data/lib/bcdice/game_system/FateCoreSystem.rb +117 -0
  26. data/lib/bcdice/game_system/Karukami.rb +84 -0
  27. data/lib/bcdice/game_system/KurayamiCrying.rb +1 -1
  28. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +4 -4
  29. data/lib/bcdice/game_system/{SterileLife.rb → StellarLife.rb} +162 -226
  30. data/lib/bcdice/game_system/SwordWorld.rb +6 -2
  31. data/lib/bcdice/game_system/SwordWorld2_0.rb +20 -5
  32. data/lib/bcdice/game_system/SwordWorld2_5.rb +6 -0
  33. data/lib/bcdice/game_system/TalesFromTheLoop.rb +83 -0
  34. data/lib/bcdice/game_system/YearZeroEngine.rb +40 -19
  35. data/lib/bcdice/game_system/beginning_idol/accessories_table.rb +31 -0
  36. data/lib/bcdice/game_system/beginning_idol/bad_status_table.rb +43 -0
  37. data/lib/bcdice/game_system/beginning_idol/chain_d66_table.rb +29 -0
  38. data/lib/bcdice/game_system/beginning_idol/chain_table.rb +37 -0
  39. data/lib/bcdice/game_system/beginning_idol/costume_table.rb +37 -0
  40. data/lib/bcdice/game_system/beginning_idol/d6_twice_table.rb +36 -0
  41. data/lib/bcdice/game_system/beginning_idol/item_table.rb +51 -0
  42. data/lib/bcdice/game_system/beginning_idol/my_skill_name_table.rb +44 -0
  43. data/lib/bcdice/game_system/beginning_idol/random_event_table.rb +31 -0
  44. data/lib/bcdice/game_system/beginning_idol/skill_table.rb +63 -0
  45. data/lib/bcdice/game_system/beginning_idol/table.rb +193 -0
  46. data/lib/bcdice/game_system/beginning_idol/with_abnormality.rb +74 -0
  47. data/lib/bcdice/game_system/beginning_idol/work_table.rb +57 -0
  48. data/lib/bcdice/game_system/one_way_heroics/random_event_table.rb +4 -4
  49. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +46 -3
  50. data/lib/bcdice/game_system/sword_world/rating_parser.rb +147 -106
  51. data/lib/bcdice/game_system.rb +8 -1
  52. data/lib/bcdice/version.rb +1 -1
  53. metadata +28 -3
@@ -30,7 +30,7 @@ module BCDice
30
30
  # choice(A[], B[], C[]) -> "A[]", "B[]", "C[]" から選ぶ
31
31
  # choice[A(), B(), C()] -> "A()", "B()", "C()" から選ぶ
32
32
  #
33
- # "choise"の後に数を指定することで、列挙した要素から重複なしで複数個を選ぶ
33
+ # "choice"の後に数を指定することで、列挙した要素から重複なしで複数個を選ぶ
34
34
  # choice2[A,B,C] -> "A", "B", "C" から重複なしで2個選ぶ
35
35
  #
36
36
  # 指定したい要素が「AからD」のように連続する項目の場合に「A-D」と省略して記述できる
@@ -192,6 +192,10 @@ module BCDice
192
192
  # @param randomizer [Randomizer]
193
193
  # @return [Result]
194
194
  def roll(randomizer)
195
+ if @items.size > 100
196
+ return Result.new("項目数は100以下としてください")
197
+ end
198
+
195
199
  items = @items.dup
196
200
  chosens = []
197
201
  @takes.times do
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/result"
4
+
5
+ module BCDice
6
+ module CommonCommand
7
+ module TallyDice
8
+ # 個数カウントダイスを表すノードをまとめるモジュール
9
+ module Node
10
+ # 個数カウントダイス:コマンドのノード
11
+ class Command
12
+ # 最大面数
13
+ MAX_SIDES = 20
14
+
15
+ # @param secret [Boolean] シークレットダイスか
16
+ # @param notation [Notation] ダイス表記
17
+ def initialize(secret:, notation:)
18
+ @secret = secret
19
+ @notation = notation
20
+ end
21
+
22
+ # @param game_system [Base] ゲームシステム
23
+ # @param randomizer [Randomizer] ランダマイザ
24
+ # @return [Result, nil]
25
+ def eval(game_system, randomizer)
26
+ dice = @notation.to_dice(game_system.round_type)
27
+ unless dice.valid?
28
+ return nil
29
+ end
30
+
31
+ if dice.sides > MAX_SIDES
32
+ return Result.new("(#{dice}) > 面数は1以上、#{MAX_SIDES}以下としてください")
33
+ end
34
+
35
+ values = dice.roll(randomizer)
36
+
37
+ values_str = (game_system.sort_barabara_dice? ? values.sort : values)
38
+ .join(",")
39
+
40
+ # TODO: Ruby 2.7以降のみサポートするようになった場合
41
+ # Enumerable#tally で書く
42
+ values_count = values
43
+ .group_by(&:itself)
44
+ .transform_values(&:length)
45
+
46
+ values_count_strs = (1..dice.sides).map do |v|
47
+ count = values_count.fetch(v, 0)
48
+
49
+ next nil if count == 0 && !dice.show_zeros?
50
+
51
+ "[#{v}]×#{values_count.fetch(v, 0)}"
52
+ end
53
+
54
+ sequence = [
55
+ "(#{dice})",
56
+ values_str,
57
+ values_count_strs.compact.join(", "),
58
+ ].compact
59
+
60
+ Result.new.tap do |r|
61
+ r.secret = @secret
62
+ r.text = sequence.join(" > ")
63
+ end
64
+ end
65
+ end
66
+
67
+ # 個数カウントダイス:ダイス表記のノード
68
+ class Notation
69
+ # @return [Integer] 振る回数
70
+ attr_reader :times
71
+ # @return [Integer] 面数
72
+ attr_reader :sides
73
+ # @return [Boolean] 個数0を表示するか
74
+ attr_reader :show_zeros
75
+
76
+ # @param times [#eval] 振る回数
77
+ # @param sides [#eval] 面数
78
+ # @param show_zeros [Boolean] 個数0を表示するか
79
+ def initialize(times:, sides:, show_zeros:)
80
+ @times = times
81
+ @sides = sides
82
+ @show_zeros = show_zeros
83
+ end
84
+
85
+ # @param round_type [Symbol] 除算の端数処理方法
86
+ # @return [Dice]
87
+ def to_dice(round_type)
88
+ times = @times.eval(round_type)
89
+ sides = @sides.eval(round_type)
90
+
91
+ Dice.new(times: times, sides: sides, show_zeros: @show_zeros)
92
+ end
93
+ end
94
+
95
+ # 個数カウントダイス:ダイスのノード
96
+ class Dice
97
+ # @return [Integer] 振る回数
98
+ attr_reader :times
99
+ # @return [Integer] 面数
100
+ attr_reader :sides
101
+ # @return [Boolean] 個数0を表示するか
102
+ attr_reader :show_zeros
103
+
104
+ alias show_zeros? show_zeros
105
+
106
+ # @param times [Integer] 振る回数
107
+ # @param sides [Integer] 面数
108
+ def initialize(times:, sides:, show_zeros:)
109
+ @times = times
110
+ @sides = sides
111
+ @show_zeros = show_zeros
112
+ end
113
+
114
+ # @return [Boolean] ダイスとして有効(振る回数、面数ともに正の数)か
115
+ def valid?
116
+ @times > 0 && @sides > 0
117
+ end
118
+
119
+ # ダイスを振る
120
+ # @param randomizer [BCDice::Randomizer] ランダマイザ
121
+ # @return [Array<Integer>] 出目の配列
122
+ def roll(randomizer)
123
+ randomizer.roll_barabara(@times, @sides)
124
+ end
125
+
126
+ # @return [String]
127
+ def to_s
128
+ show_zeros_symbol = @show_zeros ? "Z" : "Y"
129
+ "#{@times}T#{show_zeros_symbol}#{@sides}"
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,302 @@
1
+ #
2
+ # DO NOT MODIFY!!!!
3
+ # This file is automatically generated by Racc 1.5.1
4
+ # from Racc grammar file "".
5
+ #
6
+
7
+ require 'racc/parser.rb'
8
+
9
+
10
+ require "bcdice/common_command/lexer"
11
+ require "bcdice/common_command/tally_dice/node"
12
+ require "bcdice/arithmetic/node"
13
+
14
+ module BCDice
15
+ module CommonCommand
16
+ module TallyDice
17
+ class Parser < Racc::Parser
18
+
19
+
20
+ def self.parse(source)
21
+ new.parse(source)
22
+ end
23
+
24
+ def parse(source)
25
+ @lexer = Lexer.new(source)
26
+ do_parse()
27
+ rescue ParseError
28
+ nil
29
+ end
30
+
31
+ private
32
+
33
+ def next_token
34
+ @lexer.next_token
35
+ end
36
+ ##### State transition tables begin ###
37
+
38
+ racc_action_table = [
39
+ 8, 8, 18, 19, 20, 21, 8, 8, 8, 22,
40
+ 14, 15, 3, 7, 7, 14, 15, 14, 15, 7,
41
+ 7, 7, 8, 4, 8, 35, 33, 34, 36, 8,
42
+ 9, 14, 15, 14, 15, 7, 8, 7, 14, 15,
43
+ 23, 24, 7, 23, 24, 14, 15, 23, 24, 7,
44
+ 10 ]
45
+
46
+ racc_action_check = [
47
+ 2, 7, 10, 10, 11, 11, 14, 17, 15, 11,
48
+ 7, 7, 0, 2, 7, 14, 14, 15, 15, 14,
49
+ 17, 15, 20, 1, 21, 31, 31, 31, 31, 23,
50
+ 4, 20, 20, 21, 21, 20, 24, 21, 23, 23,
51
+ 12, 12, 23, 28, 28, 24, 24, 29, 29, 24,
52
+ 6 ]
53
+
54
+ racc_action_pointer = [
55
+ 2, 23, -2, nil, 30, nil, 47, -1, nil, nil,
56
+ -2, -7, 27, nil, 4, 6, nil, 5, nil, nil,
57
+ 20, 22, nil, 27, 34, nil, nil, nil, 30, 34,
58
+ nil, 19, nil, nil, nil, nil, nil ]
59
+
60
+ racc_action_default = [
61
+ -2, -23, -23, -3, -23, -1, -23, -23, -22, 37,
62
+ -23, -23, -9, -12, -23, -23, -20, -23, -5, -6,
63
+ -23, -23, -21, -23, -23, -18, -19, -4, -7, -8,
64
+ -10, -13, -11, -14, -15, -16, -17 ]
65
+
66
+ racc_goto_table = [
67
+ 6, 25, 26, 12, 1, 2, 5, 17, 11, 32,
68
+ 30, 31, nil, nil, nil, 27, 28, 29 ]
69
+
70
+ racc_goto_check = [
71
+ 4, 8, 8, 7, 1, 2, 3, 5, 6, 9,
72
+ 8, 8, nil, nil, nil, 4, 7, 7 ]
73
+
74
+ racc_goto_pointer = [
75
+ nil, 4, 5, 4, -2, -3, 1, -4, -13, -22 ]
76
+
77
+ racc_goto_default = [
78
+ nil, nil, nil, nil, 16, nil, nil, nil, 13, nil ]
79
+
80
+ racc_reduce_table = [
81
+ 0, 0, :racc_error,
82
+ 2, 18, :_reduce_1,
83
+ 0, 19, :_reduce_2,
84
+ 1, 19, :_reduce_3,
85
+ 4, 20, :_reduce_4,
86
+ 1, 22, :_reduce_5,
87
+ 1, 22, :_reduce_6,
88
+ 3, 23, :_reduce_7,
89
+ 3, 23, :_reduce_8,
90
+ 1, 23, :_reduce_none,
91
+ 3, 24, :_reduce_10,
92
+ 4, 24, :_reduce_11,
93
+ 1, 24, :_reduce_none,
94
+ 0, 26, :_reduce_13,
95
+ 1, 26, :_reduce_14,
96
+ 1, 26, :_reduce_15,
97
+ 1, 26, :_reduce_16,
98
+ 1, 26, :_reduce_17,
99
+ 2, 25, :_reduce_18,
100
+ 2, 25, :_reduce_19,
101
+ 1, 25, :_reduce_none,
102
+ 3, 21, :_reduce_21,
103
+ 1, 21, :_reduce_22 ]
104
+
105
+ racc_reduce_n = 23
106
+
107
+ racc_shift_n = 37
108
+
109
+ racc_token_table = {
110
+ false => 0,
111
+ :error => 1,
112
+ :NUMBER => 2,
113
+ :T => 3,
114
+ :Y => 4,
115
+ :Z => 5,
116
+ :R => 6,
117
+ :U => 7,
118
+ :C => 8,
119
+ :F => 9,
120
+ :S => 10,
121
+ :PLUS => 11,
122
+ :MINUS => 12,
123
+ :ASTERISK => 13,
124
+ :SLASH => 14,
125
+ :PARENL => 15,
126
+ :PARENR => 16 }
127
+
128
+ racc_nt_base = 17
129
+
130
+ racc_use_result_var = true
131
+
132
+ Racc_arg = [
133
+ racc_action_table,
134
+ racc_action_check,
135
+ racc_action_default,
136
+ racc_action_pointer,
137
+ racc_goto_table,
138
+ racc_goto_check,
139
+ racc_goto_default,
140
+ racc_goto_pointer,
141
+ racc_nt_base,
142
+ racc_reduce_table,
143
+ racc_token_table,
144
+ racc_shift_n,
145
+ racc_reduce_n,
146
+ racc_use_result_var ]
147
+
148
+ Racc_token_to_s_table = [
149
+ "$end",
150
+ "error",
151
+ "NUMBER",
152
+ "T",
153
+ "Y",
154
+ "Z",
155
+ "R",
156
+ "U",
157
+ "C",
158
+ "F",
159
+ "S",
160
+ "PLUS",
161
+ "MINUS",
162
+ "ASTERISK",
163
+ "SLASH",
164
+ "PARENL",
165
+ "PARENR",
166
+ "$start",
167
+ "expr",
168
+ "secret",
169
+ "notation",
170
+ "term",
171
+ "show_zeros",
172
+ "add",
173
+ "mul",
174
+ "unary",
175
+ "round_type" ]
176
+
177
+ Racc_debug_parser = false
178
+
179
+ ##### State transition tables end #####
180
+
181
+ # reduce 0 omitted
182
+
183
+ def _reduce_1(val, _values, result)
184
+ result = Node::Command.new(
185
+ secret: val[0],
186
+ notation: val[1]
187
+ )
188
+
189
+ result
190
+ end
191
+
192
+ def _reduce_2(val, _values, result)
193
+ result = false
194
+ result
195
+ end
196
+
197
+ def _reduce_3(val, _values, result)
198
+ result = true
199
+ result
200
+ end
201
+
202
+ def _reduce_4(val, _values, result)
203
+ result = Node::Notation.new(
204
+ times: val[0],
205
+ sides: val[3],
206
+ show_zeros: val[2]
207
+ )
208
+
209
+ result
210
+ end
211
+
212
+ def _reduce_5(val, _values, result)
213
+ result = false
214
+ result
215
+ end
216
+
217
+ def _reduce_6(val, _values, result)
218
+ result = true
219
+ result
220
+ end
221
+
222
+ def _reduce_7(val, _values, result)
223
+ result = Arithmetic::Node::BinaryOp.new(val[0], :+, val[2])
224
+ result
225
+ end
226
+
227
+ def _reduce_8(val, _values, result)
228
+ result = Arithmetic::Node::BinaryOp.new(val[0], :-, val[2])
229
+ result
230
+ end
231
+
232
+ # reduce 9 omitted
233
+
234
+ def _reduce_10(val, _values, result)
235
+ result = Arithmetic::Node::BinaryOp.new(val[0], :*, val[2])
236
+ result
237
+ end
238
+
239
+ def _reduce_11(val, _values, result)
240
+ divied_class = val[3]
241
+ result = divied_class.new(val[0], val[2])
242
+
243
+ result
244
+ end
245
+
246
+ # reduce 12 omitted
247
+
248
+ def _reduce_13(val, _values, result)
249
+ result = Arithmetic::Node::DivideWithGameSystemDefault
250
+ result
251
+ end
252
+
253
+ def _reduce_14(val, _values, result)
254
+ result = Arithmetic::Node::DivideWithCeil
255
+ result
256
+ end
257
+
258
+ def _reduce_15(val, _values, result)
259
+ result = Arithmetic::Node::DivideWithCeil
260
+ result
261
+ end
262
+
263
+ def _reduce_16(val, _values, result)
264
+ result = Arithmetic::Node::DivideWithRound
265
+ result
266
+ end
267
+
268
+ def _reduce_17(val, _values, result)
269
+ result = Arithmetic::Node::DivideWithFloor
270
+ result
271
+ end
272
+
273
+ def _reduce_18(val, _values, result)
274
+ result = val[1]
275
+ result
276
+ end
277
+
278
+ def _reduce_19(val, _values, result)
279
+ result = Arithmetic::Node::Negative.new(val[1])
280
+ result
281
+ end
282
+
283
+ # reduce 20 omitted
284
+
285
+ def _reduce_21(val, _values, result)
286
+ result = val[1]
287
+ result
288
+ end
289
+
290
+ def _reduce_22(val, _values, result)
291
+ result = Arithmetic::Node::Number.new(val[0])
292
+ result
293
+ end
294
+
295
+ def _reduce_none(val, _values, result)
296
+ val[0]
297
+ end
298
+
299
+ end # class Parser
300
+ end # module TallyDice
301
+ end # module CommonCommand
302
+ end # module BCDice
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bcdice/common_command/tally_dice/parser"
4
+
5
+ module BCDice
6
+ module CommonCommand
7
+ # 個数カウントダイスのモジュール
8
+ module TallyDice
9
+ PREFIX_PATTERN = /\d+T[YZ]\d+/.freeze
10
+
11
+ class << self
12
+ def eval(command, game_system, randomizer)
13
+ cmd = Parser.parse(command)
14
+ cmd&.eval(game_system, randomizer)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "bcdice/common_command/add_dice"
4
4
  require "bcdice/common_command/barabara_dice"
5
+ require "bcdice/common_command/tally_dice"
5
6
  require "bcdice/common_command/calc"
6
7
  require "bcdice/common_command/choice"
7
8
  require "bcdice/common_command/d66_dice"
@@ -15,6 +16,7 @@ module BCDice
15
16
  COMMANDS = [
16
17
  AddDice,
17
18
  BarabaraDice,
19
+ TallyDice,
18
20
  Calc,
19
21
  Choice,
20
22
  D66Dice,
@@ -39,7 +39,11 @@ module BCDice
39
39
  key = dice[0] * 10 + dice[1]
40
40
  chosen = @items[key]
41
41
  chosen = chosen.roll(randomizer) if chosen.respond_to?(:roll)
42
- return RollResult.new(@name, key, chosen)
42
+ RollResult.new(@name, key, chosen)
43
+ end
44
+
45
+ def choice(key)
46
+ RollResult.new(@name, key, @items[key])
43
47
  end
44
48
  end
45
49
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class Aoharubaan < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'Aoharubaan'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'あおはるばーんっ'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'あおはるはあんつ'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~HELP
17
+ カレカノ反応表( KR, KReaction )
18
+ HELP
19
+
20
+ JUDGE_ROLL_REG = /^(1d6?|d6)(\+\d+)?(>=|=>)(\d+)$/i.freeze
21
+ register_prefix('(1d6?|d6)(\+\d+)?(>=|=>)(\d+)')
22
+
23
+ def eval_game_system_specific_command(command)
24
+ command = ALIAS[command] || command
25
+
26
+ if (m = JUDGE_ROLL_REG.match(command))
27
+ roll_judge(m[2], m[4])
28
+ else
29
+ roll_tables(command, TABLES)
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def roll_judge(modifier_expression, border_expression)
36
+ modifier = modifier_expression ? Arithmetic.eval(modifier_expression, RoundType::FLOOR) : nil
37
+ border = border_expression.to_i
38
+
39
+ command_text = make_command_text(modifier, border)
40
+
41
+ dice = @randomizer.roll_once(6)
42
+ score = dice + modifier.to_i
43
+
44
+ is_success = score >= border # 「成功」か?
45
+ is_right = is_success && score == border # 「ピタリ賞」か?
46
+ is_excellent = is_success && score >= 7 # 「限界突破」か?
47
+
48
+ result_elements = []
49
+ result_elements << (is_success ? '成功' : '失敗')
50
+ result_elements << "ピタリ賞" if is_right
51
+ result_elements << "限界突破" if is_excellent
52
+
53
+ message_elements = []
54
+ message_elements << command_text
55
+ message_elements << "#{dice}+#{modifier}" if modifier
56
+ message_elements << score
57
+ message_elements << result_elements.join(" & ")
58
+
59
+ Result.new(message_elements.join(' > ')).tap do |r|
60
+ r.condition = is_success
61
+ r.critical = is_right || is_excellent
62
+ end
63
+ end
64
+
65
+ def make_command_text(modifier, border)
66
+ command = "1D6"
67
+ command = "#{command}+#{modifier}" if modifier
68
+ command = "#{command}>=#{border}"
69
+ "(#{command})"
70
+ end
71
+
72
+ ALIAS = {
73
+ "KR" => "KReaction",
74
+ }.transform_keys(&:upcase).transform_values(&:upcase).freeze
75
+
76
+ TABLES = {
77
+ "KReaction" => DiceTable::RangeTable.new(
78
+ "カレカノ反応表",
79
+ "1D6",
80
+ [
81
+ [1..2, "何となく素っ気ない気がする。"],
82
+ [3..4, "いつもと変わらない安心感。"],
83
+ [5..6, "何故だかすごくデレてきた! 嬉しくて〈テンション〉1回復。"],
84
+ ]
85
+ ),
86
+ }.transform_keys(&:upcase).freeze
87
+
88
+ register_prefix(ALIAS.keys, TABLES.keys)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class AssaultEngine < Base
6
+ # ゲームシステムの識別子
7
+ ID = 'AssaultEngine'
8
+
9
+ # ゲームシステム名
10
+ NAME = 'アサルトエンジン'
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = 'あさるとえんしん'
14
+
15
+ # ダイスボットの使い方
16
+ HELP_MESSAGE = <<~MESSAGETEXT
17
+ ・判定 AEt (t目標値)
18
+ 例: AE45 (目標値45)
19
+ ・リロール nAEt (nロール前の値、t目標値)
20
+ 例: 76AE45 (目標値45で、76を振り直す)
21
+
22
+ ・スワップ(t目標値) エネミーブックP11
23
+ 例: AES45 (目標値45、スワップ表示あり)
24
+ MESSAGETEXT
25
+
26
+ register_prefix('\d*AE')
27
+
28
+ def initialize(command)
29
+ super(command)
30
+ @round_type = RoundType::FLOOR # 端数切り捨て
31
+ end
32
+
33
+ def eval_game_system_specific_command(command)
34
+ cmd = Command::Parser.new(/AES?/, round_type: round_type).enable_prefix_number
35
+ .has_suffix_number.parse(command)
36
+ return nil unless cmd
37
+
38
+ target = cmd.suffix_number
39
+ target = 99 if target >= 100
40
+
41
+ if cmd.command.include?("AES") # SWAP初回
42
+ total = @randomizer.roll_once(100) % 100 # 0-99
43
+ swap = (total % 10) * 10 + (total / 10)
44
+ r1 = judge(target, total)
45
+ r2 = judge(target, swap)
46
+ text = "(AES#{format00(target)}) > #{r1.text} / スワップ#{r2.text}"
47
+ check_result(r1, r2, text)
48
+ elsif cmd.prefix_number.nil? # 初回ロール
49
+ total = @randomizer.roll_once(100) % 100 # 0-99
50
+ judge(target, total).tap do |r|
51
+ r.text = "(AE#{format00(target)}) > #{r.text}"
52
+ end
53
+ else # リロール
54
+ now = cmd.prefix_number
55
+ die = @randomizer.roll_once(10) % 10 # 0-9
56
+ new1 = judge(target, (now / 10 * 10) + die) # 1の位を振り直す
57
+ new2 = judge(target, now % 10 + die * 10) # 10の位を振り直す
58
+
59
+ text = "(#{format00(now)}AE#{format00(target)}) > #{die} > #{new1.text} / #{new2.text}"
60
+ check_result(new1, new2, text)
61
+ end
62
+ end
63
+
64
+ def format00(dice)
65
+ format("%02d", dice)
66
+ end
67
+
68
+ def check_result(result1, result2, text)
69
+ if result1.critical? || result2.critical?
70
+ Result.critical(text)
71
+ elsif result1.success? || result2.success?
72
+ Result.success(text)
73
+ elsif result1.fumble? && result2.fumble?
74
+ Result.fumble(text)
75
+ else
76
+ Result.failure(text)
77
+ end
78
+ end
79
+
80
+ def judge(target, total)
81
+ double = (total / 10) == (total % 10)
82
+ total_text = format00(total)
83
+ if total <= target
84
+ double ? Result.critical("(#{total_text})クリティカル") : Result.success("(#{total_text})成功")
85
+ else
86
+ double ? Result.fumble("(#{total_text})ファンブル") : Result.failure("(#{total_text})失敗")
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end