Olib 0.0.3 → 0.0.4

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,77 @@
1
+ module Olib
2
+ module Inventory
3
+ Vars.Olib[:Inventory] ||= Hash.new
4
+
5
+ @@checked = false
6
+
7
+
8
+ def Inventory.containers
9
+ Inventory.check
10
+ GameObj.containers
11
+ end
12
+
13
+
14
+ def Inventory.checked?
15
+ @@checked
16
+ end
17
+
18
+ def Inventory.[](query)
19
+ GameObj.inv.select { |item|
20
+ item.name == query || item.id == query
21
+ }
22
+ end
23
+
24
+ def Inventory.teleporter
25
+ # check for worn teleporter
26
+ candidates= GameObj.inv.select { |item|
27
+ item.name == Vars.teleporter
28
+ }
29
+
30
+ unless candidates.empty?
31
+ return Item.new(candidates.first)
32
+ end
33
+
34
+ # check in containers
35
+ Inventory.items.select { |item|
36
+ item.is? "teleporter"
37
+ }.first
38
+ end
39
+
40
+ def Inventory.items
41
+ Inventory.containers.map { |id, contents| contents.map {|item|
42
+ Item.new(item).define("container", id)
43
+ }
44
+ }.flatten
45
+ end
46
+
47
+ def Inventory.check
48
+ return self if Inventory.checked?
49
+ GameObj.inv.select{ |item|
50
+ !item.name.include?('tattoo')
51
+ }.each {|item|
52
+ if item.contents.nil?
53
+ Olib.wrap("look in ##{item.id}") { |line|
54
+ respond line =~ /Shadow engulf/
55
+
56
+ raise Olib::Errors::Mundane if line =~ /There is nothing in there.|Total|^In the (.*).$|prompt|^Shadows engulf/
57
+
58
+ if line =~ /That is closed./
59
+ Olib.wrap("open ##{item.id}") { |line|
60
+ if line =~ /You open/
61
+ multifput "look in ##{item.id}", "close ##{item.id}"
62
+ end
63
+ }
64
+ end
65
+ }
66
+ end
67
+ }
68
+ @@checked = true
69
+ return self
70
+ end
71
+
72
+ end
73
+
74
+ def Olib.Inventory
75
+ Olib::Inventory
76
+ end
77
+ end
data/lib/Olib/item.rb CHANGED
@@ -3,45 +3,466 @@ require 'Olib/dictionary'
3
3
 
4
4
  module Olib
5
5
  # special item wrapper class to wrap item types with custom, common interactions becoming syntactic sugar
6
- class Item < Gameobj_Extender
6
+ class Item < Olib::Gameobj_Extender
7
+ attr_accessor :props
7
8
 
8
- def take
9
- result = Olib.do "get ##{@id}", /#{[Olib::Gemstone_Regex.get[:success], Olib::Gemstone_Regex.get[:failure].values].flatten.join('|')}/
10
- if result =~ Olib::Gemstone_Regex.get[:failure][:buy]
11
- while(line=get)
12
- if line =~ /However, it'll be ([0-9]+) silvers for someone like you/
13
- @cost = $1.to_i
14
- @buyable = true
15
- break;
16
- elsif line =~ /The selling price is ([0-9]+) silvers/
17
- @cost = $1.to_i
18
- @buyable = true
19
- break;
20
- end
21
- break;
22
- end
23
- end
24
- result
25
- end
26
-
27
- def wear
28
- result = Olib.do "wear ##{@id}", /You can only wear|^You put|^You slide|^You attach|^You hang/
29
- if result =~ /You can only wear/
30
- return false
31
- else
32
- return true
9
+ def initialize(obj=nil)
10
+ @props = Hash.new
11
+
12
+ @props[:name] = obj.name
13
+ @props[:after_name] = obj.after_name
14
+
15
+ define :tags, []
16
+ obj.type.split(',').map { |t| tag(t) }
17
+
18
+ if is?('jar') && @props[:after_name] =~ /containing (.*+?)/
19
+ tag Dictionary.gems[:singularize].call @props[:after_name].gsub('containing', '').strip
20
+ end
21
+
22
+ if is?('gem')
23
+ tag Dictionary.gems[:singularize].call @props[:name]
24
+ end
25
+
26
+ if is?('jar') && @props[:after_name].nil?
27
+ tag('empty')
33
28
  end
29
+
30
+ if Vars.teleporter && Vars.teleporter == @props[:name]
31
+ tag('teleporter')
32
+ end
33
+
34
+ super(obj)
35
+ end
36
+
37
+ def to_s
38
+ @props.to_s
39
+ end
40
+
41
+ def is?(tag)
42
+ @props[:tags].include?(tag)
43
+ end
44
+
45
+ def tag(*tags)
46
+ @props[:tags].concat(tags)
47
+ self
34
48
  end
