Olib 0.1.2 → 2.0.0.pre.rc.1

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.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/Olib.gemspec +1 -1
  3. data/README.md +0 -0
  4. data/TODOS.md +0 -0
  5. data/lib/Olib.rb +6 -79
  6. data/lib/Olib/actor/actor.rb +0 -0
  7. data/lib/Olib/area.rb +22 -37
  8. data/lib/Olib/bounty.rb +8 -10
  9. data/lib/Olib/character/char.rb +64 -68
  10. data/lib/Olib/character/disk.rb +31 -9
  11. data/lib/Olib/character/group.rb +122 -40
  12. data/lib/Olib/character/inventory.rb +0 -0
  13. data/lib/Olib/character/mind.rb +0 -0
  14. data/lib/Olib/character/stance.rb +0 -0
  15. data/lib/Olib/combat/creature.rb +77 -128
  16. data/lib/Olib/combat/creatures.rb +52 -36
  17. data/lib/Olib/core/action.rb +8 -0
  18. data/lib/Olib/core/container.rb +32 -236
  19. data/lib/Olib/core/containers.rb +42 -0
  20. data/lib/Olib/core/errors.rb +69 -71
  21. data/lib/Olib/core/exist.rb +88 -0
  22. data/lib/Olib/core/item.rb +43 -598
  23. data/lib/Olib/core/kinds.rb +6 -0
  24. data/lib/Olib/core/rummage.rb +42 -0
  25. data/lib/Olib/core/transaction.rb +53 -0
  26. data/lib/Olib/core/use.rb +2 -5
  27. data/lib/Olib/core/utils.rb +25 -123
  28. data/lib/Olib/core/verbs.rb +304 -0
  29. data/lib/Olib/dictionary/dictionary.rb +150 -150
  30. data/lib/Olib/ext/hash.rb +7 -0
  31. data/lib/Olib/ext/matchdata.rb +14 -0
  32. data/lib/Olib/ext/string.rb +9 -0
  33. data/lib/Olib/ext/symbol.rb +13 -0
  34. data/lib/Olib/go2.rb +48 -112
  35. data/lib/Olib/loot.rb +44 -0
  36. data/lib/Olib/npcs/npc.rb +4 -0
  37. data/lib/Olib/npcs/npcs.rb +45 -0
  38. data/lib/Olib/objects/box.rb +1 -1
  39. data/lib/Olib/objects/clothing.rb +1 -1
  40. data/lib/Olib/objects/herb.rb +1 -1
  41. data/lib/Olib/objects/jar.rb +0 -0
  42. data/lib/Olib/objects/jewel.rb +7 -7
  43. data/lib/Olib/objects/jewelry.rb +1 -1
  44. data/lib/Olib/objects/scroll.rb +1 -1
  45. data/lib/Olib/objects/uncommon.rb +1 -1
  46. data/lib/Olib/objects/wand.rb +1 -1
  47. data/lib/Olib/pattern_matching/any.rb +11 -0
  48. data/lib/Olib/pattern_matching/err.rb +4 -0
  49. data/lib/Olib/pattern_matching/ok.rb +4 -0
  50. data/lib/Olib/pattern_matching/outcome.rb +35 -0
  51. data/lib/Olib/pattern_matching/pattern_matching.rb +5 -0
  52. data/lib/Olib/pattern_matching/result.rb +80 -0
  53. data/lib/Olib/pattern_matching/rill.rb +43 -0
  54. data/lib/Olib/pattern_matching/where.rb +4 -0
  55. data/lib/Olib/shops.rb +147 -155
  56. data/lib/Olib/supervisor/supervisor.rb +0 -0
  57. data/lib/Olib/version.rb +1 -1
  58. data/lib/Olib/xml.rb +43 -0
  59. metadata +28 -15
  60. data/lib/Olib/core/extender.rb +0 -29
  61. data/lib/Olib/interface/queryable.rb +0 -50
  62. data/lib/Olib/npcs.rb +0 -5
  63. data/lib/Olib/pattern.rb +0 -34
  64. data/lib/Olib/storage/app_data.rb +0 -32
  65. data/lib/Olib/try/try.rb +0 -58
  66. data/lib/Olib/utils/cli.rb +0 -81
  67. data/lib/Olib/utils/help_menu.rb +0 -166
  68. data/lib/Olib/utils/monsterbold.rb +0 -5
  69. data/lib/Olib/utils/vbulletin.rb +0 -101
