twisty 0.0.2b → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 973c95d14cceffd3e604a89a4d3e13aa78668c79
4
- data.tar.gz: 2890e7f27a04df943e73b0052b4bafeae65ef3a7
3
+ metadata.gz: 0c4b41c7bfe9c7ccc8ab8bda55ee1564de9d5940
4
+ data.tar.gz: 07135ce28c624d6b8d41dd5bd5cfd67d48764544
5
5
  SHA512:
6
- metadata.gz: fcfbb0a47cc2baf7acb9e6c78999a96ed4e0b5ed50d0684ba0786faba2e7d529bbd500501db262eac72533483951c66be4c69593b67639669f5d553758f9f1ff
7
- data.tar.gz: 91cef32321c07af3e9c27f0d6a31f625703de54ca1a8a4b706ff0a0e443a29a9619dd2b96c96533461d82aa3fc6bb049c8aea456bf6934fb6f330e1616fbfebd
6
+ metadata.gz: f9d9c48f2101a4aac3c01ed9c1c46b72608901289675d577f8696ccf7d0370e3320d40b7b18eb003f8ab8a02d234d7d1910c0b33c7017fea2c809f4af91754de
7
+ data.tar.gz: e68e5797a78c4bde6598087cd5e091b7b7840ef89acf420f3be863770036a1ad18ffd00f10603ebf2b72d6bc9a999cc8cdf1334f7dab0896d996dbfca778ac7e
@@ -7,17 +7,49 @@
7
7
  # #
8
8
  #############################################################################
9
9
 
10
+ require_relative 'engine.rb'
11
+
10
12
  require 'rtype'
11
13
 
12
14
  module Twisty
13
15
 
16
+ #Used to provide the descriptions, examples of and executable code of commands
17
+ #that the player can type.
14
18
  class Command
15
- rtype_accessor :help1, :help2, String
16
- rtype_accessor :func, Proc
19
+ #(+String+) An example of the command e.g. "take item"
20
+ attr_reader :help1
21
+ #(+String+) Short description of what the command actually does
22
+ attr_reader :help2
23
+
24
+ #Initialiser. Use Engine.define_command() instead
25
+ #
26
+ #help1:: (+String+) An example of the command e.g. "take item"
27
+ #help2:: (+String+) Short description of what the command actually does
28
+ #func:: (Proc) Code that provides the commands effect(s). *NOTE* This
29
+ # must take exactly one argument of type +Array+[+String+]
17
30
  def initialize(help1, help2, func)
18
31
  @help1 = help1
19
32
  @help2 = help2
20
- @func = func
33
+
34
+ self.define_singleton_method(:exec, func)
35
+ end
36
+
37
+ #Executes this instance of command. This is redefined on a per-instance
38
+ #basis by Command.new().
39
+ #
40
+ #args:: (+Array+[+String+]) Words the player typed in
41
+ def exec(args)
42
+ return
43
+ end
44
+
45
+ protected
46
+ #(+Engine+)
47
+ #
48
+ #Convinience class so that each instances version of Command.exec() does
49
+ #not need to contain
50
+ # engine = Engine.instance
51
+ def engine
52
+ Twisty::Engine.instance()
21
53
  end
22
54
  end
23
55
 
data/lib/twisty/engine.rb CHANGED
@@ -17,11 +17,20 @@ require_relative 'room.rb'
17
17
 
18
18
  module Twisty
19
19
 
20
+ #Main class within Twisty.
20
21
  class Engine
21
22
  include Singleton
22
23
 
23
- attr_reader :items, :rooms, :inventory
24
+ #(+Hash+{+Symbol+ => +Item+}) All Items in the game regardless of if
25
+ #they have been placed anywhere
26
+ attr_reader :items
27
+ #(+Hash+{+Symbol+ => +Room+}) All Rooms in the game regardless of if
28
+ #they can be reached
29
+ attr_reader :rooms
30
+ #(+Array+[+Symbol+]) Keys of the Items the player is carrying
31
+ attr_reader :inventory
24
32
 
33
+ #Initialiser. As this class is a singleton use Engine.instance instead
25
34
  def initialize
26
35
  @items = {}
27
36
  @rooms = {}
@@ -31,7 +40,7 @@ class Engine
31
40
 
32
41
  @playing = nil
33
42
 
34
- @commands = {} #Filled in lib/twisty.rb
43
+ @commands = {} #Filled in by lib/twisty.rb
35
44
  end
36
45
 
37
46
  ################################
@@ -41,6 +50,21 @@ class Engine
41
50
  # TODO: Make private "defining" method
42
51
 
43
52
  rtype [Symbol, String, String, Hash] => nil
