Skip to content

Commit baac0e7

Browse files
authored
[NanimonaiMura]なにもない村の追加 (#867)
* [NanimonaiMura]なにもない村の追加 * [NanimonaiMura] Fix RuboCop Style/WordArray
1 parent de939a9 commit baac0e7

3 files changed

Lines changed: 208 additions & 0 deletions

File tree

lib/bcdice/game_system.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@
183183
require "bcdice/game_system/MonotoneMuseum"
184184
require "bcdice/game_system/MonotoneMuseum_Korean"
185185
require "bcdice/game_system/MorkBorg"
186+
require "bcdice/game_system/NanimonaiMura"
186187
require "bcdice/game_system/Nechronica"
187188
require "bcdice/game_system/Nechronica_Korean"
188189
require "bcdice/game_system/NegikureNegimaki"
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# frozen_string_literal: true
2+
3+
module BCDice
4+
module GameSystem
5+
class NanimonaiMura < Base
6+
# ゲームシステムの識別子
7+
ID = "NanimonaiMura"
8+
9+
# ゲームシステム名
10+
NAME = "なにもない村"
11+
12+
# ゲームシステム名の読みがな
13+
SORT_KEY = "なにもないむら"
14+
15+
# ダイスボットの使い方
16+
HELP_MESSAGE = <<~INFO_MESSAGE_TEXT
17+
・行為判定 xNMy
18+
 x個のD10を振り、2つの出目から達成値を作成して判定します。
19+
 達成値は成功度が最も高くなる組み合わせを自動選択し、同値なら低い値を優先します。
20+
 x: ダイス数(1以上)
21+
 y: 判定値(0以上)
22+
 例)4NM55 6NM199 2NM35
23+
INFO_MESSAGE_TEXT
24+
25+
register_prefix('\d+NM\d+')
26+
27+
ResultData = Struct.new(:score, :success, :critical, :result_text, :success_level)
28+
29+
STAGE_NAMES = ['ノーマル', 'エピック', 'レジェンダリ', 'ミシック'].freeze
30+
BASE_SUCCESS_LEVELS = [1, 11, 21, 31].freeze
31+
32+
def eval_game_system_specific_command(command)
33+
roll_action(command)
34+
end
35+
36+
private
37+
38+
def roll_action(command)
39+
m = /\A(\d+)NM(\d+)\z/.match(command)
40+
return nil unless m
41+
42+
dice_count = m[1].to_i
43+
target = m[2].to_i
44+
return nil if dice_count < 1
45+
46+
dice_list = @randomizer.roll_barabara(dice_count, 10).map { |value| normalize_d10(value) }
47+
result = select_best_result(dice_list, target)
48+
49+
Result.new.tap do |r|
50+
r.text = "#{command} (#{dice_count}D10) > [#{dice_list.join(',')}] > #{result.score}#{result.result_text} > 成功度#{result.success_level}"
51+
r.condition = result.success
52+
r.critical = result.critical
53+
end
54+
end
55+
56+
def normalize_d10(value)
57+
value == 10 ? 0 : value
58+
end
59+
60+
def select_best_result(dice_list, target)
61+
candidates =
62+
if dice_list.size == 1
63+
[build_result(dice_list.first * 10, target)]
64+
else
65+
[].tap do |results|
66+
dice_list.each_index do |i|
67+
dice_list.each_index do |j|
68+
next if i == j
69+
70+
results << build_result(dice_list[i] * 10 + dice_list[j], target)
71+
end
72+
end
73+
end
74+
end
75+
76+
best_result = candidates.first
77+
78+
candidates.drop(1).each do |candidate|
79+
next if candidate.success_level < best_result.success_level
80+
next if candidate.success_level == best_result.success_level && candidate.score > best_result.score
81+
82+
best_result = candidate
83+
end
84+
85+
best_result
86+
end
87+
88+
def build_result(score, target)
89+
if score > target
90+
return ResultData.new(score, false, false, "失敗", 0)
91+
end
92+
93+
diff = target - score
94+
stage_index = [diff.div(100), STAGE_NAMES.size - 1].min
95+
critical_bonus = zoro_bonus(score)
96+
critical = !critical_bonus.nil?
97+
success_level = BASE_SUCCESS_LEVELS[stage_index] + (critical_bonus || 0)
98+
result_text = "#{STAGE_NAMES[stage_index]}#{critical ? '大成功' : '成功'}"
99+
100+
ResultData.new(score, true, critical, result_text, success_level)
101+
end
102+
103+
def zoro_bonus(score)
104+
tens = score.div(10)
105+
ones = score % 10
106+
return nil unless tens == ones
107+
108+
ones
109+
end
110+
end
111+
end
112+
end

