mgmg 1.2.4 → 1.2.5

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.
@@ -0,0 +1,323 @@
1
+ module Mgmg
2
+ using Refiner
3
+ class Equip
4
+ ParamList = %w|攻撃 物防 魔防 HP MP 腕力 器用 素早 魔力|
5
+ ElementList = %w|火 地 水|
6
+ EqPosList = %w|武 頭 胴 腕 足 飾|
7
+ def initialize(kind, weight, star, main_m, sub_m, para, element)
8
+ @kind, @weight, @star, @main, @sub, @para, @element = kind, weight, star, main_m, sub_m, para, element
9
+ @total_cost = Vec[0, 0, 0]
10
+ @history, @min_levels = [self], Hash.new
11
+ end
12
+ attr_accessor :kind, :weight, :star, :main, :sub, :para, :element, :total_cost, :history, :min_levels
13
+ def initialize_copy(other)
14
+ @kind = other.kind
15
+ @weight = other.weight
16
+ @star = other.star
17
+ @main = other.main
18
+ @sub = other.sub
19
+ @para = other.para.dup
20
+ @element = other.element.dup
21
+ @total_cost = other.total_cost.dup
22
+ @history = other.history.dup
23
+ @min_levels = other.min_levels.dup
24
+ end
25
+
26
+ def compose(other, level, outsourcing=false)
27
+ self.class.compose(self, other, level, outsourcing)
28
+ end
29
+
30
+ def to_s
31
+ par = @para.map.with_index{|e, i| e==0 ? nil : "#{ParamList[i]}:#{e.comma3}"}.compact
32
+ elm = @element.map.with_index{|e, i| e==0 ? nil : "#{ElementList[i]}#{e}"}.compact
33
+ unless elm.empty?
34
+ par << "EL:#{elm.join('')}"
35
+ end
36
+ if @kind == 28
37
+ ep = @star.map.with_index{|e, i| e==0 ? nil : "#{EqPosList[i]}:#{e}"}.compact
38
+ "複数装備#{@weight}(#{ep.join(', ')})[#{par.join(', ')}]"
39
+ else
40
+ "#{EquipName[@kind]}#{@weight}☆#{@star}(#{MaterialClass[@main]}#{MaterialClass[@sub]})[#{par.join(', ')}]"
41
+ end
42
+ end
43
+ def inspect
44
+ par = @para.map.with_index{|e, i| "#{ParamList[i]}:#{e}"}
45
+ par << ( "EL:" + @element.map.with_index{|e, i| "#{ElementList[i]}#{e}"}.join('') )
46
+ tc = "<コスト:" + @total_cost.map.with_index{|e, i| "#{ElementList[i]}#{e}"}.join('') + '>'
47
+ if @kind == 28
48
+ ep = @star.map.with_index{|e, i| "#{EqPosList[i]}:#{e}"}
49
+ "複数装備#{@weight}(#{ep.join(', ')})[#{par.join(', ')}]#{tc}"
50
+ else
51
+ "#{EquipName[@kind]}#{@weight}☆#{@star}(#{MaterialClass[@main]}#{MaterialClass[@sub]})[#{par.join(', ')}]#{tc}"
52
+ end
53
+ end
54
+
55
+ def min_level
56
+ if @kind == 28
57
+ ret = [0, 0]
58
+ @min_levels.each do |str, ml|
59
+ if str.build(-1).kind < 8
60
+ if ret[0] < ml
61
+ ret[0] = ml
62
+ end
63
+ else
64
+ if ret[1] < ml
65
+ ret[1] = ml
66
+ end
67
+ end
68
+ end
69
+ ret
70
+ else
71
+ @min_levels.values.max
72
+ end
73
+ end
74
+
75
+ %i|attack phydef magdef hp mp str dex speed magic|.each.with_index do |s, i|
76
+ define_method(s){ @para[i] }
77
+ end
78
+ def atkstr
79
+ attack()+str()
80
+ end
81
+ def atk_sd
82
+ attack()*2+str()+dex()
83
+ end
84
+ def dex_as
85
+ attack()+str()+dex()*2
86
+ end
87
+ def mag_das
88
+ magic()*4+dex_as()
89
+ end
90
+ [:fire, :earth, :water].each.with_index do |s, i|
91
+ define_method(s){ @element[i] }
92
+ end
93
+
94
+ def power
95
+ case @kind
96
+ when 0, 1
97
+ atk_sd()*2
98
+ when 2, 3
99
+ atkstr()*4
100
+ when 4
101
+ [dex_as()*2, mag_das()].max
102
+ when 5
103
+ dex_as()*2
104
+ when 6, 7
105
+ [magic()*8, atkstr()*4].max
106
+ when 28
107
+ (@para.sum*4)-((hp()+mp())*3)
108
+ else
109
+ ret = @para.max
110
+ if ret == magdef()
111
+ ret*2+magic()
112
+ else
113
+ ret*2
114
+ end
115
+ end
116
+ end
117
+ def magmag
118
+ magdef()*2+magic()
119
+ end
120
+ def fpower
121
+ if @kind < 8 || @kind == 28
122
+ power().fdiv(4)
123
+ else
124
+ power().fdiv(2)
125
+ end
126
+ end
127
+
128
+ def smith_cost(outsourcing=false)
129
+ if outsourcing
130
+ if @kind < 8
131
+ (@star**2)*2+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()
132
+ else
133
+ (@star**2)+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()
134
+ end
135
+ else
136
+ if @kind < 8
137
+ ((@star**2)*2+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2)
138
+ else
139
+ ((@star**2)+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2)
140
+ end
141
+ end
142
+ end
143
+ def comp_cost(outsourcing=false)
144
+ if outsourcing
145
+ [(@star**2)*5+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp(), 0].max
146
+ else
147
+ [((@star**2)*5+@para.sum+hp().cdiv(4)-hp()+mp().cdiv(4)-mp()).div(2), 0].max
148
+ end
149
+ end
150
+ alias :cost :comp_cost
151
+
152
+ def add!(other)
153
+ if @kind == 28
154
+ if other.kind == 28
155
+ @star.add!(other.star)
156
+ else
157
+ @star[EquipPosition[other.kind]] += 1
158
+ end
159
+ else
160
+ @star = Vec.new(6, 0)
161
+ @star[EquipPosition[@kind]] = 1
162
+ @kind = 28
163
+ if other.kind == 28
164
+ @star.add!(other.star)
165
+ else
166
+ @star[EquipPosition[other.kind]] += 1
167
+ end
168
+ end
169
+ @weight += other.weight
170
+ @main = 12
171
+ @sub = 12
172
+ @para.add!(other.para)
173
+ @element.add!(other.element)
174
+ @total_cost.add!(other.total_cost)
175
+ @history.concat(other.history)
176
+ @min_levels.merge!(other.min_levels)
177
+ self
178
+ end
179
+ def +(other)
180
+ self.dup.add!(other)
181
+ end
182
+ def coerce(other)
183
+ if other == 0
184
+ zero = self.class.new(28, 0, Vec.new(6, 0), 12, 12, Vec.new(9, 0), Vec.new(3, 0))
185
+ zero.history.clear
186
+ [zero, self]
187
+ else
188
+ raise TypeError, "Mgmg::Equip can't be coerced into other than 0"
189
+ end
190
+ end
191
+ end
192
+
193
+ class << Equip
194
+ def build(str, s_level, c_level, left_associative: true)
195
+ str = Mgmg.check_string(str)
196
+ stack, str = build_sub0([], str)
197
+ build_sub(stack, str, s_level, c_level, left_associative)
198
+ end
199
+ private def build_sub0(stack, str)
200
+ SystemEquip.each do |k, v|
201
+ if Regexp.compile(k).match(str)
202
+ stack << v
203
+ str = str.gsub(k, "<#{stack.length-1}>")
204
+ end
205
+ end
206
+ [stack, str]
207
+ end
208
+ private def build_sub(stack, str, s_level, c_level, lassoc)
209
+ if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
210
+ stack << build_sub(stack, m[2], s_level, c_level, lassoc)
211
+ build_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", s_level, c_level, lassoc)
212
+ elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
213
+ if c_level < 0
214
+ compose(build_sub(stack, m[1], s_level, c_level, lassoc), build_sub(stack, m[2], s_level, c_level, lassoc), 0, true)
215
+ else
216
+ compose(build_sub(stack, m[1], s_level, c_level, lassoc), build_sub(stack, m[2], s_level, c_level, lassoc), c_level, false)
217
+ end
218
+ elsif m = /\A\<(\d+)\>\Z/.match(str)
219
+ stack[m[1].to_i]
220
+ else
221
+ if s_level < 0
222
+ smith(str, 0, true)
223
+ else
224
+ smith(str, s_level, false)
225
+ end
226
+ end
227
+ end
228
+
229
+ def compose(main, sub, level, outsourcing)
230
+ main_k, sub_k = main.kind, sub.kind
231
+ main_s, sub_s = main.star, sub.star
232
+ main_main, sub_main = main.main, sub.main
233
+ main_sub, sub_sub = main.sub, sub.sub
234
+ para = Vec.new(9, 0)
235
+ ele = Vec.new(3, 0)
236
+
237
+ # 9パラメータ
238
+ coef = Equip9[main_k].dup
239
+ para[] = coef
240
+ para.add!(level).e_div!(2)
241
+ para.e_mul!(sub.para).e_div!(100)
242
+ coef.sub!(Equip9[sub_k])
243
+ coef.add!( 100 + (main_s-sub_s)*5 - ( ( main_main==sub_main && main_main != 9 ) ? 30 : 0 ) )
244
+ coef.add!(Material9[main_main]).sub!(Material9[sub_main])
245
+ coef.e_mul!(EquipFilter[main_k])
246
+ para.e_mul!(coef).e_div!( main_k==sub_k ? 200 : 100 )
247
+ para.add!(main.para)
248
+
249
+ # エレメント
250
+ ele[] = sub.element
251
+ ele.e_mul!([75, level].min).e_div!( main_k==sub_k ? 200 : 100 )
252
+ ele.add!(main.element)
253
+
254
+ ret = new(main_k, main.weight+sub.weight, main_s+sub_s, main_sub, sub_main, para, ele)
255
+ ret.total_cost.add!(main.total_cost).add!(sub.total_cost)
256
+ ret.total_cost[1] += ret.comp_cost(outsourcing)
257
+ ret.min_levels.merge!(main.min_levels, sub.min_levels)
258
+ ret.history = [*main.history, *sub.history, ret]
259
+ ret
260
+ end
261
+
262
+ def smith(str, level, outsourcing)
263
+ str = Mgmg.check_string(str)
264
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
265
+ raise InvalidSmithError.new(str)
266
+ end
267
+ kind = EquipIndex[m[1].to_sym]
268
+ unless kind
269
+ raise InvalidEquipClassError.new(m[1])
270
+ end
271
+ main_m, main_s, main_mc = parse_material(m[2])
272
+ sub_m, sub_s, sub_mc = parse_material(m[3])
273
+ para = Vec.new(9, 0)
274
+ ele = Vec.new(3, 0)
275
+
276
+ # 9パラメータ
277
+ para[] = Equip9[kind]
278
+ para.e_mul!(Main9[main_m]).e_div!(100)
279
+ coef = Sub9[sub_m].dup
280
+ coef.add!(level)
281
+ para.e_mul!(coef).e_div!( main_mc==sub_mc ? 200 : 100 )
282
+
283
+ # エレメント
284
+ ele[] = MainEL[main_m]
285
+ ele.e_mul!(SubEL[sub_m]).e_div!(6)
286
+
287
+ # 重量
288
+ weight = ( ( EquipWeight[kind] + SubWeight[sub_m] - level.div(2) ) * ( MainWeight[main_m] ) ).div(10000)
289
+
290
+ ret = new(kind, ( weight<1 ? 1 : weight ), (main_s+sub_s).div(2), main_mc, sub_mc, para, ele)
291
+ if kind < 8
292
+ ret.total_cost[0] = ret.smith_cost(outsourcing)
293
+ else
294
+ ret.total_cost[2] = ret.smith_cost(outsourcing)
295
+ end
296
+ ret.min_levels.store(str, str.min_level)
297
+ ret
298
+ end
299
+
300
+ def min_level(str, weight=1)
301
+ str = Mgmg.check_string(str)
302
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
303
+ raise InvalidSmithError.new(str)
304
+ end
305
+ kind = EquipIndex[m[1].to_sym]
306
+ main_m, main_s, = parse_material(m[2])
307
+ sub_m, sub_s, = parse_material(m[3])
308
+
309
+ q, r = ((weight+1)*10000).divmod(MainWeight[main_m])
310
+ l = ( EquipWeight[kind] + SubWeight[sub_m] - q + ( r==0 ? 1 : 0 ) )*2
311
+ [(main_s-1)*3, (sub_s-1)*3, l].max
312
+ end
313
+
314
+ private def parse_material(str)
315
+ m = /\A.+?(\d+)\Z/.match(str)
316
+ mat = MaterialIndex[str.to_sym]
317
+ if m.nil? || mat.nil?
318
+ raise InvalidMaterialError.new(str)
319
+ end
320
+ [mat, m[1].to_i, mat<90 ? mat.div(10): 9]
321
+ end
322
+ end
323
+ end
@@ -0,0 +1,266 @@
1
+ module Mgmg
2
+ using Refiner
3
+ class TPolynomial
4
+ def initialize(mat, kind, star, main_m, sub_m)
5
+ @mat, @kind, @star, @main, @sub = mat, kind, star, main_m, sub_m
6
+ end
7
+ attr_accessor :mat, :kind, :star, :main, :sub
8
+ def initialize_copy(obj)
9
+ @mat, @kind, @star, @main, @sub = obj.mat.dup, obj.kind, obj.star, obj.main, obj.sub
10
+ end
11
+ def evaluate(smith, comp=smith)
12
+ @mat.map_with_index do |e, i, j|
13
+ e * (smith**i) * (comp**j)
14
+ end.sum
15
+ end
16
+ def to_s(fmt=nil)
17
+ foo = []
18
+ (@mat.col_size-1).downto(0) do |c|
19
+ bar = []
20
+ (@mat.row_size-1).downto(0) do |s|
21
+ value = @mat.body[s][c]
22
+ baz = str(value, fmt)
23
+ case s
24
+ when 0
25
+ # nothing to do
26
+ when 1
27
+ baz << 'S'
28
+ else
29
+ baz << "S^#{s}"
30
+ end
31
+ bar << baz if value != 0
32
+ end
33
+ case bar.length
34
+ when 0
35
+ next
36
+ when 1
37
+ bar = bar[0]
38
+ else
39
+ bar = "(#{bar.join('+')})"
40
+ end
41
+ case c
42
+ when 0
43
+ # nothing to do
44
+ when 1
45
+ bar << 'C'
46
+ else
47
+ bar << "C^#{c}"
48
+ end
49
+ foo << bar
50
+ end
51
+ foo.join('+').tap{|r| break str(0.quo(1), fmt) if r==''}
52
+ end
53
+ private def str(value, fmt)
54
+ ret = case fmt
55
+ when NilClass
56
+ value.to_s
57
+ when String
58
+ fmt % value
59
+ when Symbol
60
+ value.__send__(fmt)
61
+ when Proc
62
+ fmt.call(value)
63
+ else
64
+ raise
65
+ end
66
+ if ret[0] == '-' || ( /\//.match(ret) && ret[0] != '(' )
67
+ "(#{ret})"
68
+ else
69
+ ret
70
+ end
71
+ end
72
+ def inspect(fmt=->(r){"Rational(#{r.numerator}, #{r.denominator})"})
73
+ foo = []
74
+ (@mat.col_size-1).downto(0) do |c|
75
+ bar = []
76
+ (@mat.row_size-1).downto(0) do |s|
77
+ value = @mat.body[s][c]
78
+ bar << str(value, fmt)
79
+ end
80
+ buff = bar[0]
81
+ buff = "#{buff}*s+#{bar[1]}" if 1 < bar.length
82
+ 2.upto(bar.length-1) do |i|
83
+ buff = "(#{buff})*s+#{bar[i]}"
84
+ end
85
+ foo << buff
86
+ end
87
+ ret = foo[0]
88
+ 1.upto(foo.length-1) do |i|
89
+ ret = "(#{ret})*c+#{foo[i]}"
90
+ end
91
+ ret
92
+ end
93
+ def leading(fmt=nil)
94
+ value = self[-1, -1]
95
+ if fmt.nil?
96
+ value
97
+ else
98
+ str(value, fmt)
99
+ end
100
+ end
101
+ def smith_balance(other, order=-1)
102
+ o_org = order
103
+ order += @mat.col_size if order < 0
104
+ if order < 0 || @mat.col_size <= order || other.mat.col_size <= order then
105
+ raise ArgumentError, "given order #{o_org} is out of range [-max(#{@mat.col_size}, #{other.mat.col_size}), max(#{@mat.col_size}, #{other.mat.col_size})-1]"
106
+ end
107
+ a, b, c, d = @mat.body[1][order], @mat.body[0][order], other.mat.body[1][order], other.mat.body[0][order]
108
+ if a == c
109
+ return( b == d )
110
+ else
111
+ return( (d-b).quo(a-c) )
112
+ end
113
+ end
114
+ def smith_fix(smith, fmt=nil)
115
+ foo = []
116
+ (@mat.col_size-1).downto(0) do |c|
117
+ bar = 0
118
+ (@mat.row_size-1).downto(0) do |s|
119
+ bar += ( @mat.body[s][c] * (smith**s) )
120
+ end
121
+ bar = str(bar, fmt)
122
+ case c
123
+ when 0
124
+ # nothing to do
125
+ when 1
126
+ bar << 'C'
127
+ else
128
+ bar << "C^#{c}"
129
+ end
130
+ foo << bar
131
+ end
132
+ foo.join('+')
133
+ end
134
+
135
+ alias :+@ :dup
136
+ def -@
137
+ ret = self.dup
138
+ ret.mat.scalar!(-1)
139
+ ret
140
+ end
141
+ def +(other)
142
+ mat = @mat.padd(other.mat)
143
+ self.class.new(mat, 28, 0, 12, 12)
144
+ end
145
+ def -(other)
146
+ mat = @mat.padd(other.mat.scalar(-1))
147
+ self.class.new(mat, 28, 0, 12, 12)
148
+ end
149
+ def scalar(val)
150
+ ret = self.dup
151
+ ret.mat.scalar!(val)
152
+ ret
153
+ end
154
+ alias :* :scalar
155
+ def quo(val)
156
+ ret = self.dup
157
+ ret.mat.scalar!(1.quo(val))
158
+ ret
159
+ end
160
+ alias :/ :quo
161
+
162
+ def partial_derivative(variable)
163
+ case variable.to_s
164
+ when /\Ac/i
165
+ if @mat.col_size <= 1
166
+ self.class.new(Mat.new(1, 1, 0), 28, 0, 12, 12)
167
+ else
168
+ mat = Mat.new(@mat.row_size, @mat.col_size-1) do |i, j|
169
+ @mat.body[i][j+1] * (j+1)
170
+ end
171
+ self.class.new(mat, 28, 0, 12, 12)
172
+ end
173
+ when /\As/i
174
+ if @mat.row_size <= 1
175
+ self.class.new(Mat.new(1, 1, 0), 28, 0, 12, 12)
176
+ else
177
+ mat = Mat.new(@mat.row_size-1, @mat.col_size) do |i, j|
178
+ @mat.body[i+1][j] * (i+1)
179
+ end
180
+ self.class.new(mat, 28, 0, 12, 12)
181
+ end
182
+ else
183
+ raise ArgumentError, "the argument must be `s' or `c', not `#{variable}'"
184
+ end
185
+ end
186
+
187
+ def [](i, j)
188
+ if (i < 0 && @mat.body.size < -i) || (j < 0 && @mat.body[0].size < -j)
189
+ raise IndexError, "(#{i}, #{j}) is out of (#{@mat.body.size}, #{@mat.body[0].size})"
190
+ end
191
+ begin
192
+ ret = @mat.body[i][j]
193
+ rescue NoMethodError
194
+ return 0
195
+ end
196
+ ret.nil? ? 0 : ret
197
+ end
198
+ end
199
+ class << TPolynomial
200
+ ParamIndex = Hash.new
201
+ %i|attack phydef magdef hp mp str dex speed magic|.each.with_index do |s, i|
202
+ ParamIndex.store(s, i)
203
+ ParamIndex.store(i, i)
204
+ ParamIndex.store(Equip::ParamList[i], i)
205
+ end
206
+ def from_equip(equip, para)
207
+ new(Mat.new(1, 1, equip.para[ParamIndex[para]]), equip.kind, equip.star, equip.main, equip.sub)
208
+ end
209
+ def smith(str, para)
210
+ unless m = /\A(.+)\((.+\d+),?(.+\d+)\)\Z/.match(str)
211
+ raise ArgumentError.new("given string `#{str}' is unparsable as a smithing recipe")
212
+ end
213
+ kind = EquipIndex[m[1].to_sym]
214
+ main_m, main_s, main_mc = Equip.__send__(:parse_material, m[2])
215
+ sub_m, sub_s, sub_mc = Equip.__send__(:parse_material, m[3])
216
+ para = ParamIndex[para]
217
+
218
+ c = ( Equip9[kind][para] * Main9[main_m][para] ).cdiv(100).quo( main_mc==sub_mc ? 200 : 100 )
219
+ new(Mat.v_array(c*Sub9[sub_m][para], c), kind, (main_s+sub_s).div(2), main_mc, sub_mc)
220
+ end
221
+ def compose(main, sub, para)
222
+ main_k, sub_k = main.kind, sub.kind
223
+ main_s, sub_s = main.star, sub.star
224
+ main_main, sub_main = main.main, sub.main
225
+ main_sub, sub_sub = main.sub, sub.sub
226
+ para = ParamIndex[para]
227
+
228
+ if Equip9[main_k][para] == 0
229
+ c = 0.quo(1)
230
+ else
231
+ c = ( 100 + Equip9[main_k][para] - Equip9[sub_k][para] + Material9[main_main][para] - Material9[sub_main][para] +
232
+ (main_s-sub_s)*5 - ( ( main_main==sub_main && main_main != 9 ) ? 30 : 0 ) ).quo( main_k==sub_k ? 40000 : 20000 )
233
+ end
234
+ mat = main.mat.padd(sub.mat.pprod(Mat.h_array(c*Equip9[main_k][para], c)))
235
+ new(mat, main_k, main_s+sub_s, main_sub, sub_main)
236
+ end
237
+ def build(str, para, left_associative: true)
238
+ str = Mgmg.check_string(str)
239
+ _para = ParamIndex[para]
240
+ if _para.nil?
241
+ raise ArgumentError, "unknown parameter symbol `#{para.inspect}' given"
242
+ end
243
+ stack, str = build_sub0([], str, _para)
244
+ build_sub(stack, str, _para, left_associative)
245
+ end
246
+ private def build_sub0(stack, str, para)
247
+ SystemEquip.each do |k, v|
248
+ stack << from_equip(v, para)
249
+ str = str.gsub(k, "<#{stack.length-1}>")
250
+ end
251
+ [stack, str]
252
+ end
253
+ private def build_sub(stack, str, para, lassoc)
254
+ if m = /\A(.*\+?)\[([^\[\]]+)\](\+?[^\[]*)\Z/.match(str)
255
+ stack << build_sub(stack, m[2], para, lassoc)
256
+ build_sub(stack, "#{m[1]}<#{stack.length-1}>#{m[3]}", para, lassoc)
257
+ elsif m = ( lassoc ? /\A(.+)\+(.+?)\Z/ : /\A(.+?)\+(.+)\Z/ ).match(str)
258
+ compose(build_sub(stack, m[1], para, lassoc), build_sub(stack, m[2], para, lassoc), para)
259
+ elsif m = /\A\<(\d+)\>\Z/.match(str)
260
+ stack[m[1].to_i]
261
+ else
262
+ smith(str, para)
263
+ end
264
+ end
265
+ end
266
+ end