53
+ #Creates a new instance of Item in Engine.items indexed by id. Use this
54
+ #instead of Item.new().
55
+ #
56
+ #id:: (+Symbol+) Key within Engine.items
57
+ #name:: Name shown in "look" and used to "take" / "drop" the Item.
58
+ # *NOTE* This MUST be a single word.
59
+ #desc:: (+String+) Long description shown when the player uses "look at"
60
+ #options:: (+Hash+{+Symbol+ => +Any}) Additional attributes of the Item
61
+ #
62
+ # At present there are only two valid options that can be
63
+ # passed via options:
64
+ # fixed:: (+Boolean+) If set to true prevents "take" from
65
+ # working on the Item. Set to +false+ by default
66
+ # storage:: (+Integer+) Indicates the number of other Items
67
+ # that this Item can contain. Set to +0+ by default
44
68
  def define_item(id, name, desc, options={})
45
69
  options = {fixed: false, storage: 0}.merge(options)
46
70
 
@@ -57,6 +81,13 @@ class Engine
57
81
  end
58
82
 
59
83
  rtype [Symbol, String, String] => nil
84
+ #Creates a new instance of Room in Engine.rooms indexed by id. Use this
85
+ #instead of Room.new().
86
+ #
87
+ #id:: (+Symbol+) Key for the Room in Engine.rooms
88
+ #name:: String (preferably one word) shown in the prompt when the player
89
+ # is located in this Room
90
+ #desc:: (+String+) The long description of the player's current location
60
91
  def define_room(id, name, desc)
61
92
  room = Twisty::Room.new(id, name, desc)
62
93
 
@@ -75,6 +106,14 @@ class Engine
75
106
  end
76
107
 
77
108
  rtype [Symbol, Symbol, String] => nil
109
+ #Creates an exit from one Room to another
110
+ #
111
+ #from:: (+Symbol+) Key for the Room where the player is before using
112
+ # "walk"
113
+ #to:: (+Symbol+) Key for the Room where the player is after using "walk"
114
+ #name:: (+String+) Used to name the _door_. This can be a word such as
115
+ # "East" rather than the name of the destination. *NOTE* Must be
116
+ # one word
78
117
  def add_door(from, to, name)
79
118
  if @rooms.has_key?(from)
80
119
  if @rooms.has_key?(to)
@@ -90,6 +129,11 @@ class Engine
90
129
  end
91
130
 
92
131
  rtype [Symbol] => nil
132
+ #Change the the room that the player is currently in to the one
133
+ #represented by the Symbol id. Unlike Engine.goto() This does not print
134
+ #any information or trigger events.
135
+ #
136
+ #id:: (+Symbol+) Key of the Room where the player will go to
93
137
  def current_room=(id)
94
138
  if @rooms.has_key? id
95
139
  @current_room = id
@@ -101,6 +145,12 @@ class Engine
101
145
  end
102
146
 
103
147
  rtype [] => nil
148
+ #Place an Item represented by the Symbol id. Unlike
149
+ #Engine.take_item_by_id() this does not remove the Item from any Room it
150
+ #may be in or trigger any events.
151
+ #
152
+ #id:: (+Symbol+) Key of the Item that will be added to the player's
153
+ # inventory
104
154
  def give(id)
105
155
  if @items.include? id
106
156
  @inventory << id
@@ -112,6 +162,16 @@ class Engine
112
162
  end
113
163
 
114
164
  rtype [Regexp, String, String, Proc] => nil
165
+ #Create a new command for the user to type. Not applicable for creating
166
+ #methods to develop the game with
167
+ #
168
+ #pattern:: (+Regexp+) Pattern that triggers the command to be run.
169
+ #*NOTE* Must be unique and unambigious
170
+ #help1:: (+String+) An example of the command. E.g. "take item"
171
+ #help2:: (+String+) A short description of what the command does
172
+ #&func:: (+Proc+) Code executed when the player types the command in.
173
+ # *NOTE* Must take one argument of type +Array+[+String+] which
174
+ # contains what the player typed
115
175
  def define_command(pattern, help1, help2, &func)
116
176
  @commands[pattern] = Command.new(help1, help2, func)
117
177
  return nil
@@ -122,21 +182,34 @@ class Engine
122
182
  #########################
123
183
 
124
184
  rtype [] => Room
185
+ #(+Room+)
186
+ #
187
+ #The instance of Room that the player is currently in
125
188
  def current_room
126
189
  @rooms[@current_room]
127
190
  end
128
191
 
129
192
  rtype [] => Hash.of(Symbol, String)
193
+ #(+Hash+{+Symbol+ => +String+})
194
+ #
195
+ #Exits of the Room the player is currently in
130
196
  def current_doors
131
197
  @rooms[@current_room].doors
132
198
  end
133
199
 
134
200
  rtype [] => Array.of(Symbol)
