mgmg 1.4.0 → 1.5.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 +25 -0
- data/README.md +37 -248
- data/lib/mgmg/cuisine.rb +140 -0
- data/lib/mgmg/equip.rb +37 -39
- data/lib/mgmg/ir.rb +400 -0
- data/lib/mgmg/optimize.rb +21 -9
- data/lib/mgmg/option.rb +85 -0
- data/lib/mgmg/poly.rb +2 -2
- data/lib/mgmg/reinforce.rb +70 -0
- data/lib/mgmg/search.rb +246 -175
- data/lib/mgmg/system_equip.rb +6 -0
- data/lib/mgmg/utils.rb +47 -1
- data/lib/mgmg/version.rb +1 -1
- data/lib/mgmg.rb +176 -62
- data/mgmg.gemspec +4 -4
- data/reference.md +453 -0
- metadata +15 -10
data/lib/mgmg/search.rb
CHANGED
@@ -1,254 +1,325 @@
|
|
1
1
|
class String
|
2
|
-
def smith_search(para, target, comp,
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
smith_min = build(-1, -1, left_associative: left_associative).min_level
|
8
|
-
end
|
9
|
-
end
|
10
|
-
if smith_max < smith_min
|
11
|
-
raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{smith_min}, #{smith_max}) are given"
|
12
|
-
elsif cut_exp < Float::INFINITY
|
2
|
+
def smith_search(para, target, comp, opt: Mgmg::Option.new)
|
3
|
+
opt = opt.dup.set_default(self)
|
4
|
+
if opt.smith_max < opt.smith_min
|
5
|
+
raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{opt.smith_min}, #{opt.smith_max}) are given"
|
6
|
+
elsif opt.cut_exp < Float::INFINITY
|
13
7
|
begin
|
14
|
-
smith_max = [smith_max, Mgmg.invexp2(cut_exp, comp)].min
|
8
|
+
opt.smith_max = [opt.smith_max, Mgmg.invexp2(opt.cut_exp, comp)].min
|
15
9
|
rescue
|
16
10
|
raise Mgmg::SearchCutException
|
17
11
|
end
|
18
12
|
end
|
19
|
-
if target <=
|
20
|
-
return smith_min
|
21
|
-
elsif
|
13
|
+
if target <= opt.irep.para_call(para, opt.smith_min, comp)
|
14
|
+
return opt.smith_min
|
15
|
+
elsif opt.irep.para_call(para, opt.smith_max, comp) < target
|
22
16
|
raise Mgmg::SearchCutException
|
23
17
|
end
|
24
|
-
while 1 < smith_max - smith_min do
|
25
|
-
smith = (smith_max - smith_min).div(2) + smith_min
|
26
|
-
if
|
27
|
-
smith_min = smith
|
18
|
+
while 1 < opt.smith_max - opt.smith_min do
|
19
|
+
smith = (opt.smith_max - opt.smith_min).div(2) + opt.smith_min
|
20
|
+
if opt.irep.para_call(para, smith, comp) < target
|
21
|
+
opt.smith_min = smith
|
28
22
|
else
|
29
|
-
smith_max = smith
|
23
|
+
opt.smith_max = smith
|
30
24
|
end
|
31
25
|
end
|
32
|
-
smith_max
|
26
|
+
opt.smith_max
|
33
27
|
end
|
34
|
-
def comp_search(para, target, smith,
|
35
|
-
|
36
|
-
if comp_max < comp_min
|
37
|
-
raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
|
38
|
-
end
|
39
|
-
if target <=
|
40
|
-
return comp_min
|
41
|
-
elsif
|
28
|
+
def comp_search(para, target, smith, opt: Mgmg::Option.new)
|
29
|
+
opt = opt.dup.set_default(self)
|
30
|
+
if opt.comp_max < opt.comp_min
|
31
|
+
raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{opt.comp_min}, #{opt.comp_max}) are given"
|
32
|
+
end
|
33
|
+
if target <= opt.irep.para_call(para, smith, opt.comp_min)
|
34
|
+
return opt.comp_min
|
35
|
+
elsif opt.irep.para_call(para, smith, opt.comp_max) < target
|
42
36
|
raise Mgmg::SearchCutException
|
43
37
|
end
|
44
|
-
while 1 < comp_max - comp_min do
|
45
|
-
comp = (comp_max - comp_min).div(2) + comp_min
|
46
|
-
if
|
47
|
-
comp_min = comp
|
38
|
+
while 1 < opt.comp_max - opt.comp_min do
|
39
|
+
comp = (opt.comp_max - opt.comp_min).div(2) + opt.comp_min
|
40
|
+
if opt.irep.para_call(para, smith, comp) < target
|
41
|
+
opt.comp_min = comp
|
48
42
|
else
|
49
|
-
comp_max = comp
|
43
|
+
opt.comp_max = comp
|
50
44
|
end
|
51
45
|
end
|
52
|
-
comp_max
|
46
|
+
opt.comp_max
|
53
47
|
end
|
54
|
-
def search(para, target,
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
minex, ret = exp, [smith_max, comp_min] if exp < minex
|
71
|
-
(comp_min+step).step(comp_max-1, step) do |comp|
|
72
|
-
break if minex < Mgmg.exp(smith_min, comp)
|
73
|
-
smith = smith_search(para, target, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
|
48
|
+
def search(para, target, opt: Mgmg::Option.new)
|
49
|
+
opt = opt.dup.set_default(self)
|
50
|
+
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
51
|
+
opt.comp_min = comp_search(para, target, opt.smith_max, opt: opt)
|
52
|
+
opt.smith_max = smith_search(para, target, opt.comp_min, opt: opt_nocut)
|
53
|
+
opt.smith_min = smith_search(para, target, opt.comp_max, opt: opt_nocut)
|
54
|
+
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.comp_min)
|
55
|
+
opt.comp_max = comp_search(para, target, opt.smith_min, opt: opt)
|
56
|
+
ret = nil
|
57
|
+
exp = Mgmg.exp(opt.smith_min, opt.comp_max)
|
58
|
+
opt.cut_exp, ret = exp, [opt.smith_min, opt.comp_max] if exp < opt.cut_exp
|
59
|
+
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.comp_min+opt.step).step(opt.comp_max-1, opt.step) do |comp|
|
62
|
+
break if opt.cut_exp < Mgmg.exp(opt.smith_min, comp)
|
63
|
+
smith = smith_search(para, target, comp, opt: opt)
|
74
64
|
exp = Mgmg.exp(smith, comp)
|
75
|
-
if exp <
|
76
|
-
|
77
|
-
elsif exp ==
|
78
|
-
if
|
65
|
+
if exp < opt.cut_exp
|
66
|
+
opt.cut_exp, ret = exp, [smith, comp]
|
67
|
+
elsif exp == opt.cut_exp
|
68
|
+
if ret.nil? or opt.irep.para_call(para, *ret) < opt.irep.para_call(para, smith, comp) then
|
79
69
|
ret = [smith, comp]
|
80
70
|
end
|
81
71
|
end
|
82
72
|
rescue Mgmg::SearchCutException
|
83
73
|
end
|
84
|
-
raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{cut_exp}" if
|
74
|
+
raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{opt.cut_exp}" if ret.nil?
|
85
75
|
ret
|
86
76
|
end
|
87
77
|
end
|
88
78
|
module Enumerable
|
89
|
-
def smith_search(para, target, armor, comp,
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
smith_min = build(-1, -1, -1, left_associative: left_associative).min_level[0]
|
95
|
-
end
|
96
|
-
end
|
97
|
-
if smith_max < smith_min
|
98
|
-
raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{smith_min}, #{smith_max}) are given"
|
99
|
-
elsif cut_exp < Float::INFINITY
|
79
|
+
def smith_search(para, target, armor, comp, opt: Mgmg::Option.new)
|
80
|
+
opt = opt.dup.set_default(self)
|
81
|
+
if opt.smith_max < opt.smith_min
|
82
|
+
raise ArgumentError, "smith_min <= smith_max is needed, (smith_min, smith_max) = (#{opt.smith_min}, #{opt.smith_max}) are given"
|
83
|
+
elsif opt.cut_exp < Float::INFINITY
|
100
84
|
begin
|
101
|
-
smith_max = [smith_max, Mgmg.invexp3(cut_exp, armor, comp)].min
|
85
|
+
opt.smith_max = [opt.smith_max, Mgmg.invexp3(opt.cut_exp, armor, comp)].min
|
102
86
|
rescue
|
103
87
|
raise Mgmg::SearchCutException
|
104
88
|
end
|
105
89
|
end
|
106
|
-
if
|
90
|
+
if opt.irep.para_call(para, opt.smith_max, armor, comp) < target
|
107
91
|
raise Mgmg::SearchCutException
|
108
|
-
elsif target <=
|
109
|
-
return smith_min
|
92
|
+
elsif target <= opt.irep.para_call(para, opt.smith_min, armor, comp)
|
93
|
+
return opt.smith_min
|
110
94
|
end
|
111
|
-
while 1 < smith_max - smith_min do
|
112
|
-
smith = (smith_max - smith_min).div(2) + smith_min
|
113
|
-
if
|
114
|
-
smith_min = smith
|
95
|
+
while 1 < opt.smith_max - opt.smith_min do
|
96
|
+
smith = (opt.smith_max - opt.smith_min).div(2) + opt.smith_min
|
97
|
+
if opt.irep.para_call(para, smith, armor, comp) < target
|
98
|
+
opt.smith_min = smith
|
115
99
|
else
|
116
|
-
smith_max = smith
|
100
|
+
opt.smith_max = smith
|
117
101
|
end
|
118
102
|
end
|
119
|
-
smith_max
|
103
|
+
opt.smith_max
|
120
104
|
end
|
121
|
-
def armor_search(para, target, smith, comp,
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
armor_min = build(-1, -1, -1, left_associative: left_associative).min_level[1]
|
127
|
-
end
|
128
|
-
end
|
129
|
-
if armor_max < armor_min
|
130
|
-
raise ArgumentError, "armor_min <= armor_max is needed, (armor_min, armor_max) = (#{armor_min}, #{armor_max}) are given"
|
131
|
-
elsif cut_exp < Float::INFINITY
|
105
|
+
def armor_search(para, target, smith, comp, opt: Mgmg::Option.new)
|
106
|
+
opt = opt.dup.set_default(self)
|
107
|
+
if opt.armor_max < opt.armor_min
|
108
|
+
raise ArgumentError, "armor_min <= armor_max is needed, (armor_min, armor_max) = (#{opt.armor_min}, #{opt.armor_max}) are given"
|
109
|
+
elsif opt.cut_exp < Float::INFINITY
|
132
110
|
begin
|
133
|
-
armor_max = [armor_max, Mgmg.invexp3(cut_exp, smith, comp)].min
|
111
|
+
opt.armor_max = [opt.armor_max, Mgmg.invexp3(opt.cut_exp, smith, comp)].min
|
134
112
|
rescue
|
135
113
|
raise Mgmg::SearchCutException
|
136
114
|
end
|
137
115
|
end
|
138
|
-
if
|
116
|
+
if opt.irep.para_call(para, smith, opt.armor_max, comp) < target
|
139
117
|
raise Mgmg::SearchCutException
|
140
|
-
elsif target <=
|
141
|
-
return armor_min
|
118
|
+
elsif target <= opt.irep.para_call(para, smith, opt.armor_min, comp)
|
119
|
+
return opt.armor_min
|
142
120
|
end
|
143
|
-
while 1 < armor_max - armor_min do
|
144
|
-
armor = (armor_max - armor_min).div(2) + armor_min
|
145
|
-
if
|
146
|
-
armor_min = armor
|
121
|
+
while 1 < opt.armor_max - opt.armor_min do
|
122
|
+
armor = (opt.armor_max - opt.armor_min).div(2) + opt.armor_min
|
123
|
+
if opt.irep.para_call(para, smith, armor, comp) < target
|
124
|
+
opt.armor_min = armor
|
147
125
|
else
|
148
|
-
armor_max = armor
|
126
|
+
opt.armor_max = armor
|
149
127
|
end
|
150
128
|
end
|
151
|
-
armor_max
|
129
|
+
opt.armor_max
|
152
130
|
end
|
153
|
-
def sa_search(para, target, comp,
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
(armor_min+1).upto(armor_max-1) do |armor|
|
171
|
-
break if minex < Mgmg.exp(smith_min, armor, comp)
|
172
|
-
smith = smith_search(para, target, armor, comp, smith_min, smith_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
|
131
|
+
def sa_search(para, target, comp, opt: Mgmg::Option.new)
|
132
|
+
opt = opt.dup.set_default(self)
|
133
|
+
opt_nocut = opt.dup; opt_nocut.cut_exp = Float::INFINITY
|
134
|
+
opt.smith_min = smith_search(para, target, opt.armor_max, comp, opt: opt_nocut)
|
135
|
+
opt.armor_min = armor_search(para, target, opt.smith_max, comp, opt: opt_nocut)
|
136
|
+
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, comp)
|
137
|
+
opt.smith_max = smith_search(para, target, opt.armor_min, comp, opt: opt_nocut)
|
138
|
+
opt.armor_max = armor_search(para, target, opt.smith_min, comp, opt: opt_nocut)
|
139
|
+
ret = nil
|
140
|
+
exp = Mgmg.exp(opt.smith_min, opt.armor_max, comp)
|
141
|
+
opt.cut_exp, ret = exp, [opt.smith_min, opt.armor_max] if exp < opt.cut_exp
|
142
|
+
exp2 = Mgmg.exp(opt.smith_max, opt.armor_min, comp)
|
143
|
+
if exp2 < exp
|
144
|
+
opt.cut_exp, ret = exp2, [opt.smith_max, opt.armor_min] if exp2 < opt.cut_exp
|
145
|
+
(opt.armor_min+1).upto(opt.armor_max-1) do |armor|
|
146
|
+
break if opt.cut_exp < Mgmg.exp(opt.smith_min, armor, comp)
|
147
|
+
smith = smith_search(para, target, armor, comp, opt: opt)
|
173
148
|
exp = Mgmg.exp(smith, armor, comp)
|
174
|
-
if exp <
|
175
|
-
|
176
|
-
elsif exp ==
|
177
|
-
if
|
149
|
+
if exp < opt.cut_exp
|
150
|
+
opt.cut_exp, ret = exp, [smith, armor]
|
151
|
+
elsif exp == opt.cut_exp
|
152
|
+
if ret.nil? or opt.irep.para_call(para, *ret, comp) < opt.irep.para_call(para, smith, armor, comp) then
|
178
153
|
ret = [smith, armor]
|
179
154
|
end
|
180
155
|
end
|
181
156
|
rescue Mgmg::SearchCutException
|
182
157
|
end
|
183
158
|
else
|
184
|
-
(smith_min+1).upto(smith_max-1) do |smith|
|
185
|
-
break if
|
186
|
-
armor = armor_search(para, target, smith, comp,
|
159
|
+
(opt.smith_min+1).upto(opt.smith_max-1) do |smith|
|
160
|
+
break if opt.cut_exp < Mgmg.exp(smith, opt.armor_min, comp)
|
161
|
+
armor = armor_search(para, target, smith, comp, opt: opt)
|
187
162
|
exp = Mgmg.exp(smith, armor, comp)
|
188
|
-
if exp <
|
189
|
-
|
190
|
-
elsif exp ==
|
191
|
-
if
|
163
|
+
if exp < opt.cut_exp
|
164
|
+
opt.cut_exp, ret = exp, [smith, armor]
|
165
|
+
elsif exp == opt.cut_exp
|
166
|
+
if ret.nil? or opt.irep.para_call(para, *ret, comp) < opt.irep.para_call(para, smith, armor, comp) then
|
192
167
|
ret = [smith, armor]
|
193
168
|
end
|
194
169
|
end
|
195
170
|
rescue Mgmg::SearchCutException
|
196
171
|
end
|
197
172
|
end
|
198
|
-
raise Mgmg::SearchCutException if
|
173
|
+
raise Mgmg::SearchCutException if ret.nil?
|
199
174
|
ret
|
200
175
|
end
|
201
|
-
def comp_search(para, target, smith, armor,
|
202
|
-
|
203
|
-
if comp_max < comp_min
|
204
|
-
raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{comp_min}, #{comp_max}) are given"
|
205
|
-
end
|
206
|
-
if target <=
|
207
|
-
return comp_min
|
208
|
-
elsif
|
209
|
-
raise ArgumentError, "given comp_max=#{comp_max} does not satisfies the target"
|
210
|
-
end
|
211
|
-
while 1 < comp_max - comp_min do
|
212
|
-
comp = (comp_max - comp_min).div(2) + comp_min
|
213
|
-
if
|
214
|
-
comp_min = comp
|
176
|
+
def comp_search(para, target, smith, armor, opt: Mgmg::Option.new)
|
177
|
+
opt = opt.dup.set_default(self)
|
178
|
+
if opt.comp_max < opt.comp_min
|
179
|
+
raise ArgumentError, "comp_min <= comp_max is needed, (comp_min, comp_max) = (#{opt.comp_min}, #{opt.comp_max}) are given"
|
180
|
+
end
|
181
|
+
if target <= opt.irep.para_call(para, smith, armor, opt.comp_min)
|
182
|
+
return opt.comp_min
|
183
|
+
elsif opt.irep.para_call(para, smith, armor, opt.comp_max) < target
|
184
|
+
raise ArgumentError, "given comp_max=#{opt.comp_max} does not satisfies the target"
|
185
|
+
end
|
186
|
+
while 1 < opt.comp_max - opt.comp_min do
|
187
|
+
comp = (opt.comp_max - opt.comp_min).div(2) + opt.comp_min
|
188
|
+
if opt.irep.para_call(para, smith, armor, comp) < target
|
189
|
+
opt.comp_min = comp
|
215
190
|
else
|
216
|
-
comp_max = comp
|
191
|
+
opt.comp_max = comp
|
217
192
|
end
|
218
193
|
end
|
219
|
-
comp_max
|
194
|
+
opt.comp_max
|
220
195
|
end
|
221
|
-
def search(para, target,
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
exp = Mgmg.exp(smith_max, armor_max, comp_min)
|
237
|
-
minex, ret = exp, [smith_max, armor_max, comp_min] if exp < minex
|
238
|
-
(comp_min+1).upto(comp_max-1) do |comp|
|
239
|
-
break if minex < Mgmg.exp(smith_min, armor_min, comp)
|
240
|
-
smith, armor = sa_search(para, target, comp, smith_min, armor_min, smith_max, armor_max, left_associative: left_associative, cut_exp: [minex, cut_exp].min)
|
196
|
+
def search(para, target, opt: Mgmg::Option.new)
|
197
|
+
opt = opt.dup.set_default(self)
|
198
|
+
opt.comp_min = comp_search(para, target, opt.smith_max, opt.armor_max, opt: opt)
|
199
|
+
opt.smith_max, opt.armor_max = sa_search(para, target, opt.comp_min, opt: opt)
|
200
|
+
opt.smith_min, opt.armor_min = sa_search(para, target, opt.comp_max, opt: opt)
|
201
|
+
raise Mgmg::SearchCutException if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, opt.comp_min)
|
202
|
+
opt.comp_max = comp_search(para, target, opt.smith_min, opt.armor_min, opt: opt)
|
203
|
+
ret = nil
|
204
|
+
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 < opt.cut_exp
|
206
|
+
exp = Mgmg.exp(opt.smith_max, opt.armor_max, opt.comp_min)
|
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|
|
209
|
+
break if opt.cut_exp < Mgmg.exp(opt.smith_min, opt.armor_min, comp)
|
210
|
+
smith, armor = sa_search(para, target, comp, opt: opt)
|
241
211
|
exp = Mgmg.exp(smith, armor, comp)
|
242
|
-
if exp <
|
243
|
-
|
244
|
-
elsif exp ==
|
245
|
-
if
|
212
|
+
if exp < opt.cut_exp
|
213
|
+
opt.cut_exp, ret = exp, [smith, armor, comp]
|
214
|
+
elsif exp == opt.cut_exp
|
215
|
+
if ret.nil? or opt.irep.para_call(para, *ret) < opt.irep.para_call(para, smith, armor, comp) then
|
246
216
|
ret = [smith, armor, comp]
|
247
217
|
end
|
248
218
|
end
|
249
219
|
rescue Mgmg::SearchCutException
|
250
220
|
end
|
251
|
-
raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{cut_exp}" if
|
221
|
+
raise Mgmg::SearchCutException, "the result exceeds given cut_exp=#{opt.cut_exp}" if ret.nil?
|
252
222
|
ret
|
253
223
|
end
|
254
224
|
end
|
225
|
+
|
226
|
+
module Mgmg
|
227
|
+
module_function def find_lowerbound(a, b, para, start, term, opt_a: Option.new, opt_b: Option.new)
|
228
|
+
if term <= start
|
229
|
+
raise ArgumentError, "start < term is needed, (start, term) = (#{start}, #{term}) are given"
|
230
|
+
end
|
231
|
+
opt_a, opt_b = opt_a.dup.set_default(a), opt_b.dup.set_default(b)
|
232
|
+
sca, scb = a.search(para, start, opt: opt_a), b.search(para, start, opt: opt_b)
|
233
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
234
|
+
if eb < ea || ( ea == eb && opt_a.irep.para_call(para, *sca) < opt_b.irep.para_call(para, *scb) )
|
235
|
+
a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
|
236
|
+
end
|
237
|
+
tag = opt_a.irep.para_call(para, *sca) + 1
|
238
|
+
sca, scb = a.search(para, term, opt: opt_a), b.search(para, term, opt: opt_b)
|
239
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
240
|
+
if ea < eb || ( ea == eb && opt_b.irep.para_call(para, *scb) < opt_a.irep.para_call(para, *sca) )
|
241
|
+
raise Mgmg::SearchCutException
|
242
|
+
end
|
243
|
+
while tag < term
|
244
|
+
sca, scb = a.search(para, tag, opt: opt_a), b.search(para, tag, opt: opt_b)
|
245
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
246
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
247
|
+
if eb < ea
|
248
|
+
return [tag-1, pb]
|
249
|
+
elsif ea == eb
|
250
|
+
if pa < pb
|
251
|
+
return [tag-1, pa]
|
252
|
+
else
|
253
|
+
tag = pb + 1
|
254
|
+
end
|
255
|
+
else
|
256
|
+
tag = pa + 1
|
257
|
+
end
|
258
|
+
end
|
259
|
+
raise UnexpectedError
|
260
|
+
end
|
261
|
+
|
262
|
+
module_function def find_upperbound(a, b, para, start, term, opt_a: Option.new, opt_b: Option.new)
|
263
|
+
if start <= term
|
264
|
+
raise ArgumentError, "term < start is needed, (start, term) = (#{start}, #{term}) are given"
|
265
|
+
end
|
266
|
+
opt_a, opt_b = opt_a.dup.set_default(a), opt_b.dup.set_default(b)
|
267
|
+
sca, scb = a.search(para, start, opt: opt_a), b.search(para, start, opt: opt_b)
|
268
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
269
|
+
if ea < eb || ( ea == eb && opt_b.irep.para_call(para, *scb) < opt_a.irep.para_call(para, *sca) )
|
270
|
+
a, b, opt_a, opt_b, sca, scb, ea, eb = b, a, opt_b, opt_a, scb, sca, eb, ea
|
271
|
+
end
|
272
|
+
tagu = opt_a.irep.para_call(para, *sca)
|
273
|
+
sca[-1] -= 2
|
274
|
+
tagl = opt_a.irep.para_call(para, *sca)
|
275
|
+
sca, scb = a.search(para, term, opt: opt_a), b.search(para, term, opt: opt_b)
|
276
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
277
|
+
if eb < ea || ( ea == eb && opt_a.irep.para_call(para, *sca) < opt_b.irep.para_call(para, *scb) )
|
278
|
+
raise Mgmg::SearchCutException
|
279
|
+
end
|
280
|
+
while term < tagu
|
281
|
+
ret = nil
|
282
|
+
sca = a.search(para, tagl, opt: opt_a)
|
283
|
+
next_tagu, next_sca = tagl, sca
|
284
|
+
scb = b.search(para, tagl, opt: opt_b)
|
285
|
+
while tagl < tagu
|
286
|
+
ea, eb = Mgmg.exp(*sca), Mgmg.exp(*scb)
|
287
|
+
pa, pb = opt_a.irep.para_call(para, *sca), opt_b.irep.para_call(para, *scb)
|
288
|
+
if ea < eb
|
289
|
+
ret = tagl
|
290
|
+
sca = a.search(para, pa + 1, opt: opt_a)
|
291
|
+
tagl = opt_a.irep.para_call(para, *sca)
|
292
|
+
scb = b.search(para, tagl, opt: opt_b)
|
293
|
+
elsif ea == eb
|
294
|
+
if pb < pa
|
295
|
+
ret = tagl
|
296
|
+
sca = a.search(para, pa + 1, opt: opt_a)
|
297
|
+
tagl = opt_a.irep.para_call(para, *sca)
|
298
|
+
scb = b.search(para, tagl, opt: opt_b)
|
299
|
+
else
|
300
|
+
scb = b.search(para, pb + 1, opt: opt_b)
|
301
|
+
tagl = opt_b.irep.para_call(para, *scb)
|
302
|
+
sca = a.search(para, tagl, opt: opt_a)
|
303
|
+
end
|
304
|
+
else
|
305
|
+
sca = a.search(para, pa + 1, opt: opt_a)
|
306
|
+
tagl = opt_a.irep.para_call(para, *sca)
|
307
|
+
scb = b.search(para, tagl, opt: opt_b)
|
308
|
+
end
|
309
|
+
end
|
310
|
+
if ret.nil?
|
311
|
+
tagu = next_tagu
|
312
|
+
next_sca[-1] -= 2
|
313
|
+
tagl = opt_a.irep.para_call(para, *next_sca)
|
314
|
+
if tagl == tagu
|
315
|
+
tagl = term
|
316
|
+
end
|
317
|
+
else
|
318
|
+
pa = opt_a.irep.para_call(para, *a.search(para, ret+1, opt: opt_a))
|
319
|
+
pb = opt_b.irep.para_call(para, *b.search(para, ret+1, opt: opt_b))
|
320
|
+
return [ret, [pa, pb].min]
|
321
|
+
end
|
322
|
+
end
|
323
|
+
raise UnexpectedError
|
324
|
+
end
|
325
|
+
end
|
data/lib/mgmg/system_equip.rb
CHANGED
@@ -323,4 +323,10 @@ module Mgmg
|
|
323
323
|
SystemEquip.store(k.sub(/脛当て\Z/, 'すね当て'), SystemEquip[k])
|
324
324
|
end
|
325
325
|
end
|
326
|
+
SystemEquip.freeze
|
327
|
+
SystemEquipRegexp = Hash.new
|
328
|
+
SystemEquip.keys.each do |k|
|
329
|
+
SystemEquipRegexp.store(k.freeze, Regexp.compile(k))
|
330
|
+
end
|
331
|
+
SystemEquipRegexp.freeze
|
326
332
|
end
|
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
|
|
@@ -46,7 +71,19 @@ module Mgmg
|
|
46
71
|
end
|
47
72
|
attr_accessor :equip
|
48
73
|
end
|
74
|
+
class InvalidReinforcementNameError < StandardError
|
75
|
+
def initialize(str)
|
76
|
+
@name = str
|
77
|
+
super("Unknown skill or preset cuisine name `#{@name}' is given.")
|
78
|
+
end
|
79
|
+
attr_accessor :name
|
80
|
+
end
|
49
81
|
class SearchCutException < StandardError; end
|
82
|
+
class UnexpectedError < StandardError
|
83
|
+
def initialize()
|
84
|
+
super("There is a bug in `mgmg' gem. Please report to https://github.com/cycloawaodorin/mgmg/issues .")
|
85
|
+
end
|
86
|
+
end
|
50
87
|
|
51
88
|
module_function def exp(smith, armor, comp=armor.tap{armor=0})
|
52
89
|
if armor <= 0
|
@@ -86,7 +123,7 @@ module Mgmg
|
|
86
123
|
Math.sqrt(exp - ((sa-1)**2) - (2*((comp-1)**2)) - 4).round + 1
|
87
124
|
end
|
88
125
|
|
89
|
-
CharacterList = /[^\(\)\+0123456789\[\]あきくしすたてなねのびりるイウガクグサジスタダチツデトドニノフブペボムラリルロンヴー一万二光兜典刀剣劣匠双古名吹咆品哮地大天太子安宝小帽弓弩当息悪戦手指斧書服木本杖業樹歴殺水氷法火炎牙物玉王産用界異的皮盾短石砕竜紫綿耳聖脛腕腿般良色衣袋覇質軍軽輝輪重量金鉄鎧闇陽靴額飾首骨鬼龍]
|
126
|
+
CharacterList = /[^\(\)\+0123456789\[\]あきくしすたてなねのびりるイウガクグサジスタダチツデトドニノフブペボムラリルロンヴー一万二光兜典刀剣劣匠双古名吹咆品哮地大天太子安宝小帽弓弩当息悪戦手指斧書服木本杖業樹歴殺水氷法火炎牙物玉王産用界異的皮盾短石砕竜紫綿耳聖脛腕腿般良色衣袋覇質軍軽輝輪重量金鉄鎧闇陽靴額飾首骨鬼龍]/.freeze
|
90
127
|
module_function def check_string(str)
|
91
128
|
str = str.gsub(/[\s \\]/, '')
|
92
129
|
if m = CharacterList.match(str)
|
@@ -130,6 +167,15 @@ module Mgmg
|
|
130
167
|
str
|
131
168
|
end
|
132
169
|
|
170
|
+
module_function def parse_material(str)
|
171
|
+
m = /\A.+?(\d+)\Z/.match(str)
|
172
|
+
mat = MaterialIndex[str.to_sym]
|
173
|
+
if m.nil? || mat.nil?
|
174
|
+
raise InvalidMaterialError.new(str)
|
175
|
+
end
|
176
|
+
[mat, m[1].to_i, mat<90 ? mat.div(10) : 9]
|
177
|
+
end
|
178
|
+
|
133
179
|
class Vec < Array
|
134
180
|
def add!(other)
|
135
181
|
case other
|
data/lib/mgmg/version.rb
CHANGED