@@ -1,91 +1,89 @@
1
- module Olib
2
- module Errors
3
- @@padding = 20
4
1
 
5
- def Errors.padding(n)
6
- @@padding = n
7
- end
2
+ module Errors
3
+ @@padding = 20
8
4
 
9
- def Errors.indent(str)
10
- str.split("\n").map { |line| [''] * @@padding * " " + line }.join("\n")
11
- end
5
+ def Errors.padding(n)
6
+ @@padding = n
7
+ end
12
8
 
13
- # used internally to handle early thread execution and error bubbling
14
- class Mundane < Exception
15
- end
9
+ def Errors.indent(str)
10
+ str.split("\n").map { |line| [''] * @@padding * " " + line }.join("\n")
11
+ end
16
12
 
17
- # used internally to insure threads died and error bubbling
18
- class TimedOut < Exception
19
- end
13
+ # used internally to handle early thread execution and error bubbling
14
+ class Mundane < Exception
15
+ end
20
16
 
21
- # used internally to handle early thread execution and error bubbling
22
- class Prempt < Exception
23
- end
17
+ # used internally to insure threads died and error bubbling
18
+ class TimedOut < Exception
19
+ end
24
20
 
25
- # used to exit a thread early due to an error that Olib cannot resolve internally
26
- class Fatal < Exception
27
- def initialize(message=nil)
28
- unless message
29
- message = String.new
30
- message.concat "\n\nAn Olib::Errors::Fatal was raised but not rescued in an Olib method"
31
- message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
32
- end
33
- super Errors.indent message
34
- end
35
- end
21
+ # used internally to handle early thread execution and error bubbling
22
+ class Prempt < Exception
23
+ end
36
24
 
37
- # If you have a full container and a script/action depends on it, this is thrown
38
- # rescue it for logic
39
- class ContainerFull < Exception
40
- def initialize(message=nil)
41
- unless message
42
- message = String.new
43
- message.concat "\n\nYou tried to add stuff to a container that was full"
44
- message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
45
- end
46
- super Errors.indent message
47
- end
48
- end
49
-
50
- class InsufficientFunds < Exception
51
- def initialize(message=nil)
52
- unless message
53
- message = String.new
54
- message.concat "\n\nYou tried to do something that costs more money that your character had on them"
55
- message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
56
- end
57
- super Errors.indent message
25
+ # used to exit a thread early due to an error that Olib cannot resolve internally
26
+ class Fatal < Exception
27
+ def initialize(message=nil)
28
+ unless message
29
+ message = String.new
30
+ message.concat "\n\nAn Errors::Fatal was raised but not rescued in an Olib method"
31
+ message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
58
32
  end
59
- end
33
+ super Errors.indent message
34
+ end
35
+ end
60
36
 
61
- class HandsFull < Exception
62
- def initialize
37
+ # If you have a full container and a script/action depends on it, this is thrown
38
+ # rescue it for logic
39
+ class ContainerFull < Exception
40
+ def initialize(message=nil)
41
+ unless message
63
42
  message = String.new
64
- message.concat "\n\nYour hands were full!"
65
- message.concat "\nyou should rescue this error if you don't want your script to break"
66
- super Errors.indent message
43
+ message.concat "\n\nYou tried to add stuff to a container that was full"
44
+ message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
67
45
  end
46
+ super Errors.indent message
68
47
  end
69
-
70
- class TooHeavy < Exception
71
- def initialize
48
+ end
49
+
50
+ class InsufficientFunds < Exception
51
+ def initialize(message=nil)
52
+ unless message
72
53
  message = String.new
73
- message.concat "\n\nYou were too heavy to do something!"
74
- message.concat "\nyou should rescue this error if you don't want your script to break"
75
- super Errors.indent message
54
+ message.concat "\n\nYou tried to do something that costs more money that your character had on them"
55
+ message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
76
56
  end
57
+ super Errors.indent message
77
58
  end
59
+ end
78
60
 
