twisty 0.0.2b
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 +7 -0
- data/lib/twisty/command.rb +24 -0
- data/lib/twisty/engine.rb +359 -0
- data/lib/twisty/entity.rb +34 -0
- data/lib/twisty/error.rb +25 -0
- data/lib/twisty/item.rb +99 -0
- data/lib/twisty/room.rb +106 -0
- data/lib/twisty.rb +106 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 973c95d14cceffd3e604a89a4d3e13aa78668c79
|
4
|
+
data.tar.gz: 2890e7f27a04df943e73b0052b4bafeae65ef3a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fcfbb0a47cc2baf7acb9e6c78999a96ed4e0b5ed50d0684ba0786faba2e7d529bbd500501db262eac72533483951c66be4c69593b67639669f5d553758f9f1ff
|
7
|
+
data.tar.gz: 91cef32321c07af3e9c27f0d6a31f625703de54ca1a8a4b706ff0a0e443a29a9619dd2b96c96533461d82aa3fc6bb049c8aea456bf6934fb6f330e1616fbfebd
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
require 'rtype'
|
11
|
+
|
12
|
+
module Twisty
|
13
|
+
|
14
|
+
class Command
|
15
|
+
rtype_accessor :help1, :help2, String
|
16
|
+
rtype_accessor :func, Proc
|
17
|
+
def initialize(help1, help2, func)
|
18
|
+
@help1 = help1
|
19
|
+
@help2 = help2
|
20
|
+
@func = func
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,359 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
require 'singleton'
|
11
|
+
require 'rtype'
|
12
|
+
|
13
|
+
require_relative 'error.rb'
|
14
|
+
require_relative 'command.rb'
|
15
|
+
require_relative 'item.rb'
|
16
|
+
require_relative 'room.rb'
|
17
|
+
|
18
|
+
module Twisty
|
19
|
+
|
20
|
+
class Engine
|
21
|
+
include Singleton
|
22
|
+
|
23
|
+
attr_reader :items, :rooms, :inventory
|
24
|
+
|
25
|
+
def initialize
|
26
|
+
@items = {}
|
27
|
+
@rooms = {}
|
28
|
+
|
29
|
+
@current_room = nil
|
30
|
+
@inventory = []
|
31
|
+
|
32
|
+
@playing = nil
|
33
|
+
|
34
|
+
@commands = {} #Filled in lib/twisty.rb
|
35
|
+
end
|
36
|
+
|
37
|
+
################################
|
38
|
+
# Game definition commands #
|
39
|
+
################################
|
40
|
+
|
41
|
+
# TODO: Make private "defining" method
|
42
|
+
|
43
|
+
rtype [Symbol, String, String, Hash] => nil
|
44
|
+
def define_item(id, name, desc, options={})
|
45
|
+
options = {fixed: false, storage: 0}.merge(options)
|
46
|
+
|
47
|
+
fixed = options[:fixed] || false
|
48
|
+
storage = options[:storage] || 0
|
49
|
+
|
50
|
+
if @items[id] == nil
|
51
|
+
@items[id] = Twisty::Item.new(id, name, desc, fixed, storage)
|
52
|
+
else
|
53
|
+
raise GameError.new "Item #{id} has already been defined"
|
54
|
+
end
|
55
|
+
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
|
59
|
+
rtype [Symbol, String, String] => nil
|
60
|
+
def define_room(id, name, desc)
|
61
|
+
room = Twisty::Room.new(id, name, desc)
|
62
|
+
|
63
|
+
if @rooms[id] == nil
|
64
|
+
@rooms[id] = room
|
65
|
+
else
|
66
|
+
raise GameError.new "Room #{id} has already been defined"
|
67
|
+
end
|
68
|
+
|
69
|
+
#First defined room is default starting point
|
70
|
+
if @rooms.size == 1
|
71
|
+
@current_room = id
|
72
|
+
end
|
73
|
+
|
74
|
+
return nil
|
75
|
+
end
|
76
|
+
|
77
|
+
rtype [Symbol, Symbol, String] => nil
|
78
|
+
def add_door(from, to, name)
|
79
|
+
if @rooms.has_key?(from)
|
80
|
+
if @rooms.has_key?(to)
|
81
|
+
@rooms[from].add_door(to, name)
|
82
|
+
else
|
83
|
+
raise GameError.new "Invalid room name: #{to}"
|
84
|
+
end
|
85
|
+
else
|
86
|
+
raise GameError.new "Invalid room name: #{from}"
|
87
|
+
end
|
88
|
+
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
rtype [Symbol] => nil
|
93
|
+
def current_room=(id)
|
94
|
+
if @rooms.has_key? id
|
95
|
+
@current_room = id
|
96
|
+
else
|
97
|
+
raise GameError.new "Room #{id} has not been defined"
|
98
|
+
end
|
99
|
+
|
100
|
+
return nil
|
101
|
+
end
|
102
|
+
|
103
|
+
rtype [] => nil
|
104
|
+
def give(id)
|
105
|
+
if @items.include? id
|
106
|
+
@inventory << id
|
107
|
+
else
|
108
|
+
raise GameError.new "Invalid item: #{id}"
|
109
|
+
end
|
110
|
+
|
111
|
+
return nil
|
112
|
+
end
|
113
|
+
|
114
|
+
rtype [Regexp, String, String, Proc] => nil
|
115
|
+
def define_command(pattern, help1, help2, &func)
|
116
|
+
@commands[pattern] = Command.new(help1, help2, func)
|
117
|
+
return nil
|
118
|
+
end
|
119
|
+
|
120
|
+
#########################
|
121
|
+
# Utility functions #
|
122
|
+
#########################
|
123
|
+
|
124
|
+
rtype [] => Room
|
125
|
+
def current_room
|
126
|
+
@rooms[@current_room]
|
127
|
+
end
|
128
|
+
|
129
|
+
rtype [] => Hash.of(Symbol, String)
|
130
|
+
def current_doors
|
131
|
+
@rooms[@current_room].doors
|
132
|
+
end
|
133
|
+
|
134
|
+
rtype [] => Array.of(Symbol)
|
135
|
+
def current_items
|
136
|
+
@rooms[@current_room].items
|
137
|
+
end
|
138
|
+
|
139
|
+
rtype [] => Array.of(Symbol)
|
140
|
+
def inventory
|
141
|
+
@inventory
|
142
|
+
end
|
143
|
+
|
144
|
+
##########################
|
145
|
+
# Game play commands #
|
146
|
+
##########################
|
147
|
+
rtype [String] => nil
|
148
|
+
def take_item_by_name(name)
|
149
|
+
current_items.each do |id|
|
150
|
+
if @items.has_key? id
|
151
|
+
if @items[id].name.downcase == name.downcase
|
152
|
+
take_item_by_id(id)
|
153
|
+
return nil
|
154
|
+
end
|
155
|
+
else
|
156
|
+
raise GameError.new "Invalid Item #{id} in #{@current_room}"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
#Implicit error condition
|
161
|
+
raise PlayError.new "There is no #{name} here"
|
162
|
+
return nil
|
163
|
+
end
|
164
|
+
|
165
|
+
rtype [Symbol] => nil
|
166
|
+
def take_item_by_id(id)
|
167
|
+
if @items.has_key? id
|
168
|
+
if current_items.include? id
|
169
|
+
if @items[id].fixed
|
170
|
+
raise PlayError.new "You can not move that"
|
171
|
+
else
|
172
|
+
if @items[id].take_event
|
173
|
+
current_room.items.delete id
|
174
|
+
@inventory << id
|
175
|
+
end
|
176
|
+
|
177
|
+
return nil
|
178
|
+
end
|
179
|
+
else
|
180
|
+
raise GameError.new "There is no #{id} in #{@current_room}"
|
181
|
+
end
|
182
|
+
else
|
183
|
+
raise GameError.new "Invalid Item #{id} in #{@current_room}"
|
184
|
+
end
|
185
|
+
|
186
|
+
return nil
|
187
|
+
end
|
188
|
+
|
189
|
+
rtype [String, String] => nil
|
190
|
+
def take_from_by_name_name(item, container)
|
191
|
+
current_items.each do |id|
|
192
|
+
if @items[id].name.downcase == container
|
193
|
+
return take_from_by_name_id(item, id)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
#Implicit error
|
198
|
+
raise PlayError.new "I can not see any #{container} here"
|
199
|
+
return nil
|
200
|
+
end
|
201
|
+
|
202
|
+
rtype [String, Symbol] => nil
|
203
|
+
def take_from_by_name_id(item, container)
|
204
|
+
@items[container].contents.each do |id|
|
205
|
+
if @items[id].name.downcase == item
|
206
|
+
if @items[id].take_event
|
207
|
+
@items[container].del_item id
|
208
|
+
@inventory << id
|
209
|
+
end
|
210
|
+
|
211
|
+
return nil
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
#Implicit Error
|
216
|
+
raise PlayError.new "I see no #{item} in the #{@items[container].name}"
|
217
|
+
return nil
|
218
|
+
end
|
219
|
+
|
220
|
+
rtype [String, String] => nil
|
221
|
+
def put_item_by_name_name(item, container)
|
222
|
+
@inventory.each do |id|
|
223
|
+
if @items[id].name.downcase == item
|
224
|
+
return put_item_by_id_name(id, container)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
#Implicit Error
|
229
|
+
raise PlayError.new "You have no #{item}"
|
230
|
+
return nil
|
231
|
+
end
|
232
|
+
|
233
|
+
rtype [Symbol, String] => nil
|
234
|
+
def put_item_by_id_name(item, container)
|
235
|
+
current_items.each do |id|
|
236
|
+
if @items[id].name.downcase == container
|
237
|
+
if @items[id].storage == 0
|
238
|
+
raise PlayError.new "It won't fit in there"
|
239
|
+
end
|
240
|
+
|
241
|
+
if @items[item].drop_event
|
242
|
+
@items[id].add_item(item)
|
243
|
+
@inventory.delete item
|
244
|
+
end
|
245
|
+
|
246
|
+
return nil
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
#Implicit Error
|
251
|
+
raise PlayError.new "I see no #{item}"
|
252
|
+
return nil
|
253
|
+
end
|
254
|
+
|
255
|
+
rtype [String] => nil
|
256
|
+
def drop_item_by_name(name)
|
257
|
+
@inventory.each do |id|
|
258
|
+
if @items.has_key? id
|
259
|
+
if @items[id].name.downcase == name
|
260
|
+
drop_item_by_id(id)
|
261
|
+
|
262
|
+
return nil
|
263
|
+
end
|
264
|
+
else
|
265
|
+
raise GameError.new "Invalid Item: #{id}"
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
#Implicit error condition
|
270
|
+
raise PlayError.new "You are not carrying that"
|
271
|
+
return nil
|
272
|
+
end
|
273
|
+
|
274
|
+
rtype [Symbol] => nil
|
275
|
+
def drop_item_by_id(id)
|
276
|
+
if @items.has_key? id
|
277
|
+
if @items[id].drop_event
|
278
|
+
current_room.items << id
|
279
|
+
@inventory.delete id
|
280
|
+
end
|
281
|
+
|
282
|
+
return nil
|
283
|
+
else
|
284
|
+
raise GameError.new "Invalid item: #{id} in inventory"
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
rtype [Symbol] => nil
|
289
|
+
def goto(to)
|
290
|
+
if @rooms.has_key? to
|
291
|
+
if current_room.exit_event and @rooms[to].enter_event
|
292
|
+
@current_room = to
|
293
|
+
end
|
294
|
+
puts current_room.name
|
295
|
+
else
|
296
|
+
raise TwistyError.new "Room #{to} has not been defined"
|
297
|
+
end
|
298
|
+
|
299
|
+
return nil
|
300
|
+
end
|
301
|
+
|
302
|
+
#######################
|
303
|
+
# Loop and Parser #
|
304
|
+
#######################
|
305
|
+
|
306
|
+
rtype [] => nil
|
307
|
+
def start_loop
|
308
|
+
@playing = true
|
309
|
+
|
310
|
+
puts current_room.name
|
311
|
+
puts
|
312
|
+
current_room.look
|
313
|
+
|
314
|
+
while @playing == true
|
315
|
+
printf "> "
|
316
|
+
begin
|
317
|
+
line = gets
|
318
|
+
if line.class == NilClass
|
319
|
+
@playing = false
|
320
|
+
return nil
|
321
|
+
end
|
322
|
+
parse(line)
|
323
|
+
rescue PlayError => e
|
324
|
+
puts e.message
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
return nil
|
329
|
+
end
|
330
|
+
|
331
|
+
rtype [] => nil
|
332
|
+
def end_loop
|
333
|
+
@playing = false
|
334
|
+
return nil
|
335
|
+
end
|
336
|
+
|
337
|
+
rtype [] => nil
|
338
|
+
def parse(line)
|
339
|
+
#Strip double spaces and downcase
|
340
|
+
tokens = line.downcase.split
|
341
|
+
line = tokens.join(' ')
|
342
|
+
|
343
|
+
@commands.each do |pattern, command|
|
344
|
+
if line =~ pattern
|
345
|
+
#Execute as if a member function
|
346
|
+
instance_exec(tokens, &command.func)
|
347
|
+
return nil
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
#Implicit error
|
352
|
+
raise PlayError.new "I don't know how to #{line}"
|
353
|
+
|
354
|
+
#Never reached
|
355
|
+
return nil
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
require 'rtype'
|
11
|
+
|
12
|
+
module Twisty
|
13
|
+
|
14
|
+
class Entity
|
15
|
+
attr_reader :id
|
16
|
+
|
17
|
+
rtype [Entity] => Boolean
|
18
|
+
def ==(other)
|
19
|
+
if other.class == self.class
|
20
|
+
return other.id == @id
|
21
|
+
elsif other.class == Symbol
|
22
|
+
return other == @id
|
23
|
+
else
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def engine
|
30
|
+
return Engine.instance()
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/twisty/error.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
module Twisty
|
11
|
+
|
12
|
+
class TwistyError < RuntimeError
|
13
|
+
attr_reader :message
|
14
|
+
|
15
|
+
def initialize(s)
|
16
|
+
@message = s
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class GameError < TwistyError
|
21
|
+
end
|
22
|
+
class PlayError < TwistyError
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/twisty/item.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
require_relative 'entity'
|
11
|
+
|
12
|
+
require 'rtype'
|
13
|
+
|
14
|
+
|
15
|
+
module Twisty
|
16
|
+
|
17
|
+
class Item < Entity
|
18
|
+
attr_reader :name, :desc, :fixed, :storage, :contents
|
19
|
+
|
20
|
+
def initialize(id, name, desc, fixed, storage)
|
21
|
+
@id = id
|
22
|
+
@name = name
|
23
|
+
@desc = desc
|
24
|
+
@fixed = fixed
|
25
|
+
@storage = storage
|
26
|
+
@contents = []
|
27
|
+
end
|
28
|
+
|
29
|
+
rtype [] => Boolean
|
30
|
+
def take_event
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
rtype [] => Boolean
|
35
|
+
def drop_event
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
|
39
|
+
rtype [] => nil
|
40
|
+
def look
|
41
|
+
puts @desc
|
42
|
+
|
43
|
+
if @storage > 0
|
44
|
+
puts "Contents:"
|
45
|
+
|
46
|
+
if @contents.length == 0
|
47
|
+
puts "Nothing"
|
48
|
+
else
|
49
|
+
@contents.each{|id| puts engine.items[id].name}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
return nil
|
54
|
+
end
|
55
|
+
|
56
|
+
rtype [Symbol] => Boolean
|
57
|
+
def contains_item?(item)
|
58
|
+
return @contents.include?(item) if @storage > 0
|
59
|
+
return false
|
60
|
+
end
|
61
|
+
|
62
|
+
rtype [Symbol] => nil
|
63
|
+
def add_item(item)
|
64
|
+
if @storage == 0
|
65
|
+
raise GameError.new "#{@id} is not a container"
|
66
|
+
else
|
67
|
+
#Skip if already contained
|
68
|
+
if contains_item?(item) == false
|
69
|
+
@contents << item
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
return nil
|
74
|
+
end
|
75
|
+
|
76
|
+
rtype [Symbol] => nil
|
77
|
+
def del_item(item)
|
78
|
+
#Skip if already contained
|
79
|
+
if contains_item?(item)
|
80
|
+
@contents.delete item
|
81
|
+
end
|
82
|
+
|
83
|
+
return nil
|
84
|
+
end
|
85
|
+
|
86
|
+
rtype [Proc] => nil
|
87
|
+
def on_take(&block)
|
88
|
+
self.define_singleton_method(:take_event, &block)
|
89
|
+
return nil
|
90
|
+
end
|
91
|
+
|
92
|
+
rtype [Proc] => nil
|
93
|
+
def on_drop(&block)
|
94
|
+
self.define_singleton_method(:drop_event, &block)
|
95
|
+
return nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
data/lib/twisty/room.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
require_relative 'entity.rb'
|
11
|
+
|
12
|
+
require 'rtype'
|
13
|
+
|
14
|
+
module Twisty
|
15
|
+
|
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
|
28
|
+
|
29
|
+
rtype [] => Boolean
|
30
|
+
def enter_event
|
31
|
+
return true
|
32
|
+
end
|
33
|
+
|
34
|
+
rtype [] => Boolean
|
35
|
+
def exit_event
|
36
|
+
return true
|
37
|
+
end
|
38
|
+
|
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
|
50
|
+
end
|
51
|
+
|
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
|
60
|
+
|
61
|
+
rtype [Proc] => nil
|
62
|
+
def on_enter(&block)
|
63
|
+
self.define_singleton_method(:enter_event, &block)
|
64
|
+
return nil
|
65
|
+
end
|
66
|
+
|
67
|
+
rtype [Proc] => nil
|
68
|
+
def on_exit(&block)
|
69
|
+
self.define_singleton_method(:exit_event, &block)
|
70
|
+
return nil
|
71
|
+
end
|
72
|
+
|
73
|
+
rtype [] => nil
|
74
|
+
def look
|
75
|
+
puts @desc
|
76
|
+
|
77
|
+
if @items.length == 0
|
78
|
+
puts "Nothing is located here"
|
79
|
+
elsif @items.length == 1
|
80
|
+
puts
|
81
|
+
|
82
|
+
puts "Located here is:"
|
83
|
+
puts engine.items[@items[0]].name
|
84
|
+
else
|
85
|
+
puts
|
86
|
+
|
87
|
+
puts "Located here are:"
|
88
|
+
@items.each{ |id| puts engine.items[id].name }
|
89
|
+
end
|
90
|
+
|
91
|
+
puts
|
92
|
+
|
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
|
101
|
+
|
102
|
+
return nil
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
data/lib/twisty.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
#############################################################################
|
2
|
+
# #
|
3
|
+
# Copyright (c) 2017, Ryan McCoskrie <work@ryanmccoskrie.me> #
|
4
|
+
# #
|
5
|
+
# This software is distributed under the MIT License which can be found #
|
6
|
+
# in the root directory. #
|
7
|
+
# #
|
8
|
+
#############################################################################
|
9
|
+
|
10
|
+
require_relative 'twisty/error.rb'
|
11
|
+
require_relative 'twisty/engine.rb'
|
12
|
+
require_relative 'twisty/command.rb'
|
13
|
+
require_relative 'twisty/entity.rb'
|
14
|
+
require_relative 'twisty/room.rb'
|
15
|
+
require_relative 'twisty/item.rb'
|
16
|
+
|
17
|
+
|
18
|
+
module Twisty
|
19
|
+
|
20
|
+
Engine.instance.define_command(
|
21
|
+
/^help$/,
|
22
|
+
"help",
|
23
|
+
"Write out the list of commands you are reading now") do |x|
|
24
|
+
@commands.values.each do |command|
|
25
|
+
puts "#{command.help1}:"
|
26
|
+
puts "#{command.help2}"
|
27
|
+
puts
|
28
|
+
end
|
29
|
+
end
|
30
|
+
Engine.instance.define_command(
|
31
|
+
/^look$/,
|
32
|
+
"look",
|
33
|
+
"Look at the current room") {|x| current_room.look()}
|
34
|
+
|
35
|
+
Engine.instance.define_command(
|
36
|
+
/^look at \w+$/,
|
37
|
+
"look at object",
|
38
|
+
"Look at a specific object") do |tokens|
|
39
|
+
found = false
|
40
|
+
current_items.each do |id|
|
41
|
+
if @items[id].name.downcase == tokens[2]
|
42
|
+
@items[id].look
|
43
|
+
found = true
|
44
|
+
break
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
#Error condidtion
|
49
|
+
raise PlayError.new "I see no #{tokens[2]}" unless found
|
50
|
+
end
|
51
|
+
Engine.instance.define_command(
|
52
|
+
/^inventory$/,
|
53
|
+
"inventory",
|
54
|
+
"Get a list of things you are carrying") do |x|
|
55
|
+
if @inventory.size == 0
|
56
|
+
puts "You are currently carrying nothing"
|
57
|
+
else
|
58
|
+
puts "You are currently carring: "
|
59
|
+
@inventory.each{|id| puts @items[id].name}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
Engine.instance.define_command(
|
63
|
+
/^take \w+$/,
|
64
|
+
"take object",
|
65
|
+
"Take an object and carry it in your inventory") do |tokens|
|
66
|
+
take_item_by_name(tokens[1])
|
67
|
+
end
|
68
|
+
Engine.instance.define_command(
|
69
|
+
/^take \w+ from \w+$/,
|
70
|
+
"take object from container",
|
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])
|
73
|
+
end
|
74
|
+
Engine.instance.define_command(
|
75
|
+
/^drop \w+$/,
|
76
|
+
"drop object",
|
77
|
+
"Remove an object from your inventory and leave it in the room") do |tokens|
|
78
|
+
drop_item_by_name(tokens[1])
|
79
|
+
end
|
80
|
+
Engine.instance.define_command(
|
81
|
+
/^put \w+ in \w+$/,
|
82
|
+
"put item in container",
|
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])
|
85
|
+
end
|
86
|
+
Engine.instance.define_command(
|
87
|
+
/^walk \w+$/,
|
88
|
+
"walk exit",
|
89
|
+
"Walk out of the room through an exit") do |tokens|
|
90
|
+
found = false
|
91
|
+
current_doors.each_pair do |to, name|
|
92
|
+
if name.downcase == tokens[1]
|
93
|
+
goto to
|
94
|
+
found = true
|
95
|
+
break
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
#Error condition
|
100
|
+
raise PlayError.new "Where is #{tokens[1]}?" unless found
|
101
|
+
end
|
102
|
+
Engine.instance.define_command(
|
103
|
+
/^quit$/,
|
104
|
+
"quit",
|
105
|
+
"Stop playing the game") {|x| @playing = false}
|
106
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: twisty
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2b
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan McCoskrie
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rtype-native
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.6.8
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.6.8
|
27
|
+
description: Adventure game library
|
28
|
+
email: work@ryanmccoskrie.me
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/twisty.rb
|
34
|
+
- lib/twisty/command.rb
|
35
|
+
- lib/twisty/engine.rb
|
36
|
+
- lib/twisty/entity.rb
|
37
|
+
- lib/twisty/error.rb
|
38
|
+
- lib/twisty/item.rb
|
39
|
+
- lib/twisty/room.rb
|
40
|
+
homepage: http://rubygems.org/gems/twisty
|
41
|
+
licenses:
|
42
|
+
- MIT
|
43
|
+
metadata: {}
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - ">"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: 1.3.1
|
58
|
+
requirements: []
|
59
|
+
rubyforge_project:
|
60
|
+
rubygems_version: 2.6.11
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: Twisty
|
64
|
+
test_files: []
|