mgmg 1.5.6 → 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 +10 -2
- data/lib/mgmg/option.rb +1 -1
- data/lib/mgmg/recipe.rb +4 -0
- data/lib/mgmg/search.rb +229 -83
- data/lib/mgmg/utils.rb +50 -2
- data/lib/mgmg/version.rb +1 -1
- data/reference.md +13 -4
- 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
    
    | @@ -158,6 +158,14 @@ | |
| 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`ちょうどの場合に例外となっていたバグを修正.
         | 
| 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/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,36 @@ 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 | 
            +
            	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
         | 
| 93 | 
            +
            	def find_max(para, max_exp, opt: Mgmg::Option.new)
         | 
| 94 | 
            +
            		opt = opt.dup.set_default(self)
         | 
| 95 | 
            +
            		exp = Mgmg.exp(opt.smith_min, opt.comp_min)
         | 
| 96 | 
            +
            		raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
         | 
| 97 | 
            +
            		ret = [Mgmg.invexp2(max_exp, opt.comp_min), opt.comp_min]
         | 
| 98 | 
            +
            		max = opt.irep.para_call(para, *ret)
         | 
| 99 | 
            +
            		(opt.comp_min+1).upto(Mgmg.invexp2c(max_exp, opt.smith_min)) do |comp|
         | 
| 100 | 
            +
            			smith = Mgmg.invexp2(max_exp, comp)
         | 
| 101 | 
            +
            			cur = opt.irep.para_call(para, smith, comp)
         | 
| 102 | 
            +
            			smith = minimize_smith(para, smith, comp, cur, opt) if max <= cur
         | 
| 103 | 
            +
            			ret, max = [smith, comp], cur if ( max < cur || ( max == cur && Mgmg.exp(smith, comp) < Mgmg.exp(*ret) ) )
         | 
| 104 | 
            +
            		end
         | 
| 75 105 | 
             
            		ret
         | 
| 76 106 | 
             
            	end
         | 
| 77 107 | 
             
            end
         | 
| @@ -138,10 +168,10 @@ module Enumerable | |
| 138 168 | 
             
            		opt.armor_max = armor_search(para, target, opt.smith_min, comp, opt: opt_nocut)
         | 
| 139 169 | 
             
            		ret = nil
         | 
| 140 170 | 
             
            		exp = Mgmg.exp(opt.smith_min, opt.armor_max, comp)
         | 
| 141 | 
            -
            		opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp  | 
| 171 | 
            +
            		opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp <= opt.cut_exp
         | 
| 142 172 | 
             
            		exp2 = Mgmg.exp(opt.smith_max, opt.armor_min, comp)
         | 
| 143 173 | 
             
            		if exp2 < exp
         | 
| 144 | 
            -
            			opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2  | 
| 174 | 
            +
            			opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2 <= opt.cut_exp
         | 
| 145 175 | 
             
            			(opt.armor_min+1).upto(opt.armor_max-1) do |armor|
         | 
| 146 176 | 
             
            				break if opt.cut_exp < Mgmg.exp(opt.smith_min, armor, comp)
         | 
| 147 177 | 
             
            				smith = smith_search(para, target, armor, comp, opt:)
         | 
| @@ -193,19 +223,79 @@ module Enumerable | |
| 193 223 | 
             
            		end
         | 
| 194 224 | 
             
            		opt.comp_max
         | 
| 195 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
         | 
| 196 286 | 
             
            	def search(para, target, opt: Mgmg::Option.new)
         | 
| 197 287 | 
             
            		opt = opt.dup.set_default(self)
         | 
| 198 288 | 
             
            		opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt:)
         | 
| 199 | 
            -
            		opt. | 
| 200 | 
            -
            		opt. | 
| 289 | 
            +
            		opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
         | 
| 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)
         | 
| 201 294 | 
             
            		raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
         | 
| 202 295 | 
             
            		opt.comp_max = comp_search(para, target, opt.smith_min, opt.armor_min, opt:)
         | 
| 203 | 
            -
            		ret = nil
         | 
| 204 296 | 
             
            		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  | 
| 206 | 
            -
            		 | 
| 207 | 
            -
            		opt.cut_exp, ret = exp, [opt.smith_max, opt.armor_max, opt.comp_min] if exp < opt.cut_exp
         | 
| 208 | 
            -
            		(opt.comp_min+1).upto(opt.comp_max-1) do |comp|
         | 
| 297 | 
            +
            		opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_min,opt. comp_max] if exp <= opt.cut_exp
         | 
| 298 | 
            +
            		(opt.comp_min).upto(opt.comp_max-1) do |comp|
         | 
| 209 299 | 
             
            			break if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, comp)
         | 
| 210 300 | 
             
            			smith, armor = sa_search(para, target, comp, opt:)
         | 
| 211 301 | 
             
            			exp = Mgmg.exp(smith, armor, comp)
         | 
| @@ -218,14 +308,46 @@ module Enumerable | |
| 218 308 | 
             
            			end
         | 
| 219 309 | 
             
            		rescue Mgmg::SearchCutException
         | 
| 220 310 | 
             
            		end
         | 
| 221 | 
            -
            		 | 
| 311 | 
            +
            		if ret.nil?
         | 
| 312 | 
            +
            			max = opt.irep.para_call(para, *find_max(para, opt.cut_exp, opt:))
         | 
| 313 | 
            +
            			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}"
         | 
| 314 | 
            +
            		end
         | 
| 315 | 
            +
            		ret
         | 
| 316 | 
            +
            	end
         | 
| 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
         | 
| 330 | 
            +
            	def find_max(para, max_exp, opt: Mgmg::Option.new)
         | 
| 331 | 
            +
            		opt = opt.dup.set_default(self)
         | 
| 332 | 
            +
            		exp = Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
         | 
| 333 | 
            +
            		raise Mgmg::SearchCutException, "the recipe requires #{exp.comma3} experiment points, which exceeds given max_exp=#{max_exp.comma3}" if max_exp < exp
         | 
| 334 | 
            +
            		ret = [Mgmg.invexp3(max_exp, opt.armor_min, opt.comp_min), opt.armor_min, opt.comp_min]
         | 
| 335 | 
            +
            		max = opt.irep.para_call(para, *ret)
         | 
| 336 | 
            +
            		(opt.comp_min).step(Mgmg.invexp3c(max_exp, opt.smith_min, opt.armor_min), opt.step) do |comp|
         | 
| 337 | 
            +
            			opt.armor_min.upto(Mgmg.invexp3(max_exp, opt.smith_min, comp)) do |armor|
         | 
| 338 | 
            +
            				smith = Mgmg.invexp3(max_exp, armor, comp)
         | 
| 339 | 
            +
            				cur = opt.irep.para_call(para, smith, armor, comp)
         | 
| 340 | 
            +
            				smith = minimize_smith(para, smith, armor, comp, cur, opt) if max <= cur
         | 
| 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
         | 
| 343 | 
            +
            			end
         | 
| 344 | 
            +
            		end
         | 
| 222 345 | 
             
            		ret
         | 
| 223 346 | 
             
            	end
         | 
| 224 347 | 
             
            end
         | 
| 225 348 |  | 
| 226 349 | 
             
            module Mgmg
         | 
| 227 350 | 
             
            	Eighth = 1.quo(8)
         | 
| 228 | 
            -
            	using Refiner
         | 
| 229 351 | 
             
            	module_function def find_lowerbound(a, b, para, start, term, opt_a: Option.new, opt_b: Option.new)
         | 
| 230 352 | 
             
            		if term <= start
         | 
| 231 353 | 
             
            			raise ArgumentError, "start < term is needed, (start, term) = (#{start}, #{term}) are given"
         | 
| @@ -244,38 +366,42 @@ module Mgmg | |
| 244 366 | 
             
            		end
         | 
| 245 367 | 
             
            		sca, scb = a.search(para, start, opt: opt_a), b.search(para, start, opt: opt_b)
         | 
| 246 368 | 
             
            		ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
         | 
| 247 | 
            -
            		 | 
| 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 )
         | 
| 248 371 | 
             
            			a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
         | 
| 249 372 | 
             
            		end
         | 
| 250 | 
            -
            		 | 
| 251 | 
            -
            		 | 
| 252 | 
            -
             | 
| 253 | 
            -
             | 
| 254 | 
            -
             | 
| 255 | 
            -
             | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 260 | 
            -
            			 | 
| 261 | 
            -
             | 
| 262 | 
            -
            			 | 
| 263 | 
            -
            				if pa < pb
         | 
| 264 | 
            -
            					return [(tag-Eighth).to_ii, pa]
         | 
| 265 | 
            -
            				else
         | 
| 266 | 
            -
            					tag = pb + Eighth
         | 
| 267 | 
            -
            				end
         | 
| 268 | 
            -
            			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
         | 
| 269 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]
         | 
| 270 399 | 
             
            			end
         | 
| 271 400 | 
             
            		end
         | 
| 272 401 | 
             
            		raise UnexpectedError
         | 
| 273 402 | 
             
            	end
         | 
| 274 403 |  | 
| 275 | 
            -
            	module_function def find_upperbound(a, b, para, start,  | 
| 276 | 
            -
            		if start <= term
         | 
| 277 | 
            -
            			raise ArgumentError, "term < start is needed, (start, term) = (#{start}, #{term}) are given"
         | 
| 278 | 
            -
            		end
         | 
| 404 | 
            +
            	module_function def find_upperbound(a, b, para, start, opt_a: Option.new, opt_b: Option.new)
         | 
| 279 405 | 
             
            		if a.kind_of?(Recipe)
         | 
| 280 406 | 
             
            			opt_a = a.option.dup
         | 
| 281 407 | 
             
            			a = a.recipe
         | 
| @@ -290,58 +416,53 @@ module Mgmg | |
| 290 416 | 
             
            		end
         | 
| 291 417 | 
             
            		sca, scb = a.search(para, start, opt: opt_a), b.search(para, start, opt: opt_b)
         | 
| 292 418 | 
             
            		ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
         | 
| 293 | 
            -
            		 | 
| 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 )
         | 
| 294 421 | 
             
            			a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
         | 
| 295 422 | 
             
            		end
         | 
| 296 | 
            -
            		 | 
| 297 | 
            -
            		 | 
| 298 | 
            -
             | 
| 299 | 
            -
             | 
| 300 | 
            -
             | 
| 301 | 
            -
             | 
| 302 | 
            -
             | 
| 303 | 
            -
             | 
| 304 | 
            -
             | 
| 305 | 
            -
             | 
| 306 | 
            -
            			 | 
| 307 | 
            -
            			 | 
| 308 | 
            -
            			 | 
| 309 | 
            -
             | 
| 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
         | 
| 310 447 | 
             
            				ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
         | 
| 311 448 | 
             
            				pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
         | 
| 312 | 
            -
            				if ea < eb
         | 
| 313 | 
            -
            					 | 
| 314 | 
            -
             | 
| 315 | 
            -
             | 
| 316 | 
            -
            					scb = b.search(para, tagl, opt: opt_b)
         | 
| 317 | 
            -
            				elsif ea == eb
         | 
| 318 | 
            -
            					if pb < pa
         | 
| 319 | 
            -
            						ret = tagl
         | 
| 320 | 
            -
            						sca = a.search(para, pa + Eighth, opt: opt_a)
         | 
| 321 | 
            -
            						tagl = opt_a.irep.para_call(para, *sca)
         | 
| 322 | 
            -
            						scb = b.search(para, tagl, opt: opt_b)
         | 
| 323 | 
            -
            					else
         | 
| 324 | 
            -
            						scb = b.search(para, pb + Eighth, opt: opt_b)
         | 
| 325 | 
            -
            						tagl = opt_b.irep.para_call(para, *scb)
         | 
| 326 | 
            -
            						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)
         | 
| 327 453 | 
             
            					end
         | 
| 328 | 
            -
             | 
| 329 | 
            -
             | 
| 330 | 
            -
            					 | 
| 331 | 
            -
            					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}"
         | 
| 332 457 | 
             
            				end
         | 
| 333 458 | 
             
            			end
         | 
| 334 | 
            -
            			if  | 
| 335 | 
            -
            				 | 
| 336 | 
            -
            				 | 
| 337 | 
            -
             | 
| 338 | 
            -
             | 
| 339 | 
            -
            					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)
         | 
| 340 464 | 
             
            				end
         | 
| 341 | 
            -
             | 
| 342 | 
            -
            				pa = opt_a.irep.para_call(para, *a.search(para, ret+Eighth, opt: opt_a))
         | 
| 343 | 
            -
            				pb = opt_b.irep.para_call(para, *b.search(para, ret+Eighth, opt: opt_b))
         | 
| 344 | 
            -
            				return [ret.to_ii, [pa, pb].min]
         | 
| 465 | 
            +
            				return [pa, pb]
         | 
| 345 466 | 
             
            			end
         | 
| 346 467 | 
             
            		end
         | 
| 347 468 | 
             
            		raise UnexpectedError
         | 
| @@ -349,7 +470,32 @@ module Mgmg | |
| 349 470 |  | 
| 350 471 | 
             
            	module_function def find_lubounds(a, b, para, lower, upper, opt_a: Mgmg::Option.new, opt_b: Mgmg::Option.new)
         | 
| 351 472 | 
             
            		xl, yl = find_lowerbound(a, b, para, lower, upper, opt_a:, opt_b:)
         | 
| 352 | 
            -
            		xu, yu = find_upperbound(a, b, para, upper,  | 
| 473 | 
            +
            		xu, yu = find_upperbound(a, b, para, upper, opt_a:, opt_b:)
         | 
| 353 474 | 
             
            		[xl, yl, xu, yu]
         | 
| 354 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
         | 
| 355 501 | 
             
            end
         | 
    
        data/lib/mgmg/utils.rb
    CHANGED
    
    | @@ -158,10 +158,58 @@ 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
         | 
| 166 | 
            +
            		if Mgmg.exp(ret, comp) <= exp
         | 
| 167 | 
            +
            			ret
         | 
| 168 | 
            +
            		else
         | 
| 169 | 
            +
            			ret-1
         | 
| 170 | 
            +
            		end
         | 
| 171 | 
            +
            	end
         | 
| 172 | 
            +
            	module_function def invexp2c(exp, s)
         | 
| 173 | 
            +
            		begin
         | 
| 174 | 
            +
            			ret = Math.sqrt((exp - (((s-1)**2)) - 3).quo(2)).floor + 2
         | 
| 175 | 
            +
            		rescue Math::DomainError
         | 
| 176 | 
            +
            			return -1
         | 
| 177 | 
            +
            		end
         | 
| 178 | 
            +
            		if Mgmg.exp(s, ret) <= exp
         | 
| 179 | 
            +
            			ret
         | 
| 180 | 
            +
            		else
         | 
| 181 | 
            +
            			ret-1
         | 
| 182 | 
            +
            		end
         | 
| 162 183 | 
             
            	end
         | 
| 163 184 | 
             
            	module_function def invexp3(exp, sa, comp)
         | 
| 164 | 
            -
            		 | 
| 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
         | 
| 191 | 
            +
            		if Mgmg.exp(ret, sa, comp) <= exp
         | 
| 192 | 
            +
            			ret
         | 
| 193 | 
            +
            		else
         | 
| 194 | 
            +
            			ret-1
         | 
| 195 | 
            +
            		end
         | 
| 196 | 
            +
            	end
         | 
| 197 | 
            +
            	module_function def invexp3c(exp, smith, armor)
         | 
| 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
         | 
| 208 | 
            +
            		if Mgmg.exp(smith, armor, ret) <= exp
         | 
| 209 | 
            +
            			ret
         | 
| 210 | 
            +
            		else
         | 
| 211 | 
            +
            			ret-1
         | 
| 212 | 
            +
            		end
         | 
| 165 213 | 
             
            	end
         | 
| 166 214 | 
             
            	module_function def clear_cache
         | 
| 167 215 | 
             
            		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`値です.
         | 