79
- class DoesntExist < Exception
80
- def initialize(message=nil)
81
- unless message
82
- message = String.new
83
- message.concat "\n\nYou tried to interact with something that no longer exists"
84
- message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
85
- end
86
- super Errors.indent message
87
- end
61
+ class HandsFull < Exception
62
+ def initialize
63
+ message = String.new
64
+ message.concat "\n\nYour hands were full!"
65
+ message.concat "\nyou should rescue this error if you don't want your script to break"
66
+ super Errors.indent message
88
67
  end
68
+ end
89
69
 
70
+ class TooHeavy < Exception
71
+ def initialize
72
+ message = String.new
73
+ message.concat "\n\nYou were too heavy to do something!"
74
+ message.concat "\nyou should rescue this error if you don't want your script to break"
75
+ super Errors.indent message
76
+ end
77
+ end
78
+
79
+ class DoesntExist < Exception
80
+ def initialize(message=nil)
81
+ unless message
82
+ message = String.new
83
+ message.concat "\n\nYou tried to interact with something that no longer exists"
84
+ message.concat "\nyou should rescue this error if it isn't fatal and you don't want your script to break"
85
+ end
86
+ super Errors.indent message
87
+ end
90
88
  end
91
89
  end
@@ -0,0 +1,88 @@
1
+
2
+ require "Olib/core/action"
3
+
4
+ class Exist
5
+ GETTER = %r[\w$]
6
+
7
+ def self.fetch(id)
8
+ [ GameObj.inv, GameObj.containers.values,
9
+ GameObj.loot, GameObj.room_desc,
10
+ GameObj.pcs, GameObj.npcs,
11
+ GameObj.right_hand, GameObj.left_hand ].flatten
12
+ .find do |item| item.id.to_s.eql?(id.to_s) end
13
+ end
14
+
15
+ def self.normalize_type_data(type)
16
+ (type or "").gsub(",", " ").split(" ")
17
+ end
18
+
19
+ attr_reader :id, :gameobj
20
+ def initialize(obj)
21
+ if obj.respond_to?(:id)
22
+ @id = obj.id
23
+ else
24
+ @id = obj
25
+ end
26
+ fail Exception, "Id<#{@id}> was not of String|Fixnum" if @id.nil?
27
+ end
28
+
29
+ def fetch()
30
+ @gameobj ||= Exist.fetch(id)
31
+ end
32
+
33
+ def respond_to_missing?(method, *args)
34
+ fetch.respond_to?(method) and method.to_s.match(GETTER)
35
+ end
36
+
37
+ def method_missing(method, *args)
38
+ if respond_to_missing?(method)
39
+ fetch.send(method, *args)
40
+ else
41
+ super
42
+ end
43
+ end
44
+
45
+ def exists?
46
+ not GameObj[id].nil?
47
+ end
48
+
49
+ def gone?
50
+ not exists?
51
+ end
52
+
53
+ def tags
54
+ Exist.normalize_type_data(type).map(&:to_sym)
55
+ end
56
+
57
+ def effects
58
+ (status or "").split(",").map(&:to_sym)
59
+ end
60
+
61
+ def to_h()
62
+ {id: id, name: name, noun: noun}
63
+ end
64
+
65
+ def ==(other)
66
+ id.to_s.eql?(other.id.to_s)
67
+ end
68
+
69
+ alias_method :eql?, :==
70
+
71
+ def to_s()
72
+ inspect()
73
+ end
74
+
75
+ def inspect(depth= 0)
76
+ indent = ""
77
+ indent = "\n" + (["\t"] * depth).join if depth > 0
78
+ body = [:id, :name, :tags].reduce("") do |acc, prop|
79
+ val = send(prop)
80
+ acc = "#{acc} #{prop}=#{val.inspect}" unless val.nil? or val.empty?
81
+ acc
82
+ end.strip
83
+
84
+ body = "#{body} contents=[#{contents.map {|i| i.inspect(depth + 1)}.join}]" unless contents.to_a.empty?
85
+
86
+ %[#{indent}#{self.class.name}(#{body})]
87
+ end
88
+ end
@@ -1,618 +1,63 @@
1
1
  require "ostruct"
2
- require "Olib/core/extender"
2
+ require "Olib/core/exist"
3
3
  require "Olib/core/use"
4
+ require "Olib/core/transaction"
4
5
 
5
6
  class GameObj
6
7
  def to_item
7
- Olib::Item.new self
8
+ Item.new self
8
9
  end
9
10
  end
10
11
 
11
- module Olib
12
- # this is the structure for a base Object
13
- # wraps an instance of GameObj and adds the ability for tags, queries
14
- class Item < Olib::Gameobj_Extender
15
- TYPES = [
16
- "reagent",
17
- ["spirit beast talismans", true],
18
- "alchemy product",
19
- ["alchemy equipment", true],
20
- "note",
21
- ["cursed", true],
22
- ["ammo", true],
23
- "box",
24
- "gem",
25
- "herb",
26
- ["food", true],
27
- ["uncommon", true],
28
- "valuable",
29
- "plinite",
30
- ["ebongate", true],
31
- ["quest", true],
32
- ["jewelry", true],
33
- ["junk", true],
34
- "lockpick",
35
- "magic",
36
- "scroll",
37
- "skin",
38
- "wand",
39
- "toy",
40
- ["armor", true],
41
- "weapon",
42
- ["clothing", true],
43
- "instrument",
44
- "jar",
45
- "lm trap",
46
- "lm tool",
47
- "scarab",
48
- #"consignment",
49
- #"gemshop",
50
- #"pawnshop",
51
- #"furrier"
52
- ]
53
-
54
- def self.type_methods
55
- TYPES.map { |type|
56
- if type.class == Array then
57
- [ Olib.methodize(type.first).to_sym, type.first ]
58
- elsif ["x"].include?(type.chars.last)
59
- [ Olib.methodize(type + "es").to_sym, type ]
60
- else
61
- [ Olib.methodize(type + "s").to_sym, type ]
62
- end
63
- }
12
+ # this is the structure for a base Object
13
+ # wraps an instance of GameObj and adds the ability for tags, queries
14
+ class Item < Exist
15
+ def self.fetch(id)
16
+ new Exist.fetch(id)
64
17
  end
65
18
 
66
- attr_accessor :props, :container
67
- # When created, it should be passed an instance of GameObj
68
- #
69
- # Example:
70
- # Olib::Item.new(GameObj.right_hand)
71
- def initialize(obj, container = nil)
72
- @container = container
73
- @props = Hash.new
74
- @props[:name] = obj.name
75
- @props[:after_name] = obj.after_name
76
- @props[:before_name]= obj.before_name
77
- @props[:desc] = [obj.before_name, obj.name, obj.after_name].compact.join(" ")
78
- @props[:noun] = obj.noun
79
- define :tags, []
80
- obj.type.split(",").map { |t| tag(t) }
81
-
82
- #tag @props[:name]
83
-
84
- if is?("jar") && @props[:after_name] =~ /containing (.*+?)/
85
- tag Dictionary.gems[:singularize].call @props[:after_name].gsub("containing", "").strip
86
- end
87
-
88
- if is?("gem")
89
- tag Dictionary.gems[:singularize].call @props[:name]
90
- end
91
-
92
- if is?("jar") && @props[:after_name].nil?
93
- tag("empty")
94
- end
95
-
96
- if Vars.teleporter && Vars.teleporter == @props[:name]
97
- tag("teleporter")
98
- end
99
-
100
- super(obj)
101
- end
102
-
103
- def to_s
104
- @props.to_s
105
- end
106
-
107
- # determine if Item is something
108
- #
109
- # example:
110
- # item.is?("jar")
111
- #
112
- def is?(tag)
113
- @props[:tags].include?(tag)
114
- end
115
-
116
- def tag(*tags)
117
- @props[:tags].concat(tags)
118
- self
119
- end
120
-
121
- def untag(*remove)
122
- @props[:tags] = @props[:tags].select { |tag| !remove.include?(tag) }
123
- end
124
-
125
- def tags
126
- @props[:tags]
127
- end
128
-
129
- def use(&block)
130
- Use.new(self, &block)
131
- end
132
-
133
- def worn?
134
- GameObj.inv.collect { |item| item.id }.include? @id
135
- end
136
-
137
- def crawl
138
- take
139
- tap._inspect.read.look
140
- self
141
- end
142
-
143
- def buy
144
- Char.deplete_wealth cost
145
- fput action "buy"
146
- self
147
- end
148
-
149
- def has?(key)
150
- !@props[key].nil?
151
- end
152
-
153
- def missing?(key)
154
- !has?(key)
155
- end
156
-
157
- def exists?
158
- GameObj[@id].nil?
159
- end
160
-
161
- def ==(other)
162
- @id == other.id
163
- end
164
-
165
- def pullable?
166
- is? "pullable"
167
- end
168
-
169
- def affordable?
170
- take
171
- return true if pullable?
172
- cost <= Char.smart_wealth
173
- end
174
-
175
- def buyable?
176
- is? "buyable"
177
- end
178
-
179
- def cost
180
- @props["cost"]
181
- end
182
-
183
- def acquire_from_shop
184
- take
185
- if pullable?
186
- return pull
187
- else
188
- Olib.wrap(action "buy"){ |line|
189
- raise Olib::Errors::InsufficientFunds if line =~ /The merchant frowns/
190
- if line =~ /You hand over/
191
- Char.deplete_wealth cost
192
- raise Olib::Errors::Mundane
193
- end
194
- }
195
- end
196
- self
197
- end
198
-
199
- def in
200
- return self if has? "contents"
201
- Olib.wrap(action "look in") { |line|
202
- if line=~/^There is nothing in there.|You gaze through (.*?) and see.../
203
- raise Olib::Errors::Mundane
204
- end
205
-
206
- # handle jar data
207
- if line =~ /Inside (.*?) you see (?<number>[\d]+) portion(|s) of (?<type>.*?). It is (more than |less than|)(?<percent>[a-z ]+)./
208
- data = line.match(/Inside (.*?) you see (?<number>[\d]+) portion(|s) of (?<type>.*?). It is (more than |less than|)(?<percentage>[a-z ]+)./)
209
- tag data[:percentage] == "full" ? "full" : "partial"
210
- define :number, data[:number].to_i
211
- raise Olib::Errors::Mundane
212
- end
213
-
214
- #handle empty jars
215
- if line =~ /The (.*?) is empty./
216
- tag "empty"
217
- raise Olib::Errors::Mundane
218
- end
219
- }
220
- self
221
- end
222
-
223
- def _drag(target)
224
- Olib.wrap("_drag ##{@id} ##{target.id}") { |line|
225
- # order of operations is important here for jars
226
- raise Olib::Errors::DoesntExist if line =~ Dictionary.put[:failure][:ne]
227
- raise Olib::Errors::Mundane if line =~ Dictionary.put[:success]
228
-
229
- if line =~ Dictionary.put[:failure][:full]
230
- tag "full"
231
- raise Olib::Errors::ContainerFull
232
- end
233
- }
234
- self
235
- end
236
-
237
- def stash
238
- _drag GameObj[props["container"]]
239
- end
240
-
241
- def shake
242
- # make sure we have a count so we need to match fewer lines
243
- self.in if is? "jar" and missing? :number
244
-
245
- Olib.wrap(action "shake"){ |line|
246
- raise Olib::Errors::Fatal if line =~ /you realize that it is empty/
247
- if line =~ /fall into your/
248
- @props[:number] = @props[:number]-1
249
- raise Olib::Errors::Fatal.new "Jar is now empty\n you should rescue this to handle it gracefully" if @props[:number] == 0
250
- raise Olib::Errors::Mundane
251
- end
252
- }
253
- self
254
- end
255
-
256
- def shop_sell(amt)
257
- if GameObj.right_hand.id != @id
258
- raise Olib::Errors::Fatal
259
- end
260
-
261
- Olib.wrap("shop sell #{amt}") {|line|
262
- raise Olib::Errors::Mundane if line =~ /^You place your/
263
- raise Olib::Errors::Fatal if line =~ /There"s no more room for anything else right now./
264
- }
265
-
266
- end
267
-
268
- SOLD = /([\d]+) silver/
269
- WRONG_SHOP = /That's not quite my field/
270
- WORTHLESS = /worthless/
271
-
272
- def sell
273
- take
274
- case result = dothistimeout("sell ##{@id}", 3, (SOLD | WRONG_SHOP | WORTHLESS))
275
- when SOLD then [:sold, OpenStruct.new(name: self.name, price: $1.to_i)]
276
- when WRONG_SHOP then [:wrong_shop, self]
277
- when WORTHLESS then [:worthless, self]
278
- else [:unhandled_case, result]
279
- end
280
- end
281
-
282
- def turn
283
- fput action "turn"
284
- self
285
- end
286
-
287
- def action(verb)
288
- "#{verb} ##{@id}"
289
- end
290
-
291
- def add(*items)
292
- items.each do |item|
293
- item._drag(self)
294
- end
295
- self
296
- end
297
-
298
- def define(key, val)
299
- @props[key] = val
300
- self
301
- end
302
-
303
- def pull(onfailure=nil)
304
- refresh_instance = false
305
- original_right = GameObj.right_hand
306
- original_left = GameObj.left_hand
307
- Olib.wrap(action "pull") { |line|
308
-
309
- if line =~ /^You pull/
310
- if line =~ /There (are|is) ([\d]+) left/
311
- refresh_instance = true
312
- end
313
- raise Olib::Errors::Mundane
314
- end
315
-
316
- if line =~ /I"m afraid that you can"t pull that./
317
- if onfailure
318
- onfailure.call(self)
319
- else
320
- raise Olib::Errors::DoesntExist
321
- end
322
- end
323
- }
324
- # for stacked items in shops
325
- if refresh_instance
326
- return Item.new(GameObj.left_hand) if original_left.nil? && !GameObj.left_hand.nil?
327
- return Item.new(GameObj.right_hand)
328
- end
329
- self
330
- end
331
-
332
- def give(target, onfailure=nil)
333
- Olib.wrap_stream("give ##{@id} to #{target}", 30) { |line|
334
- raise Olib::Errors::Mundane if line=~ /This looks perfect/
335
-
336
- if line =~ /glances at you and moves out of your reach./
337
- raise Olib::Errors::Fatal.new "You appear to have an invalid NPC definition"
338
- end
339
-
340
- }
341
-
342
- self
343
- end
344
-
345
- def remove(onfailure=nil)
346
-
347
- unless GameObj.inv.map(&:id).include? @id
348
- if onfailure
349
- onfailure.call(self)
350
- else
351
- raise Olib::Errors::DoesntExist
352
- end
353
- end
354
-
355
- Olib.wrap(action "remove") { |line|
356
- if line =~ /You cannot remove|You better get a sharp knife/
357
- if onfailure
358
- onfailure.call(self)
359
- else
360
- raise Olib::Errors::DoesntExist
361
- end
362
- end
363
-
364
- raise Olib::Errors::Mundane if GameObj.right_hand.id == @id || GameObj.left_hand.id == @id
365
- }
366
-
367
- self
368
- end
369
-
370
- def wear(onfailure=nil)
371
- if GameObj.right_hand.id != @id || GameObj.left_hand.id != @id
372
- if onfailure
373
- onfailure.call(self)
374
- else
375
- raise Olib::Errors::DoesntExist
376
- end
377
- end
378
-
379
- Olib.wrap(action "wear") { |line|
380
- if line =~ /You can"t wear that.|You can only wear/
381
- if onfailure
382
- onfailure.call(self)
383
- else
384
- raise Olib::Errors::DoesntExist
385
- end
386
- end
387
- raise Olib::Errors::Mundane if GameObj.inv.map(&:id).include? @id
388
- }
389
-
390
- self
391
-
392
- end
393
-
394
- def analyze
395
- fput "analyze ##{@id}"
396
- should_detect = false
397
- begin
398
- Timeout::timeout(1) do
399
- while(line = get)
400
- next if Olib::Dictionary.ignorable?(line)
401
- next if line =~ /sense that the item is free from merchant alteration restrictions|and sense that the item is largely free from merchant alteration restrictions|these can all be altered by a skilled merchant|please keep the messaging in mind when designing an alterations|there is no recorded information on that item|The creator has also provided the following information/
402
- @props["max_light"] = true if line =~ /light as it can get/
403
- @props["max_deep"] = true if line =~ /pockets could not possibly get any deeper/
404
- @props["max_deep"] = false if line =~ /pockets deepened/
405
- @props["max_light"] = false if line =~ /talented merchant lighten/
406
- if line =~ /Casting Elemental Detection/
407
- should_detect = true
408
- next
409
- end
410
- break if line =~ /pockets deepened|^You get no sense of whether|light as it can get|pockets could not possibly get any deeper|talented merchant lighten/
411
- @props["analyze"] = String.new unless @props["analyze"]
412
- @props["analyze"].concat line.strip
413
- @props["analyze"].concat " "
414
- end
415
- end
416
-
417
- rescue Timeout::Error
418
- # Silent
419
- end
420
- detect if should_detect
421
- temp_analysis = @props["analyze"].split(".").map(&:strip).map(&:downcase).reject {|ln| ln.empty? }
422
- @props["analyze"] = temp_analysis unless temp_analysis.empty?
423
- return self
424
- end
425
-
426
- def take
427
- return self if has? "cost"
428
-
429
- Olib.wrap(action "get") { |line|
430
- raise Errors::DoesntExist if line=~ Olib::Dictionary.get[:failure][:ne]
431
- raise Errors::HandsFull if line=~ Olib::Dictionary.get[:failure][:hands_full]
432
- raise Errors::TooHeavy if line=~ Olib::Dictionary.get[:failure][:weight]
433
-
434
- if line=~ Olib::Dictionary.get[:success]
435
- raise Olib::Errors::Mundane
436
- end
437
-
438
- if line =~ Olib::Dictionary.get[:failure][:buy]
439
- define "cost", line.match(Olib::Dictionary.get[:failure][:buy])[:cost].to_i
440
- raise Olib::Errors::Mundane
441
- end
442
-
443
- if line =~ /let me help you with that/
444
- raise Olib::Errors::Mundane
445
- end
446
-
447
- if line=~ /You"ll have to buy it if you want it/
448
- tag "buyable"
449
- raise Olib::Errors::Mundane
450
- end
451
-
452
- if line=~ /You can PULL/
453
- tag "pullable"
454
- raise Olib::Errors::Mundane
455
- end
456
-
457
- }
458
- self
459
- end
460
-
461
- def drop
462
- Script.log("#{Time.now} > dropped #{to_s}")
463
- fput action "drop"
464
- self
465
- end
466
-
467
- def _inspect
468
-
469
- return self if has? "inspect"
470
-
471
- in_inspect = false
472
-
473
- Olib.wrap_stream(action "inspect") { |line|
474
-
475
- raise Olib::Errors::Mundane if line =~ /^<prompt/ and in_inspect
476
-
477
- # skip first inspect line because it"s useless for info
478
- if line =~ /You carefully inspect|You carefully count|goat/
479
- in_inspect = true
480
- end
481
-
482
-
483
- if in_inspect
484
-
485
- if line =~ /^You estimate that (?:.*?) can store (?:a|an|some) ([a-zA-Z -]+) amount with enough space for ([a-zA-Z ]+)/
486
- @props["space"] = $1
487
- @props["number_of_items"] = $2
488
- end
489
-
490
-
491
-
492
- if line =~ /^You determine that you could wear the (.*?) ([a-zA-Z ]+)/
493
- @props["location"]= $2
494
- end
495
-
496
- if line =~ /allows you to conclude that it is ([a-zA-Z ]+)/
497
-
498
- if line =~ Dictionary.size
499
- @props["shield_type"] = $1
500
- else
501
- Dictionary.armors.each do |type, re| @props["armor_type"] = type if line =~ re end
502
- end
503
-
504
- end
505
-
506
- if line =~ /suitable for use in unarmed combat/
507
- @props["weapon_type"]= "uac"
508
- end
509
-
510
- if line =~ /requires skill in ([a-zA-Z ]+) to use effectively/
511
-
512
- @props["weapon_type"]= $1
513
- if line =~ /It appears to be a modified ([a-zA-Z -]+)/
514
- @props["weapon_base"]= $1
515
- else
516
- @props["weapon_base"]= @noun
517
- end
518
- end
519
-
520
- if line =~ /^It looks like this item has been mainly crafted out of ([a-zA-Z -]+)./
521
- @props["material"]= $1
522
- raise Olib::Errors::Mundane
523
- end
524
-
525
- if line =~ /can hold liquids/
526
- @props["liquid_container"]=true
527
- end
528
-
529
- end
530
-
531
- }
532
-
533
- return self
534
- end
535
-
536
- def look
537
- return self if has? "show"
538
- Olib.wrap(action "look") { |line|
539
- raise Olib::Errors::Mundane if line=~/^You see nothing unusual.|^You can"t quite get a good look at/
540
- define "show", line unless line=~/prompt time|You take a closer look/
541
- }
542
- self
543
- end
544
-
545
- def tap
546
- return self if has? "description"
547
- Olib.wrap(action "tap") { |line|
548
- next unless line=~ /You tap (.*?) (on|in)/
549
- define "description", $1
550
- raise Olib::Errors::Mundane
551
- }
552
- self
553
- end
554
-
555
- def price
556
- return self if(has? "price" or has? "info")
557
- Olib.wrap(action "get") { |line|
558
-
559
- if line =~ /(\d+) silvers/
560
- define "price", line.match(/(?<price>\d+) silvers/)[:price]
561
- raise Olib::Errors::Mundane
562
- end
563
-
564
- if line =~ /You can"t pick that up/
565
- define "info", true
566
- raise Olib::Errors::Mundane
567
- end
568
-
569
- Script.log "unmatched price: #{line}"
570
-
571
- }
572
- self
573
- end
19
+ attr_reader :container
20
+ # When created, it should be passed an instance of GameObj
21
+ #
22
+ # Example:
23
+ # Item.new(GameObj.right_hand)
24
+ def initialize(obj, container = nil)
25
+ super(obj.id)
26
+ @container = container
27
+ end
574
28
 
575
- def read
576
- return self if has? "read"
577
- scroll = false
578
- multiline = false
579
- Olib.wrap_stream(action "read") { |line|
29
+ def worn?
30
+ GameObj.inv.map(&:id).include?(id)
31
+ end
580
32
 
581
- raise Olib::Errors::Mundane if line =~ /^<prompt/ and (multiline or scroll)
582
- raise Olib::Errors::Mundane if line =~ /There is nothing there to read|You can"t do that./
33
+ def use(&block)
34
+ Use.new(self, &block)
35
+ end
583
36
 
584
- # if we are in a multiline state
585
- @props["read"] = @props["read"].concat line if multiline
37
+ def held?
38
+ [Char.left, Char.right].map(&:id).include?(id.to_s)
39
+ end
586
40
 
587
- # capture spell
588
- if scroll && line =~ /\(([0-9]+)\) ([a-zA-Z"\s]+)/
589
- spell = OpenStruct.new(name: $2, num: $1.to_i)
590
- #Client.notify "Spell detected ... (#{$1}) #{$2}"
591
- @props["spells"].push spell
41
+ def take()
42
+ return self if held?
43
+ fail Exception, "Error #{inspect}\nyour hands are full" if Char.left && Char.right
44
+ Action.try_or_fail(command: "get ##{id}") do held? end
45
+ return self
46
+ end
592
47
 
593
- # begin scroll
594
- elsif line =~ /It takes you a moment to focus on the/
595
- scroll = true
596
- @props["spells"] = Array.new
48
+ def to_json(*args)
49
+ to_h.to_json(*args)
50
+ end
597
51
 
598
- # open multiline
599
- elsif line =~ /^In the (.*?) language, it reads/
600
- multiline = true
601
- @props["read"] = "#{line}\n"
602
- @props["language"] = $1
52
+ def transaction(**args)
53
+ Transaction.new(take, **args)
54
+ end
603
55
 
604
- # alert to unknown
605
- elsif line =~ /but the language is not one you know. It looks like it"s written in (.*?)./
606
- Script.log "Please find a friend that can read for #{$1} in #{XMLData.room_title}"
607
- echo "Please find a friend that can read for #{$1} in #{XMLData.room_title}"
608
- raise Olib::Errors::Mundane
609
-
610
- end
611
-
612
- }
613
- return self
614
- end
56
+ def sell(**args)
57
+ transaction(**args).sell()
58
+ end
615
59
 
60
+ def stash
61
+ @container.add(self) unless @container.nil?
616
62
  end
617
-
618
63
  end