mgmg 1.4.1 → 1.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fa07550bf3367d160e4915d65e592b2295667cfb56284543f8cf43c2a92c375d
4
- data.tar.gz: 062c07e9c53d9b4ffb20332b7f9365727cbad46e93d83be49d4592ec4cae8a17
3
+ metadata.gz: d7cadbd5fef7941e004310c08f8ec597ce06381b0b305369d0e42afa08cb5016
4
+ data.tar.gz: a0d9d53d2e0284274e4558c7d27f26aeb2af6eb2649faaa07d840a5cd4f5aed8
5
5
  SHA512:
6
- metadata.gz: 1272f84d6fb42b63dc4c6e2180552f16311a9f8d65b392a2b0628e882ac7e6854d65a13e3f42549507c91bd2cdb190b1c295c514a982c64f77678cd21017cd7e
7
- data.tar.gz: 9792b236879eb2ffb01e2f25389647b235a4a2328a6a4446b8c2636b738a849ee047201c5998cbf2098799c686e0fc4bb9d803a0b52ddaa0866139e19aa9a0a1
6
+ metadata.gz: fe3d521ee8e90ae3253dacf5389035a53e40d58d0a9e574c0685d346765fdef35de371412d772b77476809cf80a2bb384e1e0b20c0ada8c265f6155ad27fcf3a
7
+ data.tar.gz: 77638a9c41f22fa7a509f409645307d2a452822bd557aa83e5d0c8e96ac8e84c93f6d9fd3df265a04dc1e91abde3f143561f410c6b397a89fe599a0ee2dcc8f7
data/CHANGELOG.md CHANGED
@@ -115,3 +115,26 @@
115
115
  - `Mgmg.#find_lowerbound`, `Mgmg.#find_upperbound`を追加.
116
116
  - 魔法の威力に対応する`Mgmg::Equip#magic2`を追加.
117
117
  - `String#min_levels`およびその関連メソッドにおいて,重量1以外を指定できるようにした.
118
+
119
+ ## 1.4.2 2022/06/09
120
+ - `Mgmg::Equip#reinforce`および`Mgmg::IR`を使うメソッド群に`reinforcement`キーワード引数を追加.
121
+ - スキルおよび料理による強化効果をシミュレートできるようになった.
122
+ - 料理については,プリセット料理名または`Mgmg.#cuisine`で生成される`Mgmg::Cuisine`オブジェクトを使う.
123
+
124
+ ## 1.5.0 2022/06/22
125
+ - `Mgmg::Option`を実装し,search系メソッドを中心としたキーワード引数を,このクラスに集約してから受け渡すようにした.
126
+ - オプションオブジェクトは`Mgmg.#option`によって生成し,キーワード引数`opt`に渡す.従来のキーワード引数は廃止された.
127
+ - この変更で,一部の受け渡し忘れのバグが修正され,パフォーマンスが改善した.
128
+ - `Enumerable#search`で無駄な処理が発生していて,処理時間がかかっていたバグを修正.
129
+ - `String#min_level`,`Enumerable#min_level`の仕様を変更し,合成後の重量を目標値にするのに必要な鍛冶・道具製作Lvを計算するようにした.
130
+ - この変更に伴い,`Mgmg::Equip#min_level`を,`Mgmg::Equip#min_levels_max`に名称変更し,`String#min_levels_max`,`Enumerable#min_levels_max`を追加した.
131
+ - 関連して,`String#max_weight`,`String#min_weight`,`Enumerable#max_weight`,`Enumerable#min_weight`,`Enumerable#max_weights`,`Enumerable#min_weights`を追加した.
132
+ - `Mgmg::Option#smith_min`,`Mgmg::Option#armor_min`のデフォルト値を,`String#min_level`,`Enumerable#min_level`を用いて設定する仕様とし,その目標重量を`Mgmg::Option#target_weight`で指定するようにした.
133
+ - `String#min_comp`,`String#min_smith`,`Enumerable#min_comp`,`Enumerable#min_smith`において,既製品のみである,合成を行わないなど,該当スキルが必要ないレシピである場合の返り値を`-1`に変更した.
134
+
135
+ ## 1.5.1 2022/06/24
136
+ - `Mgmg::Recipe`を実装し,レシピ`String`または`Enumerable`と,注目パラメータ`Symbol`,オプション`Mgmg::Option`をセットで取り扱えるようにした.
137
+ - `String#to_recipe(para=:power, allow_over20: false, **kw)`または`Enumerable#to_recipe(para=:power, **kw)`で生成できる.
138
+ - `Mgmg::Recipe#build`,`Mgmg::Recipe#search`など`String`等に対する操作と同様にでき,注目パラメータとオプションは,`to_recipe`でセットしたものがデフォルトで使われるようになる.各メソッド呼び出し時にキーワード引数を与えることで,一時的に上書きすることもできる.
139
+ - `String#to_recipe`にのみ,☆20制限のチェック機構を導入した.
140
+ - 計算を繰り返した際,複数装備の装備数が増加していってしまうバグを修正した.
data/README.md CHANGED
@@ -22,7 +22,7 @@ Excel版に比べ,入力のチェックがなされておらず,☆制限の
22
22
 
