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.
- checksums.yaml +4 -4
- data/lib/Olib.rb +32 -0
- data/lib/Olib/container.rb +64 -48
- data/lib/Olib/creature.rb +143 -58
- data/lib/Olib/creatures.rb +32 -26
- data/lib/Olib/dictionary.rb +66 -31
- data/lib/Olib/errors.rb +82 -0
- data/lib/Olib/extender.rb +6 -5
- data/lib/Olib/help_menu.rb +159 -12
- data/lib/Olib/inventory.rb +77 -0
- data/lib/Olib/item.rb +451 -30
- data/lib/Olib/shops.rb +175 -0
- data/lib/Olib/transport.rb +79 -78
- data/lib/Olib/utils.rb +223 -0
- metadata +6 -2
@@ -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
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
|
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
|
50
|
+
def untag(*remove)
|
51
|
+
@props[:tags] = @props[:tags].select { |tag| !remove.include?(tag) }
|
52
|
+
end
|
37
53
|
|
38
|
-
def
|
54
|
+
def tags
|
55
|
+
@props[:tags]
|
56
|
+
end
|
39
57
|
|
40
|
-
def
|
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.
|
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
|