201
+ #(+Array+[+Symbol+])
202
+ #
203
+ #Keys of the Items present in the Room where the player is currently
204
+ #located
135
205
  def current_items
136
206
  @rooms[@current_room].items
137
207
  end
138
208
 
139
209
  rtype [] => Array.of(Symbol)
210
+ #(+Array+[+Symbol+])
211
+ #
212
+ #Items that the user is currently carrying
140
213
  def inventory
141
214
  @inventory
142
215
  end
@@ -145,6 +218,9 @@ class Engine
145
218
  # Game play commands #
146
219
  ##########################
147
220
  rtype [String] => nil
221
+ #The "take item" command. Probably best not to call directly
222
+ #
223
+ #name:: (+String+) Name of an Item the player has typed in
148
224
  def take_item_by_name(name)
149
225
  current_items.each do |id|
150
226
  if @items.has_key? id
@@ -163,6 +239,11 @@ class Engine
163
239
  end
164
240
 
165
241
  rtype [Symbol] => nil
242
+ #Called by Engine.take_item_by_name. Probably best not to call directly
243
+ #
244
+ #id:: (+Symbol+) Index entry for the Item to be removed from the current
245
+ # room and placed in the player's inventory as found by
246
+ # Engine.take_item_by_name()
166
247
  def take_item_by_id(id)
167
248
  if @items.has_key? id
168
249
  if current_items.include? id
@@ -187,6 +268,12 @@ class Engine
187
268
  end
188
269
 
189
270
  rtype [String, String] => nil
271
+ #The "take item from item" command. Probably best not to call directly
272
+ #
273
+ #item:: (+String+) Name that the player has typed for an item to be
274
+ # inventory
275
+ #container:: (+String+) Name of an Item that the player is looking to
276
+ # remove added to the another Item from
190
277
  def take_from_by_name_name(item, container)
191
278
  current_items.each do |id|
192
279
  if @items[id].name.downcase == container
@@ -200,6 +287,12 @@ class Engine
200
287
  end
201
288
 
202
289
  rtype [String, Symbol] => nil
290
+ #Called by take_from_by_name_name. Probably best not to call directly.
291
+ #
292
+ #item:: (+String+) Name that the player has typed for an item to be
293
+ # added to the inventory
294
+ #container:: (+Symbol+) Key for the containing Item as found by
295
+ # Engine.take_from_by_name_name
203
296
  def take_from_by_name_id(item, container)
204
297
  @items[container].contents.each do |id|
205
298
  if @items[id].name.downcase == item
@@ -218,6 +311,10 @@ class Engine
218
311
  end
219
312
 
220
313
  rtype [String, String] => nil
314
+ #The "put item in item" command. Probably best not to call directly
315
+ #
316
+ #item:: (+String+) Name that the player has typed for an item to be
317
+ # added to a container
221
318
  def put_item_by_name_name(item, container)
222
319
  @inventory.each do |id|
223
320
  if @items[id].name.downcase == item
@@ -231,6 +328,13 @@ class Engine
231
328
  end
232
329
 
233
330
  rtype [Symbol, String] => nil
331
+ #Called by Engine.put_item_by_name_name. Probably best not to call
332
+ #directly
333
+ #
334
+ #item:: (+Symbol+) Key in Engine.items of the item to be placed in the
335
+ # container as found by Engine.put_item_by_name_name
336
+ #container:: (+String+) Name that the player has typed for the Item
337
+ # to act as a container
234
338
  def put_item_by_id_name(item, container)
235
339
  current_items.each do |id|
236
340
  if @items[id].name.downcase == container
@@ -253,6 +357,10 @@ class Engine
253
357
  end
254
358
 
255
359
  rtype [String] => nil
360
+ #The "drop item" command. Probably best not to call directly
361
+ #
362
+ #name:: (+String+) The name, typed by the player, of the item to be
363
+ #dropped
256
364
  def drop_item_by_name(name)
257
365
  @inventory.each do |id|
258
366
  if @items.has_key? id
@@ -272,6 +380,10 @@ class Engine
272
380
  end
273
381
 
274
382
  rtype [Symbol] => nil
383
+ #Called by Engine.drop_item_by_name. Probably best not to call directly
384
+ #
385
+ #id:: (+Symbol+) Key in Engine.items of the item to be dropped as found
386
+ #by Engine.drop_item_by_name
275
387
  def drop_item_by_id(id)
276
388
  if @items.has_key? id
277
389
  if @items[id].drop_event
@@ -286,12 +398,17 @@ class Engine
286
398
  end
287
399
 
288
400
  rtype [Symbol] => nil
