mgmg 1.4.1 → 1.4.2

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/poly.rb CHANGED
@@ -301,8 +301,8 @@ module Mgmg
301
301
  raise ArgumentError.new("given string `#{str}' is unparsable as a smithing recipe")
302
302
  end
303
303
  kind = EquipIndex[m[1].to_sym]
304
- main_m, main_s, main_mc = Equip.__send__(:parse_material, m[2])
305
- sub_m, sub_s, sub_mc = Equip.__send__(:parse_material, m[3])
304
+ main_m, main_s, main_mc = Mgmg.parse_material(m[2])
305
+ sub_m, sub_s, sub_mc = Mgmg.parse_material(m[3])
306
306
  para = ParamIndex[para]
307
307
 
308
308
  c = ( Equip9[kind][para] * Main9[main_m][para] ).cdiv(100).quo( main_mc==sub_mc ? 200 : 100 )
@@ -0,0 +1,70 @@
1
+ module Mgmg
2
+ class Reinforcement
3
+ def initialize(vec)
4
+ @vec = vec
5
+ end
6
+ attr_accessor :vec
7
+ def initialize_copy(other)
8
+ @vec = other.vec.dup
9
+ end
10
+
11
+ def to_s
12
+ '(' + @vec.map.with_index{|e, i| e==0 ? nil : "#{Equip::ParamList[i]}:#{e}"}.compact.join(', ') + ')'
13
+ end
14
+ alias :inspect :to_s
15
+ end
16
+
17
+ # 攻 物 防 HP MP 腕 器 速 魔
18
+ Skill = {
19
+ '物防御UP' => Reinforcement.new( Vec[ 0, 10, 0, 0, 0, 0, 0, 0, 0] ),
20
+ '魔防御UP' => Reinforcement.new( Vec[ 0, 0, 10, 0, 0, 0, 0, 0, 0] ),
21
+ '腕力UP' => Reinforcement.new( Vec[ 0, 0, 0, 0, 0, 10, 0, 0, 0] ),
22
+ 'メンテナンス' => Reinforcement.new( Vec[ 50, 0, 0, 0, 0, 0, 0, 0, 0] ),
23
+ 'ガードアップ' => Reinforcement.new( Vec[ 0, 50, 0, 0, 0, 0, 0, 0, 0] ),
24
+ 'パワーアップ' => Reinforcement.new( Vec[ 0, 0, 0, 0, 0, 50, 0, 0, 0] ),
25
+ 'デックスアップ' => Reinforcement.new( Vec[ 0, 0, 0, 0, 0, 0, 50, 0, 0] ),
26
+ 'スピードアップ' => Reinforcement.new( Vec[ 0, 0, 0, 0, 0, 0, 0, 50, 0] ),
27
+ 'マジックアップ' => Reinforcement.new( Vec[ 0, 0, 0, 0, 0, 0, 0, 0, 50] ),
28
+ 'オールアップ' => Reinforcement.new( Vec[ 0, 50, 0, 0, 0, 50, 50, 50, 50] ),
29
+ }
30
+
31
+ class << Reinforcement
32
+ def cuisine(c)
33
+ Reinforcement.new( Vec[*(c.vec), *Array.new(6, 0)] )
34
+ end
35
+ def compile(arg)
36
+ case arg
37
+ when Reinforcement
38
+ arg
39
+ when Cuisine
40
+ cuisine(arg)
41
+ when String
42
+ if Skill.has_key?(arg)
43
+ Skill[arg]
44
+ elsif SystemCuisine.has_key?(arg)
45
+ SystemCuisine[arg]
46
+ else
47
+ raise ArgumentError, "Unknown skill or preset cuisine name `#{arg}' is given."
48
+ end
49
+ else
50
+ raise ArgumentError, "The argument should be Mgmg::Cuisine or skill name String. (`#{arg}' is given)"
51
+ end
52
+ end
53
+ end
54
+
55
+ class Equip
56
+ def reinforce(*arg)
57
+ arg.each do |r|
58
+ r = Reinforcement.compile(r)
59
+ @para.map!.with_index do |pr, i|
60
+ if r.vec[i] == 0
61
+ pr
62
+ else
63
+ pr * (100+r.vec[i]).quo(100)
64
+ end
65
+ end
66
+ end
67
+ self
68
+ end
69
+ end
70
+ end
data/lib/mgmg/search.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  class String
2
- def smith_search(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
3
- irep = ir(left_associative: left_associative) if irep.nil?
2
+ def smith_search(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])
3
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
4
4
  if smith_min.nil?
5
5
  if min_smith
