bcdice 3.14.0 → 3.16.1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +88 -0
  3. data/i18n/Cthulhu/zh_hant.yml +1 -1
  4. data/i18n/CyberpunkRed/ko_kr.yml +389 -0
  5. data/i18n/DoubleCross/ja_jp.yml +53 -0
  6. data/i18n/DoubleCross/ko_kr.yml +52 -0
  7. data/i18n/Emoklore/ko_kr.yml +7 -0
  8. data/i18n/FutariSousa/ja_jp.yml +138 -138
  9. data/i18n/KillDeathBusiness/ja_jp.yml +198 -0
  10. data/i18n/MagicaLogia/ko_kr.yml +2 -2
  11. data/i18n/MonotoneMuseum/ko_kr.yml +227 -0
  12. data/i18n/SkynautsBouken/ja_jp.yml +28 -28
  13. data/i18n/SkynautsBouken/ko_kr.yml +114 -0
  14. data/i18n/StratoShout/ko_kr.yml +102 -102
  15. data/i18n/zh_hant.yml +5 -0
  16. data/lib/bcdice/game_system/Aionia.rb +131 -0
  17. data/lib/bcdice/game_system/Arianrhod_Korean.rb +2 -0
  18. data/lib/bcdice/game_system/ArknightsFan.rb +245 -87
  19. data/lib/bcdice/game_system/BlackJacket_Korean.rb +244 -0
  20. data/lib/bcdice/game_system/CharonSanctions.rb +112 -0
  21. data/lib/bcdice/game_system/Cthulhu7th.rb +1 -1
  22. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional/full_auto.rb +293 -0
  23. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional/rollable.rb +43 -0
  24. data/lib/bcdice/game_system/Cthulhu7th_ChineseTraditional.rb +470 -306
  25. data/lib/bcdice/game_system/CyberpunkRed.rb +1 -2
  26. data/lib/bcdice/game_system/CyberpunkRed_Korean.rb +66 -0
  27. data/lib/bcdice/game_system/DoubleCross.rb +18 -1
  28. data/lib/bcdice/game_system/DoubleCross_Korean.rb +5 -1
  29. data/lib/bcdice/game_system/EdgeFlippers.rb +315 -0
  30. data/lib/bcdice/game_system/Emoklore_Korean.rb +42 -0
  31. data/lib/bcdice/game_system/FullFace.rb +25 -3
  32. data/lib/bcdice/game_system/FutariSousa.rb +17 -5
  33. data/lib/bcdice/game_system/Garactier.rb +479 -0
  34. data/lib/bcdice/game_system/GardenOrder.rb +390 -9
  35. data/lib/bcdice/game_system/GundogRevised.rb +8 -8
  36. data/lib/bcdice/game_system/JuinKansen_Korean.rb +251 -0
  37. data/lib/bcdice/game_system/KillDeathBusiness.rb +155 -3
  38. data/lib/bcdice/game_system/KimitoYell.rb +568 -0
  39. data/lib/bcdice/game_system/Magius.rb +125 -0
  40. data/lib/bcdice/game_system/Magius_3rdNewTokyoCity.rb +62 -0
  41. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +122 -2
  42. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +4 -4
  43. data/lib/bcdice/game_system/NSSQ.rb +17 -9
  44. data/lib/bcdice/game_system/NervWhitePaper.rb +129 -0
  45. data/lib/bcdice/game_system/Revulture_Korean.rb +125 -0
  46. data/lib/bcdice/game_system/RogueLikeHalf.rb +198 -0
  47. data/lib/bcdice/game_system/RuneQuestRoleplayingInGlorantha.rb +16 -13
  48. data/lib/bcdice/game_system/ShinobiGami.rb +73 -43
  49. data/lib/bcdice/game_system/SkynautsBouken.rb +4 -4
  50. data/lib/bcdice/game_system/SkynautsBouken_Korean.rb +57 -0
  51. data/lib/bcdice/game_system/StratoShout_Korean.rb +1 -1
  52. data/lib/bcdice/game_system/SwordWorld.rb +4 -0
  53. data/lib/bcdice/game_system/SwordWorld2_5.rb +3 -2
  54. data/lib/bcdice/game_system/TensaiGunshiNiNaro.rb +51 -17
  55. data/lib/bcdice/game_system/TheIndieHack.rb +82 -0
  56. data/lib/bcdice/game_system/TorgEternity.rb +35 -6
  57. data/lib/bcdice/game_system/Ventangle_Korean.rb +130 -0
  58. data/lib/bcdice/game_system/WoW.rb +161 -0
  59. data/lib/bcdice/game_system/YankeeMustDie.rb +192 -0
  60. data/lib/bcdice/game_system/YearZeroEngine.rb +225 -28
  61. data/lib/bcdice/game_system/YuMyoKishi.rb +141 -0
  62. data/lib/bcdice/game_system/meikyu_kingdom_basic/atoz_table.rb +1184 -0
  63. data/lib/bcdice/game_system/meikyu_kingdom_basic/randr236_table.rb +254 -0
  64. data/lib/bcdice/game_system/meikyu_kingdom_basic/table.rb +54 -0
  65. data/lib/bcdice/game_system/meikyu_kingdom_basic/tk_table.rb +755 -0
  66. data/lib/bcdice/game_system/sword_world/rating_lexer.rb +1 -0
  67. data/lib/bcdice/game_system/sword_world/rating_options.rb +4 -1
  68. data/lib/bcdice/game_system/sword_world/rating_parsed.rb +5 -0
  69. data/lib/bcdice/game_system/sword_world/rating_parser.rb +129 -115
  70. data/lib/bcdice/game_system.rb +20 -0
  71. data/lib/bcdice/version.rb +1 -1
  72. metadata +31 -6