401
+ #Called by the "walk door" command. Unlike current_room=(id) this
402
+ #triggers events and only moves the player if said events run
403
+ #successfully
404
+ #
405
+ #id:: (+Symbol+) Key in Engine.rooms of the Room that the player will
406
+ # be moved to
289
407
  def goto(to)
290
408
  if @rooms.has_key? to
291
409
  if current_room.exit_event and @rooms[to].enter_event
292
410
  @current_room = to
293
411
  end
294
- puts current_room.name
295
412
  else
296
413
  raise TwistyError.new "Room #{to} has not been defined"
297
414
  end
@@ -304,15 +421,18 @@ class Engine
304
421
  #######################
305
422
 
306
423
  rtype [] => nil
424
+ #Starts the main loop of the game
425
+ #
426
+ #*NOTE* This must be included once and only once at the end of the
427
+ #program
307
428
  def start_loop
308
429
  @playing = true
309
430
 
310
- puts current_room.name
311
- puts
312
431
  current_room.look
432
+ puts
313
433
 
314
434
  while @playing == true
315
- printf "> "
435
+ printf "#{current_room.name} > "
316
436
  begin
317
437
  line = gets
318
438
  if line.class == NilClass
@@ -329,12 +449,14 @@ class Engine
329
449
  end
330
450
 
331
451
  rtype [] => nil
452
+ #Ends the main loop of the game. Use this for win and loose conditions
332
453
  def end_loop
333
454
  @playing = false
334
455
  return nil
335
456
  end
336
457
 
337
458
  rtype [] => nil
459
+ #Called by start_loop to process user inpu.
338
460
  def parse(line)
339
461
  #Strip double spaces and downcase
340
462
  tokens = line.downcase.split
@@ -342,8 +464,7 @@ class Engine
342
464
 
343
465
  @commands.each do |pattern, command|
344
466
  if line =~ pattern
345
- #Execute as if a member function
346
- instance_exec(tokens, &command.func)
467
+ command.exec(tokens)
347
468
  return nil
348
469
  end
349
470
  end
data/lib/twisty/entity.rb CHANGED
@@ -9,12 +9,26 @@
9
9
 
10
10
  require 'rtype'
11
11
 
12
+ #Author:: Ryan McCoskrie (mailto:work@ryanmccoskrie.me)
13
+ #Copyright:: Copyright (c) 2017 - 2018 RyanMcCoskrie
14
+ #License:: MIT public license
15
+
12
16
  module Twisty
13
17
 
18
+ #Super-class of Room and Item. Do not use directly.
19
+ #
20
+ #*NOTE* It is possible this class may be removed in future versions.
14
21
  class Entity
22
+ #(+Symbol+)The Symbol used to distinguish the Entity from other memebers
23
+ #of the same sub-class
15
24
  attr_reader :id
16
25
 
17
26
  rtype [Entity] => Boolean
27
+ #(+Boolean+)
28
+ #
29
+ #Checks if two different instances of Entity refer to the same datum
30
+ #
31
+ #other:: (+Entity+) instance of Entity to check for equality against
18
32
  def ==(other)
19
33
  if other.class == self.class
20
34
  return other.id == @id
@@ -25,7 +39,9 @@ class Entity
25
39
  end
26
40
  end
27
41
 
28
- protected
42
+ #(+Engine+)
43
+ #
44
+ #Convinience class to access the Engine
29
45
  def engine
30
46
  return Engine.instance()
31
47
  end
data/lib/twisty/error.rb CHANGED
@@ -9,16 +9,24 @@
9
9
 
10
10
  module Twisty
11
11
 
12
+ #Super-class of GameError and PlayError. Do not use directly
12
13
  class TwistyError < RuntimeError
14
+ #(+String+) Message detailing the exception
13
15
  attr_reader :message
14
16
 
17
+ #Initialiser
18
+ #
19
+ #s:: (+String+) Contents of TwistyError.message
15
20
  def initialize(s)
16
21
  @message = s
17
22
  end
18
23
  end
19
24
 
25
+ #Used when Twisty has found a bug in a specific game
20
26
  class GameError < TwistyError
21
27
  end
28
+
29
+ #Used to tell the player when (s)he has used a command incorrectly
22
30
  class PlayError < TwistyError
23
31
  end
24
32
 
data/lib/twisty/item.rb CHANGED
@@ -12,11 +12,34 @@ require_relative 'entity'
12
12
  require 'rtype'
13
13
 
14
14
 
15
+ #Author:: Ryan McCoskrie (mailto:work@ryanmccoskrie.me)
16
+ #Copyright:: Copyright (c) 2017 - 2018 RyanMcCoskrie
17
+ #License:: MIT public license
18
+
15
19
  module Twisty
16
20
 
21
+ # This class models objects that (movable and otherwise) that the character
22
+ # can interact with.
17
23
  class Item < Entity