6
6
  smith_min = self.min_smith.min_smith
@@ -32,8 +32,8 @@ class String
32
32
  end
33
33
  smith_max
34
34
  end
35
- def comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true, irep: nil)
36
- irep = ir(left_associative: left_associative) if irep.nil?
35
+ def comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true, irep: nil, reinforcement: [])
36
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
37
37
  comp_min = min_comp(left_associative: left_associative)
38
38
  if comp_max < comp_min
39
39
  raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
@@ -53,8 +53,8 @@ class String
53
53
  end
54
54
  comp_max
55
55
  end
56
- def search(para, target, smith_min=nil, comp_min=nil, smith_max=10000, comp_max=10000, left_associative: true, step: 1, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
57
- irep = ir(left_associative: left_associative) if irep.nil?
56
+ def search(para, target, smith_min=nil, comp_min=nil, smith_max=10000, comp_max=10000, left_associative: true, step: 1, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])
57
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
58
58
  if smith_min.nil?
59
59
  if min_smith
60
60
  smith_min = self.min_smith
@@ -73,7 +73,7 @@ class String
73
73
  minex, ret = exp, [smith_max, comp_min] if exp < minex
74
74
  (comp_min+step).step(comp_max-1, step) do |comp|
75
75
  break if minex < Mgmg.exp(smith_min, comp)
76
- smith = smith_search(para, target, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
76
+ smith = smith_search(para, target, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min, irep: irep)
77
77
  exp = Mgmg.exp(smith, comp)
78
78
  if exp < minex
79
79
  minex, ret = exp, [smith, comp]
@@ -89,8 +89,8 @@ class String
89
89
  end
90
90
  end
91
91
  module Enumerable
92
- def smith_search(para, target, armor, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
93
- irep = ir(left_associative: left_associative) if irep.nil?
92
+ def smith_search(para, target, armor, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])
93
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
94
94
  if smith_min.nil?
95
95
  if min_smith
96
96
  smith_min = self.min_smith[0]
@@ -122,8 +122,8 @@ module Enumerable
122
122
  end
123
123
  smith_max
124
124
  end
125
- def armor_search(para, target, smith, comp, armor_min=nil, armor_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
126
- irep = ir(left_associative: left_associative) if irep.nil?
125
+ def armor_search(para, target, smith, comp, armor_min=nil, armor_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])
126
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
127
127
  if armor_min.nil?
128
128
  if min_smith
129
129
  armor_min = self.min_smith[1]
@@ -155,8 +155,8 @@ module Enumerable
155
155
  end
156
156
  armor_max
157
157
  end
158
- def sa_search(para, target, comp, smith_min=nil, armor_min=nil, smith_max=10000, armor_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
159
- irep = ir(left_associative: left_associative) if irep.nil?
158
+ def sa_search(para, target, comp, smith_min=nil, armor_min=nil, smith_max=10000, armor_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])
159
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
160
160
  if min_smith
161
161
  s, a = self.min_smith
162
162
  else
@@ -204,8 +204,8 @@ module Enumerable
204
204
  raise Mgmg::SearchCutException if cut_exp < minex
205
205
  ret
206
206
  end
207
- def comp_search(para, target, smith, armor, comp_min=nil, comp_max=10000, left_associative: true, irep: nil)
208
- irep = ir(left_associative: left_associative) if irep.nil?
207
+ def comp_search(para, target, smith, armor, comp_min=nil, comp_max=10000, left_associative: true, irep: nil, reinforcement: [])
208
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
209
209
  comp_min = min_comp(left_associative: left_associative)
210
210
  if comp_max < comp_min
211
211
  raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
@@ -225,8 +225,8 @@ module Enumerable
225
225
  end
226
226
  comp_max
227
227
  end
228
- def search(para, target, smith_min=nil, armor_min=nil, comp_min=nil, smith_max=10000, armor_max=10000, comp_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil)
229
- irep = ir(left_associative: left_associative) if irep.nil?
228
+ def search(para, target, smith_min=nil, armor_min=nil, comp_min=nil, smith_max=10000, armor_max=10000, comp_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])
229
+ irep = ir(left_associative: left_associative, reinforcement: reinforcement) if irep.nil?
230
230
  if min_smith
231
231
  s, a = self.min_smith
232
232
  else
@@ -262,11 +262,11 @@ module Enumerable
262
262
  end
263
263
 
264
264
  module Mgmg
265
- module_function def find_lowerbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false)
265
+ module_function def find_lowerbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false, reinforcement: [])
266
266
  if term <= start
