mgmg 1.5.7 → 1.6.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 +4 -0
- data/lib/mgmg/option.rb +1 -1
- data/lib/mgmg/search.rb +186 -77
- data/lib/mgmg/utils.rb +26 -4
- data/lib/mgmg/version.rb +1 -1
- data/reference.md +2 -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: beb7f465bd84969abfb7ce5897d95f46171e84c2a0e3de9a14c42ccef5c23dfc
|
|
4
|
+
data.tar.gz: '09a7eda9204cb28a7a9fc24857353fb5cdcfd21e44564d4a25997658c92fdfd3'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5642dc8af3ac998c76650047c97747a32f2b631e9f6438c6a95e6068a9534dcd726d34dd8466fb1cba0e787f11847552aab4812e1b32d4320ff23a5ec8e15e18
|
|
7
|
+
data.tar.gz: a327745f26724f3f6bbeabf2ed9fcb687ca4e462ac608c219165845b6ccfeafd5a30c32fdda4ee182dd268db8e0b4528e0acc1bc819eaaae0698d9400c764797
|
data/CHANGELOG.md
CHANGED
|
@@ -165,3 +165,7 @@
|
|
|
165
165
|
## 1.5.7 2022/10/15
|
|
166
166
|
- 経験値上限を指定して,目標パラメータを最大化する製作Lvを返す`Mgmg::Recipe#find_max`を追加.
|
|
167
167
|
- `Mgmg::Recipe#search`において,解の経験値が`cut_exp`ちょうどの場合に例外となっていたバグを修正.
|
|
168
|
+
|
|
169
|
+
## 1.6.0 2022/10/18
|
|
170
|
+
- `Mgmg.#find_upperbound`のアルゴリズムを改善し,探索下限目標値の引数を削除.
|
|
171
|
+
- `Enumerable#search`,`Enumerable#find_max`が正しい解を返さない場合があったバグを修正.
|
data/lib/mgmg/option.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Mgmg
|
|
|
2
2
|
class Option
|
|
3
3
|
Defaults = {
|
|
4
4
|
left_associative: true, include_system_equips: true,
|
|
5
|
-
smith_max:
|
|
5
|
+
smith_max: 10_000, armor_max: 10_000, comp_max: 10_000
|
|
6
6
|
}
|
|
7
7
|
def initialize(
|
|
8
8
|
left_associative: Defaults[:left_associative],
|
data/lib/mgmg/search.rb
CHANGED
|
@@ -79,15 +79,27 @@ class String
|
|
|
79
79
|
ret
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
+
private def minimize_smith(para, smith, comp, cur, opt)
|
|
83
|
+
(smith-1).downto(opt.smith_min) do |s|
|
|
84
|
+
foo = opt.irep.para_call(para, s, comp)
|
|
85
|
+
if cur == foo
|
|
86
|
+
smith = s
|
|
87
|
+
else
|
|
88
|
+
break
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
smith
|
|
92
|
+
end
|
|
82
93
|
def find_max(para, max_exp, opt: Mgmg::Option.new)
|
|
83
94
|
opt = opt.dup.set_default(self)
|
|
84
95
|
exp = Mgmg.exp(opt.smith_min, opt.comp_min)
|
|
85
96
|
raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
|
|
86
97
|
ret = [Mgmg.invexp2(max_exp, opt.comp_min), opt.comp_min]
|
|
87
98
|
max = opt.irep.para_call(para, *ret)
|
|
88
|
-
(opt.comp_min+1).
|
|
99
|
+
(opt.comp_min+1).upto(Mgmg.invexp2c(max_exp, opt.smith_min)) do |comp|
|
|
89
100
|
smith = Mgmg.invexp2(max_exp, comp)
|
|
90
101
|
cur = opt.irep.para_call(para, smith, comp)
|
|
102
|
+
smith = minimize_smith(para, smith, comp, cur, opt) if max <= cur
|
|
91
103
|
ret, max = [smith, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, comp) < Mgmg.exp(*ret) ) )
|
|
92
104
|
end
|
|
93
105
|
ret
|
|
@@ -211,20 +223,79 @@ module Enumerable
|
|
|
211
223
|
end
|
|
212
224
|
opt.comp_max
|
|
213
225
|
end
|
|
226
|
+
private def search_aonly(para, target, opt: Mgmg::Option.new)
|
|
227
|
+
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
|
228
|
+
opt.armor_max = armor_search(para, target, -1, opt.comp_min, opt: opt_nocut)
|
|
229
|
+
opt.armor_min = armor_search(para, target, -1, opt.comp_max, opt: opt_nocut)
|
|
230
|
+
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.armor_min, opt.comp_min)
|
|
231
|
+
opt.comp_max = comp_search(para, target, -1, opt.armor_min, opt:)
|
|
232
|
+
ret = nil
|
|
233
|
+
exp = Mgmg.exp(opt.armor_min, opt.comp_max)
|
|
234
|
+
opt.cut_exp, ret = exp, [-1, opt.armor_min, opt.comp_max] if exp <= opt.cut_exp
|
|
235
|
+
exp = Mgmg.exp(opt.armor_max, opt.comp_min)
|
|
236
|
+
opt.cut_exp, ret = exp, [-1, opt.armor_max, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
|
|
237
|
+
(opt.comp_min+opt.step).step(opt.comp_max-1, opt.step) do |comp|
|
|
238
|
+
break if opt.cut_exp < Mgmg.exp(opt.armor_min, comp)
|
|
239
|
+
armor = armor_search(para, target, -1, comp, opt:)
|
|
240
|
+
exp = Mgmg.exp(armor, comp)
|
|
241
|
+
if exp < opt.cut_exp
|
|
242
|
+
opt.cut_exp, ret = exp, [-1, armor, comp]
|
|
243
|
+
elsif exp == opt.cut_exp
|
|
244
|
+
if ret.nil? or opt.irep.para_call(para, *ret) < opt.irep.para_call(para, -1, armor, comp) then
|
|
245
|
+
ret = [-1, armor, comp]
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
rescue Mgmg::SearchCutException
|
|
249
|
+
end
|
|
250
|
+
if ret.nil?
|
|
251
|
+
max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
|
|
252
|
+
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}"
|
|
253
|
+
end
|
|
254
|
+
ret
|
|
255
|
+
end
|
|
256
|
+
private def search_sonly(para, target, opt: Mgmg::Option.new)
|
|
257
|
+
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
|
258
|
+
opt.smith_max = smith_search(para, target, -1, opt.comp_min, opt: opt_nocut)
|
|
259
|
+
opt.smith_min = smith_search(para, target, -1, opt.comp_max, opt: opt_nocut)
|
|
260
|
+
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.comp_min)
|
|
261
|
+
opt.comp_max = comp_search(para, target, opt.smith_min, -1, opt:)
|
|
262
|
+
ret = nil
|
|
263
|
+
exp = Mgmg.exp(opt.smith_min, opt.comp_max)
|
|
264
|
+
opt.cut_exp, ret = exp, [opt.smith_min, -1, opt.comp_max] if exp <= opt.cut_exp
|
|
265
|
+
exp = Mgmg.exp(opt.smith_max, opt.comp_min)
|
|
266
|
+
opt.cut_exp, ret = exp, [opt.smith_max, -1, opt.comp_min] if ( exp < opt.cut_exp || (ret.nil? && exp==opt.cut_exp) )
|
|
267
|
+
(opt.comp_min+opt.step).step(opt.comp_max-1, opt.step) do |comp|
|
|
268
|
+
break if opt.cut_exp < Mgmg.exp(opt.smith_min, comp)
|
|
269
|
+
smith = smith_search(para, target, -1, comp, opt:)
|
|
270
|
+
exp = Mgmg.exp(smith, comp)
|
|
271
|
+
if exp < opt.cut_exp
|
|
272
|
+
opt.cut_exp, ret = exp, [smith, -1, comp]
|
|
273
|
+
elsif exp == opt.cut_exp
|
|
274
|
+
if ret.nil? or opt.irep.para_call(para, *ret) < opt.irep.para_call(para, smith, -1, comp) then
|
|
275
|
+
ret = [smith, -1, comp]
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
rescue Mgmg::SearchCutException
|
|
279
|
+
end
|
|
280
|
+
if ret.nil?
|
|
281
|
+
max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
|
|
282
|
+
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}"
|
|
283
|
+
end
|
|
284
|
+
ret
|
|
285
|
+
end
|
|
214
286
|
def search(para, target, opt: Mgmg::Option.new)
|
|
215
287
|
opt = opt.dup.set_default(self)
|
|
216
288
|
opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt:)
|
|
217
289
|
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
|
218
|
-
opt.smith_max
|
|
219
|
-
opt.
|
|
290
|
+
opt.smith_max = smith_search(para, target, opt.armor_min, opt.comp_min, opt: opt_nocut) rescue ( return search_aonly(para, target, opt:) )
|
|
291
|
+
opt.armor_max = armor_search(para, target, opt.smith_min, opt.comp_min, opt: opt_nocut) rescue ( return search_sonly(para, target, opt:) )
|
|
292
|
+
opt.smith_min = smith_search(para, target, opt.armor_max, opt.comp_max, opt: opt_nocut)
|
|
293
|
+
opt.armor_min = armor_search(para, target, opt.smith_max, opt.comp_max, opt: opt_nocut)
|
|
220
294
|
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
|
|
221
295
|
opt.comp_max = comp_search(para, target, opt.smith_min, opt.armor_min, opt:)
|
|
222
|
-
ret = nil
|
|
223
296
|
exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_max)
|
|
224
297
|
opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_min,opt. comp_max] if exp <= opt.cut_exp
|
|
225
|
-
|
|
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) )
|
|
227
|
-
(opt.comp_min+1).upto(opt.comp_max-1) do |comp|
|
|
298
|
+
(opt.comp_min).upto(opt.comp_max-1) do |comp|
|
|
228
299
|
break if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, comp)
|
|
229
300
|
smith, armor = sa_search(para, target, comp, opt:)
|
|
230
301
|
exp = Mgmg.exp(smith, armor, comp)
|
|
@@ -244,17 +315,31 @@ module Enumerable
|
|
|
244
315
|
ret
|
|
245
316
|
end
|
|
246
317
|
|
|
318
|
+
private def minimize_smith(para, smith, armor, comp, cur, opt)
|
|
319
|
+
return -1 if opt.smith_min < 0
|
|
320
|
+
(smith-1).downto(opt.smith_min) do |s|
|
|
321
|
+
foo = opt.irep.para_call(para, s, armor, comp)
|
|
322
|
+
if cur == foo
|
|
323
|
+
smith = s
|
|
324
|
+
else
|
|
325
|
+
break
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
smith
|
|
329
|
+
end
|
|
247
330
|
def find_max(para, max_exp, opt: Mgmg::Option.new)
|
|
248
331
|
opt = opt.dup.set_default(self)
|
|
249
332
|
exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
|
|
250
333
|
raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
|
|
251
334
|
ret = [Mgmg.invexp3(max_exp, opt.armor_min, opt.comp_min), opt.armor_min, opt.comp_min]
|
|
252
335
|
max = opt.irep.para_call(para, *ret)
|
|
253
|
-
(opt.comp_min
|
|
336
|
+
(opt.comp_min).step(Mgmg.invexp3c(max_exp, opt.smith_min, opt.armor_min), opt.step) do |comp|
|
|
254
337
|
opt.armor_min.upto(Mgmg.invexp3(max_exp, opt.smith_min, comp)) do |armor|
|
|
255
338
|
smith = Mgmg.invexp3(max_exp, armor, comp)
|
|
256
339
|
cur = opt.irep.para_call(para, smith, armor, comp)
|
|
340
|
+
smith = minimize_smith(para, smith, armor, comp, cur, opt) if max <= cur
|
|
257
341
|
ret, max = [smith, armor, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, armor, comp) < Mgmg.exp(*ret) ) )
|
|
342
|
+
break if armor < 0
|
|
258
343
|
end
|
|
259
344
|
end
|
|
260
345
|
ret
|
|
@@ -281,38 +366,42 @@ module Mgmg
|
|
|
281
366
|
end
|
|
282
367
|
sca, scb = a.search(para, start, opt: opt_a), b.search(para, start, opt: opt_b)
|
|
283
368
|
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
|
284
|
-
|
|
369
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
|
370
|
+
if eb < ea || ( ea == eb && pa < pb )
|
|
285
371
|
a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
|
|
286
372
|
end
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if pa < pb
|
|
301
|
-
return [(tag-Eighth).to_ii, pa]
|
|
302
|
-
else
|
|
303
|
-
tag = pb + Eighth
|
|
304
|
-
end
|
|
305
|
-
else
|
|
373
|
+
|
|
374
|
+
loop do
|
|
375
|
+
loop do
|
|
376
|
+
foo = a.find_max(para, eb, opt: opt_a)
|
|
377
|
+
break if sca == foo
|
|
378
|
+
sca, pa = foo, opt_a.irep.para_call(para, *foo)
|
|
379
|
+
scb = b.search(para, pa, opt: opt_b)
|
|
380
|
+
foo = Mgmg.exp(*scb)
|
|
381
|
+
break if eb == foo
|
|
382
|
+
eb = foo
|
|
383
|
+
end
|
|
384
|
+
ea = Mgmg.exp(*sca)
|
|
385
|
+
while ea<=eb
|
|
306
386
|
tag = pa + Eighth
|
|
387
|
+
raise Mgmg::SearchCutException, "given recipes are never reversed from start target=#{start.comma3} until term target=#{term.comma3}" if term < tag
|
|
388
|
+
sca, scb = a.search(para, tag, opt: opt_a), b.search(para, tag, opt: opt_b)
|
|
389
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
|
390
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
|
391
|
+
break if ea == eb && pa < pb
|
|
392
|
+
end
|
|
393
|
+
if eb < ea || ( ea == eb && pa < pb )
|
|
394
|
+
until ea < eb || ( ea == eb && pb < pa )
|
|
395
|
+
sca = a.find_max(para, ea-1, opt: opt_a)
|
|
396
|
+
ea, pa = Mgmg.exp(*sca), opt_a.irep.para_call(para, *sca)
|
|
397
|
+
end
|
|
398
|
+
return [pa, pb]
|
|
307
399
|
end
|
|
308
400
|
end
|
|
309
401
|
raise UnexpectedError
|
|
310
402
|
end
|
|
311
403
|
|
|
312
|
-
module_function def find_upperbound(a, b, para, start,
|
|
313
|
-
if start <= term
|
|
314
|
-
raise ArgumentError, "term < start is needed, (start, term) = (#{start}, #{term}) are given"
|
|
315
|
-
end
|
|
404
|
+
module_function def find_upperbound(a, b, para, start, opt_a: Option.new, opt_b: Option.new)
|
|
316
405
|
if a.kind_of?(Recipe)
|
|
317
406
|
opt_a = a.option.dup
|
|
318
407
|
a = a.recipe
|
|
@@ -327,58 +416,53 @@ module Mgmg
|
|
|
327
416
|
end
|
|
328
417
|
sca, scb = a.search(para, start, opt: opt_a), b.search(para, start, opt: opt_b)
|
|
329
418
|
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
|
330
|
-
|
|
419
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
|
420
|
+
if ea < eb || ( ea == eb && pb < pa )
|
|
331
421
|
a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
|
|
332
422
|
end
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
423
|
+
|
|
424
|
+
loop do
|
|
425
|
+
loop do
|
|
426
|
+
foo = a.find_max(para, eb, opt: opt_a)
|
|
427
|
+
break if sca == foo
|
|
428
|
+
sca, pa = foo, opt_a.irep.para_call(para, *foo)
|
|
429
|
+
scb = b.search(para, pa, opt: opt_b)
|
|
430
|
+
foo = Mgmg.exp(*scb)
|
|
431
|
+
break if eb == foo
|
|
432
|
+
eb = foo
|
|
433
|
+
end
|
|
434
|
+
ea = Mgmg.exp(*sca)
|
|
435
|
+
while ea==eb do
|
|
436
|
+
res = 0
|
|
437
|
+
begin
|
|
438
|
+
sca = a.find_max(para, ea-1, opt: opt_a)
|
|
439
|
+
rescue Mgmg::SearchCutException
|
|
440
|
+
res += 1
|
|
441
|
+
end
|
|
442
|
+
begin
|
|
443
|
+
scb = b.find_max(para, eb-1, opt: opt_b)
|
|
444
|
+
rescue Mgmg::SearchCutException
|
|
445
|
+
res += 1
|
|
446
|
+
end
|
|
347
447
|
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
|
348
448
|
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
|
349
|
-
if ea < eb
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
scb = b.search(para, tagl, opt: opt_b)
|
|
354
|
-
elsif ea == eb
|
|
355
|
-
if pb < pa
|
|
356
|
-
ret = tagl
|
|
357
|
-
sca = a.search(para, pa + Eighth, opt: opt_a)
|
|
358
|
-
tagl = opt_a.irep.para_call(para, *sca)
|
|
359
|
-
scb = b.search(para, tagl, opt: opt_b)
|
|
360
|
-
else
|
|
361
|
-
scb = b.search(para, pb + Eighth, opt: opt_b)
|
|
362
|
-
tagl = opt_b.irep.para_call(para, *scb)
|
|
363
|
-
sca = a.search(para, tagl, opt: opt_a)
|
|
449
|
+
if ea < eb || ( ea == eb && pb < pa )
|
|
450
|
+
until pa < pb
|
|
451
|
+
scb = b.search(para, pb+Eighth, opt: opt_b)
|
|
452
|
+
pb = opt_b.irep.para_call(para, *scb)
|
|
364
453
|
end
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
scb = b.search(para, tagl, opt: opt_b)
|
|
454
|
+
return [pa, pb]
|
|
455
|
+
elsif res == 2
|
|
456
|
+
raise Mgmg::SearchCutException, "given recipes are never reversed from the start target=#{start.comma3} until #{pa.comma3}"
|
|
369
457
|
end
|
|
370
458
|
end
|
|
371
|
-
if
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
tagl = term
|
|
459
|
+
if ea < eb
|
|
460
|
+
pb = opt_b.irep.para_call(para, *scb)
|
|
461
|
+
until pa < pb
|
|
462
|
+
scb = b.search(para, pb+Eighth, opt: opt_b)
|
|
463
|
+
pb = opt_b.irep.para_call(para, *scb)
|
|
377
464
|
end
|
|
378
|
-
|
|
379
|
-
pa = opt_a.irep.para_call(para, *a.search(para, ret+Eighth, opt: opt_a))
|
|
380
|
-
pb = opt_b.irep.para_call(para, *b.search(para, ret+Eighth, opt: opt_b))
|
|
381
|
-
return [ret.to_ii, [pa, pb].min]
|
|
465
|
+
return [pa, pb]
|
|
382
466
|
end
|
|
383
467
|
end
|
|
384
468
|
raise UnexpectedError
|
|
@@ -386,7 +470,32 @@ module Mgmg
|
|
|
386
470
|
|
|
387
471
|
module_function def find_lubounds(a, b, para, lower, upper, opt_a: Mgmg::Option.new, opt_b: Mgmg::Option.new)
|
|
388
472
|
xl, yl = find_lowerbound(a, b, para, lower, upper, opt_a:, opt_b:)
|
|
389
|
-
xu, yu = find_upperbound(a, b, para, upper,
|
|
473
|
+
xu, yu = find_upperbound(a, b, para, upper, opt_a:, opt_b:)
|
|
390
474
|
[xl, yl, xu, yu]
|
|
391
475
|
end
|
|
476
|
+
module_function def find_lubounds2(a, b, para, lower, upper, opt_a: Mgmg::Option.new, opt_b: Mgmg::Option.new)
|
|
477
|
+
xl, yl, xu, yu = find_lubounds(a, b, para, lower, upper, opt_a: Mgmg::Option.new, opt_b: Mgmg::Option.new)
|
|
478
|
+
if a.kind_of?(Recipe)
|
|
479
|
+
opt_a = a.option.dup
|
|
480
|
+
a = a.recipe
|
|
481
|
+
else
|
|
482
|
+
opt_a = opt_a.dup.set_default(a)
|
|
483
|
+
end
|
|
484
|
+
if b.kind_of?(Recipe)
|
|
485
|
+
opt_b = b.option.dup
|
|
486
|
+
b = b.recipe
|
|
487
|
+
else
|
|
488
|
+
opt_b = opt_b.dup.set_default(b)
|
|
489
|
+
end
|
|
490
|
+
sca, scb = a.search(para, lower, opt: opt_a), b.search(para, lower, opt: opt_b)
|
|
491
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
|
492
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
|
493
|
+
if eb < ea || ( ea == eb && pa < pb )
|
|
494
|
+
a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
|
|
495
|
+
end
|
|
496
|
+
sca, scb = a.search(para, xl, opt: opt_a), b.search(para, yu, opt: opt_b)
|
|
497
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
|
498
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
|
499
|
+
[sca, ea, pa, scb, eb, pb]
|
|
500
|
+
end
|
|
392
501
|
end
|
data/lib/mgmg/utils.rb
CHANGED
|
@@ -158,7 +158,11 @@ module Mgmg
|
|
|
158
158
|
end
|
|
159
159
|
end
|
|
160
160
|
module_function def invexp2(exp, comp)
|
|
161
|
-
|
|
161
|
+
begin
|
|
162
|
+
ret = Math.sqrt(exp - (2*((comp-1)**2)) - 3).floor + 2
|
|
163
|
+
rescue Math::DomainError
|
|
164
|
+
return -1
|
|
165
|
+
end
|
|
162
166
|
if Mgmg.exp(ret, comp) <= exp
|
|
163
167
|
ret
|
|
164
168
|
else
|
|
@@ -166,7 +170,11 @@ module Mgmg
|
|
|
166
170
|
end
|
|
167
171
|
end
|
|
168
172
|
module_function def invexp2c(exp, s)
|
|
169
|
-
|
|
173
|
+
begin
|
|
174
|
+
ret = Math.sqrt((exp - (((s-1)**2)) - 3).quo(2)).floor + 2
|
|
175
|
+
rescue Math::DomainError
|
|
176
|
+
return -1
|
|
177
|
+
end
|
|
170
178
|
if Mgmg.exp(s, ret) <= exp
|
|
171
179
|
ret
|
|
172
180
|
else
|
|
@@ -174,7 +182,12 @@ module Mgmg
|
|
|
174
182
|
end
|
|
175
183
|
end
|
|
176
184
|
module_function def invexp3(exp, sa, comp)
|
|
177
|
-
|
|
185
|
+
return invexp2(exp, comp) if sa < 0
|
|
186
|
+
begin
|
|
187
|
+
ret = Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).floor + 2
|
|
188
|
+
rescue Math::DomainError
|
|
189
|
+
return -1
|
|
190
|
+
end
|
|
178
191
|
if Mgmg.exp(ret, sa, comp) <= exp
|
|
179
192
|
ret
|
|
180
193
|
else
|
|
@@ -182,7 +195,16 @@ module Mgmg
|
|
|
182
195
|
end
|
|
183
196
|
end
|
|
184
197
|
module_function def invexp3c(exp, smith, armor)
|
|
185
|
-
|
|
198
|
+
if smith < 0
|
|
199
|
+
return invexp2c(exp, armor)
|
|
200
|
+
elsif armor < 0
|
|
201
|
+
return invexp2c(exp, smith)
|
|
202
|
+
end
|
|
203
|
+
begin
|
|
204
|
+
ret = Math.sqrt((exp - ((smith-1)**2) - ((armor-1)**2) - 4).quo(2)).floor + 2
|
|
205
|
+
rescue Math::DomainError
|
|
206
|
+
return -1
|
|
207
|
+
end
|
|
186
208
|
if Mgmg.exp(smith, armor, ret) <= exp
|
|
187
209
|
ret
|
|
188
210
|
else
|
data/lib/mgmg/version.rb
CHANGED
data/reference.md
CHANGED
|
@@ -161,7 +161,7 @@
|
|
|
161
161
|
|
|
162
162
|
`opt_a`,`opt_b`には,それぞれ`a`と`b`に関するオプションパラメータを指定します.`smith_min`,`armor_min`,`min_smith`,`left_associative`,`reinforcement`,`irep`を使用します.
|
|
163
163
|
|
|
164
|
-
## `Mgmg.#find_upperbound(a, b, para, start,
|
|
164
|
+
## `Mgmg.#find_upperbound(a, b, para, start, opt_a: Mgmg.option(), opt_b: Mgmg.option())`
|
|
165
165
|
`Mgmg.#find_lowerbound`とは逆に,目標値を下げながら,優劣が逆転する最大の目標値を探索し,返します.返り値は`[逆転する最大目標値, 逆転前の最小para値]`です.目標値が,前者よりも少しでも大きいと逆転が起こらず(逆転する目標値の上限),少しだけ大きい時の`para`値が後者になります.
|
|
166
166
|
|
|
167
167
|
`opt_a`,`opt_b`は,`Mgmg.#find_lowerbound`と同様です.
|
|
@@ -455,7 +455,7 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
|
|
|
455
455
|
|smith_min|`recipe.min_level(target_weight)`|非対応|鍛冶Lvに関する探索範囲の最小値|`String#search`など|
|
|
456
456
|
|armor_min|`recipe.min_level(*target_weight)[1]`|非対応|防具製作Lvに関する探索範囲の最小値|`Enumerable#search`など.`String`系では代わりに`smith_min`を使う|
|
|
457
457
|
|comp_min|`recipe.min_comp`|非対応|道具製作Lvに関する探索範囲の最小値|`String#search`など|
|
|
458
|
-
|smith_max, armor_max, comp_max|`
|
|
458
|
+
|smith_max, armor_max, comp_max|`10,000`|対応|各製作Lvの探索範囲の最大値|`String#search`など|
|
|
459
459
|
|target_weight|`0`|非対応|`smith_min`のデフォルト値計算に使う目標重量|`String#search`など|
|
|
460
460
|
|step|`1`|非対応|探索時において道具製作Lvを動かす幅|`String#search`など|
|
|
461
461
|
|magdef_maximize|`true`|非対応|目標を魔防最大(真)かコスト最小(偽)にするためのスイッチ|`String#phydef_optimize`|
|
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.
|
|
4
|
+
version: 1.6.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- KAZOON
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2022-10-
|
|
11
|
+
date: 2022-10-18 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.24
|
|
108
108
|
signing_key:
|
|
109
109
|
specification_version: 4
|
|
110
110
|
summary: Calculate specs of equipments of Megurimeguru, a game produced by Kou.
|