18
- attr_reader :name, :desc, :fixed, :storage, :contents
19
-
24
+ #(+String+) One-word name of the Item
25
+ attr_reader :name
26
+ #(+String+) Description printed when the Item is looked at.
27
+ attr_reader :desc
28
+ #(+Boolean+) Indicates if the Item can not be moved
29
+ attr_reader :fixed
30
+ #(+Integer+) Number of other Items this instance can store
31
+ attr_reader :storage
32
+ #(+Array+[+Symbol+]) Other Item this instance is currently storiing
33
+ attr_reader :contents
34
+
35
+ #Initialiser. Please use Engine.define_item() instead
36
+ #
37
+ #id:: (+Symbol+) Key in Engine.items of the Item
38
+ #name:: (+String+) One-word name of the Item
39
+ #desc:: A long description of the Item printed when the player uses
40
+ # "look at item"
41
+ #fixed:: (+Boolean+) If set to +false+ the Item can not be taken
42
+ #storage:: (+Integer+) The number of other Items this instance can hold
20
43
  def initialize(id, name, desc, fixed, storage)
21
44
  @id = id
22
45
  @name = name
@@ -27,16 +50,52 @@ class Item < Entity
27
50
  end
28
51
 
29
52
  rtype [] => Boolean
53
+ #(+Boolean+)
54
+ #
55
+ #Executed when the Item is picked up. This function can be redefined
56
+ #on a per-instance basis using on_take(&block). If this returns false
57
+ #take will fail
30
58
  def take_event
59
+ puts "Taken"
31
60
  return true
32
61
  end
33
62
 
34
63
  rtype [] => Boolean
64
+ #(+Boolean+)
65
+ #
66
+ #Executed when the Item is picked up. This function can be redefined
67
+ #on a per-instance basis using on_drop(&block). If this returns false
68
+ #drop will fail.
35
69
  def drop_event
70
+ puts "Dropped"
36
71
  return true
37
72
  end
38
73
 
74
+ rtype [Symbol] => Boolean
75
+ #(+Boolean+)
76
+ #
77
+ #Executed when another Item is placed inside this instance. This
78
+ #function can be redefined on a per-instance basis using on_add(&block).
79
+ #If this return false add_item will fail
80
+ #
81
+ #item:: (+Symbol+) Key in Engine.items of the item being added
82
+ def put_content_event(item)
83
+ return true
84
+ end
85
+
86
+ rtype [Symbol] => Boolean
87
+ #(+Boolean+)
88
+ #
89
+ #Executed an Item inside this instance of Item is removed by the player.
90
+ #If this returns false "take X from Y" will fail.
91
+ #
92
+ #item:: (+Symbol+) Key in Engine.items of the item being taken
93
+ def take_content_event(item)
94
+ puts "Taken"
95
+ end
96
+
39
97
  rtype [] => nil
98
+ #Prints the description and the names of the contents if applicable
40
99
  def look
41
100
  puts @desc
42
101
 
@@ -54,12 +113,20 @@ class Item < Entity
54
113
  end
55
114
 
56
115
  rtype [Symbol] => Boolean
116
+ #(+Boolean+)
117
+ #
118
+ #Returns +true+ if this item contains another represented by the symbol
119
+ #item
57
120
  def contains_item?(item)
58
121
  return @contents.include?(item) if @storage > 0
59
- return false
60
122
  end
61
123
 
62
124
  rtype [Symbol] => nil
125
+ #Stores another Item represented by the Symbol item and stores it
126
+ #within this Item if:
127
+ # * storage > 0
128
+ # * contents.size < 0
129
+ # * insert_event() returns true
63
130
  def add_item(item)
64
131
  if @storage == 0
65
132
  raise GameError.new "#{@id} is not a container"
@@ -74,6 +141,11 @@ class Item < Entity
74
141
  end
75
142
 
76
143
  rtype [Symbol] => nil
144
+ #Removes an Item contained within this instance
145
+ #*NOTE* This does not place the Item in the player's inventory
146
+ #
147
+ #item:: (+Symbol+) Key in Engine.items of the Item being placed in this
148
+ # instance of Item
77
149
  def del_item(item)
78
150
  #Skip if already contained
79
151
  if contains_item?(item)
@@ -84,16 +156,46 @@ class Item < Entity
84
156
  end
85
157
 
86
158
  rtype [Proc] => nil
159
+ #Redefines Item::take_event for this specific instance
160
+ #
161
+ #&block:: (+Proc+ => +Boolean+) The new version of Item.take_event for
162
+ # this specific instance *NOTE* Must return a +Boolean+
87
163
  def on_take(&block)
88
164
  self.define_singleton_method(:take_event, &block)
89
165
  return nil
90
166
  end
91
167
 