@@ -0,0 +1,192 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BCDice
4
+ module GameSystem
5
+ class YankeeMustDie < Base
6
+ # ゲームシステムの識別子
7
+ ID = "YankeeMustDie"
8
+
9
+ # ゲームシステム名
10
+ NAME = "ヤンキーマストダイ"
11
+
12
+ # ゲームシステム名の読みがな
13
+ SORT_KEY = "やんきいますとたい"
14
+
15
+ HELP_MESSAGE = <<~TEXT
16
+ ■ 判定の方法
17
+ 基本形式:
18
+ (YD+a>=b) または (YD+a>b)
19
+ a:能力値、技能レベル、ドウグ等による修正値(複数指定可)
20
+ b:目標となる成功段階
21
+
22
+ ■ 成功の条件
23
+ >=b:目標となる成功段階b以上の場合に成功となります。この条件では、目標となる成功段階と同じ数値でも成功とみなされます。
24
+ >b:目標となる成功段階bより高い成功段階を出した場合に成功となります。この条件では、目標となる成功段階と同じ数値では失敗となります。
25
+
26
+ ■ 各種表
27
+  関係表 RT
28
+  場面表 ST
29
+  ハプニング表 HT
30
+  闇堕ち表 DT
31
+ TEXT
32
+
33
+ def initialize(command)
34
+ super(command)
35
+ @sort_barabara_dice = true
36
+ @sides_implicit_d = 10
37
+ end
38
+
39
+ def eval_game_system_specific_command(command)
40
+ return check_action(command) || roll_tables(command, TABLES)
41
+ end
42
+
43
+ def check_action(command)
44
+ parser = Command::Parser.new("YD", round_type: @round_type)
45
+ .restrict_cmp_op_to(:>=, :>, nil)
46
+ parsed = parser.parse(command)
47
+ unless parsed
48
+ return nil
49
+ end
50
+
51
+ dice_all = []
52
+ loop do
53
+ dice_list = @randomizer.roll_barabara(3, 10).sort
54
+ dice_all.push(dice_list)
55
+ break unless dice_list.uniq.one?
56
+ end
57
+
58
+ achievement_value = dice_all.flatten.sum(parsed.modify_number)
59
+ if achievement_value <= 9
60
+ success_level = 0
61
+ elsif achievement_value <= 19
62
+ success_level = 1
63
+ elsif achievement_value <= 29
64
+ success_level = 2
65
+ elsif achievement_value <= 39
66
+ success_level = 3
67
+ elsif achievement_value <= 49
68
+ success_level = 4
69
+ elsif achievement_value <= 59
70
+ success_level = 5
71
+ elsif achievement_value <= 69
72
+ success_level = 6
73
+ elsif achievement_value <= 79
74
+ success_level = 7
75
+ elsif achievement_value <= 89
76
+ success_level = 8
77
+ elsif achievement_value <= 99
78
+ success_level = 9
79
+ else
80
+ success_level = 10
81
+ end
82
+
83
+ if parsed.cmp_op == :>
84
+ is_success = success_level > parsed.target_number
85
+ is_failure = !is_success
86
+ success_message = is_success ? '成功' : '失敗'
87
+ elsif parsed.cmp_op == :>=
88
+ is_success = success_level >= parsed.target_number
89
+ is_failure = !is_success
90
+ success_message = is_success ? '成功' : '失敗'
91
+ else
92
+ is_success = false
93
+ is_failure = false
94
+ success_message = nil
95
+ end
96
+
97
+ dice_to_message_arr = []
98
+ dice_all.each do |arr|
99
+ dice_to_message_arr.append("#{arr.sum}[#{arr.join(',')}]")
100
+ end
101
+
102
+ sequence = [
103
+ parsed.to_s,
104
+ format("#{dice_to_message_arr.join(' + ')} %+d", parsed.modify_number),
105
+ achievement_value,
106
+ "成功段階#{success_level}"
107
+ ]
108
+
109
+ if success_message
110
+ sequence.append(success_message)
111
+ end
112
+
113
+ Result.new.tap do |r|
114
+ r.text = sequence.join(" > ")
115
+ r.success = is_success
116
+ r.failure = is_failure
117
+ end
118
+ end
119
+
120
+ TABLES = {
121
+ 'RT' => DiceTable::Table.new(
122
+ '関係表',
123
+ '1D10',
124
+ [
125
+ 'マブダチ:相手とは、マブダチ(親友) だ。いつからマブダチなのかはプレイヤー同士で相談して決めること。',
126
+ '先輩/後輩:相手とは、先輩と後輩の間柄だ。なんの先輩後輩かはプレイヤー同士で相談して決めること。',
127
+ '兄弟:相手とは、血縁であったり契りを交わした兄弟だ。兄弟になった経緯はプレイヤー同士で相談して決めること。',
128
+ 'ライバル:相手とは、良きライバル関係にある。どのようなライバル関係かはプレイヤー同士で相談して決めること。',
129
+ '仲間:相手とは、同じチームなどに所属している仲間だ。どんなチームかはプレイヤー同士で相談して決めること。',
130
+ 'ジモティー:相手とは、同じ地元の仲間、幼馴染だ。いつから幼馴染なのかはプレイヤー同士で相談して決めること。',
131
+ 'おな中:相手とは、出身中学(小学校・高校も可) が同じだ。どんな中学だったのかはプレイヤー同士で決めること。',
132
+ '相棒:相手は、唯一無二の相棒だ。いつから相棒なのかはプレイヤー同士で相談して決めること。',
133
+ 'ゾッコン:相手は、唯一無二の相棒だ。いつから相棒なのかはプレイヤー同士で相談して決めること。',
134
+ '犬猿:相手とは、犬猿の仲である。犬猿の仲であるが、なぜ共に行動するのかはプレイヤー同士で相談して決めること。'
135
+ ]
136
+ ),
137
+ 'ST' => DiceTable::Table.new(
138
+ '場面表',
139
+ '1D10',
140
+ [
141
+ 'サ店(喫茶店)',
142
+ 'クラブ',
143
+ '工業団地',
144
+ '神社/教会',
145
+ '学校',
146
+ '埠頭',
147
+ '繁華街',
148
+ 'ゲーセン',
149
+ '公園',
150
+ '河原'
151
+ # 特殊な場合のみ発生する
152
+ # '病院'
153
+ ]
154
+ ),
155
+ 'HT' => DiceTable::Table.new(
156
+ 'ハプニング表',
157
+ '1D10',
158
+ [
159
+ '単車ドロ:愛車を盗まれる。次の自身の手番を迎えるまで、愛車が1台使用不能になる。所有している愛車が複数ある場合はランダムに1台を選ぶ。',
160
+ '職質:サツにドウグを取り上げられる。次の自身の手番を迎えるまで、素手を除くドウグが1つ使用不能になる。所有しているドウグが複数ある場合はランダムに1つを選ぶ。',
161
+ '不調:どうにも愛車やドウグが体になじまない次の判定の成功段階がー1される。',
162
+ '乱闘:不良との喧嘩に巻き込まれた。PC は1d10 点のダメージを受ける。',
163
+ '大人:悪辣な大人に遭遇して怒りが募る。PC は不良度が1d10 点上昇する',
164
+ '仲違い:つまらないことで喧嘩になって友情に亀裂が入る。場面に登場している【関係】を結んでいるキャラクターの中からランダムに対象を1 人選ぶ。シナリオが終了するまで対象との【関係】が失われる。',
165
+ '悪名:ボスの悪名が広がることによって自然とボスの取り巻きが増える。次の戦闘フェイズにモブが敵として1 人参加する。モブの種類はGM が決定する。',
166
+ '凶暴化:ボスの思考が先鋭化して凶悪になる。シナリオが終了するまでボスが与えるダメージを+2 する。この効果は累積するが、上昇した能力値は戦力には影響しない。',
167
+ '警戒:ボスは自身の周りでうごめく不穏な気配に警戒を強める。ボスの【HP 最大値】と【HP 現在値】を+10 する。この効果は累積する。',
168
+ '不運:ツキがなくなってきた気がする...。ラッキーナンバーの数値が2下がる(最低1)。すでにラッキーナンバーを使用済みであれば効果を受けない。'
169
+ ]
170
+ ),
171
+ 'DT' => DiceTable::Table.new(
172
+ '闇堕ち表',
173
+ '1D10',
174
+ [
175
+ '出奔:すべての人間関係を捨ててどこか遠くへ旅に出る。',
176
+ '半グレ:半グレ集団とつるむようになり、悪事に手を染めるようになる。',
177
+ '指名手配:重大な犯罪を起こして指名手配されて逃亡者となる。',
178
+ '事故:大事故に遭い意識不明の重体となり長期入院する。',
179
+ 'ヤク中:薬物中毒者となり、薬を得るためなら何でもするようになる。',
180
+ '借金:イカれた人間を信奉するようになり多額の借金を背負わされる。',
181
+ '傀儡:悪意を持って人間を利用しようとする勢力に祭り上げられ傀儡と化す。',
182
+ '身代わり:犯罪を犯した人間の身代わりにされて追われる身となる。',
183
+ '逮捕:度を越えた暴力沙汰を度々起こして警察に逮捕される。',
184
+ '失踪:ヤバい事件に首を突っ込んで謎の失踪を遂げる。'
185
+ ]
186
+ )
187
+ }.freeze
188
+
189
+ register_prefix('YD', TABLES.keys)
190
+ end
191
+ end
192
+ end
@@ -14,24 +14,35 @@ module BCDice
14
14
 
