mgmg 1.4.0 → 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 +25 -0
- data/README.md +37 -248
- data/lib/mgmg/cuisine.rb +140 -0
- data/lib/mgmg/equip.rb +37 -39
- data/lib/mgmg/ir.rb +400 -0
- data/lib/mgmg/optimize.rb +21 -9
- data/lib/mgmg/option.rb +85 -0
- data/lib/mgmg/poly.rb +2 -2
- data/lib/mgmg/reinforce.rb +70 -0
- data/lib/mgmg/search.rb +246 -175
- data/lib/mgmg/system_equip.rb +6 -0
- data/lib/mgmg/utils.rb +47 -1
- data/lib/mgmg/version.rb +1 -1
- data/lib/mgmg.rb +176 -62
- data/mgmg.gemspec +4 -4
- data/reference.md +453 -0
- metadata +15 -10
data/lib/mgmg.rb
CHANGED
@@ -3,113 +3,228 @@ require_relative './mgmg/utils'
|
|
3
3
|
require_relative './mgmg/const'
|
4
4
|
require_relative './mgmg/equip'
|
5
5
|
require_relative './mgmg/poly'
|
6
|
+
require_relative './mgmg/ir'
|
6
7
|
require_relative './mgmg/system_equip'
|
8
|
+
require_relative './mgmg/cuisine'
|
9
|
+
require_relative './mgmg/reinforce'
|
10
|
+
require_relative './mgmg/option'
|
7
11
|
require_relative './mgmg/search'
|
8
12
|
require_relative './mgmg/optimize'
|
9
13
|
|
10
14
|
class String
|
11
|
-
def
|
12
|
-
|
15
|
+
def min_weight(opt: Mgmg::Option.new)
|
16
|
+
build(build(opt: opt).min_levels_max, opt: opt).weight
|
13
17
|
end
|
14
|
-
def
|
15
|
-
|
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)
|
44
|
+
end
|
45
|
+
def min_levels_max(w=1, opt: Mgmg::Option.new)
|
46
|
+
min_levels(w, opt: opt).values.append(-1).max
|
47
|
+
end
|
48
|
+
def min_smith(opt: Mgmg::Option.new)
|
49
|
+
Mgmg::Equip.min_smith(self, opt: opt)
|
16
50
|
end
|
17
|
-
def
|
18
|
-
Mgmg::Equip.
|
51
|
+
def min_comp(opt: Mgmg::Option.new)
|
52
|
+
Mgmg::Equip.min_comp(self, opt: opt)
|
19
53
|
end
|
20
|
-
def
|
21
|
-
Mgmg::Equip.
|
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)
|
22
56
|
end
|
23
|
-
def
|
24
|
-
Mgmg::
|
57
|
+
def ir(opt: Mgmg::Option.new)
|
58
|
+
Mgmg::IR.build(self, left_associative: opt.left_associative, reinforcement: opt.reinforcement)
|
25
59
|
end
|
26
|
-
def poly(para=:cost,
|
27
|
-
la = left_associative
|
60
|
+
def poly(para=:cost, opt: Mgmg::Option.new)
|
28
61
|
case para
|
29
62
|
when :atkstr
|
30
|
-
self.poly(:attack,
|
63
|
+
self.poly(:attack, opt: opt) + self.poly(:str, opt: opt)
|
31
64
|
when :atk_sd
|
32
|
-
self.poly(:attack,
|
65
|
+
self.poly(:attack, opt: opt) + self.poly(:str, opt: opt).quo(2) + self.poly(:dex, opt: opt).quo(2)
|
33
66
|
when :dex_as
|
34
|
-
self.poly(:dex,
|
67
|
+
self.poly(:dex, opt: opt) + self.poly(:attack, opt: opt).quo(2) + self.poly(:str, opt: opt).quo(2)
|
35
68
|
when :mag_das
|
36
|
-
self.poly(:magic,
|
69
|
+
self.poly(:magic, opt: opt) + self.poly(:dex_as, opt: opt).quo(2)
|
37
70
|
when :magmag
|
38
|
-
self.poly(:magdef,
|
71
|
+
self.poly(:magdef, opt: opt) + self.poly(:magic, opt: opt).quo(2)
|
39
72
|
when :pmdef
|
40
|
-
pd = self.poly(:phydef,
|
41
|
-
md = self.poly(:magmag,
|
73
|
+
pd = self.poly(:phydef, opt: opt)
|
74
|
+
md = self.poly(:magmag, opt: opt)
|
42
75
|
pd <= md ? pd : md
|
43
76
|
when :cost
|
44
77
|
if Mgmg::SystemEquip.keys.include?(self)
|
45
78
|
return Mgmg::TPolynomial.new(Mgmg::Mat.new(1, 1, 0.quo(1)), 28, 0, 12, 12)
|
46
79
|
end
|
47
|
-
built = self.build(-1)
|
80
|
+
built = self.build(-1, opt: opt)
|
48
81
|
const = (built.star**2) * ( /\+/.match(self) ? 5 : ( built.kind < 8 ? 2 : 1 ) )
|
49
|
-
ret = poly(:attack,
|
50
|
-
ret += poly(:hp,
|
51
|
-
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)
|
52
85
|
ret.mat.body[0][0] += const
|
53
86
|
ret
|
54
87
|
else
|
55
|
-
Mgmg::TPolynomial.build(self, para, left_associative:
|
88
|
+
Mgmg::TPolynomial.build(self, para, left_associative: opt.left_associative)
|
56
89
|
end
|
57
90
|
end
|
58
|
-
def eff(para, smith, comp=smith,
|
59
|
-
a = build(smith, comp,
|
60
|
-
b = build(smith+1, comp,
|
61
|
-
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)
|
62
95
|
sden = smith==0 ? 1 : 2*smith-1
|
63
96
|
cden = comp==0 ? 4 : 8*comp
|
64
97
|
[(b-a).quo(sden), (c-a).quo(cden)]
|
65
98
|
end
|
66
|
-
def peff(para, smith, comp=smith,
|
67
|
-
poly(para,
|
99
|
+
def peff(para, smith, comp=smith, opt: Mgmg::Option.new)
|
100
|
+
poly(para, opt: opt).eff(smith, comp)
|
68
101
|
end
|
69
|
-
def show(smith=-1, comp=smith,
|
70
|
-
|
102
|
+
def show(smith=-1, comp=smith, para: :power, opt: Mgmg::Option.new)
|
103
|
+
rein = case opt.reinforcement
|
104
|
+
when Array
|
105
|
+
opt.reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
|
106
|
+
else
|
107
|
+
[Mgmg::Reinforcement.compile(opt.reinforcement)]
|
108
|
+
end
|
109
|
+
built = build(smith, comp, opt: opt)
|
71
110
|
pstr = '%.3f' % built.para_call(para)
|
72
111
|
pstr.sub!(/\.?0+\Z/, '')
|
73
112
|
puts "Building"
|
74
113
|
puts " #{self}"
|
75
|
-
|
114
|
+
rein = rein.empty? ? '' : " reinforced by {#{rein.join(',')}}"
|
115
|
+
puts "with levels (#{smith}, #{comp})#{rein} yields (#{pstr}, #{built.total_cost})"
|
76
116
|
puts " #{built}"
|
77
117
|
end
|
78
|
-
def phydef_optimize(smith=nil, comp=smith,
|
79
|
-
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)
|
80
120
|
end
|
81
|
-
def buster_optimize(smith=nil, comp=smith,
|
82
|
-
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)
|
83
123
|
end
|
84
124
|
end
|
85
125
|
module Enumerable
|
86
|
-
def build(smith=-1, armor=smith, comp=armor.tap{armor=smith},
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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)
|
91
133
|
else
|
92
|
-
str.build(armor, comp,
|
134
|
+
str.build(armor, comp, opt: opt)
|
93
135
|
end
|
94
|
-
end.
|
136
|
+
end.reinforce(*rein)
|
137
|
+
end
|
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)
|
95
142
|
end
|
96
|
-
def show(smith=-1, armor=smith, comp=armor.tap{armor=smith},
|
97
|
-
|
143
|
+
def show(smith=-1, armor=smith, comp=armor.tap{armor=smith}, para: :power, opt: Mgmg::Option.new)
|
144
|
+
rein = case opt.reinforcement
|
145
|
+
when Array
|
146
|
+
opt.reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
|
147
|
+
else
|
148
|
+
[Mgmg::Reinforcement.compile(opt.reinforcement)]
|
149
|
+
end
|
150
|
+
built = self.build(smith, armor, comp, opt: opt)
|
98
151
|
pstr = '%.3f' % built.para_call(para)
|
99
152
|
pstr.sub!(/\.?0+\Z/, '')
|
100
153
|
puts "Building"
|
101
154
|
puts " #{self.join(', ')}"
|
102
|
-
|
155
|
+
rein = rein.empty? ? '' : " reinforced by {#{rein.join(',')}}"
|
156
|
+
puts "with levels (#{smith}, #{armor}, #{comp})#{rein} yields (#{pstr}, #{built.total_cost})"
|
103
157
|
puts " #{built}"
|
104
158
|
end
|
105
|
-
def
|
106
|
-
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)
|
107
223
|
end
|
108
|
-
def
|
109
|
-
ret = [
|
110
|
-
|
111
|
-
|
112
|
-
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
|
113
228
|
ret[0] = [ret[0], level].max
|
114
229
|
else
|
115
230
|
ret[1] = [ret[1], level].max
|
@@ -117,12 +232,11 @@ module Enumerable
|
|
117
232
|
end
|
118
233
|
ret
|
119
234
|
end
|
120
|
-
def min_smith(
|
121
|
-
ret = [
|
235
|
+
def min_smith(opt: Mgmg::Option.new)
|
236
|
+
ret = [-1, -1]
|
122
237
|
self.each do |str|
|
123
|
-
s = Mgmg::Equip.min_smith(str,
|
124
|
-
|
125
|
-
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
|
126
240
|
ret[0] = [ret[0], s].max
|
127
241
|
else
|
128
242
|
ret[1] = [ret[1], s].max
|
@@ -130,9 +244,9 @@ module Enumerable
|
|
130
244
|
end
|
131
245
|
ret
|
132
246
|
end
|
133
|
-
def min_comp(
|
247
|
+
def min_comp(opt: Mgmg::Option.new)
|
134
248
|
self.map do |str|
|
135
|
-
Mgmg::Equip.min_comp(str,
|
136
|
-
end.max
|
249
|
+
Mgmg::Equip.min_comp(str, opt: opt)
|
250
|
+
end.append(-1).max
|
137
251
|
end
|
138
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
|