92
168
  rtype [Proc] => nil
169
+ #Redefines Item::drop_event for this specific instance
170
+ #
171
+ #&block:: (+Proc+ => +Boolean+) The new version of Item.drop_event for
172
+ # this specific instance *NOTE* Must return a +Boolean+
93
173
  def on_drop(&block)
94
174
  self.define_singleton_method(:drop_event, &block)
95
175
  return nil
96
176
  end
177
+
178
+ rtype [Proc] => nil
179
+ #Redefines Item::put_content_event for this specific instance
180
+ #
181
+ #&block:: (+Proc+ => +Boolean+) The new version of
182
+ # Item.put_content_event for this specific instance.
183
+ # *NOTE* Must return a +Boolean+
184
+ def on_put_content(&block)
185
+ self.define_singleton_method(:put_content_event, &block)
186
+ return nil
187
+ end
188
+
189
+ rtype [Proc] => nil
190
+ #Redefines Item::take_content_event for this specific instance
191
+ #
192
+ #&block:: (+Proc+ => +Boolean+) The new version of
193
+ # Item.take_content_event for this specific instance.
194
+ # *NOTE* Must return a +Boolean+
195
+ def on_put_content(&block)
196
+ self.define_singleton_method(:put_content_event, &block)
197
+ return nil
198
+ end
97
199
  end
98
200
 
99
201
  end
data/lib/twisty/room.rb CHANGED
@@ -11,96 +11,149 @@ require_relative 'entity.rb'
11
11
 
12
12
  require 'rtype'
13
13
 
14
+ #Author:: Ryan McCoskrie (mailto:work@ryanmccoskrie.me)
15
+ #Copyright:: Copyright (c) 2017 - 2018 RyanMcCoskrie
16
+ #License:: MIT public license
17
+
14
18
  module Twisty
15
19
 
16
- class Room < Entity
17
- attr_reader :name, :desc, :doors
18
- attr_accessor :items
19
-
20
- rtype [Symbol, String, String] => Array
21
- def initialize(id, name, desc)
22
- @id = id
23
- @name = name
24
- @desc = desc
25
- @doors = {}
26
- @items = []
27
- end
20
+ #This class models the locations within the game.
21
+ class Room < Entity
22
+ #(+String+) Short name shown in the prompt
23
+ attr_reader :name
24
+ #(+String+) Description printed when the player types "look"
25
+ attr_reader :desc
26
+ #(+Hash+{+String+ => +Symbol+}) Names and keys in Engine.rooms of the
27
+ #locations the player can move from
28
+ attr_reader :doors
29
+ #(+Array+[+String+]) Items in the room. Does not include Items stored
30
+ #inside other Items
31
+ attr_accessor :items
32
+
33
+ rtype [Symbol, String, String] => Array
34
+ #Initializer. Please use Twisty::Engine::define_room() instead.
35
+ #
36
+ #id:: (+Symbol+) that represents the Room in Engine.rooms()
37
+ #name:: (+String+) Name shown to the player in the prompt
38
+ #desc:: (+String+) Long description shown when the player types "look"
39
+ def initialize(id, name, desc)
40
+ @id = id
41
+ @name = name
42
+ @desc = desc
43
+ @doors = {}
44
+ @items = []
45
+ end
28
46
 
29
- rtype [] => Boolean
30
- def enter_event
31
- return true
32
- end
47
+ rtype [] => Boolean
48
+ #(+Boolean+)
49
+ #
50
+ #Executed when the player attempts to enter the Room. This can be
51
+ #redefined on a per-instance basis using Room.on_enter(&block). If this
52
+ #returns +false+ the player will be blocked from entering
53
+ def enter_event
54
+ return true
55
+ end
33
56
 
34
- rtype [] => Boolean
35
- def exit_event
36
- return true
37
- end
57
+ rtype [] => Boolean
58
+ #(+Boolean+)
59
+ #
60
+ #Executed when the player attempts to exit the Room. This can be
61
+ #redefined on a per-instance basis using on_exit(&block). If this
62
+ #returns +false+ the player will be blocked from exiting
63
+ def exit_event
64
+ return true
65
+ end
38
66
 