| @@ -155,7 +161,7 @@ | |
| 155 161 |  | 
| 156 162 | 
             
            `opt_a`,`opt_b`には,それぞれ`a`と`b`に関するオプションパラメータを指定します.`smith_min`,`armor_min`,`min_smith`,`left_associative`,`reinforcement`,`irep`を使用します.
         | 
| 157 163 |  | 
| 158 | 
            -
            ## `Mgmg.#find_upperbound(a, b, para, start,  | 
| 164 | 
            +
            ## `Mgmg.#find_upperbound(a, b, para, start, opt_a: Mgmg.option(), opt_b: Mgmg.option())`
         | 
| 159 165 | 
             
            `Mgmg.#find_lowerbound`とは逆に,目標値を下げながら,優劣が逆転する最大の目標値を探索し,返します.返り値は`[逆転する最大目標値, 逆転前の最小para値]`です.目標値が,前者よりも少しでも大きいと逆転が起こらず(逆転する目標値の上限),少しだけ大きい時の`para`値が後者になります.
         | 
| 160 166 |  | 
| 161 167 | 
             
            `opt_a`,`opt_b`は,`Mgmg.#find_lowerbound`と同様です.
         | 
| @@ -449,7 +455,7 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s | |
| 449 455 | 
             
            |smith_min|`recipe.min_level(target_weight)`|非対応|鍛冶Lvに関する探索範囲の最小値|`String#search`など|
         | 
| 450 456 | 
             
            |armor_min|`recipe.min_level(*target_weight)[1]`|非対応|防具製作Lvに関する探索範囲の最小値|`Enumerable#search`など.`String`系では代わりに`smith_min`を使う|
         | 
| 451 457 | 
             
            |comp_min|`recipe.min_comp`|非対応|道具製作Lvに関する探索範囲の最小値|`String#search`など|
         | 
| 452 | 
            -
            |smith_max, armor_max, comp_max|` | 
| 458 | 
            +
            |smith_max, armor_max, comp_max|`10,000`|対応|各製作Lvの探索範囲の最大値|`String#search`など|
         | 
| 453 459 | 
             
            |target_weight|`0`|非対応|`smith_min`のデフォルト値計算に使う目標重量|`String#search`など|
         | 
| 454 460 | 
             
            |step|`1`|非対応|探索時において道具製作Lvを動かす幅|`String#search`など|
         | 
| 455 461 | 
             
            |magdef_maximize|`true`|非対応|目標を魔防最大(真)かコスト最小(偽)にするためのスイッチ|`String#phydef_optimize`|
         | 
| @@ -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. | 
| 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- | 
| 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.
         |