35
49
 
36
- def remove; fput "remove ##{@id}"; self; end
50
+ def untag(*remove)
51
+ @props[:tags] = @props[:tags].select { |tag| !remove.include?(tag) }
52
+ end
37
53
 
38
- def buy ; fput "buy ##{@id}"; self; end
54
+ def tags
55
+ @props[:tags]
56
+ end
39
57
 
40
- def give(target); fput "give ##{@id} to #{target}"; self; end
58
+ def worn?
59
+ GameObj.inv.collect { |item| item.id }.include? @id
60
+ end
61
+
62
+ def crawl
63
+ take
64
+ tap._inspect.read.look
65
+ self
66
+ end
67
+
68
+ def buy
69
+ fput action 'buy'
70
+ self
71
+ end
72
+
73
+ def has?(key)
74
+ !@props[key].nil?
75
+ end
76
+
77
+ def missing?(key)
78
+ !has?(key)
79
+ end
80
+
81
+ def pullable?
82
+ is? 'pullable'
83
+ end
84
+
85
+ def buyable?
86
+ is? 'buyable'
87
+ end
88
+
89
+ def cost
90
+ @props['cost']
91
+ end
92
+
93
+ def acquire_from_shop
94
+ take
95
+ if pullable?
96
+ return pull
97
+ else
98
+ Olib.wrap(action "buy"){ |line|
99
+ raise Olib::Errors::InsufficientFunds if line =~ /The merchant frowns/
100
+ raise Olib::Errors::Mundane if line =~ /You hand over/
101
+ }
102
+ end
103
+ self
104
+ end
105
+
106
+ def in
107
+ return self if has? 'contents'
108
+ Olib.wrap(action 'look in') { |line|
109
+ raise Olib::Errors::Mundane if line=~/^There is nothing in there./
110
+
111
+ # handle jar data
112
+ if line =~ /Inside (.*?) you see (?<number>[\d]+) portion(|s) of (?<type>.*?). It is (more than |less than|)(?<percent>[a-z ]+)./
113
+ data = line.match(/Inside (.*?) you see (?<number>[\d]+) portion(|s) of (?<type>.*?). It is (more than |less than|)(?<percentage>[a-z ]+)./)
114
+ tag data[:percentage] == 'full' ? "full" : "partial"
115
+ define :number, data[:number].to_i
116
+ raise Olib::Errors::Mundane
117
+ end
118
+
119
+ #handle empty jars
120
+ if line =~ /The (.*?) is empty./
121
+ tag 'empty'
122
+ raise Olib::Errors::Mundane
123
+ end
124
+ }
125
+ self
126
+ end
41
127
 
42
128
  def _drag(target)