15
15
  # ダイスボットの使い方
16
16
  HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17
- ・判定コマンド(nYZEx+x+x)
18
- (難易度)YZE(能力ダイス数)+(技能ダイス数)+(アイテムダイス数) # (6のみを数える)
17
+ ・ダイスプール判定コマンド(nYZEx+x+x+m)
18
+ (難易度)YZE(能力ダイス数)+(技能ダイス数)+(アイテムダイス数)+(修正値) # (6のみを数える)
19
+ (難易度)YZE(能力ダイス数)+(技能ダイス数)+(アイテムダイス数)-(修正値) # (6のみを数える)
19
20
 
20
- ・判定コマンド(nMYZx+x+x)
21
+ ・ダイスプール判定コマンド(nMYZx+x+x)
21
22
  (難易度)MYZ(能力ダイス数)+(技能ダイス数)+(アイテムダイス数) # (1と6を数え、プッシュ可能数を表示)
22
23
  (難易度)MYZ(能力ダイス数)-(技能ダイス数)+(アイテムダイス数) # (1と6を数え、プッシュ可能数を表示、技能のマイナス指定)
23
24
 
24
25
  ※ 難易度と技能、アイテムダイス数は省略可能
26
+
27
+ ・ステップダイス判定コマンド(nYZSx+x+m+f)
28
+ (難易度)YZS(能力ダイス面数)+(技能ダイス面数)+(修正値) # (1,6を数え、プッシュ可能数を表示)
29
+ (難易度)YZS(能力ダイス面数)+(技能ダイス面数)-(修正値) # (1,6を数え、プッシュ可能数を表示)
30
+ (難易度)YZS(能力ダイス面数)+(技能ダイス面数)+(修正値)A # (1,6を数え、プッシュ可能数を表示、有利)
31
+ (難易度)YZS(能力ダイス面数)+(技能ダイス面数)-(修正値)A # (1,6を数え、プッシュ可能数を表示、有利)
32
+ (難易度)YZS(能力ダイス面数)+(技能ダイス面数)+(修正値)D # (1,6を数え、プッシュ可能数を表示、不利)
33
+ (難易度)YZS(能力ダイス面数)+(技能ダイス面数)-(修正値)D # (1,6を数え、プッシュ可能数を表示、不利)
25
34
  INFO_MESSAGE_TEXT