23
23
  $ gem install mgmg
24
24
 
25
- あるいは,http://cycloawaodorin.sakura.ne.jp/sonota/mgmg/mgmg.html にてAjax版を利用することもできます.Ajax版は一部の機能しか実装されていませんが,Ruby環境がない場合にも利用できます.
25
+ あるいは,[Ajax版](http://cycloawaodorin.sakura.ne.jp/sonota/mgmg/mgmg.html) を利用することもできます.Ajax版は一部の機能しか実装されていませんが,Ruby環境がない場合にも利用できます.
26
26
 
27
27
  ## 使い方
28
28
  並列型多段合成杖を製作し,標準出力に出力する.
@@ -53,19 +53,36 @@ puts r.build(122, 139, 232)
53
53
  #=> 複数装備9(武:1, 頭:1, 飾:2)[攻撃:15, 物防:34, 魔防:28, HP:241, MP:71, 器用:223, 素早:222, 魔力:6,604]
54
54
  ```
55
55
 
56
- 重量1または2で作るのに必要な防具製作Lvを確認する.
56
+ 製作品の重量及び特定の重量にするために必要な鍛冶・防具製作Lvを確認する.
57
57
 
58
58
  ```ruby
59
- p ['重鎧(皮1010)'.min_level, '重鎧(皮10金10)'.min_level(2)]
60
- #=> [162, 42]
59
+ r = 'サンダル(骨2皮1)+[重鎧(金3金3)+[フード(骨2宝1)+[重鎧(皮10金10)+軽鎧(鉄10皮1)]]]'
60
+ p r.min_levels # 各材料装備を重量1で作るのに必要な防具製作Lv
61
+ #=> {"サンダル(骨2皮1)"=>3, "重鎧(金3金3)"=>202, "フード(骨2宝1)"=>3, "重鎧(皮10金10)"=>162, "軽鎧(鉄10皮1)"=>68}
62
+ p r.min_levels(2) # 同重量2以下
63
+ #=> {"サンダル(骨2皮1)"=>3, "重鎧(金3金3)"=>102, "フード(骨2宝1)"=>3, "重鎧(皮10金10)"=>42, "軽鎧(鉄10皮1)"=>27}
64
+ p [r.min_weight, r.max_weight] # 最小重量と最大重量
65
+ #=> [5, 10]
66
+ p r.min_level # 最小重量で作るのに必要な防具製作Lv
67
+ #=> 202
68
+ p r.min_level(7) # 重量7以下で作るのに必要な防具製作Lv
69
+ #=> 102
70
+ p r.min_level(-1) # 最小重量+1=重量6以下で作るのに必要な防具製作Lv
71
+ #=> 162
61
72
  ```
62
73
 
63
- 合成レシピから必要製作Lvを確認する.
74
+ 注目パラメータやオプションパラメータを,レシピ文字列とセットにして取り回す.
64
75
  ```ruby
65
- p '[(水玉10火玉5)+本(101)]+[本(水玉5綿2)+杖(101)]'.min_levels
66
- #=> {"杖(水玉10火玉5)"=>92, "本(骨10鉄1)"=>48, "本(水玉5綿2)"=>12, "杖(骨10鉄1)"=>28}
67
- p '[(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build.min_level
68
- #=> 92
76
+ r = '[[斧(10皮1)+剣(101)]+剣(鉄10皮1)]+剣(101)'
77
+ r = r.to_recipe(:atkstr, target_weight: 5) # 注目パラメータを攻撃力+腕力,目標重量を5に設定
78
+ p [r.min_level, r.min_level(0)] # 必要な鍛冶Lvのデフォルトが目標重量ベースに
79
+ #=> [72, 168] # 鍛冶Lv72で重量5(目標)に,鍛冶Lv168で重量4(最小)になる
80
+ puts r.build(27, 42) # 変換前と同様に合成等もできる
81
+ #=> 斧8☆20(鉄鉄)[攻撃:1,112, 腕力:18] # 鍛冶Lv27だと重量8に
82
+ p r.para_call(27, 42) # 注目パラメータのみを計算
83
+ #=> 1130 # 1112+18=1130
84
+ puts r.build(nil) # 目標重量を達成する最小製作Lvで製作
85
+ #=> 斧5☆20(鉄鉄)[攻撃:1,436, 腕力:24] # 製作Lvを nil にすると,目標重量のための最小製作Lv (72, 42) で製作
69
86
  ```
70
87
 
71
88
  近似多項式を得る.
@@ -91,7 +108,31 @@ p [sc, Mgmg.exp(*sc)]
91
108
  #=> [[155, 376], 304969]
92
109
  ```
93
110
 
94
- 各メソッドの詳しい説明等は[リファレンス](./reference.md)を参照されたい.
111
+ 最小重量で製作できない鍛冶レベルを探索範囲に含める.
112
+
113
+ ```ruby
114
+ r = '双短剣(金3皮1)+[杖(水1綿1)+[斧(玉5水1)+[杖(鉄1綿1)+[[斧(木2金3)+剣(鉄10皮1)]+[剣(木2綿1)+双短剣(鉄10皮1)]]]]]'
115
+ r = r.to_recipe(:atk_sd, target_weight: 9)
116
+ sc = r.search(2000) # to_recipe で注目パラメータを入れているので,ここでは不要
117
+ p [sc, Mgmg.exp(*sc)]
118
+ #=> [[70, 130], 38046] # オプションなしの場合は鍛冶Lv100以上を探索するため,[[100, 126], 41054] になる
119
+ ```
120
+
121
+ 探索の際,スキル及び料理を考慮する.
122
+
123
+ ```ruby
124
+ r = '重鎧(皮2綿1)+[帽子(宝1宝1)+[重鎧(玉5金3)+[帽子(宝1宝1)+[重鎧(玉5金6)+[軽鎧(金3骨1)+[重鎧(皮2骨1)+軽鎧(鉄10綿1)]]]]]]'
125
+ r = r.to_recipe(:phydef, buff: %w|物防御UP アースドランと氷河酒の蒸し焼き ガードアップ|)
126
+ sc = r.search(100_000)
127
+ p [sc, Mgmg.exp(*sc)]
128
+ #=> [[120, 264], 152502]
129
+ puts r.build(*sc) # 実際に作って確認
130
+ #=> 重鎧8☆20(綿宝)[物防:100,396.0, 魔防:4]
131
+ puts r.build(*sc, buff: []) # 一時的に強化を解除して素の性能を確認
132
+ #=> 重鎧8☆20(綿宝)[物防:32,538, 魔防:4]
133
+ ```
134
+
135
+ 各メソッドの詳しい説明等は [リファレンス](./reference.md) を参照されたい.
95
136
 
96
137
  ### 表記ゆれについて
97
138
  本ゲームでは,装備種別の名称に,下記の表のような表記ゆれが存在します.
@@ -0,0 +1,140 @@
1
+ module Mgmg
2
+ using Refiner
3
+ class Cuisine
4
+ def initialize(vec)
5
+ @vec = vec
6
+ end
7
+ attr_accessor :vec
8
+ def initialize_copy(other)
9
+ @vec = other.vec.dup
10
+ end
11
+
12
+ def attack
13
+ @vec[0]
14
+ end
15
+ def phydef
16
+ @vec[1]
17
+ end
18
+ def magdef
19
+ @vec[2]
20
+ end
21
+ def to_s
22
+ "料理[攻撃:#{self.attack}, 物防:#{self.phydef}, 魔防:#{self.magdef}]"
23
+ end
24
+ alias :inspect :to_s
25
+ end
26
+
27
+ SystemCuisine = {
28
+ '焼き肉' => Cuisine.new( Vec[ 5, 0, 0] ), # ☆1
29
+ '焼き金肉' => Cuisine.new( Vec[10, 0, 0] ), # ☆3
30
+ '焼き黄金肉' => Cuisine.new( Vec[15, 0, 0] ), # ☆5
31
+ '焼きリンゴ' => Cuisine.new( Vec[ 0, 5, 0] ), # ☆1
32
+ '焼きイチゴ' => Cuisine.new( Vec[ 0, 10, 0] ), # ☆3
33
+ '焼きネギタマ' => Cuisine.new( Vec[ 0, 15, 0] ), # ☆5
34
+ 'サボテン焼き1' => Cuisine.new( Vec[ 5, 5, 0] ), # ☆1
35
+ 'サボテンバーガー' => Cuisine.new( Vec[10, 10, 0] ), # ☆3
36
+ 'サボテン焼き7' => Cuisine.new( Vec[15, 15, 0] ), # ☆7
37
+ '獣肉とカエン酒の丸焼き' => Cuisine.new( Vec[ 8, 0, 0] ), # 料理Lv0
38
+ 'ドランギョと煉獄酒の丸焼き' => Cuisine.new( Vec[15, 11, 6] ), # 料理Lv15
39
+ 'ドラバーンと煉獄酒の丸焼き' => Cuisine.new( Vec[23, 17, 9] ), # 料理Lv24
40
+ 'フレドランと煉獄酒の丸焼き' => Cuisine.new( Vec[59, 0, 0] ), # 料理Lv27
41
+ 'ダークドンと煉獄酒の丸焼き' => Cuisine.new( Vec[35, 26, 21] ), # 料理Lv27
42
+ 'ダークドンと氷河酒の丸焼き' => Cuisine.new( Vec[26, 35, 15] ), # 料理Lv27
43
+ 'ウッチと氷酒の蒸し焼き' => Cuisine.new( Vec[ 0, 11, 10] ), # 料理Lv0
44
+ 'ゴッチと氷酒の蒸し焼き' => Cuisine.new( Vec[ 0, 15, 13] ), # 料理Lv3
45
+ 'ガガッチと氷水酒の蒸し焼き' => Cuisine.new( Vec[ 0, 19, 15] ), # 料理Lv6
46
+ 'ガガッチと氷河酒の蒸し焼き' => Cuisine.new( Vec[ 0, 22, 16] ), # 料理Lv12
47
+ 'ドランギョと氷河酒の蒸し焼き' => Cuisine.new( Vec[ 6, 24, 11] ), # 料理Lv15
48
+ 'ドラバーンと氷河酒の蒸し焼き' => Cuisine.new( Vec[10, 35, 19] ), # 料理Lv24
49
+ 'アースドランと氷河酒の蒸し焼き' => Cuisine.new( Vec[ 0, 87, 0] ), # 料理Lv27
50
+ 'ダークドンと氷河酒の蒸し焼き' => Cuisine.new( Vec[15, 52, 38] ), # 料理Lv27
51
+ 'ダークドンと煉獄酒の蒸し焼き' => Cuisine.new( Vec[15, 52, 38] ), # 料理Lv27
52
+ 'ウッチとカエン酒の蒸し焼き' => Cuisine.new( Vec[ 0, 10, 11] ), # 料理Lv0
53
+ 'ゴッチとカエン酒の蒸し焼き' => Cuisine.new( Vec[ 0, 13, 15] ), # 料理Lv3
54
+ 'ガガッチと爆炎酒の蒸し焼き' => Cuisine.new( Vec[ 0, 15, 19] ), # 料理Lv6
55
+ 'ガガッチと煉獄酒の蒸し焼き' => Cuisine.new( Vec[ 0, 16, 22] ), # 料理Lv12
56
+ 'ドランギョと煉獄酒の蒸し焼き' => Cuisine.new( Vec[ 9, 18, 15] ), # 料理Lv15
57
+ 'ドラバーンと煉獄酒の蒸し焼き' => Cuisine.new( Vec[14, 26, 25] ), # 料理Lv24
58
+ 'アクアドランと煉獄酒の蒸し焼き' => Cuisine.new( Vec[ 0, 0, 87] ), # 料理Lv27
59
+ }
60
+ SystemCuisine.keys.each do |k|
61
+ ary = k.scan(%r|(.+)と(.+)の(.+)|)[0]
62
+ if ary
63
+ c = case ary[2]
64
+ when '丸焼き'
65
+ '焼き'
66
+ when '蒸し焼き'
67
+ '蒸し'
68
+ else
69
+ raise UnexpectedError
70
+ end
71
+ SystemCuisine.store("#{ary[0]}の#{ary[1]}#{c}", SystemCuisine[k])
72
+ end
73
+ end
74
+
75
+ MainFood = {
76
+ '獣肉' => Vec[10, 0, 0],
77
+ 'ウッチ' => Vec[ 0, 10, 10],
78
+ 'ゴッチ' => Vec[ 0, 12, 12],
79
+ 'ガガッチ' => Vec[ 0, 14, 14],
80
+ 'ドランギョ' => Vec[15, 15, 10],
81
+ 'ドラバーン' => Vec[20, 20, 15],
82
+ 'フレドラン' => Vec[50, 0, 0],
83
+ 'アースドラン' => Vec[ 0, 50, 0],
84
+ 'アクアドラン' => Vec[ 0, 0, 50],
85
+ 'ダークドン' => Vec[30, 30, 30],
86
+ }
87
+ SubFood = {
88
+ '氷酒' => Vec[ 50, 70, 50],
89
+ '氷水酒' => Vec[ 50, 90, 50],
90
+ '氷河酒' => Vec[ 50, 110, 50],
91
+ 'カエン酒' => Vec[ 70, 50, 70],
92
+ '爆炎酒' => Vec[ 90, 50, 90],
93
+ '煉獄酒' => Vec[110, 50, 110],
94
+ }
95
+ Cookery = {
96
+ '焼き' => Vec[50, 50, 30],
97
+ '蒸す' => Vec[30, 75, 75],
98
+ }
99
+ Cookery.store('丸焼き', Cookery['焼き'])
100
+ Cookery.store('すき焼き', Cookery['焼き'])
101
+ Cookery.store('焼く', Cookery['焼き'])
102
+ Cookery.store('焼', Cookery['焼き'])
103
+ Cookery.store('蒸し焼き', Cookery['蒸す'])
104
+ Cookery.store('ボイル', Cookery['蒸す'])
105
+ Cookery.store('蒸し', Cookery['蒸す'])
106
+ Cookery.store('蒸', Cookery['蒸す'])
107
+
108
+ class << Cuisine
109
+ def cook(cookery_s, main_s, sub_s, level)
110
+ begin
111
+ c = Cookery[cookery_s]
112
+ m = MainFood[main_s]
113
+ s = SubFood[sub_s]
114
+ v = Vec[1, 1, 1]
115
+ v.e_mul!(m).e_mul!(c).e_mul!(s.dup.add!(100+level)).e_div!(10000)
116
+ new(v)
117
+ rescue
118
+ arg = [cookery_s, main_s, sub_s, level].inspect
119
+ raise ArgumentError, "Some of arguments for cooking seems to be wrong. #{arg} is given, but they should be [cookery (String), main food (String), sub food (String), cooking level (Integer)]. Not all of cookeries and foods are supported."
120
+ end
121
+ end
122
+ end
123
+
124
+ module_function def cuisine(*arg)
125
+ case arg.size
126
+ when 3
127
+ if arg.all?{ |e| e.kind_of?(Integer) } then
128
+ Cuisine.new( Vec[*arg] )
129
+ else
130
+ raise ArgumentError, "All the cuisine parameters must be Integer."
131
+ end
132
+ when 1
133
+ SystemCuisine[arg[0]] or raise ArgumentError, "The cuisine name `#{arg[0]}' is not supported."
134
+ when 4
135
+ Cuisine.cook(*arg)
136
+ else
137
+ raise ArgumentError, 'The number of argument must be 1, 3 or 4.'
138
+ end
139
+ end
140
+ end
data/lib/mgmg/equip.rb CHANGED
@@ -13,7 +13,7 @@ module Mgmg
13
13
  def initialize_copy(other)
14
14
  @kind = other.kind
15
15
  @weight = other.weight
16
- @star = other.star
16
+ @star = other.star.dup
17
17
  @main = other.main
18
18
  @sub = other.sub
19
19
  @para = other.para.dup
@@ -57,15 +57,15 @@ module Mgmg
57
57
  @min_levels
58
58
  else
59
59
  @min_levels.map do |key, value|
60
- [key, key.min_level(w)]
60
+ [key, Equip.min_level(key, w)]
61
61
  end.to_h
62
62
  end
63
63
  end
64
- def min_level(w=1)
64
+ def min_levels_max(w=1)
65
65
  if @kind == 28
66
- ret = [0, 0]
66
+ ret = [-1, -1]
67
67
  min_levels(w).each do |str, ml|
68
- if str.build(-1).kind < 8
68
+ if str.build.kind < 8
69
69
  if ret[0] < ml
70
70
  ret[0] = ml
71
71
  end
@@ -77,7 +77,7 @@ module Mgmg
77
77
  end
78
78
  ret
79
79
  else
80
- min_levels(w).values.append(0).max
80
+ min_levels(w).values.append(-1).max
81
81
  end
82
82
  end
83
83
 
@@ -193,15 +193,9 @@ module Mgmg
193
193
  def +(other)
194
194
  self.dup.add!(other)
195
195
  end
196
- def coerce(other)
197
- if other == 0
198
- zero = self.class.new(28, 0, Vec.new(6, 0), 12, 12, Vec.new(9, 0), Vec.new(3, 0))
199
- zero.history.clear
200
- [zero, self]
201
- else
202
- raise TypeError, "Mgmg::Equip can't be coerced into other than 0"
203
- end
204
- end
196
+ Zero = self.new(28, 0, Vec.new(6, 0).freeze, 12, 12, Vec.new(9, 0).freeze, Vec.new(3, 0).freeze)
197
+ Zero.total_cost.freeze; Zero.history.clear.freeze
198
+ Zero.freeze
205
199
  end
206
200
 
207
201
  class << Equip
@@ -212,7 +206,7 @@ module Mgmg
212
206
  end
213
207
  private def build_sub0(stack, str)
214
208
  SystemEquip.each do |k, v|
215
- if Regexp.compile(k).match(str)
209
+ if SystemEquipRegexp[k].match(str)
216
210
  stack << v
217
211
  str = str.gsub(k, "<#{stack.length-1}>")
218
212
  end
@@ -305,7 +299,7 @@ module Mgmg
305
299
 
306
300
  ret = new(kind, ( weight<1 ? 1 : weight ), (main_s+sub_s).div(2), main_mc, sub_mc, para, ele)
307
301
  ret.total_cost[kind < 8 ? 0 : 2] += ret.smith_cost(outsourcing)
308
- ret.min_levels.store(str, str.min_level)
302
+ ret.min_levels.store(str, Equip.min_level(str))
309
303
  ret
310
304
  end
311
305
 
@@ -323,14 +317,14 @@ module Mgmg
323
317
  [(main_s-1)*3, (sub_s-1)*3, l].max
324
318
  end
325
319
 
326
- def min_comp(str, left_associative: true)
320
+ def min_comp(str, opt: Option.new)
327
321
  str = Mgmg.check_string(str)
328
322
  stack, str = minc_sub0([], str)
329
- (minc_sub(stack, str, left_associative)[1]-1)*3
323
+ (minc_sub(stack, str, opt.left_associative)[1]-1)*3
330
324
  end
331
325
  private def minc_sub0(stack, str)
332
326
  SystemEquip.each do |k, v|
333
- if Regexp.compile(k).match(str)
327
+ if SystemEquipRegexp[k].match(str)
334
328
  stack << v.star
335
329
  str = str.gsub(k, "<#{stack.length-1}>")
336
330
  end
@@ -352,14 +346,15 @@ module Mgmg
352
346
  end
353
347
  end
354
348
 
355
- def min_smith(str, left_associative: true)
349
+ def min_smith(str, opt: Option.new)
356
350
  str = Mgmg.check_string(str)
357
351
  stack, str = mins_sub0([], str)
358
- (([mins_sub(stack, str, left_associative)]+stack).max-1)*3
352
+ ret = (([mins_sub(stack, str, opt.left_associative)]+stack).max-1)*3
353
+ ret < 0 ? -1 : ret
359
354
  end
360
355
  private def mins_sub0(stack, str)
361
356
  SystemEquip.each do |k, v|
362
- if Regexp.compile(k).match(str)
357
+ if SystemEquipRegexp[k].match(str)
363
358
  stack << 0
364
359
  str = str.gsub(k, "<#{stack.length-1}>")
365
360
  end
@@ -373,7 +368,7 @@ module Mgmg
373
368
  elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
374
369
  [mins_sub(stack, m[1], lassoc), mins_sub(stack, m[2], lassoc)].max
375
370
  elsif m = /\A\<(\d+)\>\Z/.match(str)
376
- 1
371
+ 0
377
372
  else
378
373
  mins_sub2(str)
379
374
  end