39
- rtype [Symbol, String] => nil
40
- def add_door(to, name)
41
- if name.split().length != 1
42
- raise GameError.new "Door name must be one word"
43
- elsif @doors.has_key? name
44
- raise GameError.new "Door with name #{name} already exist in #{@id}"
45
- else
46
- @doors[to] = name
47
- end
48
-
49
- return nil
67
+ rtype [Symbol, String] => nil
68
+ #Adds an exit from this room to another
69
+ #*NOTE* For most purposes Engine.add_door() would be more convinient
70
+ #*NOTE* The "door" only works in one direction and that the exit is
71
+ #referred to by the String name, not the name of the other Room.
72
+ #
73
+ #to:: (+Symbol+) Key in Engine.rooms of the location the player will
74
+ # be moved to if "walk" is sucessfully executed
75
+ #name:: (+String+) Name displayed by "look" and typed as part of "walk".
76
+ # This can be a word such as "East" instead of the destination's
77
+ # actual name
78
+ def add_door(to, name)
79
+ if name.split().length != 1
80
+ raise GameError.new "Door name must be one word"
81
+ elsif @doors.has_key? name
82
+ raise GameError.new "Door with name #{name} already exist in #{@id}"
83
+ else
84
+ @doors[to] = name
50
85
  end
51
86
 
52
- rtype [Symbol] => Array.of(Symbol)
53
- def add_item(id)
54
- if @items.include? id
55
- raise GameError.new "Duplicate item in room #{@id}"
56
- else
57
- @items << id
58
- end
59
- end
87
+ return nil
88
+ end
60
89
 
61
- rtype [Proc] => nil
62
- def on_enter(&block)
63
- self.define_singleton_method(:enter_event, &block)
64
- return nil
90
+ rtype [Symbol] => Array.of(Symbol)
91
+ #Places an Item within a the Room. Note that is must first be defined
92
+ #with Twisty::Engine::define_item()
93
+ #
94
+ #id:: (+Symbol+) Key in Engine.items for the Item that will be added to
95
+ # the Room
96
+ def add_item(id)
97
+ if @items.include? id
98
+ raise GameError.new "Duplicate item in room #{@id}"
99
+ else
100
+ @items << id
65
101
  end
102
+ end
66
103
 
67
- rtype [Proc] => nil
68
- def on_exit(&block)
69
- self.define_singleton_method(:exit_event, &block)
70
- return nil
71
- end
104
+ rtype [Proc] => nil
105
+ #Used to redefine enter_event
106
+ #
107
+ #&block:: (+Proc+ => +Boolean+) Code executed on entering the Room.
108
+ # *NOTE* If this returns +false+ the player "walk" will fail
109
+ def on_enter(&block)
110
+ self.define_singleton_method(:enter_event, &block)
111
+ return nil
112
+ end
72
113
 
73
- rtype [] => nil
74
- def look
75
- puts @desc
114
+ rtype [Proc] => nil
115
+ #Used to redefine exit_event
116
+ #
117
+ #&block:: (+Proc+ => +Boolean+) Code executed on exiting the Room.
118
+ # *NOTE* If this returns +false+ the player "walk" will fail
119
+ def on_exit(&block)
120
+ self.define_singleton_method(:exit_event, &block)
121
+ return nil
122
+ end
76
123
 
77
- if @items.length == 0
78
- puts "Nothing is located here"
79
- elsif @items.length == 1
80
- puts
124
+ rtype [] => nil
125
+ #Prints the description of the Room and its contents / exits if
126
+ #applicable.
127
+ def look
128
+ puts @desc
81
129
 
82
- puts "Located here is:"
83
- puts engine.items[@items[0]].name
84
- else
85
- puts
130
+ if @items.length == 0
131
+ puts "Nothing is located here"
132
+ elsif @items.length == 1
133
+ puts
86
134
 
87
- puts "Located here are:"
88
- @items.each{ |id| puts engine.items[id].name }
89
- end
135
+ puts "Located here is:"
136
+ puts engine.items[@items[0]].name
137
+ else
138
+ puts
90
139
 
91
- puts
140
+ puts "Located here are:"
141
+ @items.each{ |id| puts engine.items[id].name }
142
+ end
92
143
 
93
- if doors.length == 0
94
- puts "There is no exit"
95
- elsif doors.length == 1
96
- puts "The only exit is: #{@doors.values[0]}"
97
- else
98
- puts "The exits are:"
99
- @doors.values.each{|name| puts name}
100
- end
144
+ puts
101
145
 
102
- return nil
146
+ if doors.length == 0
147
+ puts "There is no exit"
148
+ elsif doors.length == 1
149
+ puts "The only exit is: #{@doors.values[0]}"
150
+ else
151
+ puts "The exits are:"
152
+ @doors.values.each{|name| puts name}
103
153
  end
154
+
155
+ return nil
104
156
  end
157
+ end
105
158
 
106
159
  end
data/lib/twisty.rb CHANGED
@@ -21,7 +21,7 @@ Engine.instance.define_command(
21
21
  /^help$/,
22
22
  "help",
23
23
  "Write out the list of commands you are reading now") do |x|
24
- @commands.values.each do |command|
24
+ engine.commands.values.each do |command|
25
25
  puts "#{command.help1}:"
26
26
  puts "#{command.help2}"
27
27
  puts