26
35
 
27
- DIFFICULTY_INDEX = 1 # 難易度のインデックス
28
- COMMAND_TYPE_INDEX = 2 # コマンドタイプのインデックス
29
- ABILITY_INDEX = 3 # 能力値ダイスのインデックス
30
- SKILL_SIGNED_INDEX = 5 # 技能値ダイス符号のインデックス
31
- SKILL_INDEX = 6 # 技能値ダイスのインデックス
32
- GEAR_INDEX = 8 # アイテムダイスのインデックス
36
+ DIFFICULTY_INDEX = 1 # 難易度のインデックス
37
+ COMMAND_TYPE_INDEX = 2 # コマンドタイプのインデックス
38
+ ABILITY_INDEX = 3 # 能力値ダイスのインデックス
39
+ SKILL_SIGNED_INDEX = 5 # 技能値ダイス符号のインデックス
40
+ SKILL_INDEX = 6 # 技能値ダイスのインデックス
41
+ GEAR_INDEX = 8 # アイテムダイスのインデックス
42
+ MODIFIER_SIGNED_INDEX = 10 # 修正値の符号のインデックス
43
+ MODIFIER_INDEX = 11 # 修正値のインデックス
33
44
 
34
- register_prefix('(\d+)?(YZE|MYZ)')
45
+ register_prefix('(\d+)?(YZE|MYZ|YZS)')
35
46
 
