mgmg 1.5.6 → 1.5.7
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 +6 -2
- data/lib/mgmg/recipe.rb +4 -0
- data/lib/mgmg/search.rb +48 -11
- data/lib/mgmg/utils.rb +28 -2
- data/lib/mgmg/version.rb +1 -1
- data/reference.md +11 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 959345a0547c379e6ea2cc55e56283b580429c6b25d2a50df0c3ac9c7b02f8db
|
4
|
+
data.tar.gz: 8832f8ad1f54c1f06c77a2c72b25631fbfa9e9f98b5fe0d48ae15c7dd15568da
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d22e5011de865ee5a40550ca1341ae7f5c4ea696f086c95e9ce7be273cd2c4d1acbd6b676c1e87371fc1af05bfd90c1dc796d2b3076a3f5f7a01c1336bed7856
|
7
|
+
data.tar.gz: a70bd19a98d4212ff63d535be59b528d054dc4cbf981eda4bed20ef9e4dce065bc48f7aa4a15e9e6b90542872dde0c3537558557ce3ad1e4129ab174ceb84b8b
|
data/CHANGELOG.md
CHANGED
@@ -158,6 +158,10 @@
|
|
158
158
|
- `String#min_level`において,正しい答えを返さなくなったバグを修正.
|
159
159
|
|
160
160
|
## 1.5.6 2022/07/17
|
161
|
-
- `
|
161
|
+
- `Mgmg.#find_lowerbound`,`Mgmg.#find_upperbound`における探索刻み幅を1から1/8に変更し,コーナーケースでの精度を上昇させた.
|
162
162
|
- `Enumerable#min_level`が,原料☆によるレベル制限を無視した値を返すことがあったバグを修正.
|
163
|
-
- `
|
163
|
+
- `Mgmg.#find_lowerbound`や`Mgmg::IR#atk_sd` などにおいて,返り値が,分母が1の`Rational`である場合,代わりに`Integer`を返すように修正.
|
164
|
+
|
165
|
+
## 1.5.7 2022/10/15
|
166
|
+
- 経験値上限を指定して,目標パラメータを最大化する製作Lvを返す`Mgmg::Recipe#find_max`を追加.
|
167
|
+
- `Mgmg::Recipe#search`において,解の経験値が`cut_exp`ちょうどの場合に例外となっていたバグを修正.
|
data/lib/mgmg/recipe.rb
CHANGED
@@ -93,6 +93,10 @@ module Mgmg
|
|
93
93
|
opt = temp_opt(**kw)
|
94
94
|
@recipe.search(para, target, opt:)
|
95
95
|
end
|
96
|
+
def find_max(max_exp, para: @para, **kw)
|
97
|
+
opt = temp_opt(**kw)
|
98
|
+
@recipe.find_max(para, max_exp, opt:)
|
99
|
+
end
|
96
100
|
private def correct_level(s, ac, x, opt)
|
97
101
|
if s.nil?
|
98
102
|
if x.equal?(false)
|
data/lib/mgmg/search.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
using Mgmg::Refiner
|
1
2
|
class String
|
2
3
|
def smith_search(para, target, comp, opt: Mgmg::Option.new)
|
3
4
|
opt = opt.dup.set_default(self)
|
@@ -55,9 +56,9 @@ class String
|
|
55
56
|
opt.comp_max = comp_search(para, target, opt.smith_min, opt:)
|
56
57
|
ret = nil
|
57
58
|
exp = Mgmg.exp(opt.smith_min, opt.comp_max)
|
58
|
-
opt.cut_exp, ret = exp, [opt.smith_min, opt.comp_max] if exp
|
59
|
+
opt.cut_exp, ret = exp, [opt.smith_min, opt.comp_max] if exp <= opt.cut_exp
|
59
60
|
exp = Mgmg.exp(opt.smith_max, opt.comp_min)
|
60
|
-
opt.cut_exp, ret = exp, [opt.smith_max, opt.comp_min] if exp < opt.cut_exp
|
61
|
+
opt.cut_exp, ret = exp, [opt.smith_max, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
|
61
62
|
(opt.comp_min+opt.step).step(opt.comp_max-1, opt.step) do |comp|
|
62
63
|
break if opt.cut_exp < Mgmg.exp(opt.smith_min, comp)
|
63
64
|
smith = smith_search(para, target, comp, opt:)
|
@@ -71,7 +72,24 @@ class String
|
|
71
72
|
end
|
72
73
|
rescue Mgmg::SearchCutException
|
73
74
|
end
|
74
|
-
|
75
|
+
if ret.nil?
|
76
|
+
max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
|
77
|
+
raise Mgmg::SearchCutException, "the maximum output with given cut_exp=#{opt.cut_exp.comma3} is #{max.comma3}, which does not reach given target=#{target.comma3}"
|
78
|
+
end
|
79
|
+
ret
|
80
|
+
end
|
81
|
+
|
82
|
+
def find_max(para, max_exp, opt: Mgmg::Option.new)
|
83
|
+
opt = opt.dup.set_default(self)
|
84
|
+
exp = Mgmg.exp(opt.smith_min, opt.comp_min)
|
85
|
+
raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
|
86
|
+
ret = [Mgmg.invexp2(max_exp, opt.comp_min), opt.comp_min]
|
87
|
+
max = opt.irep.para_call(para, *ret)
|
88
|
+
(opt.comp_min+1).step(Mgmg.invexp2c(max_exp, opt.smith_min), opt.step) do |comp|
|
89
|
+
smith = Mgmg.invexp2(max_exp, comp)
|
90
|
+
cur = opt.irep.para_call(para, smith, comp)
|
91
|
+
ret, max = [smith, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, comp) < Mgmg.exp(*ret) ) )
|
92
|
+
end
|
75
93
|
ret
|
76
94
|
end
|
77
95
|
end
|
@@ -138,10 +156,10 @@ module Enumerable
|
|
138
156
|
opt.armor_max = armor_search(para, target, opt.smith_min, comp, opt: opt_nocut)
|
139
157
|
ret = nil
|
140
158
|
exp = Mgmg.exp(opt.smith_min, opt.armor_max, comp)
|
141
|
-
opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp
|
159
|
+
opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp <= opt.cut_exp
|
142
160
|
exp2 = Mgmg.exp(opt.smith_max, opt.armor_min, comp)
|
143
161
|
if exp2 < exp
|
144
|
-
opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2
|
162
|
+
opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2 <= opt.cut_exp
|
145
163
|
(opt.armor_min+1).upto(opt.armor_max-1) do |armor|
|
146
164
|
break if opt.cut_exp < Mgmg.exp(opt.smith_min, armor, comp)
|
147
165
|
smith = smith_search(para, target, armor, comp, opt:)
|
@@ -196,15 +214,16 @@ module Enumerable
|
|
196
214
|
def search(para, target, opt: Mgmg::Option.new)
|
197
215
|
opt = opt.dup.set_default(self)
|
198
216
|
opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt:)
|
199
|
-
opt.
|
200
|
-
opt.
|
217
|
+
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
218
|
+
opt.smith_max, opt.armor_max = sa_search(para, target, opt.comp_min, opt: opt_nocut)
|
219
|
+
opt.smith_min, opt.armor_min = sa_search(para, target, opt.comp_max, opt: opt_nocut)
|
201
220
|
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
|
202
221
|
opt.comp_max = comp_search(para, target, opt.smith_min, opt.armor_min, opt:)
|
203
222
|
ret = nil
|
204
223
|
exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_max)
|
205
|
-
opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_min,opt. comp_max] if exp
|
224
|
+
opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_min,opt. comp_max] if exp <= opt.cut_exp
|
206
225
|
exp = Mgmg.exp(opt.smith_max, opt.armor_max, opt.comp_min)
|
207
|
-
opt.cut_exp, ret = exp, [opt.smith_max, opt.armor_max, opt.comp_min] if exp < opt.cut_exp
|
226
|
+
opt.cut_exp, ret = exp, [opt.smith_max, opt.armor_max, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
|
208
227
|
(opt.comp_min+1).upto(opt.comp_max-1) do |comp|
|
209
228
|
break if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, comp)
|
210
229
|
smith, armor = sa_search(para, target, comp, opt:)
|
@@ -218,14 +237,32 @@ module Enumerable
|
|
218
237
|
end
|
219
238
|
rescue Mgmg::SearchCutException
|
220
239
|
end
|
221
|
-
|
240
|
+
if ret.nil?
|
241
|
+
max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
|
242
|
+
raise Mgmg::SearchCutException, "the maximum output with given cut_exp=#{opt.cut_exp.comma3} is #{max.comma3}, which does not reach given target=#{target.comma3}"
|
243
|
+
end
|
244
|
+
ret
|
245
|
+
end
|
246
|
+
|
247
|
+
def find_max(para, max_exp, opt: Mgmg::Option.new)
|
248
|
+
opt = opt.dup.set_default(self)
|
249
|
+
exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
|
250
|
+
raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
|
251
|
+
ret = [Mgmg.invexp3(max_exp, opt.armor_min, opt.comp_min), opt.armor_min, opt.comp_min]
|
252
|
+
max = opt.irep.para_call(para, *ret)
|
253
|
+
(opt.comp_min+1).step(Mgmg.invexp3c(max_exp, opt.smith_min, opt.armor_min), opt.step) do |comp|
|
254
|
+
opt.armor_min.upto(Mgmg.invexp3(max_exp, opt.smith_min, comp)) do |armor|
|
255
|
+
smith = Mgmg.invexp3(max_exp, armor, comp)
|
256
|
+
cur = opt.irep.para_call(para, smith, armor, comp)
|
257
|
+
ret, max = [smith, armor, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, armor, comp) < Mgmg.exp(*ret) ) )
|
258
|
+
end
|
259
|
+
end
|
222
260
|
ret
|
223
261
|
end
|
224
262
|
end
|
225
263
|
|
226
264
|
module Mgmg
|
227
265
|
Eighth = 1.quo(8)
|
228
|
-
using Refiner
|
229
266
|
module_function def find_lowerbound(a, b, para, start, term, opt_a: Option.new, opt_b: Option.new)
|
230
267
|
if term <= start
|
231
268
|
raise ArgumentError, "start < term is needed, (start, term) = (#{start}, #{term}) are given"
|
data/lib/mgmg/utils.rb
CHANGED
@@ -158,10 +158,36 @@ module Mgmg
|
|
158
158
|
end
|
159
159
|
end
|
160
160
|
module_function def invexp2(exp, comp)
|
161
|
-
Math.sqrt(exp - (2*((comp-1)**2)) - 3).
|
161
|
+
ret = Math.sqrt(exp - (2*((comp-1)**2)) - 3).floor + 2
|
162
|
+
if Mgmg.exp(ret, comp) <= exp
|
163
|
+
ret
|
164
|
+
else
|
165
|
+
ret-1
|
166
|
+
end
|
167
|
+
end
|
168
|
+
module_function def invexp2c(exp, s)
|
169
|
+
ret = Math.sqrt((exp - (((s-1)**2)) - 3).quo(2)).floor + 2
|
170
|
+
if Mgmg.exp(s, ret) <= exp
|
171
|
+
ret
|
172
|
+
else
|
173
|
+
ret-1
|
174
|
+
end
|
162
175
|
end
|
163
176
|
module_function def invexp3(exp, sa, comp)
|
164
|
-
Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).
|
177
|
+
ret = Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).floor + 2
|
178
|
+
if Mgmg.exp(ret, sa, comp) <= exp
|
179
|
+
ret
|
180
|
+
else
|
181
|
+
ret-1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
module_function def invexp3c(exp, smith, armor)
|
185
|
+
ret = Math.sqrt((exp - ((smith-1)**2) - ((armor-1)**2) - 4).quo(2)).floor + 2
|
186
|
+
if Mgmg.exp(smith, armor, ret) <= exp
|
187
|
+
ret
|
188
|
+
else
|
189
|
+
ret-1
|
190
|
+
end
|
165
191
|
end
|
166
192
|
module_function def clear_cache
|
167
193
|
CacheMLS.clear; Equip::Cache.clear; Equip::CacheML.clear; TPolynomial::Cache.clear; IR::Cache.clear
|
data/lib/mgmg/version.rb
CHANGED
data/reference.md
CHANGED
@@ -130,7 +130,7 @@
|
|
130
130
|
`opt`は,`comp_min`,`comp_max`,`left_associative`,`reinforcement`,`irep`を使用します.
|
131
131
|
|
132
132
|
## `String#search(para, target, opt: Mgmg.option())`
|
133
|
-
`c_min=comp_search(para, target, opt.smith_max, opt: opt)` から `c_max=comp_search(para, target, opt.smith_min, opt: opt)` まで,`opt.step`ずつ動かして,
|
133
|
+
道具製作Lvを `c_min=comp_search(para, target, opt.smith_max, opt: opt)` から `c_max=comp_search(para, target, opt.smith_min, opt: opt)` まで,`opt.step`ずつ動かして,
|
134
134
|
`smith_search`を行い,その過程で得られた最小経験値の鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.
|
135
135
|
レシピ中の,対象パラメータの種別値がすべて奇数,または全て偶数であるなら,`opt.step`を`2`にしても探索すべき範囲を網羅できます.
|
136
136
|
その他は`String#smith_seach`と同様です.
|
@@ -139,12 +139,18 @@
|
|
139
139
|
|
140
140
|
## `Enumerable#search(para, target, opt: Mgmg.option())`
|
141
141
|
複数装備の組について,`para`の値が`target`以上となる最小経験値の`[鍛冶Lv,防具製作Lv,道具製作Lv]`を返します.
|
142
|
-
武器のみなら防具製作Lv
|
142
|
+
武器のみなら防具製作Lvは`-1`,防具のみなら鍛冶Lvは`-1`,合成なしなら道具製作Lvは`0`となります.
|
143
143
|
|
144
144
|
`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`です.
|
145
145
|
|
146
146
|
その他は,`String#smith_seach`と同様です.
|
147
147
|
|
148
|
+
## `String#find_max(para, max_exp, opt: Mgmg.option())`
|
149
|
+
経験値の合計が`max_exp`以下の範囲で,`para`の値が最大となる鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.`para`の値が最大となる組が複数存在する場合,経験値が小さい方が優先されます.
|
150
|
+
|
151
|
+
## `Enumerable#find_max(para, max_exp, opt: Mgmg.option())`
|
152
|
+
複数装備の組について,経験値の合計が`max_exp`以下の範囲で,`para`の値が最大となる鍛冶Lv,防具製作Lv,道具製作Lvからなる配列を返します.`para`の値が最大となる組が複数存在する場合,経験値が小さい方が優先されます.
|
153
|
+
|
148
154
|
## `Mgmg.#find_lowerbound(a, b, para, start, term, opt_a: Mgmg.option(), opt_b: Mgmg.option())`
|
149
155
|
レシピ`a`とレシピ`b`について,`para`の値を目標値以上にする最小経験値の組において,目標値`start`における優劣が逆転する目標値の下限を探索し,返します.
|
150
156
|
返り値は`[逆転しない最大目標値, 逆転時の最小para値]`です.前者は逆転目標値の下限,後者は,目標値が前者よりも少しだけ大きいときの`para`値です.
|
@@ -482,6 +488,9 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
|
|
482
488
|
## `Mgmg::Recipe#search(target, para: self.para, **kw)`
|
483
489
|
`self.recipe.search`を呼び出して返します.注目パラメータはセットされたものを自動的に渡しますが,別のパラメータを使いたい場合,キーワード引数で指定します.その他のキーワード引数を与えた場合,オプションのうち,与えられたパラメータのみ一時的に上書きします.
|
484
490
|
|
491
|
+
## `Mgmg::Recipe#find_max(max_exp, para: self.para, **kw)`
|
492
|
+
`self.recipe.find_max`を呼び出して返します.注目パラメータはセットされたものを自動的に渡しますが,別のパラメータを使いたい場合,キーワード引数で指定します.その他のキーワード引数を与えた場合,オプションのうち,与えられたパラメータのみ一時的に上書きします.
|
493
|
+
|
485
494
|
## `Mgmg::Recipe#min_level(w=self.option.target_weight, include_outsourcing=false)`
|
486
495
|
`self.recipe.min_level(w, include_outsourcing)`を返します.`w`のデフォルトパラメータが`target_weight`になっている以外は`String#min_level`または`Enumerable#min_level`と同じです.
|
487
496
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mgmg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KAZOON
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -104,7 +104,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
104
|
- !ruby/object:Gem::Version
|
105
105
|
version: '0'
|
106
106
|
requirements: []
|
107
|
-
rubygems_version: 3.3.
|
107
|
+
rubygems_version: 3.3.23
|
108
108
|
signing_key:
|
109
109
|
specification_version: 4
|
110
110
|
summary: Calculate specs of equipments of Megurimeguru, a game produced by Kou.
|