mgmg 1.2.3

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e033136e63c2d84439c95d9bf8265fac1ed43e1c4cb082f8e62bf60eb4fbdfa0
4
+ data.tar.gz: 2dd59b7568c61514a449fa99ca37475eb58f30d63d768e2f5f9e158e5baa5531
5
+ SHA512:
6
+ metadata.gz: 97a6fa387ed0c2abaebce8bd1f9fb10aa4e68081bad91e2d1e9598b4f59a93a0a33396d4b0abf3e83dd1e5e44da2b279245910263a1658be05b6ca0161023901
7
+ data.tar.gz: 1f8ee1fea00e28ac361acc4162cd51eeda3173f1d23b07ac67e7415a0da2c3cd979cb0770c43ddbf3f7b969bd70606e81f56a1db3eee22043e70ce1359419ff7
data/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ /bin/* linguist-vendored
2
+ *.md linguist-documentation
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /Gemfile.lock
10
+ /test.rb
11
+ /test/
data/CHANGELOG.md ADDED
@@ -0,0 +1,74 @@
1
+ # 更新履歴
2
+
3
+ ## 1.0.0 2018/12/22
4
+ - 初版.
5
+
6
+ ## 1.0.1 2018/12/23
7
+ - 魔水の副重量が間違っていたバグを修正.
8
+ - `Mgmg::Equip#magmag`を追加.
9
+
10
+ ## 1.0.2 2018/12/23
11
+ - `Mgmg::Equip#+`を追加し,`Array#equip`を削除.
12
+ - `Enumerable#map(&:build).sum`的なことをする`Enumerable#build`を追加した.
13
+
14
+ ## 1.0.3 2018/12/30
15
+ - `Integer`へのモンキーパッチを`Refinements`に置き換えた(外部から見えなくなった).無駄に2倍にしていたエレメント値の主原料値を戻した.
16
+
17
+ ## 1.0.4 2019/01/11
18
+ - `Mgmg::Equip#power`では数字が大きくなり,わかりにくくなるため,`Float`にして正規の威力値を返す`Mgmg::Equip#fpower`を追加した.
19
+
20
+ ## 1.0.5 2019/01/12
21
+ - HPの材質値を5倍にしてしまっていたバグを修正.
22
+
23
+ ## 1.0.6 2019/01/13
24
+ - 消費エレメント計算において,WikiではHPのみ1/4倍となっていたところ,Excel版ではMPも1/4倍されていたため,MPも1/4倍となるように修正.
25
+
26
+ ## 1.0.7 2019/02/26
27
+ - github に登録.gem 化し,rubygems.org に登録.
28
+
29
+ ## 1.0.8 2019/03/15
30
+ - マニュアル等の不備を修正.
31
+
32
+ ## 1.0.9 2019/05/30
33
+ - 丸めを無視した多項式近似(変数は製作レベル)を表す `Mgmg::TPolynomial`およびこれを生成するメソッド String#poly を追加.
34
+
35
+ ## 1.0.10 2019/06/29
36
+ - 消費エレメント量を返す`Mgmg::Equip#total_cost`を追加.
37
+ - `Mgmg::Equip#inspect`の返り値にこれを含めるように変更.
38
+ - `String#build`等において,製作Lvを負の値にすると,街の製作屋に依頼した場合のコストを計算するように変更.
39
+
40
+ ## 1.0.11 2019/06/29
41
+ - ローブの表記ゆれとして,法衣の入力を許容するように.
42
+
43
+ ## 1.1.0 2019/07/27
44
+ - 量産品の本と一般的な本の魔力が入れ替わっていたバグを修正.
45
+ - MPを持つ装備の消費エレメント量計算が間違っていたバグを修正.
46
+ - (今まで製作品のみに対応していた)既成品の表記ゆれに対応し,正しいアイテム名を受け入れるように修正した.
47
+ - `Enumerable#build()`の引数が2個だけ入力された場合のレベル設定を,`comp=[smith,armor].max`から`comp=armor.tap{armor=smith}`に変更.
48
+ - `Mgmg::Equip#fpower`および`Mgmg::Equip#power`の仕様を変更.
49
+ - 魔防が最大の防具に対する`Mgmg::Equip#fpower`の返り値を実効魔防値に変更.
50
+ - 複数装備に対する`Mgmg::Equip#fpower`の返り値を9パラ合計値(HPとMPは1/4倍)に変更.
51
+ - `Mgmg::Equip#power`の返り値も,その2倍または4倍の整数値に変更.
52
+ - 完全ではないが,レシピ文字列の正当性チェックを導入し,どの部分文字列でパース失敗となったかを例外メッセージに入れた.
53
+ - 不正文字種の混入,括弧の対応不備をチェック.
54
+ - 部分文字列に対して,鍛冶・防具製作レシピとして,装備種別名として,素材としてのいずれで解釈して失敗したかを示すように.
55
+ - 既成品の名前を間違えた場合,鍛冶・防具製作レシピとして解釈できなかった扱いになる.
56
+ - その他,README.md,CHANGELOG.md の細部を修正.
57
+
58
+ ## 1.2.0 2019/08/04
59
+ - `Mgmg::TPolynomial`に,基礎的な演算を行うメソッドを追加した.
60
+ - 加減及びスカラー倍に関するもの: `+`, `-`, `scalar`, `*`, `quo`, `/`, `+@`, `-@`
61
+ - 偏微分: `partial_derivative`
62
+ - 近似多項式において,floor(種別値*主原料値)部分に丸め後の値を使うように変更した.
63
+ - レシピ中の空白文字とバックスラッシュを無視するようにした.
64
+
65
+ ## 1.2.1 2019/08/07
66
+ - `String#poly`が受け取れる引数に`:cost`を追加.消費エレメント量に関する近似多項式を返す.
67
+ - 主装備の種別値が0であることにより,継承されないはずのパラメータについて,近似多項式計算で誤って継承していたバグを修正.
68
+ - `Mgmg::TPolynomial#to_s`において,`self`が零多項式の場合に空文字列を返していたのを,`0/1`を`fmt`で文字列に変換した値を返すように修正.
69
+
70
+ ## 1.2.2 2019/08/07
71
+ - `Mgmg::`指定忘れのバグを修正.
72
+
73
+ ## 1.2.3 2019/11/10
74
+ - typoに基づくバグの修正.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in mgmg.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,233 @@
1
+ # Mgmg
2
+ This gem is a tool for a game in Japanese language, therefore the following are described in Japanese. English is not supported.
3
+
4
+ ## これは何?
5
+ mgmgは耕氏の [巡り廻る](http://rebellionrpg.blog80.fc2.com/) の武器・防具の製作及び合成のシミュレーションを行うRubyのGemです.原作(ゲーム)を解析したわけではなく,攻略Wiki上で公開されている [巡り廻る装備計算機(ver0.99.06).xls](https://wikiwiki.jp/guruguru/%E8%A3%85%E5%82%99%E5%93%81%E5%90%88%E6%88%90#n07db4f5) の計算をRuby上で行います.基本的に同じ計算をしていますが,数学的な同値変換(量子化誤差の配慮なし)を行っている他,Excel版が浮動小数点数演算を行っているのに対して,本ライブラリでは整数演算で完結しています.これらの違いの他,バグによって結果が変わる可能性があります.
6
+
7
+ ## 特徴
8
+ 後述の`String#build`によってレシピ文字列から直接計算できる点が一番の押しです.Excel版に比べ,レシピの試行錯誤を(計算能力ではなく,入力の容易さの意味で)高速に処理できると思います.製作Lvを変化させたときのグラフを生成するなども容易にできます.また,ごく一部(キャラクリ初期装備)を除く全ての既成品に対応しています.
9
+
10
+ ## 制限
11
+ Excel版に比べ,入力のチェックがなされておらず,☆制限の違反等を明示的には示しません.
12
+ メイン機能である`String#build`では,材料ごとに異なる製作Lvで製作した場合をシミュレートできません.本ライブラリのメソッドを組み合わせて用いると対応できますが,面倒くさいのでその方法は解説しません.
13
+
14
+ また,実機とは異なる結果が得られる場合があることがわかっています.防具製作Lv139,道具製作Lv234において
15
+ ```
16
+ 指輪(木10金3)+[手袋(金3石1)+指輪(木10皮1)]
17
+ ```
18
+ を実機(ver1.19)で製作すると器用603になりますが,Excel版,本ライブラリともに器用604と計算されます.
19
+
20
+ ## インストール
21
+ 下記でインストールします.
22
+
23
+ $ gem install mgmg
24
+
25
+ あるいは,http://cycloawaodorin.sakura.ne.jp/sonota/mgmg/mgmg.html にてAjax版を利用することもできます.Ajax版は一部の機能しか実装されていませんが,Ruby環境がない場合にも利用できます.
26
+
27
+ ## 使い方
28
+ 並列型多段合成杖を製作し,標準出力に出力.
29
+
30
+ ```ruby
31
+ puts '[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build(112, 176)
32
+ #=> 杖4☆20(骨綿)[攻撃:119, MP:104, 魔力:1,859, EL:水2]
33
+ ```
34
+
35
+ 複数装備を製作し,そのすべてを装備した場合の合計値を標準出力に出力.
36
+
37
+ ```ruby
38
+ puts %w|本(金3骨1)+[弓(骨1綿1)+[杖(金3金3)+[弓(綿1綿1)+[杖(宝10金6)+本(骨9鉄2)]]]] フード(石10骨9) 首飾り(宝10水10) 指輪(木10金10)|.build(122, 139, 232)
39
+ #=> 複数装備9(武:1, 頭:1, 飾:2)[攻撃:15, 物防:34, 魔防:28, HP:241, MP:71, 器用:223, 素早:222, 魔力:6,604]
40
+ ```
41
+
42
+ 重量1または2で作るのに必要な防具製作Lvを確認する.
43
+
44
+ ```ruby
45
+ p ['重鎧(皮10金10)'.min_level, '重鎧(皮10金10)'.min_level(2)]
46
+ #=> [162, 42]
47
+ ```
48
+
49
+ 近似多項式を得る.
50
+
51
+ ```ruby
52
+ puts '[斧(牙10金10)+剣(鉄10皮1)]+剣(鉄10皮1)'.poly(:attack).to_s('%.4g')
53
+ #=> (0.02588S+3.364)C+(4.677S+699.9)
54
+ ```
55
+
56
+ 既成品の性能を確認.
57
+
58
+ ```ruby
59
+ puts '小竜咆哮'.build(-1)
60
+ #=> 弓1☆10(木骨)[攻撃:50, 器用:120, 素早:50]
61
+ ```
62
+
63
+ ### 表記ゆれについて
64
+ 本ゲームでは,装備種別の名称に,下記の表のような表記ゆれが存在します.
65
+
66
+ |劣悪|店売り・歴戦|製作選択肢ver1.21|製作品ver1.21|製作選択肢ver1.22β37|製作品ver1.22β37|
67
+ |:-|:-|:-|:-|:-|:-|
68
+ |弩|弩|弩|ボウガン|弩|弩|
69
+ |ローブ|法衣|ローブ|ローブ|法衣|法衣|
70
+ |-|手袋|グローブ|グローブ|手袋|手袋|
71
+ |-|脛当て|すね当て|脛当て|すね当て|脛当て|
72
+
73
+ 本ライブラリでは,既成品,製作品ともにこれらの表記を同一視し,いずれを用いたレシピも処理できるようにしています.
74
+ 「ボウガン」の一般的な表記ゆれである「ボーガン」も受け付けています.
75
+
76
+ 「正式な装備種別名」は「製作品ver1.22β37」が妥当であろうと考え,`Mgmg::Equip#to_s`などではこれを用いるようにしています.
77
+
78
+ ## リファレンス
79
+ 本ライブラリで定義される主要なメソッドを以下に解説します.
80
+
81
+ ### `String#build(smith, comp=smith, left_associative: true)`
82
+ レシピ文字列である`self`を解釈し,鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として鍛冶・防具製作及び武器・防具合成を行った結果を後述の`Mgmg::Equip`クラスのインスタンスとして生成し,返します.例えば,
83
+ ```ruby
84
+ '[杖(水玉10火玉5)+本(骨10鉄1)]+[本(水玉5綿2)+杖(骨10鉄1)]'.build(112, 176)
85
+ ```
86
+ のようにします.基本的に`[]`による合成順序の指定が必要ですが,不確定の場合,`left_associative`が真なら左結合,偽なら右結合として解釈します.
87
+ ```ruby
88
+ 'ローブ(綿10皮10)+歴戦の服'
89
+ ```
90
+ のように,既成品を含む合成レシピも解釈します.キャラクリ初期装備の劣悪な服,劣悪な小手以外のあらゆる装備を網羅しています.劣悪な服,劣悪な小手はキャラクリ以外での初期装備品として解釈します.`comp`を省略した場合,`smith`と同じ値として処理します.
91
+
92
+ `self`が解釈不能な場合,例外が発生します.また,製作Lvや完成品の☆制限のチェックを行っていないほか,本ライブラリでは`武器+防具`や`防具+武器`の合成も可能になっています.街の鍛冶・防具製作・道具製作屋に任せた場合をシミュレートする場合は製作Lvを負の値(`-1`など,負であれば何でもよい)にします(製作Lv0相当の性能を計算し,消費エレメント量は委託仕様となります).
93
+
94
+ ### `String#min_level(weight=1)`
95
+ `self`を`weight`以下で作るための最低製作Lvを返します.`build`と異なり,合成や既成品は解釈できません.また,素材の☆による最低製作Lvとのmaxを返すため,街の鍛冶・防具製作屋に頼んだ場合の重量は`self.build(-1).weight`で確認する必要があります.`weight`を省略した場合,重量1となる製作Lvを返します.
96
+
97
+ ### `Enumerable#build(smith, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)`
98
+ 複数のレシピ文字列からなる`self`の各要素を製作し,そのすべてを装備したときの`Mgmg::Equip`を返します.製作では`鍛冶Lv=smith`, `防具製作Lv=armor`, `道具製作Lv=comp`とします.1つしか指定しなければすべてそのLv,2つなら1つ目を`smith=armor`,2つ目を`comp`に,3つならそれぞれの値とします.`left_associative`はそのまま`String#build`に渡されます.製作Lvが負の場合,製作Lv0として計算した上で,消費エレメント量は街の製作屋に頼んだ場合の値を計算します.武器複数など,同時装備が不可能な場合でも,特にチェックはされません.
99
+
100
+ ### `String#poly(para, left_associative: true)`
101
+ レシピ文字列である`self`を解釈し,`para`で指定した9パラ値について,丸めを無視した鍛冶・防具製作Lvと道具製作Lvの2変数からなる多項式関数を示す`Mgmg::TPolynomial`クラスのインスタンスを生成し,返します.`para`は次のシンボルのいずれかを指定します.
102
+ ```ruby
103
+ :attack, :phydef, :magdef, :hp, :mp, :str, :dex, :speed, :magic
104
+ ```
105
+ これらは,`Mgmg::Equip`から当該属性値を取得するためのメソッド名と同一です.`left_associative`は`String#build`の場合と同様です.
106
+
107
+ `para`として,複数の9パラ値を組み合わせた以下のシンボルを指定することもできます.
108
+ ```ruby
109
+ :atkstr, :atk_sd, :dex_as, :mag_das, :magmag
110
+ ```
111
+ これらは同名のメソッドと異なり,本来の威力値等に関する近似多項式を返し,4倍化や2倍化はされていません.また,自動選択の`:power`は指定できません.
112
+
113
+ また,`:cost`を渡すことで,消費エレメント量に関する近似多項式を得られます.`self`に`"+"`が含まれていれば合成品とみなし,最後の合成に必要な地エレメント量を,それ以外では,武器なら消費火エレメント量を,防具なら消費水エレメント量を返します.ただし,`self`が既成品そのものの場合,零多項式を返します.
114
+
115
+ ### `Mgmg::Equip`
116
+ 前述の`String#build`によって生成される装備品のクラスです.複数装備の合計値を表す「複数装備」という種別の装備品の場合もあります.以下のようなインスタンスメソッドが定義されています.
117
+
118
+ ### `Mgmg::Equip#to_s`
119
+ ```ruby
120
+ "杖4☆20(骨綿)[攻撃:119, MP:104, 魔力:1,859, EL:水2]"
121
+ ```
122
+ のような,わかりやすい形式の文字列に変換します.上の例で「4」は重量,「骨」は主材質,「綿」は副材質を表します.各種数値が必要な場合は次以降に説明するメソッドをご利用ください.複数装備の場合は以下のような文字列になります.
123
+ ```ruby
124
+ "複数装備9(武:1, 頭:1, 飾:2)[攻撃:15, 物防:34, 魔防:28, HP:241, MP:71, 器用:223, 素早:222, 魔力:6,604]"
125
+ ```
126
+ 「9」は合計重量,(武:1, 頭:1, 飾:2)は武器を1つ,頭防具を1つ,装飾品を2つ装備していることを示します.装備している場合は「胴」「腕」「足」も記述されます.
127
+
128
+ ### `Mgmg::Equip#inspect`
129
+ `Mgmg::Equip#to_s`の出力に加え,0となる9パラ値を省略せず,総消費エレメント量を連結した文字列を出力します.すなわち,
130
+ ```ruby
131
+ "杖4☆20(骨綿)[攻撃:119, 物防:0, 魔防:0, HP:0, MP:104, 腕力:0, 器用:0, 素早:0, 魔力:1859, EL:火0地0水2]<コスト:火491地3150水0>"
132
+ ```
133
+ のような文字列を返します.
134
+
135
+ ### `Mgmg::Equip#weight, star`
136
+ それぞれ重量,☆数を整数値で返します.「複数装備」の場合,`weight`は総重量,`star`は装備数に関する値が返ります.
137
+
138
+ ### `Mgmg::Equip#attack, phydef, magdef, hp, mp, str, dex, speed, magic, fire, earth, water`
139
+ それぞれ
140
+ ```
141
+ 攻撃,物防,魔防,HP,MP,腕力,器用,素早さ,魔力,火EL,地EL,水EL
142
+ ```
143
+ の値を`Integer`で返します.
144
+
145
+ ### `Mgmg::Equip#atkstr, atk_sd, dex_as, mag_das`
146
+ それぞれ
147
+ ```
148
+ 攻撃+腕力,攻撃x2+腕力+器用,器用x2+攻撃+腕力,魔力x4+器用x2+攻撃+腕力
149
+ ```
150
+ の値を返します.これらはそれぞれ
151
+ ```
152
+ (剣,斧,杖,本),(短剣,双短剣),(弓,弩),(バスターアロー)
153
+ ```
154
+ の威力の定数倍の値です.トリックプレーやディバイドには対応していません.
155
+
156
+ ### `Mgmg::Equip#power`
157
+ 武器種別ごとに適した威力計算値の4倍の値を返します.具体的には以下の値です.
158
+
159
+ |武器種別|威力計算値の4倍|
160
+ |:-|:-|
161
+ |短剣,双短剣|攻撃x4+腕力x2+器用x2|
162
+ |剣,斧|攻撃x4+腕力x4|
163
+ |弓|max(器用x4+攻撃x2+腕力x2, 魔力x4+器用x2+攻撃+腕力)|
164
+ |弩|器用x4+攻撃x2+腕力x2|
165
+ |杖,本|max(魔力x8,攻撃x4+腕力x4)|
166
+
167
+ 弓,杖,本では`self`の性能から用途を判別し,高威力となるものの値を返します.防具に対してこのメソッドを呼び出すと,9パラメータのうち最も高い値を返します.
168
+
169
+ 防具の場合,9パラメータのうち,最大のものの2倍の値を返します.ただし,最大の値に魔防が含まれている場合,代わりに「魔防x2+魔力」を返します.
170
+
171
+ 複数装備の場合,9パラメータの合計値の4倍を返します.ただし,HPとMPは4倍にしません.HPとMPの特例は,消費エレメント量の計算と同様とするものです.
172
+
173
+ いずれの場合も,EL値,重量,☆は無視されます.
174
+
175
+ ### `Mgmg::Equip#fpower`
176
+ 武器または複数装備の場合,`Mgmg::Equip#power.fdiv(4)`を返します.防具の場合,`Mgmg::Equip#power.fdiv(2)`を返します.
177
+
178
+ ### `Mgmg::Equip#magmag`
179
+ 「魔防x2+魔力」の値を返します.魔力の半分が魔防に加算されることから,実際の魔防性能に比例した値となります.
180
+
181
+ ### `Mgmg::Equip#total_cost`
182
+ 製作に必要な総エレメント量を,火,地,水の順のベクトルとして返します.ケージの十分性の確認には,下記の`comp_cost`を用います.
183
+
184
+ ### `Mgmg::Equip#comp_cost(outsourcing=false)`
185
+ `self`が合成によって作られたものだとした場合の消費地エレメント量を返します.地ケージ確保のための確認用途が多いと思うので短い`cost`をエイリアスとしています.`outsourcing`が真の場合,街の道具製作屋に頼んだ場合のコストを返します.
186
+
187
+ ### `Mgmg::Equip#smith_cost(outsourcing=false)`
188
+ `self`が鍛冶・防具製作によって作られたものだったものだとした場合の消費火・水エレメント量を返します.`outscourcing`が真の場合,街の鍛冶屋・防具製作屋に頼んだ場合のコストを返します.
189
+
190
+ ### `Mgmg::Equip#+(other)`
191
+ `self`と`other`を装備した「複数装備」の`Mgmg::Equip`を返します.`self`と`other`はいずれも単品でも「複数装備」でも構いません.武器複数などの装備可否チェックはされません.
192
+
193
+ ### `Mgmg::TPolynomial`
194
+ 前述の`String#poly`によって生成される二変数多項式のクラスです.最初のTはtwo-variableのTです.以下のようなメソッドが定義されています.
195
+
196
+ ### `Mgmg::TPolynomial#to_s(fmt=nil)`
197
+ 鍛冶・防具製作LvをS,道具製作LvをCとして,`self`を表す数式文字列を返します.係数`coeff`を文字列に変換する際,`fmt`の値に応じて次の方法を用います.
198
+
199
+ |`fmt`のクラス|変換法|
200
+ |:-|:-|
201
+ |`NilClass`|`coeff.to_s`|
202
+ |`String`|`fmt % [coeff]`|
203
+ |`Symbol`|`coeff.__send__(fmt)`|
204
+ |`Proc`|`fmt.call(coeff)`|
205
+
206
+ 通常,係数は`Rational`であるため,`'%.2e'`などを指定するのがオススメです.
207
+
208
+ ### `Mgmg::TPolynomial#inspect(fmt=->(r){"Rational(#{r.numerator}, #{r.denominator})"})`
209
+ `Mgmg::TPolynomial#to_s`と同様ですが,鍛冶・防具製作Lvを`s`,道具製作Lvを`c`としたRubyの式として解釈可能な文字列を返します.つまり,係数をリテラル,掛け算を`*`で表現しています.`fmt`は`Mgmg::TPolynomial#to_s`と同様で,適当な値を指定することでRuby以外の言語でも解釈可能になります.例えば,精度が問題でないならば,`'%e'`とすると,大抵の言語で解釈可能な文字列を生成できます.
210
+
211
+ ### `Mgmg::TPolynomial#evaluate(smith, comp=smith)`
212
+ 鍛冶・防具製作Lvを`smith`,道具製作Lvを`comp`として値を計算します.丸めを無視しているため,実際の合成結果以上の値が返ります.
213
+
214
+ ### `Mgmg::TPolynomial#smith_fix(smith, fmt=nil)`
215
+ 鍛冶・防具製作Lvを`smith`で固定し,道具製作Lvのみを変数とする多項式として,`to_s(fmt)`したような文字列を返します.
216
+
217
+ ### `Mgmg::TPolynomial#scalar(value)`
218
+ 多項式として`value`倍した式を返します.
219
+ alias として`*`があるほか`scalar(1.quo(value))`として`quo`,`/`,`scalar(1)`として`+@`,`scalar(-1)`として`-@`が定義されています.
220
+
221
+ ### `Mgmg::TPolynomial#+(other)`, `Mgmg::TPolynomial#-(other)`
222
+ 多項式として`self+other`または`self-other`を計算し,結果を返します.
223
+ `other`は`Mgmg::TPolynomial`であることが想定されており,スカラー値は使えません.
224
+
225
+ ### `Mgmg::TPolynomial#partial_derivative(variable)`
226
+ 多項式として偏微分し,その微分係数を返します.
227
+ `variable`はどの変数で偏微分するかを指定するもので,`"s"`なら鍛冶・防具製作Lv,`"c"`なら道具製作Lvで偏微分します.
228
+
229
+ ## 謝辞
230
+ 面白いゲームを作ってくださった耕様および,高精度なシミュレータを作製し,本ライブラリの作製を可能とした,Excel版装備計算機の作者様に感謝いたします.
231
+
232
+ ## Contributing
233
+ バグ報告等は https://github.com/cycloawaodorin/mgmg/issues にて.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "mgmg"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/lib/mgmg.rb ADDED
@@ -0,0 +1,189 @@
1
+ require "mgmg/version"
2
+ require 'mgmg/const'
3
+
4
+ module Mgmg
5
+ class << Equip
6
+ def build(str, s_level, c_level, left_associative: true)
7
+ str = Mgmg.check_string(str)
8
+ stack, str = build_sub0([], str)
9
+ build_sub(stack, str, s_level, c_level, left_associative)
10
+ end
11
+ private def build_sub0(stack, str)
12
+ SystemEquip.each do |k, v|
13
+ if Regexp.compile(k).match(str)
14
+ stack << v
15
+ str = str.gsub(k, "<#{stack.length-1}>")
16
+ end
17
+ end
18
+ [stack, str]
19
+ end
20
+ private def build_sub(stack, str, s_level, c_level, lassoc)
21
+ if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
22
+ stack << build_sub(stack, m[2], s_level, c_level, lassoc)
23
+ build_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", s_level, c_level, lassoc)
24
+ elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
25
+ if c_level < 0
26
+ compose(build_sub(stack, m[1], s_level, c_level, lassoc), build_sub(stack, m[2], s_level, c_level, lassoc), 0, true)
27
+ else
28
+ compose(build_sub(stack, m[1], s_level, c_level, lassoc), build_sub(stack, m[2], s_level, c_level, lassoc), c_level, false)
29
+ end
30
+ elsif m = /\A\<(\d+)\>\Z/.match(str)
31
+ stack[m[1].to_i]
32
+ else
33
+ if s_level < 0
34
+ smith(str, 0, true)
35
+ else
36
+ smith(str, s_level, false)
37
+ end
38
+ end
39
+ end
40
+
41
+ def compose(main, sub, level, outsourcing)
42
+ main_k, sub_k = main.kind, sub.kind
43
+ main_s, sub_s = main.star, sub.star
44
+ main_main, sub_main = main.main, sub.main
45
+ main_sub, sub_sub = main.sub, sub.sub
46
+ para = Vec.new(9, 0)
47
+ ele = Vec.new(3, 0)
48
+
49
+ # 9パラメータ
50
+ coef = Equip9[main_k].dup
51
+ para[] = coef
52
+ para.add!(level).e_div!(2)
53
+ para.e_mul!(sub.para).e_div!(100)
54
+ coef.sub!(Equip9[sub_k])
55
+ coef.add!( 100 + (main_s-sub_s)*5 - ( ( main_main==sub_main && main_main != 9 ) ? 30 : 0 ) )
56
+ coef.add!(Material9[main_main]).sub!(Material9[sub_main])
57
+ coef.e_mul!(EquipFilter[main_k])
58
+ para.e_mul!(coef).e_div!( main_k==sub_k ? 200 : 100 )
59
+ para.add!(main.para)
60
+
61
+ # エレメント
62
+ ele[] = sub.element
63
+ ele.e_mul!([75, level].min).e_div!( main_k==sub_k ? 200 : 100 )
64
+ ele.add!(main.element)
65
+
66
+ ret = new(main_k, main.weight+sub.weight, main_s+sub_s, main_sub, sub_main, para, ele)
67
+ ret.total_cost.add!(main.total_cost).add!(sub.total_cost)
68
+ ret.total_cost[1] += ret.comp_cost(outsourcing)
69
+ ret
70
+ end
71
+
72
+ def smith(str, level, outsourcing)
73
+ str = Mgmg.check_string(str)
74
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
75
+ raise InvalidSmithError.new(str)
76
+ end
77
+ kind = EquipIndex[m[1].to_sym]
78
+ unless kind
79
+ raise InvalidEquipClassError.new(m[1])
80
+ end
81
+ main_m, main_s, main_mc = parse_material(m[2])
82
+ sub_m, sub_s, sub_mc = parse_material(m[3])
83
+ para = Vec.new(9, 0)
84
+ ele = Vec.new(3, 0)
85
+
86
+ # 9パラメータ
87
+ para[] = Equip9[kind]
88
+ para.e_mul!(Main9[main_m]).e_div!(100)
89
+ coef = Sub9[sub_m].dup
90
+ coef.add!(level)
91
+ para.e_mul!(coef).e_div!( main_mc==sub_mc ? 200 : 100 )
92
+
93
+ # エレメント
94
+ ele[] = MainEL[main_m]
95
+ ele.e_mul!(SubEL[sub_m]).e_div!(6)
96
+
97
+ # 重量
98
+ weight = ( ( EquipWeight[kind] + SubWeight[sub_m] - level.div(2) ) * ( MainWeight[main_m] ) ).div(10000)
99
+
100
+ ret = new(kind, ( weight<1 ? 1 : weight ), (main_s+sub_s).div(2), main_mc, sub_mc, para, ele)
101
+ if kind < 8
102
+ ret.total_cost[0] = ret.smith_cost(outsourcing)
103
+ else
104
+ ret.total_cost[2] = ret.smith_cost(outsourcing)
105
+ end
106
+ ret
107
+ end
108
+
109
+ def min_level(str, weight=1)
110
+ str = Mgmg.check_string(str)
111
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
112
+ raise InvalidSmithError.new(str)
113
+ end
114
+ kind = EquipIndex[m[1].to_sym]
115
+ main_m, main_s, = parse_material(m[2])
116
+ sub_m, sub_s, = parse_material(m[3])
117
+
118
+ q, r = ((weight+1)*10000).divmod(MainWeight[main_m])
119
+ l = ( EquipWeight[kind] + SubWeight[sub_m] - q + ( r==0 ? 1 : 0 ) )*2
120
+ [(main_s-1)*3, (sub_s-1)*3, l].max
121
+ end
122
+
123
+ private def parse_material(str)
124
+ m = /\A.+?(\d+)\Z/.match(str)
125
+ mat = MaterialIndex[str.to_sym]
126
+ if m.nil? || mat.nil?
127
+ raise InvalidMaterialError.new(str)
128
+ end
129
+ [mat, m[1].to_i, mat<90 ? mat.div(10): 9]
130
+ end
131
+ end
132
+ end
133
+
134
+ class String
135
+ def min_level(w=1)
136
+ Mgmg::Equip.min_level(self, w)
137
+ end
138
+ def build(smith, comp=smith, left_associative: true)
139
+ Mgmg::Equip.build(self, smith, comp, left_associative: left_associative)
140
+ end
141
+ def poly(para, left_associative: true)
142
+ case para
143
+ when :atkstr
144
+ self.poly(:attack) + self.poly(:str)
145
+ when :atk_sd
146
+ self.poly(:attack) + self.poly(:str).quo(2) + self.poly(:dex).quo(2)
147
+ when :dex_as
148
+ self.poly(:dex) + self.poly(:attack).quo(2) + self.poly(:str).quo(2)
149
+ when :mag_das
150
+ self.poly(:magic) + self.poly(:dex_as).quo(2)
151
+ when :magmag
152
+ self.poly(:magdef) + self.poly(:magic).quo(2)
153
+ when :cost
154
+ if Mgmg::SystemEquip.keys.include?(self)
155
+ return Mgmg::TPolynomial.new(Mgmg::Mat.new(1, 1, 0.quo(1)), 28, 0, 12, 12)
156
+ end
157
+ built = self.build(-1)
158
+ const = (built.star**2) * ( /\+/.match(self) ? 5 : ( built.kind < 8 ? 2 : 1 ) )
159
+ ret = poly(:attack) + poly(:phydef) + poly(:magdef)
160
+ ret += poly(:hp).quo(4) + poly(:mp).quo(4)
161
+ ret += poly(:str) + poly(:dex) + poly(:speed) + poly(:magic)
162
+ ret.mat.body[0][0] += const
163
+ ret
164
+ else
165
+ Mgmg::TPolynomial.build(self, para, left_associative: left_associative)
166
+ end
167
+ end
168
+ def show(smith, comp=smith, left_associative: true)
169
+ built = self.build(smith, comp, left_associative: left_associative)
170
+ pstr = '%.3f' % built.fpower
171
+ pstr.sub!(/\.?0+\Z/, '')
172
+ puts "Building"
173
+ puts " #{self}"
174
+ puts "with levels (#{smith}, #{comp}) yields (#{pstr}, #{built.total_cost})"
175
+ puts " #{built}"
176
+ end
177
+ end
178
+ module Enumerable
179
+ def build(smith, armor=smith, comp=armor.tap{armor=smith}, left_associative: true)
180
+ self.map do |str|
181
+ m = /\A\[*([^\+]+)/.match(str)
182
+ if Mgmg::EquipPosition[m[1].build(0).kind] == 0
183
+ str.build(smith, comp, left_associative: left_associative)
184
+ else
185
+ str.build(armor, comp, left_associative: left_associative)
186
+ end
187
+ end.sum
188
+ end
189
+ end