36
47
  def dice_info_init()
37
48
  @total_success_dice = 0
@@ -44,16 +55,97 @@ module BCDice
44
55
  end
45
56
 
46
57
  def eval_game_system_specific_command(command)
47
- m = /\A(\d+)?(YZE|MYZ)(\d+)((\+|-)(\d+))?(\+(\d+))?/.match(command)
58
+ resolute_action(command) ||
59
+ resolute_push_action(command) ||
60
+ resolute_step_action(command)
61
+ end
62
+
63
+ def resolute_action(command)
64
+ m = /\A(\d+)?(YZE)(\d+)((\+)(\d+))?(\+(\d+))?((\+|-)(\d+))?/.match(command)
48
65
  unless m
49
- return ''
66
+ return nil
50
67
  end
51
68
 
52
69
  dice_info_init
53
70
 
54
71
  @difficulty = m[DIFFICULTY_INDEX].to_i
72
+ attribute = m[ABILITY_INDEX].to_i
73
+ skill = m[SKILL_INDEX].to_i
74
+ gear = m[GEAR_INDEX].to_i
75
+ modifier = m[MODIFIER_INDEX].to_i
76
+ if m[MODIFIER_SIGNED_INDEX] == '-'
77
+ if skill >= modifier
78
+ skill -= modifier
79
+ else
80
+ modifier -= skill
81
+ skill = 0
82
+ if gear >= modifier
83
+ gear -= modifier
84
+ else
85
+ modifier -= gear
86
+ gear = 0
87
+ if attribute >= modifier
88
+ attribute -= modifier
89
+ else
90
+ attribute = 0
91
+ end
92
+ end
93
+ end
94
+ else
95
+ skill += modifier
96
+ end
97
+
98
+ @total_success_dice = 0
99
+
100
+ dice_pool = attribute
101
+ ability_dice_text, success_dice, botch_dice = make_dice_roll(dice_pool)
102
+
103
+ @total_success_dice += success_dice
104
+ @total_botch_dice += botch_dice
105
+ @base_botch_dice += botch_dice # 能力ダメージ
106
+ @push_dice += (dice_pool - (success_dice + botch_dice))
107
+
108
+ dice_count_text = "(#{dice_pool}D6)"
109
+ dice_text = ability_dice_text
110
+
111
+ if m[SKILL_INDEX]
112
+ dice_pool = skill
113
+ skill_dice_text, success_dice, botch_dice = make_dice_roll(dice_pool)
114
+
115
+ @total_success_dice += success_dice
116
+ @total_botch_dice += botch_dice
117
+ @skill_botch_dice += botch_dice # 技能ダイスの1はpushで振り直し可能(例えマイナス技能でも)
118
+ @push_dice += (dice_pool - success_dice) # 技能ダイスのみ1を含むので、ここでは1を計算に入れない
119
+
120
+ dice_count_text += "+(#{dice_pool}D6)"
121
+ dice_text += "+#{skill_dice_text}"
122
+ end
123
+
124
+ if m[GEAR_INDEX]
125
+ dice_pool = gear
126
+ gear_dice_text, success_dice, botch_dice = make_dice_roll(dice_pool)
127
+
128
+ @total_success_dice += success_dice
129
+ @total_botch_dice += botch_dice
130
+ @gear_botch_dice += botch_dice # ギアダメージ
131
+ @push_dice += (dice_pool - (success_dice + botch_dice))
132
+
133
+ dice_count_text += "+(#{dice_pool}D6)"
134
+ dice_text += "+#{gear_dice_text}"
135
+ end
136
+
137
+ return make_result_with_yze(dice_count_text, dice_text)
138
+ end
139
+
140
+ def resolute_push_action(command)
141
+ m = /\A(\d+)?(MYZ)(\d+)((\+|-)(\d+))?(\+(\d+))?/.match(command)
142
+ unless m
143
+ return nil
144
+ end
55
145
 
