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
|