mgmg 1.4.2 → 1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +25 -13
- data/lib/mgmg/equip.rb +18 -23
- data/lib/mgmg/ir.rb +3 -10
- data/lib/mgmg/optimize.rb +21 -9
- data/lib/mgmg/option.rb +85 -0
- data/lib/mgmg/reinforce.rb +3 -3
- data/lib/mgmg/search.rb +182 -222
- data/lib/mgmg/system_equip.rb +6 -0
- data/lib/mgmg/utils.rb +9 -2
- data/lib/mgmg/version.rb +1 -1
- data/lib/mgmg.rb +161 -72
- data/mgmg.gemspec +4 -4
- data/reference.md +127 -48
- metadata +11 -10
data/lib/mgmg.rb
CHANGED
@@ -7,79 +7,106 @@ require_relative './mgmg/ir'
|
|
7
7
|
require_relative './mgmg/system_equip'
|
8
8
|
require_relative './mgmg/cuisine'
|
9
9
|
require_relative './mgmg/reinforce'
|
10
|
+
require_relative './mgmg/option'
|
10
11
|
require_relative './mgmg/search'
|
11
12
|
require_relative './mgmg/optimize'
|
12
13
|
|
13
14
|
class String
|
14
|
-
def
|
15
|
-
|
15
|
+
def min_weight(opt: Mgmg::Option.new)
|
16
|
+
build(build(opt: opt).min_levels_max, opt: opt).weight
|
16
17
|
end
|
17
|
-
def
|
18
|
-
|
18
|
+
def max_weight(include_outsourcing=false, opt: Mgmg::Option.new)
|
19
|
+
if include_outsourcing
|
20
|
+
build(-1, opt: opt).weight
|
21
|
+
else
|
22
|
+
build(min_smith(opt: opt), opt: opt).weight
|
23
|
+
end
|
24
|
+
end
|
25
|
+
def min_level(w=0, include_outsourcing=false, opt: Mgmg::Option.new)
|
26
|
+
built = build(-1, opt: opt)
|
27
|
+
w = build(built.min_levels_max, -1, opt: opt).weight - w if w <= 0
|
28
|
+
return -1 if include_outsourcing && built.weight <= w
|
29
|
+
ms = min_smith(opt: opt)
|
30
|
+
return ms if build(ms, opt: opt).weight <= w
|
31
|
+
ary = [ms]
|
32
|
+
4.downto(1) do |wi| # 単品の最大重量は[斧|重鎧](金10石10)の5
|
33
|
+
built.min_levels(wi).values.each do |v|
|
34
|
+
(ary.include?(v) or ary << v) if ms < v
|
35
|
+
end
|
36
|
+
end
|
37
|
+
ary.sort.each do |l|
|
38
|
+
return l if build(l, opt: opt).weight <= w
|
39
|
+
end
|
40
|
+
raise ArgumentError, "w=`#{w}' is given, but the minimum weight for the recipe is `#{min_weight(opt: opt)}'."
|
41
|
+
end
|
42
|
+
def min_levels(w=1, opt: Mgmg::Option.new)
|
43
|
+
build(opt: opt).min_levels(w)
|
19
44
|
end
|
20
|
-
def
|
21
|
-
|
45
|
+
def min_levels_max(w=1, opt: Mgmg::Option.new)
|
46
|
+
min_levels(w, opt: opt).values.append(-1).max
|
22
47
|
end
|
23
|
-
def
|
24
|
-
Mgmg::Equip.
|
48
|
+
def min_smith(opt: Mgmg::Option.new)
|
49
|
+
Mgmg::Equip.min_smith(self, opt: opt)
|
25
50
|
end
|
26
|
-
def
|
27
|
-
Mgmg::Equip.
|
51
|
+
def min_comp(opt: Mgmg::Option.new)
|
52
|
+
Mgmg::Equip.min_comp(self, opt: opt)
|
28
53
|
end
|
29
|
-
def
|
30
|
-
Mgmg::
|
54
|
+
def build(smith=-1, comp=smith, opt: Mgmg::Option.new)
|
55
|
+
Mgmg::Equip.build(self, smith, comp, left_associative: opt.left_associative).reinforce(*opt.reinforcement)
|
31
56
|
end
|
32
|
-
def
|
33
|
-
|
57
|
+
def ir(opt: Mgmg::Option.new)
|
58
|
+
Mgmg::IR.build(self, left_associative: opt.left_associative, reinforcement: opt.reinforcement)
|
59
|
+
end
|
60
|
+
def poly(para=:cost, opt: Mgmg::Option.new)
|
34
61
|
case para
|
35
62
|
when :atkstr
|
36
|
-
self.poly(:attack,
|
63
|
+
self.poly(:attack, opt: opt) + self.poly(:str, opt: opt)
|
37
64
|
when :atk_sd
|
38
|
-
self.poly(:attack,
|
65
|
+
self.poly(:attack, opt: opt) + self.poly(:str, opt: opt).quo(2) + self.poly(:dex, opt: opt).quo(2)
|
39
66
|
when :dex_as
|
40
|
-
self.poly(:dex,
|
67
|
+
self.poly(:dex, opt: opt) + self.poly(:attack, opt: opt).quo(2) + self.poly(:str, opt: opt).quo(2)
|
41
68
|
when :mag_das
|
42
|
-
self.poly(:magic,
|
69
|
+
self.poly(:magic, opt: opt) + self.poly(:dex_as, opt: opt).quo(2)
|
43
70
|
when :magmag
|
44
|
-
self.poly(:magdef,
|
71
|
+
self.poly(:magdef, opt: opt) + self.poly(:magic, opt: opt).quo(2)
|
45
72
|
when :pmdef
|
46
|
-
pd = self.poly(:phydef,
|
47
|
-
md = self.poly(:magmag,
|
73
|
+
pd = self.poly(:phydef, opt: opt)
|
74
|
+
md = self.poly(:magmag, opt: opt)
|
48
75
|
pd <= md ? pd : md
|
49
76
|
when :cost
|
50
77
|
if Mgmg::SystemEquip.keys.include?(self)
|
51
78
|
return Mgmg::TPolynomial.new(Mgmg::Mat.new(1, 1, 0.quo(1)), 28, 0, 12, 12)
|
52
79
|
end
|
53
|
-
built = self.build(-1)
|
80
|
+
built = self.build(-1, opt: opt)
|
54
81
|
const = (built.star**2) * ( /\+/.match(self) ? 5 : ( built.kind < 8 ? 2 : 1 ) )
|
55
|
-
ret = poly(:attack,
|
56
|
-
ret += poly(:hp,
|
57
|
-
ret += poly(:str,
|
82
|
+
ret = poly(:attack, opt: opt) + poly(:phydef, opt: opt) + poly(:magdef, opt: opt)
|
83
|
+
ret += poly(:hp, opt: opt).quo(4) + poly(:mp, opt: opt).quo(4)
|
84
|
+
ret += poly(:str, opt: opt) + poly(:dex, opt: opt) + poly(:speed, opt: opt) + poly(:magic, opt: opt)
|
58
85
|
ret.mat.body[0][0] += const
|
59
86
|
ret
|
60
87
|
else
|
61
|
-
Mgmg::TPolynomial.build(self, para, left_associative:
|
88
|
+
Mgmg::TPolynomial.build(self, para, left_associative: opt.left_associative)
|
62
89
|
end
|
63
90
|
end
|
64
|
-
def eff(para, smith, comp=smith,
|
65
|
-
a = build(smith, comp,
|
66
|
-
b = build(smith+1, comp,
|
67
|
-
c = build(smith, comp+2,
|
91
|
+
def eff(para, smith, comp=smith, opt: Mgmg::Option.new)
|
92
|
+
a = build(smith, comp, opt: opt).para_call(para)
|
93
|
+
b = build(smith+1, comp, opt: opt).para_call(para)
|
94
|
+
c = build(smith, comp+2, opt: opt).para_call(para)
|
68
95
|
sden = smith==0 ? 1 : 2*smith-1
|
69
96
|
cden = comp==0 ? 4 : 8*comp
|
70
97
|
[(b-a).quo(sden), (c-a).quo(cden)]
|
71
98
|
end
|
72
|
-
def peff(para, smith, comp=smith,
|
73
|
-
poly(para,
|
99
|
+
def peff(para, smith, comp=smith, opt: Mgmg::Option.new)
|
100
|
+
poly(para, opt: opt).eff(smith, comp)
|
74
101
|
end
|
75
|
-
def show(smith=-1, comp=smith,
|
76
|
-
rein = case reinforcement
|
102
|
+
def show(smith=-1, comp=smith, para: :power, opt: Mgmg::Option.new)
|
103
|
+
rein = case opt.reinforcement
|
77
104
|
when Array
|
78
|
-
reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
|
105
|
+
opt.reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
|
79
106
|
else
|
80
|
-
[Mgmg::Reinforcement.compile(reinforcement)]
|
107
|
+
[Mgmg::Reinforcement.compile(opt.reinforcement)]
|
81
108
|
end
|
82
|
-
built =
|
109
|
+
built = build(smith, comp, opt: opt)
|
83
110
|
pstr = '%.3f' % built.para_call(para)
|
84
111
|
pstr.sub!(/\.?0+\Z/, '')
|
85
112
|
puts "Building"
|
@@ -88,37 +115,39 @@ class String
|
|
88
115
|
puts "with levels (#{smith}, #{comp})#{rein} yields (#{pstr}, #{built.total_cost})"
|
89
116
|
puts " #{built}"
|
90
117
|
end
|
91
|
-
def phydef_optimize(smith=nil, comp=smith,
|
92
|
-
Mgmg::Optimize.phydef_optimize(self, smith, comp,
|
118
|
+
def phydef_optimize(smith=nil, comp=smith, opt: Mgmg::Option.new)
|
119
|
+
Mgmg::Optimize.phydef_optimize(self, smith, comp, opt: opt)
|
93
120
|
end
|
94
|
-
def buster_optimize(smith=nil, comp=smith,
|
95
|
-
Mgmg::Optimize.buster_optimize(self, smith, comp,
|
121
|
+
def buster_optimize(smith=nil, comp=smith, opt: Mgmg::Option.new)
|
122
|
+
Mgmg::Optimize.buster_optimize(self, smith, comp, opt: opt)
|
96
123
|
end
|
97
124
|
end
|
98
125
|
module Enumerable
|
99
|
-
def build(smith=-1, armor=smith, comp=armor.tap{armor=smith},
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
126
|
+
def build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, opt: Mgmg::Option.new)
|
127
|
+
opt = opt.dup
|
128
|
+
rein = opt.reinforcement
|
129
|
+
opt.reinforcement = []
|
130
|
+
self.sum(Mgmg::Equip::Zero) do |str|
|
131
|
+
if Mgmg::EquipPosition[str.build(opt: opt).kind] == 0
|
132
|
+
str.build(smith, comp, opt: opt)
|
104
133
|
else
|
105
|
-
str.build(armor, comp,
|
134
|
+
str.build(armor, comp, opt: opt)
|
106
135
|
end
|
107
|
-
end
|
136
|
+
end.reinforce(*rein)
|
108
137
|
end
|
109
|
-
def ir(
|
110
|
-
self.sum do |str|
|
111
|
-
str.ir(
|
112
|
-
end.add_reinforcement(reinforcement)
|
138
|
+
def ir(opt: Mgmg::Option.new)
|
139
|
+
self.sum(Mgmg::IR::Zero) do |str|
|
140
|
+
str.ir(opt: opt)
|
141
|
+
end.add_reinforcement(opt.reinforcement)
|
113
142
|
end
|
114
|
-
def show(smith=-1, armor=smith, comp=armor.tap{armor=smith},
|
115
|
-
rein = case reinforcement
|
143
|
+
def show(smith=-1, armor=smith, comp=armor.tap{armor=smith}, para: :power, opt: Mgmg::Option.new)
|
144
|
+
rein = case opt.reinforcement
|
116
145
|
when Array
|
117
|
-
reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
|
146
|
+
opt.reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
|
118
147
|
else
|
119
|
-
[Mgmg::Reinforcement.compile(reinforcement)]
|
148
|
+
[Mgmg::Reinforcement.compile(opt.reinforcement)]
|
120
149
|
end
|
121
|
-
built = self.build(smith, armor, comp,
|
150
|
+
built = self.build(smith, armor, comp, opt: opt)
|
122
151
|
pstr = '%.3f' % built.para_call(para)
|
123
152
|
pstr.sub!(/\.?0+\Z/, '')
|
124
153
|
puts "Building"
|
@@ -127,14 +156,75 @@ module Enumerable
|
|
127
156
|
puts "with levels (#{smith}, #{armor}, #{comp})#{rein} yields (#{pstr}, #{built.total_cost})"
|
128
157
|
puts " #{built}"
|
129
158
|
end
|
130
|
-
def
|
131
|
-
build(
|
159
|
+
def min_weight(opt: Mgmg::Option.new)
|
160
|
+
build(*build(opt: opt).min_levels_max, -1, opt: opt).weight
|
161
|
+
end
|
162
|
+
def max_weight(include_outsourcing=false, opt: Mgmg::Option.new)
|
163
|
+
if include_outsourcing
|
164
|
+
build(-1, opt: opt).weight
|
165
|
+
else
|
166
|
+
build(*min_smith(opt: opt), -1, opt: opt).weight
|
167
|
+
end
|
168
|
+
end
|
169
|
+
def min_weights(opt: Mgmg::Option.new)
|
170
|
+
weapons, armors = [], []
|
171
|
+
each do |str|
|
172
|
+
if Mgmg::EquipPosition[str.build(opt: opt).kind] == 0
|
173
|
+
weapons << str
|
174
|
+
else
|
175
|
+
armors << str
|
176
|
+
end
|
177
|
+
end
|
178
|
+
[weapons.min_weight(opt: opt), armors.min_weight(opt: opt)]
|
179
|
+
end
|
180
|
+
def max_weights(include_outsourcing=false, opt: Mgmg::Option.new)
|
181
|
+
weapons, armors = [], []
|
182
|
+
each do |str|
|
183
|
+
if Mgmg::EquipPosition[str.build(opt: opt).kind] == 0
|
184
|
+
weapons << str
|
185
|
+
else
|
186
|
+
armors << str
|
187
|
+
end
|
188
|
+
end
|
189
|
+
[weapons.max_weight(include_outsourcing, opt: opt), armors.max_weight(include_outsourcing, opt: opt)]
|
190
|
+
end
|
191
|
+
def min_level(ws=0, wa=ws, include_outsourcing=false, opt: Mgmg::Option.new)
|
192
|
+
weapons, armors = [], []
|
193
|
+
each do |str|
|
194
|
+
if Mgmg::EquipPosition[str.build(opt: opt).kind] == 0
|
195
|
+
weapons << str
|
196
|
+
else
|
197
|
+
armors << str
|
198
|
+
end
|
199
|
+
end
|
200
|
+
ms, ma = min_smith(opt: opt)
|
201
|
+
rs = min_level_sub(ws, ms, 0, weapons, include_outsourcing, opt: opt)
|
202
|
+
ra = min_level_sub(wa, ma, 1, armors, include_outsourcing, opt: opt)
|
203
|
+
[rs, ra]
|
204
|
+
end
|
205
|
+
private def min_level_sub(w, ms, i, recipe, include_outsourcing, opt: Mgmg::Option.new)
|
206
|
+
built = recipe.build(opt: opt)
|
207
|
+
w = recipe.build(built.min_levels_max[i], opt: opt).weight - w if w <= 0
|
208
|
+
return -1 if include_outsourcing && built.weight <= w
|
209
|
+
return ms if build(ms, opt: opt).weight <= w
|
210
|
+
ary = [ms]
|
211
|
+
4.downto(1) do |wi|
|
212
|
+
built.min_levels(wi).values.each do |v|
|
213
|
+
(ary.include?(v) or ary << v) if ms << v
|
214
|
+
end
|
215
|
+
end
|
216
|
+
ary.sort.each do |l|
|
217
|
+
return l if recipe.build(l, opt: opt).weight <= w
|
218
|
+
end
|
219
|
+
raise ArgumentError, "w#{%w|s a|[i]}=`#{w}' is given, but the minimum weight for the #{%w|weapon(s) armor(s)|[i]} is `#{recipe.min_weight(opt: opt)}'."
|
220
|
+
end
|
221
|
+
def min_levels(w=1, opt: Mgmg::Option.new)
|
222
|
+
build(opt: opt).min_levels(w)
|
132
223
|
end
|
133
|
-
def
|
134
|
-
ret = [
|
135
|
-
|
136
|
-
|
137
|
-
if Mgmg::EquipPosition[m[1].build(0).kind] == 0
|
224
|
+
def min_levels_max(w=1, opt: Mgmg::Option.new)
|
225
|
+
ret = [-1, -1]
|
226
|
+
min_levels(w, opt: opt).each do |str, level|
|
227
|
+
if Mgmg::EquipPosition[str.build(opt: opt).kind] == 0
|
138
228
|
ret[0] = [ret[0], level].max
|
139
229
|
else
|
140
230
|
ret[1] = [ret[1], level].max
|
@@ -142,12 +232,11 @@ module Enumerable
|
|
142
232
|
end
|
143
233
|
ret
|
144
234
|
end
|
145
|
-
def min_smith(
|
146
|
-
ret = [
|
235
|
+
def min_smith(opt: Mgmg::Option.new)
|
236
|
+
ret = [-1, -1]
|
147
237
|
self.each do |str|
|
148
|
-
s = Mgmg::Equip.min_smith(str,
|
149
|
-
|
150
|
-
if Mgmg::EquipPosition[m[1].build(0).kind] == 0
|
238
|
+
s = Mgmg::Equip.min_smith(str, opt: opt)
|
239
|
+
if Mgmg::EquipPosition[str.build(opt: opt).kind] == 0
|
151
240
|
ret[0] = [ret[0], s].max
|
152
241
|
else
|
153
242
|
ret[1] = [ret[1], s].max
|
@@ -155,9 +244,9 @@ module Enumerable
|
|
155
244
|
end
|
156
245
|
ret
|
157
246
|
end
|
158
|
-
def min_comp(
|
247
|
+
def min_comp(opt: Mgmg::Option.new)
|
159
248
|
self.map do |str|
|
160
|
-
Mgmg::Equip.min_comp(str,
|
161
|
-
end.max
|
249
|
+
Mgmg::Equip.min_comp(str, opt: opt)
|
250
|
+
end.append(-1).max
|
162
251
|
end
|
163
252
|
end
|
data/mgmg.gemspec
CHANGED
@@ -35,9 +35,9 @@ Gem::Specification.new do |spec|
|
|
35
35
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
36
36
|
spec.require_paths = ["lib"]
|
37
37
|
|
38
|
-
spec.add_development_dependency "bundler", ">= 2.
|
39
|
-
spec.add_development_dependency "rake", ">= 13.0.
|
40
|
-
spec.add_development_dependency "irb", ">= 1.
|
38
|
+
spec.add_development_dependency "bundler", ">= 2.3.16"
|
39
|
+
spec.add_development_dependency "rake", ">= 13.0.6"
|
40
|
+
spec.add_development_dependency "irb", ">= 1.4.1"
|
41
41
|
|
42
|
-
spec.required_ruby_version = '>=
|
42
|
+
spec.required_ruby_version = '>= 3.1.0'
|
43
43
|
end
|
data/reference.md
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# リファレンス
|
2
2
|
本ライブラリで定義される主要なメソッドを以下に解説します.
|
3
3
|
|
4
|
-
## `String#build(smith=-1, comp=smith,
|
4
|
+
## `String#build(smith=-1, comp=smith, opt: Mgmg.option())`
|
5
5
|
レシピ文字列である`self`を解釈し,鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として鍛冶・防具製作及び武器・防具合成を行った結果を[後述](#mgmgequip)の`Mgmg::Equip`クラスのインスタンスとして生成し,返します.例えば,
|
6
6
|
```ruby
|
7
7
|
'[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build(112, 176)
|
8
8
|
```
|
9
|
-
のようにします.基本的に`[]`による合成順序の指定が必要ですが,不確定の場合,`left_associative`が真なら左結合,偽なら右結合として解釈します.
|
9
|
+
のようにします.基本的に`[]`による合成順序の指定が必要ですが,不確定の場合,`opt.left_associative`が真なら左結合,偽なら右結合として解釈します.
|
10
10
|
```ruby
|
11
11
|
'法衣(綿10皮10)+歴戦の服'
|
12
12
|
```
|
@@ -14,33 +14,69 @@
|
|
14
14
|
|
15
15
|
`self`が解釈不能な場合,例外が発生します.また,製作Lvや完成品の☆制限のチェックを行っていないほか,本ライブラリでは`武器+防具`や`防具+武器`の合成も可能になっています.街の鍛冶・防具製作・道具製作屋に任せた場合をシミュレートする場合は製作Lvを負の値(`-1`など,負であれば何でもよい)にします(製作Lv0相当の性能を計算し,消費エレメント量は委託仕様となります).
|
16
16
|
|
17
|
-
|
18
|
-
複数のレシピ文字列からなる`self`の各要素を製作し,そのすべてを装備したときの`Mgmg::Equip`を返します.製作では`鍛冶Lv=smith`, `防具製作Lv=armor`, `道具製作Lv=comp`とします.1つしか指定しなければすべてそのLv,2つなら1つ目を`smith=armor`,2つ目を`comp`に,3つならそれぞれの値とします.`left_associative`はそのまま`String#build`に渡されます.製作Lvが負の場合,製作Lv0として計算した上で,消費エレメント量は街の製作屋に頼んだ場合の値を計算します.武器複数など,同時装備が不可能な場合でも,特にチェックはされません.
|
17
|
+
`opt`は,`left_associative`のみ使用します.
|
19
18
|
|
20
|
-
## `
|
21
|
-
|
19
|
+
## `Enumerable#build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, opt: Mgmg.option())`
|
20
|
+
複数のレシピ文字列からなる`self`の各要素を製作し,そのすべてを装備したときの`Mgmg::Equip`を返します.製作では`鍛冶Lv=smith`, `防具製作Lv=armor`, `道具製作Lv=comp`とします.1つしか指定しなければすべてそのLv,2つなら1つ目を`smith=armor`,2つ目を`comp`に,3つならそれぞれの値とします.製作Lvが負の場合,製作Lv0として計算した上で,消費エレメント量は街の製作屋に頼んだ場合の値を計算します.武器複数など,同時装備が不可能な場合でも,特にチェックはされません.
|
22
21
|
|
23
|
-
|
22
|
+
`opt`は,`left_associative`のみ使用します.
|
23
|
+
|
24
|
+
## `String#min_weight(opt: Mgmg.option())`
|
25
|
+
製作可能な最小重量を返します.基本的には合成回数+1ですが,既製品を含む場合はその限りではありません.
|
26
|
+
|
27
|
+
製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
28
|
+
|
29
|
+
## `String#max_weight(include_outsourcing=false, opt: Mgmg.option())`
|
30
|
+
製作可能な最大重量を返します.`include_outsourcing`が真の場合,委託製作時の重量を返します.
|
31
|
+
委託製作では,製作Lv0相当となるため,素材の☆による最低製作Lvで作るよりも重くなる場合があります.
|
32
|
+
|
33
|
+
製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
34
|
+
|
35
|
+
## `String#min_level(w=0, include_outsourcing=false, opt: Mgmg.option())`
|
36
|
+
`self`を重量`w`以下で作るための最低製作Lvを返します.
|
37
|
+
`w`が`0`以下の場合,`self.min_weight-w`を指定した場合と同じになります.
|
38
|
+
|
39
|
+
`include_outsourcing`が真の場合,委託製作で目標重量が達成可能な場合,`-1`を返します.
|
40
|
+
偽の場合,返り値の最小値(`w`が`self.max_weight`以上の場合)は素材の☆による最低製作Lvになります.
|
41
|
+
|
42
|
+
`w`が最小重量より小さい場合,`ArgumentError`となります.製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
43
|
+
|
44
|
+
## `String#min_levels(weight=1, opt: Mgmg.option())`
|
24
45
|
合成レシピの各鍛冶・防具製作品に対して,レシピ文字列をキー,重量1で作製するために必要な製作Lvを値とした`Hash`を返します.重量はすべての装備について同じ値しか指定できません.
|
25
|
-
最大値は,`self.build.min_level`によって得られます.
|
26
46
|
|
27
|
-
|
47
|
+
製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
48
|
+
|
49
|
+
## `Enumerable#max_weight(include_outsourcing=false, opt: Mgmg.option())`,`Enumerable#min_weight(opt: Mgmg.option())`
|
50
|
+
製作可能な最大・最小重量を返します.`opt`を含め,`String#max_weight`,`String#min_weight`と同様です.
|
51
|
+
|
52
|
+
## `Enumerable#max_weights(include_outsourcing=false, opt: Mgmg.option())`,`Enumerable#min_weights(opt: Mgmg.option())`
|
53
|
+
`self`を武器の集合と防具の集合に分け,`[武器の最大・最小重量, 防具の最大・最小重量]`を返します.その他は`String#max_weight`,`String#min_weight`と同様です.
|
54
|
+
|
55
|
+
## `Enumerable#min_levels(weight=1, opt: Mgmg.option())`
|
28
56
|
すべての要素`str`に対する`str.min_levels`をマージした`Hash`を返します.
|
29
57
|
|
30
|
-
|
31
|
-
|
58
|
+
製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
59
|
+
|
60
|
+
## `Enumerable#min_levels_max(weight=1, opt: Mgmg.option())`
|
61
|
+
`self.min_levels`から武器,防具それぞれに対する最大値を求め,`[必要最小鍛冶Lv, 必要最小防具製作Lv]`を返します.武器,防具の一方のみが含まれる場合,もう一方は`-1`になります.
|
32
62
|
|
33
|
-
|
34
|
-
|
63
|
+
製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
64
|
+
|
65
|
+
## `String#min_comp(opt: Mgmg.option())`,`Enumerable#min_comp(opt: Mgmg.option())`
|
66
|
+
レシピ通りに合成するのに必要な道具製作Lvを返します.ただし,全体が「[]」で囲われているか,非合成レシピの場合,代わりに`-1`を返します.
|
35
67
|
|
36
68
|
`Enumerable`の場合,すべての要素に対する最大値を返します.
|
37
69
|
|
38
|
-
|
39
|
-
|
70
|
+
`opt`は,`left_associative`のみ使用します.
|
71
|
+
|
72
|
+
## `String#min_smith(opt: Mgmg.option())`,`Enumerable#min_smith(opt: Mgmg.option())`
|
73
|
+
レシピ通りに製作するのに必要な鍛冶・防具製作Lvを返します.製作物の重量については考慮せず,鍛冶・防具製作に必要な☆条件を満たすために必要な製作Lvを返します.既製品のみから構成される場合は`-1`になります.
|
74
|
+
|
75
|
+
`Enumerable`の場合,すべての要素に対し,武器,防具それぞれの最大値を求め,`[必要最小鍛冶Lv, 必要最小防具製作Lv]`を返します.武器,防具の一方のみが含まれる場合,もう一方は`-1`になります.
|
40
76
|
|
41
|
-
|
77
|
+
製作を行うため,`opt`が指定可能ですが,特に結果には影響しません.
|
42
78
|
|
43
|
-
## `String#poly(para=:cost,
|
79
|
+
## `String#poly(para=:cost, opt: Mgmg.option())`
|
44
80
|
レシピ文字列である`self`を解釈し,`para`で指定した9パラ値について,丸めを無視した鍛冶・防具製作Lvと道具製作Lvの2変数からなる多項式関数を示す`Mgmg::TPolynomial`クラスのインスタンスを生成し,返します.`para`は次のシンボルのいずれかを指定します.
|
45
81
|
```ruby
|
46
82
|
:attack, :phydef, :magdef, :hp, :mp, :str, :dex, :speed, :magic
|
@@ -55,78 +91,98 @@
|
|
55
91
|
|
56
92
|
また,`:cost`を渡すことで,消費エレメント量に関する近似多項式を得られます.`self`に`"+"`が含まれていれば合成品とみなし,最後の合成に必要な地エレメント量を,それ以外では,武器なら消費火エレメント量を,防具なら消費水エレメント量を返します.ただし,`self`が既成品そのものの場合,零多項式を返します.
|
57
93
|
|
58
|
-
|
94
|
+
`opt`は,`left_associative`のみ使用します.
|
95
|
+
|
96
|
+
## `String#ir(opt: Mgmg.option())`
|
59
97
|
レシピ文字列である`self`を解釈し,9パラ値について,丸めを考慮した鍛冶・防具製作Lvと道具製作Lvの2変数からなる関数オブジェクトを保持する`Mgmg::IR`クラスのインスタンスを生成し,返します.詳しくは,[後述](#mgmgir)の`Mgmg::IR`クラスの説明を参照ください.
|
60
98
|
|
61
|
-
`reinforcement
|
99
|
+
`opt`は,`left_associative`と`reinforcement`を使用します.
|
62
100
|
|
63
|
-
## `Enumerable#ir(
|
101
|
+
## `Enumerable#ir(opt: Mgmg.option())`
|
64
102
|
複数のレシピ文字列からなる`self`の各要素を製作し,そのすべてを装備したときの`Mgmg::IR`を返します.この場合,鍛冶Lv,防具製作Lv,道具製作Lvの3変数からなる関数オブジェクトを保持するものとして扱われます.各装備の種別に応じ,鍛冶Lvまたは防具製作Lvを適用し,9パラ値を計算します.
|
65
103
|
|
66
|
-
|
104
|
+
`opt`は,`left_associative`と`reinforcement`を使用します.
|
105
|
+
|
106
|
+
## `String#smith_seach(para, target, comp, opt: Mgmg.option())`
|
67
107
|
`para`の値が`target`以上となるのに必要な最小の鍛冶・防具製作Lvを二分探索で探索して返します.
|
68
|
-
道具製作Lvは`comp`で固定,鍛冶・防具製作Lvを`smith_min`と`smith_max`で挟み込んで探索します.
|
108
|
+
道具製作Lvは`comp`で固定,鍛冶・防具製作Lvを`opt.smith_min`と`opt.smith_max`で挟み込んで探索します.
|
69
109
|
|
70
|
-
`smith_min
|
71
|
-
`
|
110
|
+
`opt.smith_min`のデフォルト値は重量`opt.target_weight`で製作するのに必要な鍛冶・防具製作Lv (`self.min_level(opt.target_weight)`)です.
|
111
|
+
`opt.target_weight`のデフォルト値は`0`で,`0`以下の場合の挙動は[前述](#stringmin_levelw0-include_outsourcingfalse-opt-mgmgoption)の`String#min_level`を参照してください.
|
112
|
+
`opt.smith_min<opt.smith_max`でないとき,`opt.smith_max`で`para`が`target`以上でないときは`ArgumentError`となります.
|
72
113
|
|
73
114
|
`para`は,`Mgmg::Equip`のメソッド名をシンボルで指定(`:power, :fpower`も可)します.
|
74
115
|
反転などの影響で,探索範囲において`para`の値が(広義)単調増加になっていない場合,正しい結果を返しません.
|
75
|
-
`cut_exp`以下の経験値で`target`以上を達成できない場合,`Mgmg::SearchCutException`を発生します.
|
116
|
+
`opt.cut_exp`以下の経験値で`target`以上を達成できない場合,`Mgmg::SearchCutException`を発生します.
|
76
117
|
|
77
|
-
`irep
|
78
|
-
`reinforcement`が渡された場合,`para`を強化された値として計算します.`irep`が指定されている場合は無視されます.
|
118
|
+
`opt`は,上記の他に`left_associative`,`reinforcement`,`irep`を使用します.
|
79
119
|
|
80
|
-
## `String#comp_search(para, target, smith,
|
120
|
+
## `String#comp_search(para, target, smith, opt: Mgmg.option())`
|
81
121
|
`String#smith_seach`とは逆に,鍛冶・防具製作Lvを固定して最小の道具製作Lvを探索します.
|
82
|
-
|
122
|
+
探索の起点である`opt.comp_min`のデフォルト値は,製作に必要な最小の道具製作Lv (`self.min_comp`)です.
|
83
123
|
その他は`String#smith_seach`と同様です.
|
84
124
|
|
85
|
-
|
86
|
-
|
125
|
+
`opt`は,`comp_min`,`comp_max`,`left_associative`,`reinforcement`,`irep`を使用します.
|
126
|
+
|
127
|
+
## `String#search(para, target, opt: Mgmg.option())`
|
128
|
+
`c_min=comp_search(para, target, opt.smith_max, opt: opt)` から `c_max=comp_search(para, target, opt.smith_min, opt: opt)` まで,`opt.step`ずつ動かして,
|
87
129
|
`smith_search`を行い,その過程で得られた最小経験値の鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.
|
88
|
-
レシピ中の,対象パラメータの種別値がすべて奇数,または全て偶数であるなら,`step`を`2`にしても探索すべき範囲を網羅できます.
|
130
|
+
レシピ中の,対象パラメータの種別値がすべて奇数,または全て偶数であるなら,`opt.step`を`2`にしても探索すべき範囲を網羅できます.
|
89
131
|
その他は`String#smith_seach`と同様です.
|
90
132
|
|
91
|
-
|
133
|
+
`opt`は,`String#smith_search`または`String#comp_search`で使われるすべてのパラメータを使用します.
|
134
|
+
|
135
|
+
## `Enumerable#search(para, target, opt: Mgmg.option())`
|
92
136
|
複数装備の組について,`para`の値が`target`以上となる最小経験値の`[鍛冶Lv,防具製作Lv,道具製作Lv]`を返します.
|
93
137
|
武器のみなら防具製作Lvは`0`,防具のみなら鍛冶Lvは`0`,合成なしなら道具製作Lvは`0`となります.
|
94
|
-
その他は`String#smith_seach`と同様です.
|
95
138
|
|
96
|
-
|
139
|
+
`opt.smith_min`および`opt.armor_min`のデフォルト値は,武器・防具の各総重量を`opt.target_weight`で製作するのに必要な鍛冶・防具製作Lv (`self.min_level(*opt.target_weight)`)です.`opt.target_weight`には2要素からなる配列を指定しますが,整数が与えられた場合,それを2つ並べた配列と同等のものとして扱います.合計重量を指定することにはならないので注意してください.`opt.target_weight`のデフォルト値は`0`です.
|
140
|
+
|
141
|
+
その他は,`String#smith_seach`と同様です.
|
142
|
+
|
143
|
+
## `Mgmg.#find_lowerbound(a, b, para, start, term, opt_a: Mgmg.option(), opt_b: Mgmg.option())`
|
97
144
|
レシピ`a`とレシピ`b`について,`para`の値を目標値以上にする最小経験値の組において,目標値`start`における優劣が逆転する目標値の下限を探索し,返します.
|
98
145
|
返り値は`[逆転しない最大目標値, 逆転時の最小para値]`です.前者は逆転目標値の下限,後者は,目標値が前者よりも少しだけ大きいときの`para`値です.
|
99
146
|
ここで,最小経験値が小さい方,または最小経験値が同じなら,そのときの`para`値が大きい方をよりよいものと解釈します.
|
100
147
|
`term`は`start`より大きい値とします.目標値`term`における優劣が,目標値`start`における優劣と同じ場合,`Mgmg::SearchCutException`を発生します.
|
101
148
|
`a`と`b`は`String`でもその`Enumerable`でも構いません.
|
102
149
|
|
103
|
-
`
|
104
|
-
これらが`nil`で,`min_smith`が真ならば,重量を無視した製作可能最小Lvが指定されます.`min_smith`が偽(デフォルト)ならば,最小重量で製作可能な製作Lvが指定されます.重量を無視した製作可能Lvでの重量が3で,重量が2以下となる製作Lvで探索したい場合などは,`smith_min_a`,`smith_min_b`,`armor_min_a`,`armor_min_b`を具体的に指定してください.
|
150
|
+
`opt_a`,`opt_b`には,それぞれ`a`と`b`に関するオプションパラメータを指定します.`smith_min`,`armor_min`,`min_smith`,`left_associative`,`reinforcement`,`irep`を使用します.
|
105
151
|
|
106
|
-
## `Mgmg.#find_upperbound(a, b, para, start, term,
|
152
|
+
## `Mgmg.#find_upperbound(a, b, para, start, term, opt_a: Mgmg.option(), opt_b: Mgmg.option())`
|
107
153
|
`Mgmg.#find_lowerbound`とは逆に,目標値を下げながら,優劣が逆転する最大の目標値を探索し,返します.返り値は`[逆転する最大目標値, 逆転前の最小para値]`です.目標値が,前者よりも少しでも大きいと逆転が起こらず(逆転する目標値の上限),少しだけ大きい時の`para`値が後者になります.
|
108
154
|
|
109
|
-
|
155
|
+
`opt_a`,`opt_b`は,`Mgmg.#find_lowerbound`と同様です.
|
156
|
+
|
157
|
+
## `String#eff(para, smith, comp=smith, opt: Mgmg.option())`
|
110
158
|
[`smith`を1上げたときの`para`値/(`smith`を1上げるのに必要な経験値), `comp`を1上げたときの`para`値/(`comp`を2上げるのに必要な経験値)]を返します.
|
111
159
|
`para`は,`Mgmg::Equip`のメソッド名をシンボルで指定(`:power, :fpower`も可)します.
|
112
160
|
|
113
|
-
|
114
|
-
|
161
|
+
`opt`は`String#build`にそのまま渡されます.
|
162
|
+
|
163
|
+
## `String#peff(para, smith, comp=smith, opt: Mgmg.option())`
|
164
|
+
近似多項式における偏微分値を使用した場合の,`String#eff`と同様の値を返します.`self.poly(para, opt: opt).eff(smith, comp)`と等価です.
|
115
165
|
|
116
|
-
|
166
|
+
`opt`は`String#poly`にそのまま渡されます.
|
167
|
+
|
168
|
+
## `String#phydef_optimize(smith=nil, comp=smith, opt: Mgmg.option())`
|
117
169
|
反転物防装備の反転材の種別,素材の最適化を行い,修正したレシピを返します.
|
118
170
|
`smith`,`comp`は探索を行う製作レベルを表し,`smith`が`nil`の場合,近似多項式で最適化を行います.近似多項式では,道具製作レベルの次数が高い項の係数を最適化します.
|
119
|
-
物防を最大化するレシピのうち,`magdef_maximize`が真なら魔防を最大化する組み合わせ,偽ならコストを最小化(≒魔防を最小化)する組み合わせを探索します.
|
171
|
+
物防を最大化するレシピのうち,`opt.magdef_maximize`が真なら魔防を最大化する組み合わせ,偽ならコストを最小化(≒魔防を最小化)する組み合わせを探索します.
|
120
172
|
ある範囲での全数探索を行うため,段数の多いレシピでは計算量が膨大になるほか,厳密な最適化を保証するものではなく,今後のアップデートで解が変わるような変更が入る可能性があります.
|
121
173
|
|
122
|
-
|
174
|
+
`opt`は,上記の`magdef_maximize`が使われるほか,`String#build`または`String#poly`にそのまま渡されます.
|
175
|
+
|
176
|
+
## `String#buster_optimize(smith=nil, comp=smith, opt: Mgmg.option())`
|
123
177
|
`String#phydef_optimize`の魔力弓版で,反転材の素材の最適化を行い,修正したレシピを返します.
|
124
178
|
|
179
|
+
`opt`は,`String#build`または`String#poly`にそのまま渡されます.
|
180
|
+
|
125
181
|
## `Mgmg.#exp(smith, armor, comp=armor.tap{armor=0})`
|
126
182
|
鍛冶Lvを0から`smith`に,防具製作Lvを0から`armor`に,道具製作Lvを0から`comp`に上げるのに必要な総経験値を返します.鍛冶Lvと防具製作Lvは逆でも同じです.
|
127
183
|
|
128
184
|
## `Mgmg::Equip`
|
129
|
-
[前述](#stringbuildsmith-1-compsmith-
|
185
|
+
[前述](#stringbuildsmith-1-compsmith-opt-mgmgoption)の`String#build`によって生成される装備品のクラスです.複数装備の合計値を表す「複数装備」という種別の装備品の場合もあります.以下のようなインスタンスメソッドが定義されています.
|
130
186
|
|
131
187
|
## `Mgmg::Equip#to_s`
|
132
188
|
```ruby
|
@@ -212,7 +268,7 @@
|
|
212
268
|
レシピ中の,鍛冶・防具製作物の文字列をキー,重量`weight`で生成するのに必要な最小レベルを値とした`Hash`を返します.
|
213
269
|
「複数装備」の場合,各装備の`min_levels`をマージした`Hash`を返します.
|
214
270
|
|
215
|
-
## `Mgmg::Equip#
|
271
|
+
## `Mgmg::Equip#min_levels_max(weight=1)`
|
216
272
|
`min_levels(weight)`の値の最大値を返します.「複数装備」の場合,`[鍛冶の必要レベル,防具製作の必要レベル]`を返します.
|
217
273
|
|
218
274
|
## `Mgmg::Equip#reinforce(*arg)`
|
@@ -236,7 +292,7 @@
|
|
236
292
|
|オールアップ|物防,腕力,器用,素早,魔力x1.5|本アクティブ|
|
237
293
|
|
238
294
|
## `Mgmg::TPolynomial`
|
239
|
-
[前述](#stringpolyparacost-
|
295
|
+
[前述](#stringpolyparacost-opt-mgmgoption)の`String#poly`によって生成される二変数多項式のクラスです.最初のTはtwo-variableのTです.以下のようなメソッドが定義されています.
|
240
296
|
|
241
297
|
## `Mgmg::TPolynomial#to_s(fmt=nil)`
|
242
298
|
鍛冶・防具製作LvをS,道具製作LvをCとして,`self`を表す数式文字列を返します.係数`coeff`を文字列に変換する際,`fmt`の値に応じて次の方法を用います.
|
@@ -282,7 +338,7 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
|
|
282
338
|
一方のみが欲しい場合,`Mgmg::TPolynomial#smith_eff(smith, comp=smith)`,`Mgmg::TPolynomial#smith_eff(smith, comp=smith)`が使えます.
|
283
339
|
|
284
340
|
## `Mgmg::IR`
|
285
|
-
[前述](#
|
341
|
+
[前述](#stringiropt-mgmgoption)の`String#ir`または`Enumerable#ir`によって生成される,9パラ値を計算するための,2変数または3変数の関数オブジェクトを保持するクラスです.`Mgmg::IR`では,`Mgmg::Equip`と異なり,重量,EL値,総消費エレメントを取り扱いません.
|
286
342
|
|
287
343
|
## `Mgmg::IR#to_s`
|
288
344
|
例えば,「斧(牙9皮9)+短剣(鉄9皮2)」のレシピに対して,
|
@@ -372,3 +428,26 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
|
|
372
428
|
調理法,主食材,副食材,料理Lvを指定し,対応する料理の効果の**概算値**を計算します.計算式は [Wikiの記述](https://wikiwiki.jp/guruguru/%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0/%E9%A3%9F%E7%B3%A7%E5%93%81#y1576f2d) に基づきますが,正確ではないことがわかっています.例えば,`('蒸す', 'アースドラン', '氷河酒', 27)`の物防は87ですが,この計算式では88になります.調理法,主食材,副食材は文字列で,料理Lvは整数で指定します.
|
373
429
|
|
374
430
|
調理法は「焼き」か「蒸す」,主食材は「獣肉」「ウッチ」「ゴッチ」「ガガッチ」「ドランギョ」「ドラバーン」「フレドラン」「アースドラン」「アクアドラン」「ダークドン」,副食材は「氷酒」「氷水酒」「氷河酒」「カエン酒」「爆炎酒」「煉獄酒」のみ対応しています.攻撃,物防,魔防の強化を考える場合,これらで十分と判断しての選択となっています.なお,副食材の数値は,Wikiの表で順番が間違っていると思われる部分を修正しています.
|
431
|
+
|
432
|
+
## `Mgmg::Option`
|
433
|
+
多くのメソッドのオプション引数をまとめるクラスです.このクラスのインスタンスを使ってそれぞれのメソッドに引き渡します.
|
434
|
+
|
435
|
+
## `Mgmg.#option(recipe=nil, **kw)`
|
436
|
+
`kw`はキーワード引数本体です.定義されているキーワードと意味,使用される主なメソッドは下表の通りです.デフォルト値は簡易的な表示であり,細かい点では不正確です.
|
437
|
+
`recipe`にレシピ`String`または`Enumerable`を渡すと,そのレシピを使ってデフォルト値を具体化しますが,各メソッドで自動的に具体化されるため,通常は必要ありません.
|
438
|
+
|
439
|
+
|キーワード|デフォルト値|意味|主なメソッド,備考|
|
440
|
+
|:-|:-|:-|:-|
|
441
|
+
|left_associative|`true`|レシピ文字列を左結合で解釈する|`Mgmg::Option`を使用するすべてのメソッド|
|
442
|
+
|smith_min|`recipe.min_level(target_weight)`|鍛冶Lvに関する探索範囲の最小値|`String#search`など|
|
443
|
+
|armor_min|`recipe.min_level(*target_weight)[1]`|防具製作Lvに関する探索範囲の最小値|`Enumerable#search`など.`String`系では代わりに`smith_min`を使う|
|
444
|
+
|comp_min|`recipe.min_comp`|道具製作Lvに関する探索範囲の最小値|`String#search`など|
|
445
|
+
|smith_max, armor_max, comp_max|`10000`|各製作Lvの探索範囲の最大値|`String#search`など|
|
446
|
+
|target_weight|`0`|`smith_min`のデフォルト値計算に使う目標重量|`String#search`など|
|
447
|
+
|step|`1`|探索時において道具製作Lvを動かす幅|`String#search`など|
|
448
|
+
|magdef_maximize|`true`|目標を魔防最大(真)かコスト最小(偽)にするためのスイッチ|`String#phydef_optimize`|
|
449
|
+
|reinforcement|`[]`|[前述](#mgmgequipreinforcearg)の`Mgmg::Equip#reinforce`による強化リスト|一部を除くすべてのメソッド|
|
450
|
+
|buff|`[]`|`reinforcement`のエイリアス|どちらか一方のみを指定する|
|
451
|
+
|irep|`recipe.ir()`|`Mgmg::IR`の使い回しによる高速化|`String#search`など,内部的に使用|
|
452
|
+
|cut_exp|`Float::INFINITY`|探索時の総経験値の打ち切り値|`String#search`など,内部的に使用|
|
453
|
+
|