56
- command_type = m[COMMAND_TYPE_INDEX]
146
+ dice_info_init
147
+
148
+ @difficulty = m[DIFFICULTY_INDEX].to_i
57
149
 
58
150
  @total_success_dice = 0
59
151
 
@@ -73,10 +165,7 @@ module BCDice
73
165
  skill_dice_text, success_dice, botch_dice = make_dice_roll(dice_pool)
74
166
 
75
167
  skill_unsigned = m[SKILL_SIGNED_INDEX]
76
- if command_type == 'YZE' && skill_unsigned == '-'
77
- # YZEはシンプルに動作するコマンドなのでマイナス技能の処理は対応しない。
78
- return "YZEコマンドでは技能ダイスをマイナス指定できません。"
79
- elsif command_type == 'MYZ' && skill_unsigned == '-'
168
+ if skill_unsigned == '-'
80
169
  @total_success_dice -= success_dice # マイナス技能の成功は通常の成功と相殺される
81
170
  else
82
171
  @total_success_dice += success_dice
@@ -103,17 +192,7 @@ module BCDice
103
192
  dice_text += "+#{gear_dice_text}"
104
193
  end
105
194
 
106
- return make_result_text(command_type, dice_count_text, dice_text)
107
- end
108
-
109
- def make_result_text(command_type, dice_count_text, dice_text)
110
- if command_type == 'YZE'
111
- return make_result_with_yze(dice_count_text, dice_text)
112
- elsif command_type == 'MYZ'
113
- return make_result_with_myz(dice_count_text, dice_text)
114
- end
115
-
116
- return 'Error' # 到達しないはず
195
+ return make_result_with_myz(dice_count_text, dice_text)
117
196
  end
118
197
 
119
198
  def make_result_with_yze(dice_count_text, dice_text)
@@ -150,6 +229,124 @@ module BCDice
150
229
 
151
230
  return "[#{dice_list.join(',')}]", success_dice, botch_dice
152
231
  end