43
- Olib.do "_drag ##{@id} ##{target.id}", /#{[Olib::Gemstone_Regex.put[:success], Olib::Gemstone_Regex.put[:failure].values].flatten.join("|")}/
129
+ Olib.wrap("_drag ##{@id} ##{target.id}") { |line|
130
+ # order of operations is important here for jars
131
+ raise Olib::Errors::DoesntExist if line =~ Dictionary.put[:failure][:ne]
132
+ raise Olib::Errors::Mundane if line =~ Dictionary.put[:success]
133
+
134
+ if line =~ Dictionary.put[:failure][:full]
135
+ tag 'full'
136
+ raise Olib::Errors::ContainerFull
137
+ end
138
+ }
139
+ self
140
+ end
141
+
142
+ def stash
143
+ _drag GameObj[props['container']]
144
+ end
145
+
146
+ def shake
147
+ # make sure we have a count so we need to match fewer lines
148
+ self.in if is? 'jar' and missing? :number
149
+
150
+ Olib.wrap(action "shake"){ |line|
151
+ raise Olib::Errors::Fatal if line =~ /you realize that it is empty/
152
+ if line =~ /fall into your/
153
+ @props[:number] = @props[:number]-1
154
+ raise Olib::Errors::Fatal.new "Jar is now empty\n you should rescue this to handle it gracefully" if @props[:number] == 0
155
+ raise Olib::Errors::Mundane
156
+ end
157
+ }
158
+ self
159
+ end
160
+
161
+ def shop_sell(amt)
162
+ if GameObj.right_hand.id != @id
163
+ raise Olib::Errors::Fatal
164
+ end
165
+
166
+ Olib.wrap("shop sell #{amt}") {|line|
167
+ raise Olib::Errors::Mundane if line =~ /^You place your/
168
+ raise Olib::Errors::Fatal if line =~ /There's no more room for anything else right now./
169
+ }
170
+
171
+ end
172
+
173
+
174
+ def turn
175
+ fput action 'turn'
176
+ self
177
+ end
178
+
179
+ def action(verb)
180
+ "#{verb} ##{@id}"
181
+ end
182
+
183
+ def add(*items)
184
+ items.each { |item|
185
+ item._drag(self)
186
+ }
187
+ self
188
+ end
189
+
190
+ def define(key, val)
191
+ @props[key] = val
192
+ self
193
+ end
194
+
195
+ def pull(onfailure=nil)
196
+ refresh_instance = false
197
+ original_right = GameObj.right_hand
198
+ original_left = GameObj.left_hand
199
+ Olib.wrap(action "pull") { |line|
200
+
201
+ if line =~ /^You pull/
202
+ if line =~ /There (are|is) ([\d]+) left/
203
+ refresh_instance = true
204
+ end
205
+ raise Olib::Errors::Mundane
206
+ end
207
+
208
+ if line =~ /I'm afraid that you can't pull that./
209
+ if onfailure
210
+ onfailure.call(self)
211
+ else
212
+ raise Olib::Errors::DoesntExist
213
+ end
214
+ end
215
+ }
216
+ # for stacked items in shops
217
+ if refresh_instance
218
+ return Item.new(GameObj.left_hand) if original_left.nil? && !GameObj.left_hand.nil?
219
+ return Item.new(GameObj.right_hand)
220
+ end
221
+ self
222
+ end
223
+
224
+ def give(target, onfailure=nil)
225
+ Olib.wrap_stream("give ##{@id} to #{target}", 30) { |line|
226
+
227
+ }
228
+
229
+ self
230
+ end
231
+
232
+ def remove(onfailure=nil)
233
+
234
+ unless GameObj.inv.map(&:id).include? @id
235
+ if onfailure
236
+ onfailure.call(self)
237
+ else
238
+ raise Olib::Errors::DoesntExist
239
+ end
240
+ end
241
+
242
+ Olib.wrap(action "remove") { |line|
243
+ if line =~ /You cannot remove|You better get a sharp knife/
244
+ if onfailure
245
+ onfailure.call(self)
246
+ else
247
+ raise Olib::Errors::DoesntExist
248
+ end
249
+ end
250
+
251
+ raise Olib::Errors::Mundane if GameObj.right_hand.id == @id || GameObj.left_hand.id == @id
252
+ }
253
+
254
+ self
255
+ end
256
+
257
+ def wear(onfailure=nil)
258
+ if GameObj.right_hand.id != @id || GameObj.left_hand.id != @id
259
+ if onfailure
260
+ onfailure.call(self)
261
+ else
262
+ raise Olib::Errors::DoesntExist
263
+ end
264
+ end
265
+
266
+ Olib.wrap(action "wear") { |line|
267
+ if line =~ /You can't wear that.|You can only wear/
268
+ if onfailure
269
+ onfailure.call(self)
270
+ else
271
+ raise Olib::Errors::DoesntExist
272
+ end
273
+ end
274
+ raise Olib::Errors::Mundane if GameObj.inv.map(&:id).include? @id
275
+ }
276
+
277
+ self
278
+
279
+ end
280
+
281
+ def analyze
282
+ # reserved
283
+ end
284
+
285
+ def take
286
+ return self if has? 'cost'
287
+
288
+ Olib.wrap(action 'get') { |line|
289
+ raise Errors::DoesntExist if line=~ Olib::Dictionary.get[:failure][:ne]
290
+ raise Errors::HandsFull if line=~ Olib::Dictionary.get[:failure][:hands_full]
291
+ raise Errors::TooHeavy if line=~ Olib::Dictionary.get[:failure][:weight]
292
+
293
+ if line=~ Olib::Dictionary.get[:success]
294
+ raise Olib::Errors::Mundane
295
+ end
296
+
297
+ if line =~ Olib::Dictionary.get[:failure][:buy]
298
+ define 'cost', line.match(Olib::Dictionary.get[:failure][:buy])[:cost].to_i
299
+ end
300
+
301
+ if line=~ /You'll have to buy it if you want it/
302
+ tag 'buyable'
303
+ raise Olib::Errors::Mundane
304
+ end
305
+
306
+ if line=~ /You can PULL/
307
+ tag 'pullable'
308
+ raise Olib::Errors::Mundane
309
+ end
310
+
311
+ }
312
+ self
313
+ end
314
+
315
+ def _inspect
316
+
317
+ return self if has? 'inspect'
318
+
319
+ in_inspect = false
320
+
321
+ Olib.wrap_stream(action 'inspect') { |line|
322
+
323
+ raise Olib::Errors::Mundane if line =~ /^<prompt/ and in_inspect
324
+
325
+ # skip first inspect line because it's useless for info
326
+ if line =~ /You carefully inspect|You carefully count|goat/
327
+ in_inspect = true
328
+ end
329
+
330
+
331
+ if in_inspect
332
+
333
+ if line =~ /^You estimate that (?:.*?) can store (?:a|an|some) ([a-zA-Z -]+) amount with enough space for ([a-zA-Z ]+)/
334
+ @props['space'] = $1
335
+ @props['number_of_items'] = $2
336
+ end
337
+
338
+
339
+
340
+ if line =~ /^You determine that you could wear the (.*?) ([a-zA-Z ]+)/
341
+ @props['location']= $2
342
+ end
343
+
344
+ if line =~ /allows you to conclude that it is ([a-zA-Z ]+)/
345
+
346
+ if line =~ Dictionary.size
347
+ @props['shield_type'] = $1
348
+ else
349
+ Dictionary.armors.each do |type, re| @props['armor_type'] = type if line =~ re end
350
+ end
351
+
352
+ end
353
+
354
+ if line =~ /suitable for use in unarmed combat/
355
+ @props['weapon_type']= "uac"
356
+ end
357
+
358
+ if line =~ /requires skill in ([a-zA-Z ]+) to use effectively/
359
+
360
+ @props['weapon_type']= $1
361
+ if line =~ /It appears to be a modified ([a-zA-Z -]+)/
362
+ @props['weapon_base']= $1
363
+ else
364
+ @props['weapon_base']= @noun
365
+ end
366
+ end
367
+
368
+ if line =~ /^It looks like this item has been mainly crafted out of ([a-zA-Z -]+)./
369
+ @props['material']= $1
370
+ raise Olib::Errors::Mundane
371
+ end
372
+
373
+ if line =~ /can hold liquids/
374
+ @props['liquid_container']=true
375
+ end
376
+
377
+ end
378
+
379
+ }
380
+
381
+ return self
382
+ end
383
+
384
+ def look
385
+ return self if has? 'show'
386
+ Olib.wrap(action 'look') { |line|
387
+ raise Olib::Errors::Mundane if line=~/^You see nothing unusual.|^You can't quite get a good look at/
388
+ define 'show', line unless line=~/<prompt|You take a closer look/
389
+ }
390
+ self
391
+ end
392
+
393
+ def tap
394
+ return self if has? 'description'
395
+ Olib.wrap(action 'tap') { |line|
396
+ next unless line=~ /You tap (.*?) (on|in)/
397
+ define 'description', $1
398
+ raise Olib::Errors::Mundane
399
+ }
400
+ self
401
+ end
402
+
403
+ def price
404
+ return self if(has? 'price' or has? 'info')
405
+ Olib.wrap(action 'get') { |line|
406
+
407
+ if line =~ /(\d+) silvers/
408
+ define 'price', line.match(/(?<price>\d+) silvers/)[:price]
409
+ raise Olib::Errors::Mundane
410
+ end
411
+
412
+ if line =~ /You can't pick that up/
413
+ define "info", true
414
+ raise Olib::Errors::Mundane
415
+ end
416
+
417
+ Script.log "unmatched price: #{line}"
418
+
419
+ }
420
+ self
421
+ end
422
+
423
+ def read
424
+ return self if has? 'read'
425
+ scroll = false
426
+ multiline = false
427
+ Olib.wrap_stream(action 'read') { |line|
428
+
429
+ raise Olib::Errors::Mundane if line =~ /^<prompt/ and (multiline or scroll)
430
+ raise Olib::Errors::Mundane if line =~ /There is nothing there to read|You can't do that./
431
+
432
+ # if we are in a multiline state
433
+ @props['read'] = @props['read'].concat line if multiline
434
+
435
+ # capture spell
436
+ if scroll && line =~ /\(([0-9]+)\) ([a-zA-Z'\s]+)/
437
+ n = $1
438
+ name = $2
439
+ spell = {'n' => $1, 'name' => $2}
440
+ #Client.notify "Spell detected ... (#{$1}) #{$2}"
441
+ @props['spells'].push spell
442
+
443
+ # begin scroll
444
+ elsif line =~ /It takes you a moment to focus on the/
445
+ scroll = true
446
+ @props['spells'] = Array.new
447
+
448
+ # open multiline
449
+ elsif line =~ /^In the (.*?) language, it reads/
450
+ multiline = true
451
+ @props['read'] = "#{line}\n"
452
+ @props['language'] = $1
453
+
454
+ # alert to unknown
455
+ elsif line =~ /but the language is not one you know. It looks like it's written in (.*?)./
456
+ Script.log "Please find a friend that can read for #{$1} in #{XMLData.room_title}"
457
+ echo "Please find a friend that can read for #{$1} in #{XMLData.room_title}"
458
+ raise Olib::Errors::Mundane
459
+
460
+ end
461
+
462
+ }
463
+ return self
44
464
  end
45
465
 
46
466
  end
467
+
47
468
  end