test/data/NanimonaiMura.toml

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
[[ test ]]
2+
game_system = "NanimonaiMura"
3+
input = "4NM55"
4+
output = "4NM55 (4D10) > [3,0,6,9] > 3 > ノーマル成功 > 成功度1"
5+
success = true
6+
rands = [
7+
{ sides = 10, value = 3 },
8+
{ sides = 10, value = 10 },
9+
{ sides = 10, value = 6 },
10+
{ sides = 10, value = 9 },
11+
]
12+
13+
[[ test ]]
14+
game_system = "NanimonaiMura"
15+
input = "6NM199"
16+
output = "6NM199 (6D10) > [0,6,1,1,5,5] > 55 > エピック大成功 > 成功度16"
17+
success = true
18+
critical = true
19+
rands = [
20+
{ sides = 10, value = 10 },
21+
{ sides = 10, value = 6 },
22+
{ sides = 10, value = 1 },
23+
{ sides = 10, value = 1 },
24+
{ sides = 10, value = 5 },
25+
{ sides = 10, value = 5 },
26+
]
27+
28+
[[ test ]]
29+
game_system = "NanimonaiMura"
30+
input = "2NM33"
31+
output = "2NM33 (2D10) > [5,7] > 57 > 失敗 > 成功度0"
32+
failure = true
33+
rands = [
34+
{ sides = 10, value = 5 },
35+
{ sides = 10, value = 7 },
36+
]
37+
38+
[[ test ]]
39+
game_system = "NanimonaiMura"
40+
input = "1NM35"
41+
output = "1NM35 (1D10) > [3] > 30 > ノーマル成功 > 成功度1"
42+
success = true
43+
rands = [
44+
{ sides = 10, value = 3 },
45+
]
46+
47+
[[ test ]]
48+
game_system = "NanimonaiMura"
49+
input = "2NM50"
50+
output = "2NM50 (2D10) > [0,0] > 0 > ノーマル大成功 > 成功度1"
51+
success = true
52+
critical = true
53+
rands = [
54+
{ sides = 10, value = 10 },
55+
{ sides = 10, value = 10 },
56+
]
57+
58+
[[ test ]]
59+
game_system = "NanimonaiMura"
60+
input = "3NM156"
61+
output = "3NM156 (3D10) > [4,5,6] > 45 > エピック成功 > 成功度11"
62+
success = true
63+
rands = [
64+
{ sides = 10, value = 4 },
65+
{ sides = 10, value = 5 },
66+
{ sides = 10, value = 6 },
67+
]
68+
69+
[[ test ]]
70+
game_system = "NanimonaiMura"
71+
input = "2NM30"
72+
output = "2NM30 (2D10) > [4,4] > 44 > 失敗 > 成功度0"
73+
failure = true
74+
rands = [
75+
{ sides = 10, value = 4 },
76+
{ sides = 10, value = 4 },
77+
]
78+
79+
[[ test ]]
80+
game_system = "NanimonaiMura"
81+
input = "0NM55"
82+
output = ""
83+
rands = []
84+
85+
[[ test ]]
86+
game_system = "NanimonaiMura"
87+
input = "NM55"
88+
output = ""
89+
rands = []
90+
91+
[[ test ]]
92+
game_system = "NanimonaiMura"
93+
input = "4NM"
94+
output = ""
95+
rands = []

0 commit comments

Comments
 (0)