232
+
233
+ def make_dice_a_roll(count, type)
234
+ dice_list = @randomizer.roll_barabara(count, type)
235
+ botch_dice = dice_list.count(1)
236
+ success_dice = dice_list.count { |val| val >= 6 }
237
+ success_level = success_dice + dice_list.count { |val| val >= 10 }
238
+
239
+ @total_success_dice += success_level
240
+ @total_botch_dice += botch_dice
241
+ @push_dice += (count - (success_dice + botch_dice))
242
+
243
+ return "[#{dice_list.join(',')}]", botch_dice
244
+ end
245
+
246
+ def get_rolling_dice(dice_type1, dice_type2, dice_upgrade)
247
+ dice_type1 = 4 if dice_type1 < 4
248
+ dice_type2 = 4 if dice_type2 < 4
249
+
250
+ while dice_upgrade > 0
251
+ if dice_type1 >= dice_type2
252
+ dice_type2 += 2 if dice_type2 < 12
253
+ else
254
+ dice_type1 += 2 if dice_type1 < 12
255
+ end
256
+ dice_upgrade -= 1
257
+ end
258
+
259
+ while dice_upgrade < 0
260
+ if dice_type1 <= dice_type2
261
+ dice_type2 -= 2 if dice_type2 > 4
262
+ else
263
+ dice_type1 -= 2 if dice_type1 > 4
264
+ end
265
+ dice_upgrade += 1
266
+ end
267
+
268
+ if dice_type1 == 4 && dice_type2 == 4
269
+ dice_type1 = 6
270
+ end
271
+
272
+ return dice_type1, dice_type2
273
+ end
274
+
275
+ def resolute_step_action(command)
276
+ m = /\A(\d+)?(YZS)(\d+)((\+)(\d+))?((\+|-)(\d+))?(A|D)?/.match(command)
277
+ unless m
278
+ return nil
279
+ end
280
+
281
+ dice_info_init
282
+
283
+ @difficulty = m[DIFFICULTY_INDEX].to_i
284
+ attribute = m[ABILITY_INDEX].to_i
285
+ skill = m[SKILL_INDEX].to_i
286
+ modifier = m[7].to_i
287
+ advantage = m[10]
288
+
289
+ dice_count_text = ""
290
+ dice_text = ""
291
+
292
+ dice_type1, dice_type2 = get_rolling_dice(attribute, skill, modifier)
293
+
294
+ if dice_type1 <= dice_type2
295
+ if advantage
296
+ if advantage == "A" && (dice_type1 > 4)
297
+ ability_dice_text, botch_dice = make_dice_a_roll(2, dice_type1)
298
+
299
+ @base_botch_dice += botch_dice # 能力ダメージ
300
+ dice_count_text = "(2D#{dice_type1})"
301
+ dice_text = ability_dice_text
302
+ end
303
+ else
304
+ if dice_type1 > 4
305
+ ability_dice_text, botch_dice = make_dice_a_roll(1, dice_type1)
306
+
307
+ @base_botch_dice += botch_dice # 能力ダメージ
308
+ dice_count_text = "(1D#{dice_type1})"
309
+ dice_text = ability_dice_text
310
+ end
311
+ end
312
+ if dice_type2 > 4
313
+ skill_dice_text, botch_dice = make_dice_a_roll(1, dice_type2)
314
+
315
+ @skill_botch_dice += botch_dice
316
+ dice_count_text += "+" unless dice_count_text == ""
317
+ dice_text += "+" unless dice_text == ""
318
+ dice_count_text += "(1D#{dice_type2})"
319
+ dice_text += skill_dice_text
320
+ end
321
+ else
322
+ if dice_type1 > 4
323
+ ability_dice_text, botch_dice = make_dice_a_roll(1, dice_type1)
324
+
325
+ @base_botch_dice += botch_dice # 能力ダメージ
326
+ dice_count_text = "(1D#{dice_type1})"
327
+ dice_text = ability_dice_text
328
+ end
329
+ if advantage
330
+ if advantage == "A" && (dice_type2 > 4)
331
+ skill_dice_text, botch_dice = make_dice_a_roll(2, dice_type2)
332
+
333
+ @skill_botch_dice += botch_dice
334
+ dice_count_text += "+(2D#{dice_type2})"
335
+ dice_text += "+#{skill_dice_text}"
336
+ end
337
+ else
338
+ if dice_type2 > 4
339
+ skill_dice_text, botch_dice = make_dice_a_roll(1, dice_type2)
340
+
341
+ @skill_botch_dice += botch_dice
342
+ dice_count_text += "+(1D#{dice_type2})"
343
+ dice_text += "+#{skill_dice_text}"
344
+ end
345
+ end
346
+ end
347
+
348
+ return make_result_with_myz(dice_count_text, dice_text)
349
+ end
153
350
  end
154
351
  end