267
267
  raise ArgumentError, "start < term is needed, (start, term) = (#{start}, #{term}) are given"
268
268
  end
269
- ira, irb = a.ir, b.ir
269
+ ira, irb = a.ir(reinforcement: reinforcement), b.ir(reinforcement: reinforcement)
270
270
  sca, scb = a.search(para, start, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, start, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
271
271
  ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
272
272
  if eb < ea || ( ea == eb && ira.para_call(para, *sca) < irb.para_call(para, *scb) )
@@ -298,11 +298,11 @@ module Mgmg
298
298
  raise UnexpectedError
299
299
  end
300
300
 
301
- module_function def find_upperbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false)
301
+ module_function def find_upperbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false, reinforcement: [])
302
302
  if start <= term
303
303
  raise ArgumentError, "term < start is needed, (start, term) = (#{start}, #{term}) are given"
304
304
  end
305
- ira, irb = a.ir, b.ir
305
+ ira, irb = a.ir(reinforcement: reinforcement), b.ir(reinforcement: reinforcement)
306
306
  sca, scb = a.search(para, start, smith_min_a, armor_min_a, min_smith: min_smith, irep: ira), b.search(para, start, smith_min_b, armor_min_b, min_smith: min_smith, irep: irb)
307
307
  ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
308
308
  if ea < eb || ( ea == eb && irb.para_call(para, *scb) < ira.para_call(para, *sca) )
data/lib/mgmg/utils.rb CHANGED
@@ -14,6 +14,31 @@ module Mgmg
14
14
  end
15
15
  end
16
16
  end
17
+ refine Float do
18
+ alias :cdiv :quo # Floatの場合は普通の割り算
19
+ def comma3
20
+ s = self.to_s
21
+ case s
22
+ when %r|e|
23
+ s
24
+ when %r|\.|
25
+ ary = s.split('.')
26
+ ary[0].gsub(/(\d)(?=(\d{3})+(?!\d))/, '\1,') + '.' + ary[1]
27
+ else
28
+ s
29
+ end
30
+ end
31
+ end
32
+ refine Rational do
33
+ alias :cdiv :quo # Rationalの場合は普通の割り算
34
+ def comma3
35
+ if self.denominator == 1
36
+ self.numerator.comma3
37
+ else
38
+ self.to_f.comma3
39
+ end
40
+ end
41
+ end
17
42
  end
18
43
  using Refiner
19
44
 
data/lib/mgmg/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mgmg
2
- VERSION = "1.4.1"
2
+ VERSION = "1.4.2"
3
3
  end
data/lib/mgmg.rb CHANGED
@@ -5,6 +5,8 @@ require_relative './mgmg/equip'
5
5
  require_relative './mgmg/poly'
6
6
  require_relative './mgmg/ir'
7
7
  require_relative './mgmg/system_equip'
8
+ require_relative './mgmg/cuisine'
9
+ require_relative './mgmg/reinforce'
8
10
  require_relative './mgmg/search'
9
11
  require_relative './mgmg/optimize'
10
12
 
@@ -24,8 +26,8 @@ class String
24
26
  def build(smith=-1, comp=smith, left_associative: true)
25
27
  Mgmg::Equip.build(self, smith, comp, left_associative: left_associative)
26
28
  end
27
- def ir(left_associative: true)
28
- Mgmg::IR.build(self, left_associative: left_associative)
29
+ def ir(left_associative: true, reinforcement: [])
30
+ Mgmg::IR.build(self, left_associative: left_associative, reinforcement: reinforcement)
29
31
  end
30
32
  def poly(para=:cost, left_associative: true)
31
33
  la = left_associative
@@ -70,13 +72,20 @@ class String
70
72
  def peff(para, smith, comp=smith, left_associative: true)
71
73
  poly(para, left_associative: left_associative).eff(smith, comp)
72
74
  end
73
- def show(smith=-1, comp=smith, left_associative: true, para: :power)
74
- built = self.build(smith, comp, left_associative: left_associative)
75
+ def show(smith=-1, comp=smith, left_associative: true, para: :power, reinforcement: [])
76
+ rein = case reinforcement
77
+ when Array
78
+ reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
79
+ else
80
+ [Mgmg::Reinforcement.compile(reinforcement)]
81
+ end
82
+ built = self.build(smith, comp, left_associative: left_associative).reinforce(*rein)
75
83
  pstr = '%.3f' % built.para_call(para)
76
84
  pstr.sub!(/\.?0+\Z/, '')
77
85
  puts "Building"
78
86
  puts " #{self}"
