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.
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 min_level(w=1)
12
- Mgmg::Equip.min_level(self, w)
15
+ def min_weight(opt: Mgmg::Option.new)
16
+ build(build(opt: opt).min_levels_max, opt: opt).weight
13
17
  end
14
- def min_levels(left_associative: true)
15
- build(-1, -1, left_associative: left_associative).min_levels
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 min_smith(left_associative: true)
18
- Mgmg::Equip.min_smith(self, left_associative: left_associative)
51
+ def min_comp(opt: Mgmg::Option.new)
52
+ Mgmg::Equip.min_comp(self, opt: opt)
19
53
  end
20
- def min_comp(left_associative: true)
21
- Mgmg::Equip.min_comp(self, left_associative: left_associative)
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 build(smith=-1, comp=smith, left_associative: true)
24
- Mgmg::Equip.build(self, smith, comp, left_associative: left_associative)
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, left_associative: true)
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, left_associative: la) + self.poly(:str, left_associative: la)
63
+ self.poly(:attack, opt: opt) + self.poly(:str, opt: opt)
31
64
  when :atk_sd
32
- self.poly(:attack, left_associative: la) + self.poly(:str, left_associative: la).quo(2) + self.poly(:dex, left_associative: la).quo(2)
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, left_associative: la) + self.poly(:attack, left_associative: la).quo(2) + self.poly(:str, left_associative: la).quo(2)
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, left_associative: la) + self.poly(:dex_as, left_associative: la).quo(2)
69
+ self.poly(:magic, opt: opt) + self.poly(:dex_as, opt: opt).quo(2)
37
70
  when :magmag
38
- self.poly(:magdef, left_associative: la) + self.poly(:magic, left_associative: la).quo(2)
71
+ self.poly(:magdef, opt: opt) + self.poly(:magic, opt: opt).quo(2)
39
72
  when :pmdef
40
- pd = self.poly(:phydef, left_associative: la)
41
- md = self.poly(:magmag, left_associative: la)
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, left_associative: la) + poly(:phydef, left_associative: la) + poly(:magdef, left_associative: la)
50
- ret += poly(:hp, left_associative: la).quo(4) + poly(:mp, left_associative: la).quo(4)
51
- ret += poly(:str, left_associative: la) + poly(:dex, left_associative: la) + poly(:speed, left_associative: la) + poly(:magic, left_associative: la)
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: la)
88
+ Mgmg::TPolynomial.build(self, para, left_associative: opt.left_associative)
56
89
  end
57
90
  end
58
- def eff(para, smith, comp=smith, left_associative: true)
59
- a = build(smith, comp, left_associative: left_associative).para_call(para)
60
- b = build(smith+1, comp, left_associative: left_associative).para_call(para)
61
- c = build(smith, comp+2, left_associative: left_associative).para_call(para)
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, left_associative: true)
67
- poly(para, left_associative: left_associative).eff(smith, comp)
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, left_associative: true, para: :power)
70
- built = self.build(smith, comp, left_associative: left_associative)
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
- puts "with levels (#{smith}, #{comp}) yields (#{pstr}, #{built.total_cost})"
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, left_associative: true, magdef_maximize: true)
79
- Mgmg::Optimize.phydef_optimize(self, smith, comp, left_associative: left_associative, magdef_maximize: magdef_maximize)
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, left_associative: true)
82
- Mgmg::Optimize.buster_optimize(self, smith, comp, left_associative: left_associative)
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}, left_associative: true)
87
- self.map do |str|
88
- m = /\A\[*([^\+]+)/.match(str)
89
- if Mgmg::EquipPosition[m[1].build(0).kind] == 0
90
- str.build(smith, comp, left_associative: left_associative)
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, left_associative: left_associative)
134
+ str.build(armor, comp, opt: opt)
93
135
  end
94
- end.sum
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}, left_associative: true, para: :power)
97
- built = self.build(smith, armor, comp, left_associative: left_associative)
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
- puts "with levels (#{smith}, #{armor}, #{comp}) yields (#{pstr}, #{built.total_cost})"
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 min_levels(left_associative: true)
106
- build(-1, -1, -1, left_associative: left_associative).min_levels
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 min_level(left_associative: true)
109
- ret = [0, 0]
110
- build(-1, -1, -1, left_associative: left_associative).min_levels.each do |str, level|
111
- m = /\A\[*([^\+]+)/.match(str)
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(left_associative: true)
121
- ret = [0, 0]
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, left_associative: left_associative)
124
- m = /\A\[*([^\+]+)/.match(str)
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(left_associative: true)
247
+ def min_comp(opt: Mgmg::Option.new)
134
248
  self.map do |str|
135
- Mgmg::Equip.min_comp(str, left_associative: left_associative)
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.1.2"
39
- spec.add_development_dependency "rake", ">= 13.0.1"
40
- spec.add_development_dependency "irb", ">= 1.2.3"
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 = '>= 2.4.0'
42
+ spec.required_ruby_version = '>= 3.1.0'
43
43
  end