155
352
  end
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bcdice/base'
4
+
5
+ module BCDice
6
+ module GameSystem
7
+ class YuMyoKishi < Base
8
+ # ゲームシステムの識別子
9
+ ID = 'YuMyoKishi'
10
+
11
+ # ゲームシステム名
12
+ NAME = '幽冥鬼使'
13
+
14
+ # ゲームシステム名の読みがな
15
+ #
16
+ # 「ゲームシステム名の読みがなの設定方法」(docs/dicebot_sort_key.md)を参考にして
17
+ # 設定してください
18
+ SORT_KEY = 'ゆうみようきし'
19
+
20
+ # ダイスボットの使い方
21
+ HELP_MESSAGE = <<~MESSAGETEXT
22
+ ■判定 YM+a>=b a:技能値(省略可) b:目標値(省略可)
23
+  例:YM+4>=8: 技能値による修正が+4で、目標値8の克服判定を行う
24
+    YM>=8 : 技能値による修正なしで、目標値8の克服判定を行う
25
+    YM+6 : 技能値による修正が+6で、達成値を確認する
26
+
27
+ ■代償表 COT
28
+ ■転禍表 TRT
29
+ MESSAGETEXT
30
+
31
+ TABLES = {
32
+ "COT" => DiceTable::Table.new(
33
+ "代償表",
34
+ "2D6",
35
+ [
36
+ "不慮の出逢い",
37
+ "深淵を覗くとき",
38
+ "時間の消費",
39
+ "奇妙な情報",
40
+ "優柔不断",
41
+ "注意散漫",
42
+ "心身耗弱",
43
+ "不穏な情報",
44
+ "遺留品",
45
+ "迫りくる危機",
46
+ "正体の露見",
47
+ ]
48
+ ),
49
+ "TRT" => DiceTable::Table.new(
50
+ "転禍表",
51
+ "2D6",
52
+ [
53
+ "○○と瓜二つ",
54
+ "絶対絶命",
55
+ "悪癖災う",
56
+ "冷酷な指令",
57
+ "おびえる視線",
58
+ "絡みつく妖気",
59
+ "容赦ない評定",
60
+ "無力な市民",
61
+ "未練阻む",
62
+ "縁の枷",
63
+ "邪悪な刻印",
64
+ ]
65
+ ),
66
+ }.freeze
67
+
68
+ # ダイスボットで使用するコマンドを配列で列挙する
69
+ register_prefix("YM", TABLES.keys)
70
+
71
+ def eval_game_system_specific_command(command)
72
+ debug("eval_game_system_specific_command Begin")
73
+
74
+ return roll_command(command) || roll_tables(command, TABLES)
75
+ end
76
+
77
+ def roll_command(command)
78
+ parser = Command::Parser.new('YM', round_type: round_type)
79
+ .restrict_cmp_op_to(:>=, nil)
80
+ cmd = parser.parse(command)
81
+
82
+ unless cmd
83
+ return nil
84
+ end
85
+
86
+ dice_list = @randomizer.roll_barabara(4, 6)
87
+ value, status = sip_pat_a(dice_list)
88
+ achievement = status == :wumian ? 0 : value + cmd.modify_number
89
+ roll_text = [
90
+ cmd.to_s,
91
+ dice_list.join(','),
92
+ value,
93
+ value == achievement ? nil : achievement,
94
+ ].compact.join(" > ")
95
+
96
+ if cmd.target_number.nil?
97
+ if status == :wumian
98
+ Result.failure(roll_text)
99
+ elsif status == :yise
100
+ Result.critical(roll_text)
101
+ else
102
+ Result.new(roll_text)
103
+ end
104
+ elsif status == :wumian
105
+ Result.failure([roll_text, "可"].join(" > "))
106
+ elsif status == :yise
107
+ Result.critical([roll_text, "優"].join(" > "))
108
+ elsif achievement >= cmd.target_number
109
+ Result.success([roll_text, "良"].join(" > "))
110
+ else
111
+ Result.failure([roll_text, "可"].join(" > "))
112
+ end
113
+ end
114
+
115
+ def sip_pat_a(dice_list) # 十八仔
116
+ result = dice_list.each_with_object(Hash.new(0)) do |cur, acc|
117
+ acc[cur] += 1
118
+ end
119
+ case result.count
120
+ when 1
121
+ # 全てゾロ目
122
+ [20, :yise] # 一色
123
+ when 2
124
+ if result.values == [2, 2]
125
+ # 同値のダイスが2つずつ
126
+ [result.keys.max * 2, :normal]
127
+ else
128
+ # 3つの同値と1つの目のダイス
129
+ [result.keys.sum, :normal]
130
+ end
131
+ when 3
132
+ # 2つの同値と1つずつの目のダイス
133
+ [result.select { |_k, v| v == 1 }.keys.sum, :normal]
134
+ else
135
+ # 全部バラバラ
136
+ [0, :wumian] # 無面
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end