79
- puts "with levels (#{smith}, #{comp}) yields (#{pstr}, #{built.total_cost})"
87
+ rein = rein.empty? ? '' : " reinforced by {#{rein.join(',')}}"
88
+ puts "with levels (#{smith}, #{comp})#{rein} yields (#{pstr}, #{built.total_cost})"
80
89
  puts " #{built}"
81
90
  end
82
91
  def phydef_optimize(smith=nil, comp=smith, left_associative: true, magdef_maximize: true)
@@ -88,27 +97,34 @@ class String
88
97
  end
89
98
  module Enumerable
90
99
  def build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)
91
- self.map do |str|
100
+ self.sum do |str|
92
101
  m = /\A\[*([^\+]+)/.match(str)
93
102
  if Mgmg::EquipPosition[m[1].build(0).kind] == 0
94
103
  str.build(smith, comp, left_associative: left_associative)
95
104
  else
96
105
  str.build(armor, comp, left_associative: left_associative)
97
106
  end
98
- end.sum
107
+ end
99
108
  end
100
- def ir(left_associative: true)
101
- self.map do |str|
109
+ def ir(left_associative: true, reinforcement: [])
110
+ self.sum do |str|
102
111
  str.ir(left_associative: left_associative)
103
- end.sum
112
+ end.add_reinforcement(reinforcement)
104
113
  end
105
- def show(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true, para: :power)
106
- built = self.build(smith, armor, comp, left_associative: left_associative)
114
+ def show(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true, para: :power, reinforcement: [])
115
+ rein = case reinforcement
116
+ when Array
117
+ reinforcement.map{|r| Mgmg::Reinforcement.compile(r)}
118
+ else
119
+ [Mgmg::Reinforcement.compile(reinforcement)]
120
+ end
121
+ built = self.build(smith, armor, comp, left_associative: left_associative).reinforce(*rein)
107
122
  pstr = '%.3f' % built.para_call(para)
108
123
  pstr.sub!(/\.?0+\Z/, '')
109
124
  puts "Building"
110
125
  puts " #{self.join(', ')}"
111
- puts "with levels (#{smith}, #{armor}, #{comp}) yields (#{pstr}, #{built.total_cost})"
126
+ rein = rein.empty? ? '' : " reinforced by {#{rein.join(',')}}"
127
+ puts "with levels (#{smith}, #{armor}, #{comp})#{rein} yields (#{pstr}, #{built.total_cost})"
112
128
  puts " #{built}"
113
129
  end
114
130
  def min_levels(w=1, left_associative: true)
data/reference.md CHANGED
@@ -2,7 +2,7 @@
2
2
  本ライブラリで定義される主要なメソッドを以下に解説します.
3
3
 
4
4
  ## `String#build(smith=-1, comp=smith, left_associative: true)`
5
- レシピ文字列である`self`を解釈し,鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として鍛冶・防具製作及び武器・防具合成を行った結果を後述の`Mgmg::Equip`クラスのインスタンスとして生成し,返します.例えば,
5
+ レシピ文字列である`self`を解釈し,鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として鍛冶・防具製作及び武器・防具合成を行った結果を[後述](#mgmgequip)の`Mgmg::Equip`クラスのインスタンスとして生成し,返します.例えば,
6
6
  ```ruby
7
7
  '[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build(112, 176)
8
8
  ```
@@ -55,38 +55,45 @@
55
55
 
56
56
  また,`:cost`を渡すことで,消費エレメント量に関する近似多項式を得られます.`self`に`"+"`が含まれていれば合成品とみなし,最後の合成に必要な地エレメント量を,それ以外では,武器なら消費火エレメント量を,防具なら消費水エレメント量を返します.ただし,`self`が既成品そのものの場合,零多項式を返します.
57
57
 
58
- ## `String#ir(left_associative: true)`
59
- レシピ文字列である`self`を解釈し,9パラ値について,丸めを考慮した鍛冶・防具製作Lvと道具製作Lvの2変数からなる関数オブジェクトを保持する`Mgmg::IR`クラスのインスタンスを生成し,返します.詳しくは,後述の`Mgmg::IR`クラスの説明を参照ください.
58
+ ## `String#ir(left_associative: true, reinforcement: [])`
59
+ レシピ文字列である`self`を解釈し,9パラ値について,丸めを考慮した鍛冶・防具製作Lvと道具製作Lvの2変数からなる関数オブジェクトを保持する`Mgmg::IR`クラスのインスタンスを生成し,返します.詳しくは,[後述](#mgmgir)の`Mgmg::IR`クラスの説明を参照ください.
60
60
 
61
- ## `Enumerable#ir(left_associative: true)`
61
+ `reinforcement`には,[後述](#mgmgequipreinforcearg)の`Mgmg::Equip#reinforce`に渡す引数と同様のものを,一つの配列にまとめて渡します.強化が一つだけの場合,その引数を裸で渡すこともできます.
62
+
63
+ ## `Enumerable#ir(left_associative: true, reinforcement: [])`
62
64
  複数のレシピ文字列からなる`self`の各要素を製作し,そのすべてを装備したときの`Mgmg::IR`を返します.この場合,鍛冶Lv,防具製作Lv,道具製作Lvの3変数からなる関数オブジェクトを保持するものとして扱われます.各装備の種別に応じ,鍛冶Lvまたは防具製作Lvを適用し,9パラ値を計算します.
63
65
 
64
- ## `String#smith_seach(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false)`
66
+ ## `String#smith_seach(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])`
65
67
  `para`の値が`target`以上となるのに必要な最小の鍛冶・防具製作Lvを二分探索で探索して返します.
66
68
  道具製作Lvは`comp`で固定,鍛冶・防具製作Lvを`smith_min`と`smith_max`で挟み込んで探索します.
69
+
67
70
  `smith_min`が`nil`のとき,`min_smith`が真なら重量を問わず☆的に必要な最小の鍛冶・防具製作Lv (`self.min_smith`),偽なら最小重量で製作するのに必要な鍛冶・防具製作Lv (`self.build.min_level`)を使用します.
68
71
  `smith_min<smith_max`でないとき,`smith_max`で`para`が`target`以上でないときは`ArgumentError`となります.
72
+
69
73
  `para`は,`Mgmg::Equip`のメソッド名をシンボルで指定(`:power, :fpower`も可)します.
70
74
  反転などの影響で,探索範囲において`para`の値が(広義)単調増加になっていない場合,正しい結果を返しません.
71
75
  `cut_exp`以下の経験値で`target`以上を達成できない場合,`Mgmg::SearchCutException`を発生します.
72
76
 
73
- ## `String#comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true)`
77
+ `irep`に`Mgmg::IR`オブジェクトが渡された場合,`self`を無視して`irep`を使って探索します.
78
+ `reinforcement`が渡された場合,`para`を強化された値として計算します.`irep`が指定されている場合は無視されます.
79
+
80
+ ## `String#comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true, irep: nil, reinforcement: [])`
74
81
  `String#smith_seach`とは逆に,鍛冶・防具製作Lvを固定して最小の道具製作Lvを探索します.
75
82
  `comp_min`が`nil`のときは,製作に必要な最小の道具製作Lv (`self.min_comp`)を使用します.
76
83
  その他は`String#smith_seach`と同様です.
77
84
 
78
- ## `String#search(para, target, smith_min=nil, comp_min=nil, smith_max=10000, comp_max=10000, left_associative: true, step: 1, cut_exp: Float::INFINITY, min_smith: false)`
85
+ ## `String#search(para, target, smith_min=nil, comp_min=nil, smith_max=10000, comp_max=10000, left_associative: true, step: 1, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])`
79
86
  `c_min=comp_search(para, target, smith_max, comp_min, comp_max)` から `c_max=comp_search(para, target, smith_max, comp_min, comp_max)` まで,`step`ずつ動かして,
80
87
  `smith_search`を行い,その過程で得られた最小経験値の鍛冶・防具製作Lvと道具製作Lvからなる配列を返します.
81
88
  レシピ中の,対象パラメータの種別値がすべて奇数,または全て偶数であるなら,`step`を`2`にしても探索すべき範囲を網羅できます.
82
- `cut_exp`以下の経験値で`target`以上を達成できない場合,`Mgmg::SearchCutException`を発生します.
89
+ その他は`String#smith_seach`と同様です.
83
90
 
84
- ## `Enumerable#search(para, target, smith_min=nil, armor_min=nil, comp_min=nil, smith_max=10000, armor_max=10000, comp_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false)`
91
+ ## `Enumerable#search(para, target, smith_min=nil, armor_min=nil, comp_min=nil, smith_max=10000, armor_max=10000, comp_max=10000, left_associative: true, cut_exp: Float::INFINITY, min_smith: false, irep: nil, reinforcement: [])`
85
92
  複数装備の組について,`para`の値が`target`以上となる最小経験値の`[鍛冶Lv,防具製作Lv,道具製作Lv]`を返します.
86
93
  武器のみなら防具製作Lvは`0`,防具のみなら鍛冶Lvは`0`,合成なしなら道具製作Lvは`0`となります.
87
- `cut_exp`以下の経験値で`target`以上を達成できない場合,`Mgmg::SearchCutException`を発生します.
94
+ その他は`String#smith_seach`と同様です.
88
95
 
89
- ## `Mgmg.#find_lowerbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false)`
96
+ ## `Mgmg.#find_lowerbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false, reinforcement: [])`
90
97
  レシピ`a`とレシピ`b`について,`para`の値を目標値以上にする最小経験値の組において,目標値`start`における優劣が逆転する目標値の下限を探索し,返します.
91
98
  返り値は`[逆転しない最大目標値, 逆転時の最小para値]`です.前者は逆転目標値の下限,後者は,目標値が前者よりも少しだけ大きいときの`para`値です.
92
99
  ここで,最小経験値が小さい方,または最小経験値が同じなら,そのときの`para`値が大きい方をよりよいものと解釈します.
@@ -96,7 +103,7 @@
96
103
  `smith_min_a`,`smith_min_b`,`armor_min_a`,`armor_min_b`は,それぞれ`a`と`b`の探索最小鍛冶・防具製作Lvを指定します.`a`,`b`が`String`の場合,防具についても`smith_min_a`,`smith_min_b`を指定します.`Enumerable`の場合は,鍛冶と防具製作についてそれぞれ指定します.
97
104
  これらが`nil`で,`min_smith`が真ならば,重量を無視した製作可能最小Lvが指定されます.`min_smith`が偽(デフォルト)ならば,最小重量で製作可能な製作Lvが指定されます.重量を無視した製作可能Lvでの重量が3で,重量が2以下となる製作Lvで探索したい場合などは,`smith_min_a`,`smith_min_b`,`armor_min_a`,`armor_min_b`を具体的に指定してください.
98
105
 
99
- ## `Mgmg.#find_upperbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false)`
106
+ ## `Mgmg.#find_upperbound(a, b, para, start, term, smith_min_a: nil, smith_min_b: nil, armor_min_a: nil, armor_min_b: nil, min_smith: false, reinforcement: [])`
100
107
  `Mgmg.#find_lowerbound`とは逆に,目標値を下げながら,優劣が逆転する最大の目標値を探索し,返します.返り値は`[逆転する最大目標値, 逆転前の最小para値]`です.目標値が,前者よりも少しでも大きいと逆転が起こらず(逆転する目標値の上限),少しだけ大きい時の`para`値が後者になります.
101
108
 
102
109
  ## `String#eff(para, smith, comp=smith, left_associative: true)`
@@ -119,7 +126,7 @@
119
126
  鍛冶Lvを0から`smith`に,防具製作Lvを0から`armor`に,道具製作Lvを0から`comp`に上げるのに必要な総経験値を返します.鍛冶Lvと防具製作Lvは逆でも同じです.
120
127
 
121
128
  ## `Mgmg::Equip`
122
- 前述の`String#build`によって生成される装備品のクラスです.複数装備の合計値を表す「複数装備」という種別の装備品の場合もあります.以下のようなインスタンスメソッドが定義されています.
129
+ [前述](#stringbuildsmith-1-compsmith-left_associative-true)の`String#build`によって生成される装備品のクラスです.複数装備の合計値を表す「複数装備」という種別の装備品の場合もあります.以下のようなインスタンスメソッドが定義されています.
123
130
 
124
131
  ## `Mgmg::Equip#to_s`
125
132
  ```ruby
@@ -208,8 +215,28 @@
208
215
  ## `Mgmg::Equip#min_level(weight=1)`
209
216
  `min_levels(weight)`の値の最大値を返します.「複数装備」の場合,`[鍛冶の必要レベル,防具製作の必要レベル]`を返します.
210
217
 
218
+ ## `Mgmg::Equip#reinforce(*arg)`
219
+ `self`を破壊的に変更し,スキルや料理で強化した値をシミュレートします.
220
+ 引数には,スキル名または[後述](#mgmgcuisine)する`Mgmg::Cuisine`オブジェクトを並べます.
221
+ [料理店の料理](#引数1つ)および[登録されている料理](#引数3つ)については,料理名の`String`を直接指定することもできます.
222
+ 同一のスキルを複数並べるなど,実際には重複しない組み合わせであっても,特に配慮せずにすべて重ねて強化します.
223
+ 現在対応しているスキルは以下の通りです(効果に誤りがあればご指摘ください).
224
+
225
+ |スキル|効果|備考|
226
+ |:-|:-|:-|
227
+ |物防御UP|物防x1.1|剣パッシブ|
228
+ |魔防御UP|魔防x1.1|本パッシブ|
229
+ |腕力UP|腕力x1.1|斧パッシブ|
230
+ |メンテナンス|攻撃x1.5|弩アクティブ|
231
+ |ガードアップ|物防x1.5|剣アクティブ|
232
+ |パワーアップ|腕力x1.5|本アクティブ|
233
+ |デックスアップ|器用x1.5|弓アクティブ|
234
+ |スピードアップ|素早x1.5|短剣アクティブ|
235
+ |マジックアップ|魔力x1.5|本アクティブ|
236
+ |オールアップ|物防,腕力,器用,素早,魔力x1.5|本アクティブ|
237
+
211
238
  ## `Mgmg::TPolynomial`
212
- 前述の`String#poly`によって生成される二変数多項式のクラスです.最初のTはtwo-variableのTです.以下のようなメソッドが定義されています.
239
+ [前述](#stringpolyparacost-left_associative-true)の`String#poly`によって生成される二変数多項式のクラスです.最初のTはtwo-variableのTです.以下のようなメソッドが定義されています.
213
240
 
214
241
  ## `Mgmg::TPolynomial#to_s(fmt=nil)`
215
242
  鍛冶・防具製作LvをS,道具製作LvをCとして,`self`を表す数式文字列を返します.係数`coeff`を文字列に変換する際,`fmt`の値に応じて次の方法を用います.
@@ -255,7 +282,7 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
255
282
  一方のみが欲しい場合,`Mgmg::TPolynomial#smith_eff(smith, comp=smith)`,`Mgmg::TPolynomial#smith_eff(smith, comp=smith)`が使えます.
256
283
 
257
284
  ## `Mgmg::IR`
258
- 前述の`String#ir`または`Enumerable#ir`によって生成される,9パラ値を計算するための,2変数または3変数の関数オブジェクトを保持するクラスです.`Mgmg::IR`では,`Mgmg::Equip`と異なり,重量,EL値,総消費エレメントを取り扱いません.
285
+ [前述](#stringirleft_associative-true-reinforcement-)の`String#ir`または`Enumerable#ir`によって生成される,9パラ値を計算するための,2変数または3変数の関数オブジェクトを保持するクラスです.`Mgmg::IR`では,`Mgmg::Equip`と異なり,重量,EL値,総消費エレメントを取り扱いません.
259
286
 
260
287
  ## `Mgmg::IR#to_s`
261
288
  例えば,「斧(牙9皮9)+短剣(鉄9皮2)」のレシピに対して,
@@ -287,3 +314,61 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
287
314
 
288
315
  ## `Mgmg::IR#smith_cost, comp_cost(s, c=s, outsourcing=false)`
289
316
  `Mgmg::Equip`における同名メソッドと同様に,鍛冶・防具製作コストまたは武具合成コストを計算して返します.複数装備では意味のある値を計算できないため,製作Lvの3種入力はできません.
317
+ また,これらのメソッドのみ,`reinforcement`を無視します.
318
+
319
+ ## `Mgmg::Cuisine`
320
+ [前述](#mgmgequipreinforcearg)の`Mgmg::Equip#reinforce`で使用する料理オブジェクトです.料理効果のうち,攻撃,物防,魔防のみが装備を強化できるため,この3パラメータのみを取り扱います.
321
+
322
+ ## `Mgmg.#cuisine(*arg)`
323
+ `Mgmg::Cuisine`オブジェクトを生成するためのモジュール関数です.引数の数によって,下記のように生成します.
324
+
325
+ ### 引数1つ
326
+ 街の料理点の料理名を指定します.対応している料理は以下のとおりです.サボテン焼きは☆1と☆7の2種類があるため,区別のために数字を付与した名前を指定します.
327
+ また,次節のプリセット料理も,同様に料理名のみで指定できます.
328
+
329
+ |料理名|攻撃|物防|魔防|
330
+ |:-|-:|-:|-:|
331
+ |焼き肉|5|0|0|
332
+ |焼き金肉|10|0|0|
333
+ |焼き黄金肉|15|0|0|
334
+ |焼きリンゴ|0|5|0|
335
+ |焼きイチゴ|0|10|0|
336
+ |焼きネギタマ|0|15|0|
337
+ |サボテン焼き1|5|5|0|
338
+ |サボテンバーガー|10|10|0|
339
+ |サボテン焼き7|15|15|0|
340
+
341
+ ### 引数3つ
342
+ 攻撃,物防,魔防の強化値を,この順で直接整数で指定します.任意の強化値を指定できますが,強化値は別で調べておく必要があります.
343
+ 以下の料理については,作成できる最小料理Lvで作成したときの強化値は表の通りで,これらはプリセットとして,料理名のみを引数として指定できます.
344
+ これらの料理名については,エイリアスとして,「(主食材)の(副食材)(焼き|蒸し)」の形式も受け付けます.
345
+
346
+ |料理名|料理Lv|攻撃|物防|魔防|
347
+ |:-|-:|-:|-:|-:|
348
+ |獣肉とカエン酒の丸焼き|0|8|0|0|
349
+ |ウッチと氷酒の蒸し焼き|0|0|11|10|
350
+ |ウッチとカエン酒の蒸し焼き|0|0|10|11|
351
+ |ゴッチと氷酒の蒸し焼き|3|0|15|13|
352
+ |ゴッチとカエン酒の蒸し焼き|3|0|13|15|
353
+ |ガガッチと氷水酒の蒸し焼き|6|0|19|15|
354
+ |ガガッチと爆炎酒の蒸し焼き|6|0|15|19|
355
+ |ガガッチと氷河酒の蒸し焼き|12|0|22|16|
356
+ |ガガッチと煉獄酒の蒸し焼き|12|0|16|22|
357
+ |ドランギョと煉獄酒の丸焼き|15|15|11|6|
358
+ |ドランギョと煉獄酒の蒸し焼き|15|9|18|15|
359
+ |ドランギョと氷河酒の蒸し焼き|15|6|24|11|
360
+ |ドラバーンと煉獄酒の丸焼き|24|23|17|9|
361
+ |ドラバーンと煉獄酒の蒸し焼き|24|14|26|25|
362
+ |ドラバーンと氷河酒の蒸し焼き|24|10|35|19|
363
+ |フレドランと煉獄酒の丸焼き|27|59|0|0|
364
+ |ダークドンと煉獄酒の丸焼き|27|35|26|21|
365
+ |ダークドンと氷河酒の丸焼き|27|26|35|15|
366
+ |ダークドンと煉獄酒の蒸し焼き|27|21|38|52|
367
+ |ダークドンと氷河酒の蒸し焼き|27|15|52|38|
368
+ |アースドランと氷河酒の蒸し焼き|27|0|87|0|
369
+ |アクアドランと煉獄酒の蒸し焼き|27|0|0|87|
370
+
371
+ ### 引数4つ
372
+ 調理法,主食材,副食材,料理Lvを指定し,対応する料理の効果の**概算値**を計算します.計算式は [Wikiの記述](https://wikiwiki.jp/guruguru/%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0/%E9%A3%9F%E7%B3%A7%E5%93%81#y1576f2d) に基づきますが,正確ではないことがわかっています.例えば,`('蒸す', 'アースドラン', '氷河酒', 27)`の物防は87ですが,この計算式では88になります.調理法,主食材,副食材は文字列で,料理Lvは整数で指定します.
373
+
374
+ 調理法は「焼き」か「蒸す」,主食材は「獣肉」「ウッチ」「ゴッチ」「ガガッチ」「ドランギョ」「ドラバーン」「フレドラン」「アースドラン」「アクアドラン」「ダークドン」,副食材は「氷酒」「氷水酒」「氷河酒」「カエン酒」「爆炎酒」「煉獄酒」のみ対応しています.攻撃,物防,魔防の強化を考える場合,これらで十分と判断しての選択となっています.なお,副食材の数値は,Wikiの表で順番が間違っていると思われる部分を修正しています.
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.1
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - KAZOON
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-06 00:00:00.000000000 Z
11
+ date: 2022-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,10 +69,12 @@ files:
69
69
  - bin/setup
70
70
  - lib/mgmg.rb
71
71
  - lib/mgmg/const.rb
72
+ - lib/mgmg/cuisine.rb
72
73
  - lib/mgmg/equip.rb
73
74
  - lib/mgmg/ir.rb
74
75
  - lib/mgmg/optimize.rb
75
76
  - lib/mgmg/poly.rb
77
+ - lib/mgmg/reinforce.rb
76
78
  - lib/mgmg/search.rb
77
79
  - lib/mgmg/system_equip.rb
78
80
  - lib/mgmg/utils.rb
@@ -100,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
100
102
  - !ruby/object:Gem::Version
101
103
  version: '0'
102
104
  requirements: []
103
- rubygems_version: 3.3.4
105
+ rubygems_version: 3.3.15
104
106
  signing_key:
105
107
  specification_version: 4
106
108
  summary: Calculate specs of equipments of Megurimeguru, a game produced by Kou.