@@ -30,67 +30,67 @@ Engine.instance.define_command(
30
30
  Engine.instance.define_command(
31
31
  /^look$/,
32
32
  "look",
33
- "Look at the current room") {|x| current_room.look()}
33
+ "Look at the current room") {|x| engine.current_room.look()}
34
34
 
35
35
  Engine.instance.define_command(
36
36
  /^look at \w+$/,
37
37
  "look at object",
38
38
  "Look at a specific object") do |tokens|
39
39
  found = false
40
- current_items.each do |id|
41
- if @items[id].name.downcase == tokens[2]
42
- @items[id].look
40
+ engine.current_items.each do |id|
41
+ if engine.items[id].name.downcase == tokens[2]
42
+ engine.items[id].look
43
43
  found = true
44
44
  break
45
45
  end
46
46
  end
47
47
 
48
48
  #Error condidtion
49
- raise PlayError.new "I see no #{tokens[2]}" unless found
49
+ raise PlayError.new "I see no #{tokens[2]}" if not found
50
50
  end
51
51
  Engine.instance.define_command(
52
52
  /^inventory$/,
53
53
  "inventory",
54
54
  "Get a list of things you are carrying") do |x|
55
- if @inventory.size == 0
55
+ if engine.inventory.size == 0
56
56
  puts "You are currently carrying nothing"
57
57
  else
58
58
  puts "You are currently carring: "
59
- @inventory.each{|id| puts @items[id].name}
59
+ engine.inventory.each{|id| puts engine.items[id].name}
60
60
  end
61
61
  end
62
62
  Engine.instance.define_command(
63
63
  /^take \w+$/,
64
64
  "take object",
65
65
  "Take an object and carry it in your inventory") do |tokens|
66
- take_item_by_name(tokens[1])
66
+ engine.take_item_by_name(tokens[1])
67
67
  end
68
68
  Engine.instance.define_command(
69
69
  /^take \w+ from \w+$/,
70
70
  "take object from container",
71
71
  "Take an object out of a container and carry it your inventory") do |tokens|
72
- take_from_by_name_name(tokens[1], tokens[3])
72
+ engine.take_from_by_name_name(tokens[1], tokens[3])
73
73
  end
74
74
  Engine.instance.define_command(
75
75
  /^drop \w+$/,
76
76
  "drop object",
77
77
  "Remove an object from your inventory and leave it in the room") do |tokens|
78
- drop_item_by_name(tokens[1])
78
+ engine.drop_item_by_name(tokens[1])
79
79
  end
80
80
  Engine.instance.define_command(
81
81
  /^put \w+ in \w+$/,
82
82
  "put item in container",
83
83
  "Remove an object from your inventory and leave it in a container") do |tokens|
84
- put_item_by_name_name(tokens[1], tokens[3])
84
+ engine.put_item_by_name_name(tokens[1], tokens[3])
85
85
  end
86
86
  Engine.instance.define_command(
87
87
  /^walk \w+$/,
88
88
  "walk exit",
89
89
  "Walk out of the room through an exit") do |tokens|
90
90
  found = false
91
- current_doors.each_pair do |to, name|
91
+ engine.current_doors.each_pair do |to, name|
92
92
  if name.downcase == tokens[1]
93
- goto to
93
+ engine.goto to
94
94
  found = true
95
95
  break
96
96
  end
@@ -102,5 +102,5 @@ Engine.instance.define_command(
102
102
  Engine.instance.define_command(
103
103
  /^quit$/,
104
104
  "quit",
105
- "Stop playing the game") {|x| @playing = false}
105
+ "Stop playing the game") {|x| engine.end_loop()}
106
106
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: twisty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2b
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan McCoskrie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-09 00:00:00.000000000 Z
11
+ date: 2018-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rtype-native
@@ -37,7 +37,7 @@ files:
37
37
  - lib/twisty/error.rb
38
38
  - lib/twisty/item.rb
39
39
  - lib/twisty/room.rb
40
- homepage: http://rubygems.org/gems/twisty
40
+ homepage: http://gitlab.com/RyanMcCoskrie/Twisty
41
41
  licenses:
42
42
  - MIT
43
43
  metadata: {}
@@ -52,12 +52,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
52
52
  version: '0'
53
53
  required_rubygems_version: !ruby/object:Gem::Requirement
54
54
  requirements:
55
- - - ">"
55
+ - - ">="
56
56
  - !ruby/object:Gem::Version
57
- version: 1.3.1
57
+ version: '0'
58
58
  requirements: []
59
59
  rubyforge_project:
60
- rubygems_version: 2.6.11
60
+ rubygems_version: 2.5.2.1
61
61
  signing_key:
62
62
  specification_version: 4
63
63
  summary: Twisty