mgmg 1.2.5 → 1.3.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 +7 -0
- data/README.md +55 -11
- data/lib/mgmg.rb +64 -4
- data/lib/mgmg/equip.rb +70 -1
- data/lib/mgmg/poly.rb +9 -0
- data/lib/mgmg/utils.rb +4 -0
- data/lib/mgmg/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 48ad2b791e601abcf8108fcfceabed64d97b5beeb949e3b409fcb0ef7de148ed
|
|
4
|
+
data.tar.gz: 2154c226324c09f202a660bef0b344c3ee57a792dc14e889a9caedb79e5adfb8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a40d7b79dd7666a8fc1aa3985bd79f074d80f26ddd28b3c92cdef826edb28406154f3151fe1de5583a4ec3139d6710f71390f7fa60e1c896f2d9452f3dd00b70
|
|
7
|
+
data.tar.gz: cf7c8fe93611cad843f0bca7da77f02c24fbe5f7c2b932741f8ce94c80b73df1f355501521b6aabad99a17670d1649f5c7637721974bd096b6eb70726825d0b7
|
data/CHANGELOG.md
CHANGED
|
@@ -80,3 +80,10 @@
|
|
|
80
80
|
- `Mgmg::TPolynomial#leading(fmt=nil)`, `Mgmg::TPolynomial#[](i, j)`を追加.
|
|
81
81
|
- `Mgmg::Equip#history`, `Mgmg::Equip#min_levels`, `Mgmg::Equip#min_level`を追加.
|
|
82
82
|
- ソースコードのファイル配置を整理.
|
|
83
|
+
|
|
84
|
+
## 1.3.0 2020/08/26
|
|
85
|
+
- 既製品に対する`Mgmg::Equip#min_level`の返り値を`nil`から`0`に変更.
|
|
86
|
+
- `String#build`において,第1引数にもデフォルト値`-1`を設定し,引数なしで委託製作相当とするように変更.
|
|
87
|
+
- `String#poly`のデフォルト引数を`:cost`に設定.
|
|
88
|
+
- `Mgmg.#exp`,`String#eff`,`String#peff`,`String#min_levels`を追加.
|
|
89
|
+
- `String#smith_search`, `String#comp_search`, `String#min_smith`, `String#min_comp`を追加.
|
data/README.md
CHANGED
|
@@ -35,17 +35,26 @@ puts '[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.b
|
|
|
35
35
|
複数装備を製作し,そのすべてを装備した場合の合計値を標準出力に出力.
|
|
36
36
|
|
|
37
37
|
```ruby
|
|
38
|
-
|
|
38
|
+
ary = %w|本(金3骨1)+[弓(骨1綿1)+[杖(金3金3)+[弓(綿1綿1)+[杖(宝10金6)+本(骨9鉄2)]]]] フード(石10骨9) 首飾り(宝10水10) 指輪(木10金10)|
|
|
39
|
+
puts ary.build(122, 139, 232)
|
|
39
40
|
#=> 複数装備9(武:1, 頭:1, 飾:2)[攻撃:15, 物防:34, 魔防:28, HP:241, MP:71, 器用:223, 素早:222, 魔力:6,604]
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
重量1または2で作るのに必要な防具製作Lv
|
|
43
|
+
重量1または2で作るのに必要な防具製作Lvを確認.
|
|
43
44
|
|
|
44
45
|
```ruby
|
|
45
46
|
p ['重鎧(皮10金10)'.min_level, '重鎧(皮10金10)'.min_level(2)]
|
|
46
47
|
#=> [162, 42]
|
|
47
48
|
```
|
|
48
49
|
|
|
50
|
+
合成レシピから必要製作Lvを確認.
|
|
51
|
+
```ruby
|
|
52
|
+
p '[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.min_levels
|
|
53
|
+
#=> {"杖(水玉10火玉5)"=>92, "本(骨10鉄1)"=>48, "本(水玉5綿2)"=>12, "杖(骨10鉄1)"=>28}
|
|
54
|
+
p '[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build.min_level
|
|
55
|
+
#=> 92
|
|
56
|
+
```
|
|
57
|
+
|
|
49
58
|
近似多項式を得る.
|
|
50
59
|
|
|
51
60
|
```ruby
|
|
@@ -56,7 +65,7 @@ puts '[斧(牙10金10)+剣(鉄10皮1)]+剣(鉄10皮1)'.poly(:attack).to_s('%.4g'
|
|
|
56
65
|
既成品の性能を確認.
|
|
57
66
|
|
|
58
67
|
```ruby
|
|
59
|
-
puts '小竜咆哮'.build
|
|
68
|
+
puts '小竜咆哮'.build
|
|
60
69
|
#=> 弓1☆10(木骨)[攻撃:50, 器用:120, 素早:50]
|
|
61
70
|
```
|
|
62
71
|
|
|
@@ -78,26 +87,36 @@ puts '小竜咆哮'.build(-1)
|
|
|
78
87
|
## リファレンス
|
|
79
88
|
本ライブラリで定義される主要なメソッドを以下に解説します.
|
|
80
89
|
|
|
81
|
-
### `String#build(smith, comp=smith, left_associative: true)`
|
|
90
|
+
### `String#build(smith=-1, comp=smith, left_associative: true)`
|
|
82
91
|
レシピ文字列である`self`を解釈し,鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として鍛冶・防具製作及び武器・防具合成を行った結果を後述の`Mgmg::Equip`クラスのインスタンスとして生成し,返します.例えば,
|
|
83
92
|
```ruby
|
|
84
93
|
'[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build(112, 176)
|
|
85
94
|
```
|
|
86
95
|
のようにします.基本的に`[]`による合成順序の指定が必要ですが,不確定の場合,`left_associative`が真なら左結合,偽なら右結合として解釈します.
|
|
87
96
|
```ruby
|
|
88
|
-
'
|
|
97
|
+
'法衣(綿10皮10)+歴戦の服'
|
|
89
98
|
```
|
|
90
99
|
のように,既成品を含む合成レシピも解釈します.キャラクリ初期装備の劣悪な服,劣悪な小手以外のあらゆる装備を網羅しています.劣悪な服,劣悪な小手はキャラクリ以外での初期装備品として解釈します.`comp`を省略した場合,`smith`と同じ値として処理します.
|
|
91
100
|
|
|
92
101
|
`self`が解釈不能な場合,例外が発生します.また,製作Lvや完成品の☆制限のチェックを行っていないほか,本ライブラリでは`武器+防具`や`防具+武器`の合成も可能になっています.街の鍛冶・防具製作・道具製作屋に任せた場合をシミュレートする場合は製作Lvを負の値(`-1`など,負であれば何でもよい)にします(製作Lv0相当の性能を計算し,消費エレメント量は委託仕様となります).
|
|
93
102
|
|
|
103
|
+
### `Enumerable#build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)`
|
|
104
|
+
複数のレシピ文字列からなる`self`の各要素を製作し,そのすべてを装備したときの`Mgmg::Equip`を返します.製作では`鍛冶Lv=smith`, `防具製作Lv=armor`, `道具製作Lv=comp`とします.1つしか指定しなければすべてそのLv,2つなら1つ目を`smith=armor`,2つ目を`comp`に,3つならそれぞれの値とします.`left_associative`はそのまま`String#build`に渡されます.製作Lvが負の場合,製作Lv0として計算した上で,消費エレメント量は街の製作屋に頼んだ場合の値を計算します.武器複数など,同時装備が不可能な場合でも,特にチェックはされません.
|
|
105
|
+
|
|
94
106
|
### `String#min_level(weight=1)`
|
|
95
|
-
`self`を`weight`以下で作るための最低製作Lvを返します.`build`と異なり,合成や既成品は解釈できません.また,素材の☆による最低製作Lvとのmaxを返すため,街の鍛冶・防具製作屋に頼んだ場合の重量は`self.build
|
|
107
|
+
`self`を`weight`以下で作るための最低製作Lvを返します.`build`と異なり,合成や既成品は解釈できません.また,素材の☆による最低製作Lvとのmaxを返すため,街の鍛冶・防具製作屋に頼んだ場合の重量は`self.build.weight`で確認する必要があります.`weight`を省略した場合,重量1となる製作Lvを返します.
|
|
96
108
|
|
|
97
|
-
### `
|
|
98
|
-
|
|
109
|
+
### `String#min_levels(left_associative: true)`
|
|
110
|
+
合成レシピの各鍛冶・防具製作品に対して,レシピ文字列をキー,重量1で作製するために必要な製作Lvを値とした`Hash`を返します.重量1以外は指定できません.
|
|
111
|
+
最大値は,`self.build.min_level`によって得られます.
|
|
112
|
+
|
|
113
|
+
### `String#min_comp(left_associative: true)`
|
|
114
|
+
レシピ通りに合成するのに必要な道具製作Lvを返します.ただし,全体が「[]」で囲われているか,非合成レシピの場合,代わりに`0`を返します.
|
|
99
115
|
|
|
100
|
-
### `String#
|
|
116
|
+
### `String#min_smith(left_associative: true)`
|
|
117
|
+
レシピ通りに製作するのに必要な鍛冶・防具製作Lvを返します.製作物の重量については考慮せず,鍛冶・防具製作に必要な☆条件を満たすために必要な製作Lvを返します.
|
|
118
|
+
|
|
119
|
+
### `String#poly(para=:cost, left_associative: true)`
|
|
101
120
|
レシピ文字列である`self`を解釈し,`para`で指定した9パラ値について,丸めを無視した鍛冶・防具製作Lvと道具製作Lvの2変数からなる多項式関数を示す`Mgmg::TPolynomial`クラスのインスタンスを生成し,返します.`para`は次のシンボルのいずれかを指定します.
|
|
102
121
|
```ruby
|
|
103
122
|
:attack, :phydef, :magdef, :hp, :mp, :str, :dex, :speed, :magic
|
|
@@ -112,6 +131,27 @@ puts '小竜咆哮'.build(-1)
|
|
|
112
131
|
|
|
113
132
|
また,`:cost`を渡すことで,消費エレメント量に関する近似多項式を得られます.`self`に`"+"`が含まれていれば合成品とみなし,最後の合成に必要な地エレメント量を,それ以外では,武器なら消費火エレメント量を,防具なら消費水エレメント量を返します.ただし,`self`が既成品そのものの場合,零多項式を返します.
|
|
114
133
|
|
|
134
|
+
### `String#smith_seach(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true)`
|
|
135
|
+
`para`の値が`target`以上となるのに必要な最小の鍛冶・防具製作Lvを二分探索で探索して返します.
|
|
136
|
+
道具製作Lvは`comp`で固定,鍛冶・防具製作Lvを`smith_min`と`smith_max`で挟み込んで探索します.
|
|
137
|
+
`smith_min`が`nil`のとき,最小重量で製作するのに必要な鍛冶・防具製作Lv (`self.build.min_level`)を使用します.
|
|
138
|
+
重量を無視して,製作に必要な最小Lvである`self.min_smith`まで探索したい場合,明示的に指定します.
|
|
139
|
+
`smith_min<smith_max`でないとき,`smith_max`で`para`が`target`以上でないときは`ArgumentError`となります.
|
|
140
|
+
`para`は,`Mgmg::Equip`のメソッド名をシンボルで指定(`:power, :fpower`も可)します.
|
|
141
|
+
反転などの影響で,探索範囲において`para`の値が(広義)単調増加になっていない場合,正しい結果を返しません.
|
|
142
|
+
|
|
143
|
+
### `String#comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true)`
|
|
144
|
+
`String#smith_seach`とは逆に,鍛冶・防具製作Lvを固定して最小の道具製作Lvを探索します.
|
|
145
|
+
`comp_min`が`nil`のときは,製作に必要な最小の道具製作Lv (`self.min_comp`)を使用します.
|
|
146
|
+
その他は`String#smith_seach`と同様です.
|
|
147
|
+
|
|
148
|
+
### `String#eff(para, smith, comp=smith, left_associative: true)`
|
|
149
|
+
[`smith`を1上げたときの`para`値/(`smith`を1上げるのに必要な経験値), `comp`を1上げたときの`para`値/(`comp`を2上げるのに必要な経験値)]を返します.
|
|
150
|
+
`para`は,`Mgmg::Equip`のメソッド名をシンボルで指定(`:power, :fpower`も可)します.
|
|
151
|
+
|
|
152
|
+
### `String#peff(para, smith, comp=smith, left_associative: true)`
|
|
153
|
+
近似多項式における偏微分値を使用した場合の,`String#eff`と同様の値を返します.`self.poly(para, left_associative: left_associative).eff(smith, comp)`と等価です.
|
|
154
|
+
|
|
115
155
|
### `Mgmg::Equip`
|
|
116
156
|
前述の`String#build`によって生成される装備品のクラスです.複数装備の合計値を表す「複数装備」という種別の装備品の場合もあります.以下のようなインスタンスメソッドが定義されています.
|
|
117
157
|
|
|
@@ -222,10 +262,10 @@ ver2.00β12以降では武器なら火,防具なら水エレメントと半々
|
|
|
222
262
|
`Mgmg::TPolynomial#to_s`と同様ですが,鍛冶・防具製作Lvを`s`,道具製作Lvを`c`としたRubyの式として解釈可能な文字列を返します.つまり,係数をリテラル,掛け算を`*`で表現しています.`fmt`は`Mgmg::TPolynomial#to_s`と同様で,適当な値を指定することでRuby以外の言語でも解釈可能になります.例えば,精度が問題でないならば,`'%e'`とすると,大抵の言語で解釈可能な文字列を生成できます.
|
|
223
263
|
|
|
224
264
|
### `Mgmg::TPolynomial#leading(fmt=nil)`
|
|
225
|
-
最高次係数を返します.`fmt`が`nil`なら数値(`Rational`)をそのまま,それ以外なら`Mgmg::TPolynomial#to_s
|
|
265
|
+
最高次係数を返します.`fmt`が`nil`なら数値(`Rational`)をそのまま,それ以外なら`Mgmg::TPolynomial#to_s`と同様の方式で文字列に変換して返します.ただし,レシピの段数に応じた最高次数を返すため,レシピ次第では本メソッドの返り値が`0`となり,それより低い次数の項が最高次となることもあり得ます.そのようなケースでの真の最高次の探索はしません.
|
|
226
266
|
|
|
227
267
|
### `Mgmg::TPolynomial#[](i, j)`
|
|
228
|
-
鍛冶・防具製作Lvを
|
|
268
|
+
鍛冶・防具製作Lvをs,道具製作Lvをcとして,s<sup>i</sup>c<sup>j</sup> の係数を返します.負の値を指定すると,最高次から降順に数えた次数の項の係数を返します.例えば`i, j = -1, -1`なら,最高次の係数となります.引数が正で範囲外なら`0`を返し,負で範囲外なら`IndexError`を上げます.
|
|
229
269
|
|
|
230
270
|
### `Mgmg::TPolynomial#evaluate(smith, comp=smith)`
|
|
231
271
|
鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として値を計算します.丸めを無視しているため,実際の合成結果以上の値が返ります.
|
|
@@ -245,6 +285,10 @@ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`s
|
|
|
245
285
|
多項式として偏微分し,その微分係数を返します.
|
|
246
286
|
`variable`はどの変数で偏微分するかを指定するもので,`"s"`なら鍛冶・防具製作Lv,`"c"`なら道具製作Lvで偏微分します.
|
|
247
287
|
|
|
288
|
+
### `Mgmg::TPolynomial#eff(smith, comp=smith)`
|
|
289
|
+
製作Lv(`smith`, `comp`)における鍛冶・防具製作Lv効率と道具製作Lv効率からなる配列を返します.
|
|
290
|
+
一方のみが欲しい場合,`Mgmg::TPolynomial#smith_eff(smith, comp=smith)`,`Mgmg::TPolynomial#smith_eff(smith, comp=smith)`が使えます.
|
|
291
|
+
|
|
248
292
|
## 謝辞
|
|
249
293
|
面白いゲームを作ってくださった耕様および,高精度なシミュレータを作製し,本ライブラリの作製を可能とした,Excel版装備計算機の作者様に感謝いたします.
|
|
250
294
|
|
data/lib/mgmg.rb
CHANGED
|
@@ -9,10 +9,19 @@ class String
|
|
|
9
9
|
def min_level(w=1)
|
|
10
10
|
Mgmg::Equip.min_level(self, w)
|
|
11
11
|
end
|
|
12
|
-
def
|
|
12
|
+
def min_levels(left_associative: true)
|
|
13
|
+
build(-1, -1, left_associative: left_associative).min_levels
|
|
14
|
+
end
|
|
15
|
+
def min_smith(left_associative: true)
|
|
16
|
+
Mgmg::Equip.min_smith(self, left_associative: left_associative)
|
|
17
|
+
end
|
|
18
|
+
def min_comp(left_associative: true)
|
|
19
|
+
Mgmg::Equip.min_comp(self, left_associative: left_associative)
|
|
20
|
+
end
|
|
21
|
+
def build(smith=-1, comp=smith, left_associative: true)
|
|
13
22
|
Mgmg::Equip.build(self, smith, comp, left_associative: left_associative)
|
|
14
23
|
end
|
|
15
|
-
def poly(para, left_associative: true)
|
|
24
|
+
def poly(para=:cost, left_associative: true)
|
|
16
25
|
case para
|
|
17
26
|
when :atkstr
|
|
18
27
|
self.poly(:attack) + self.poly(:str)
|
|
@@ -39,7 +48,58 @@ class String
|
|
|
39
48
|
Mgmg::TPolynomial.build(self, para, left_associative: left_associative)
|
|
40
49
|
end
|
|
41
50
|
end
|
|
42
|
-
def
|
|
51
|
+
def eff(para, smith, comp=smith, left_associative: true)
|
|
52
|
+
a = build(smith, comp, left_associative: left_associative).method(para).call
|
|
53
|
+
b = build(smith+1, comp, left_associative: left_associative).method(para).call
|
|
54
|
+
c = build(smith, comp+2, left_associative: left_associative).method(para).call
|
|
55
|
+
sden = smith==0 ? 1 : 2*smith-1
|
|
56
|
+
cden = comp==0 ? 4 : 8*comp
|
|
57
|
+
[(b-a).quo(sden), (c-a).quo(cden)]
|
|
58
|
+
end
|
|
59
|
+
def peff(para, smith, comp=smith, left_associative: true)
|
|
60
|
+
poly(para, left_associative: left_associative).eff(smith, comp)
|
|
61
|
+
end
|
|
62
|
+
def smith_search(para, target, comp, smith_min=nil, smith_max=10000, left_associative: true)
|
|
63
|
+
smith_min = build(-1, -1, left_associative: left_associative).min_level if smith_min.nil?
|
|
64
|
+
if smith_max < smith_min
|
|
65
|
+
raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{smith_min}, #{smith_max}) are given"
|
|
66
|
+
end
|
|
67
|
+
if target <= build(smith_min, comp, left_associative: left_associative).method(para).call
|
|
68
|
+
return smith_min
|
|
69
|
+
elsif build(smith_max, comp, left_associative: left_associative).method(para).call < target
|
|
70
|
+
raise ArgumentError, "given smith_max=#{smith_max} does not satisfies the target"
|
|
71
|
+
end
|
|
72
|
+
while 1 < smith_max - smith_min do
|
|
73
|
+
smith = (smith_max - smith_min).div(2) + smith_min
|
|
74
|
+
if build(smith, comp, left_associative: left_associative).method(para).call < target
|
|
75
|
+
smith_min = smith
|
|
76
|
+
else
|
|
77
|
+
smith_max = smith
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
smith_max
|
|
81
|
+
end
|
|
82
|
+
def comp_search(para, target, smith, comp_min=nil, comp_max=10000, left_associative: true)
|
|
83
|
+
comp_min = min_comp(left_associative: left_associative)
|
|
84
|
+
if comp_max < comp_min
|
|
85
|
+
raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
|
|
86
|
+
end
|
|
87
|
+
if target <= build(smith, comp_min, left_associative: left_associative).method(para).call
|
|
88
|
+
return comp_min
|
|
89
|
+
elsif build(smith, comp_max, left_associative: left_associative).method(para).call < target
|
|
90
|
+
raise ArgumentError, "given comp_max=#{comp_max} does not satisfies the target"
|
|
91
|
+
end
|
|
92
|
+
while 1 < comp_max - comp_min do
|
|
93
|
+
comp = (comp_max - comp_min).div(2) + comp_min
|
|
94
|
+
if build(smith, comp, left_associative: left_associative).method(para).call < target
|
|
95
|
+
comp_min = comp
|
|
96
|
+
else
|
|
97
|
+
comp_max = comp
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
comp_max
|
|
101
|
+
end
|
|
102
|
+
def show(smith=-1, comp=smith, left_associative: true)
|
|
43
103
|
built = self.build(smith, comp, left_associative: left_associative)
|
|
44
104
|
pstr = '%.3f' % built.fpower
|
|
45
105
|
pstr.sub!(/\.?0+\Z/, '')
|
|
@@ -50,7 +110,7 @@ class String
|
|
|
50
110
|
end
|
|
51
111
|
end
|
|
52
112
|
module Enumerable
|
|
53
|
-
def build(smith, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)
|
|
113
|
+
def build(smith=-1, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)
|
|
54
114
|
self.map do |str|
|
|
55
115
|
m = /\A\[*([^\+]+)/.match(str)
|
|
56
116
|
if Mgmg::EquipPosition[m[1].build(0).kind] == 0
|
data/lib/mgmg/equip.rb
CHANGED
|
@@ -68,7 +68,7 @@ module Mgmg
|
|
|
68
68
|
end
|
|
69
69
|
ret
|
|
70
70
|
else
|
|
71
|
-
@min_levels.values.max
|
|
71
|
+
@min_levels.values.append(0).max
|
|
72
72
|
end
|
|
73
73
|
end
|
|
74
74
|
|
|
@@ -319,5 +319,74 @@ module Mgmg
|
|
|
319
319
|
end
|
|
320
320
|
[mat, m[1].to_i, mat<90 ? mat.div(10): 9]
|
|
321
321
|
end
|
|
322
|
+
|
|
323
|
+
def min_comp(str, left_associative: true)
|
|
324
|
+
str = Mgmg.check_string(str)
|
|
325
|
+
stack, str = minc_sub0([], str)
|
|
326
|
+
(minc_sub(stack, str, left_associative)[1]-1)*3
|
|
327
|
+
end
|
|
328
|
+
private def minc_sub0(stack, str)
|
|
329
|
+
SystemEquip.each do |k, v|
|
|
330
|
+
if Regexp.compile(k).match(str)
|
|
331
|
+
stack << v.star
|
|
332
|
+
str = str.gsub(k, "<#{stack.length-1}>")
|
|
333
|
+
end
|
|
334
|
+
end
|
|
335
|
+
[stack, str]
|
|
336
|
+
end
|
|
337
|
+
private def minc_sub(stack, str, lassoc)
|
|
338
|
+
if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
|
|
339
|
+
stack << minc_sub(stack, m[2], lassoc)[0]
|
|
340
|
+
minc_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", lassoc)
|
|
341
|
+
elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
|
|
342
|
+
a, _ = minc_sub(stack, m[1], lassoc)
|
|
343
|
+
b, _ = minc_sub(stack, m[2], lassoc)
|
|
344
|
+
[a+b, [a, b].max]
|
|
345
|
+
elsif m = /\A\<(\d+)\>\Z/.match(str)
|
|
346
|
+
[stack[m[1].to_i], 1]
|
|
347
|
+
else
|
|
348
|
+
[smith(str, 0, true).star, 1]
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def min_smith(str, left_associative: true)
|
|
353
|
+
str = Mgmg.check_string(str)
|
|
354
|
+
stack, str = mins_sub0([], str)
|
|
355
|
+
(([mins_sub(stack, str, left_associative)]+stack).max-1)*3
|
|
356
|
+
end
|
|
357
|
+
private def mins_sub0(stack, str)
|
|
358
|
+
SystemEquip.each do |k, v|
|
|
359
|
+
if Regexp.compile(k).match(str)
|
|
360
|
+
stack << 0
|
|
361
|
+
str = str.gsub(k, "<#{stack.length-1}>")
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
[stack, str]
|
|
365
|
+
end
|
|
366
|
+
private def mins_sub(stack, str, lassoc)
|
|
367
|
+
if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
|
|
368
|
+
stack << mins_sub(stack, m[2], lassoc)
|
|
369
|
+
mins_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", lassoc)
|
|
370
|
+
elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
|
|
371
|
+
[mins_sub(stack, m[1], lassoc), mins_sub(stack, m[2], lassoc)].max
|
|
372
|
+
elsif m = /\A\<(\d+)\>\Z/.match(str)
|
|
373
|
+
1
|
|
374
|
+
else
|
|
375
|
+
mins_sub2(str)
|
|
376
|
+
end
|
|
377
|
+
end
|
|
378
|
+
private def mins_sub2(str)
|
|
379
|
+
str = Mgmg.check_string(str)
|
|
380
|
+
unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
|
|
381
|
+
raise InvalidSmithError.new(str)
|
|
382
|
+
end
|
|
383
|
+
kind = EquipIndex[m[1].to_sym]
|
|
384
|
+
unless kind
|
|
385
|
+
raise InvalidEquipClassError.new(m[1])
|
|
386
|
+
end
|
|
387
|
+
main_m, main_s, main_mc = parse_material(m[2])
|
|
388
|
+
sub_m, sub_s, sub_mc = parse_material(m[3])
|
|
389
|
+
[main_s, sub_s].max
|
|
390
|
+
end
|
|
322
391
|
end
|
|
323
392
|
end
|
data/lib/mgmg/poly.rb
CHANGED
|
@@ -183,6 +183,15 @@ module Mgmg
|
|
|
183
183
|
raise ArgumentError, "the argument must be `s' or `c', not `#{variable}'"
|
|
184
184
|
end
|
|
185
185
|
end
|
|
186
|
+
def smith_eff(smith, comp=smith)
|
|
187
|
+
partial_derivative('s').evaluate(smith, comp).quo(2*(smith-1))
|
|
188
|
+
end
|
|
189
|
+
def comp_eff(smith, comp=smith)
|
|
190
|
+
partial_derivative('c').evaluate(smith, comp).quo(4*(comp-1))
|
|
191
|
+
end
|
|
192
|
+
def eff(smith, comp=smith)
|
|
193
|
+
[smith_eff(smith, comp), comp_eff(smith, comp)]
|
|
194
|
+
end
|
|
186
195
|
|
|
187
196
|
def [](i, j)
|
|
188
197
|
if (i < 0 && @mat.body.size < -i) || (j < 0 && @mat.body[0].size < -j)
|
data/lib/mgmg/utils.rb
CHANGED
|
@@ -47,6 +47,10 @@ module Mgmg
|
|
|
47
47
|
attr_accessor :equip
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
module_function def exp(smith, comp)
|
|
51
|
+
((smith-1)**2) + (2*((comp-1)**2)) + 3
|
|
52
|
+
end
|
|
53
|
+
|
|
50
54
|
CharacterList = /[^\(\)\+0123456789\[\]あきくしすたてなねのびりるイウガクグサジスタダチツデトドニノフブペボムラリルロンヴー一万二光兜典刀剣劣匠双古名吹咆品哮地大天太子安宝小帽弓弩当息悪戦手指斧書服木本杖業樹歴殺水氷法火炎牙物玉王産用界異的皮盾短石砕竜紫綿耳聖脛腕腿般良色衣袋覇質軍軽輝輪重量金鉄鎧闇陽靴額飾首骨鬼龍]/
|
|
51
55
|
module_function def check_string(str)
|
|
52
56
|
str = str.gsub(/[\s \\]/, '')
|
data/lib/mgmg/version.rb
CHANGED
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.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- KAZOON
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-08-
|
|
11
|
+
date: 2020-08-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|