Class: Twisty::Engine

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/twisty/engine.rb

Overview

Main class within Twisty.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEngine

Initialiser. As this class is a singleton use Engine.instance instead



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/twisty/engine.rb', line 36

def initialize
	@items = {}
	@rooms = {}

	@current_room = nil
	@inventory = []

	@playing = nil

	@commands = {} #Filled in by lib/twisty.rb
end

Instance Attribute Details

#commandsObject (readonly)

(Hash[Command]) Hash of user typeable commands indexed by regular expression



33
34
35
# File 'lib/twisty/engine.rb', line 33

def commands
  @commands
end

#inventoryObject (readonly)

(Array[Symbol])

Items that the user is currently carrying



31
32
33
# File 'lib/twisty/engine.rb', line 31

def inventory
  @inventory
end

#itemsObject (readonly)

(Hash=> Item) All Items in the game regardless of if they have been placed anywhere



26
27
28
# File 'lib/twisty/engine.rb', line 26

def items
  @items
end

#roomsObject (readonly)

(Hash=> Room) All Rooms in the game regardless of if they can be reached



29
30
31
# File 'lib/twisty/engine.rb', line 29

def rooms
  @rooms
end

Instance Method Details

#add_door(from, to, name) ⇒ Object

Creates an exit from one Room to another

from

(Symbol) Key for the Room where the player is before using

"walk"
to

(Symbol) Key for the Room where the player is after using “walk”

name

(String) Used to name the door. This can be a word such as

"East" rather than the name of the destination. *NOTE* Must be
one word


119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/twisty/engine.rb', line 119

def add_door(from, to, name)
	if @rooms.has_key?(from)
		if @rooms.has_key?(to)
			@rooms[from].add_door(to, name)
		else
			raise GameError.new "Invalid room name: #{to}"
		end
	else
		raise GameError.new "Invalid room name: #{from}"
	end

	return nil
end

#current_doorsObject

(Hash=> String)

Exits of the Room the player is currently in



198
199
200
# File 'lib/twisty/engine.rb', line 198

def current_doors
	@rooms[@current_room].doors
end

#current_itemsObject

(Array[Symbol])

Keys of the Items present in the Room where the player is currently located



207
208
209
# File 'lib/twisty/engine.rb', line 207

def current_items
	@rooms[@current_room].items
end

#current_roomObject

(Room)

The instance of Room that the player is currently in



190
191
192
# File 'lib/twisty/engine.rb', line 190

def current_room
	@rooms[@current_room]
end

#current_room=(id) ⇒ Object

Change the the room that the player is currently in to the one represented by the Symbol id. Unlike Engine.goto() This does not print any information or trigger events.

id

(Symbol) Key of the Room where the player will go to



139
140
141
142
143
144
145
146
147
# File 'lib/twisty/engine.rb', line 139

def current_room=(id)
	if @rooms.has_key? id
		@current_room = id
	else
		raise GameError.new "Room #{id} has not been defined"
	end

	return nil
end

#define_command(pattern, help1, help2, &func) ⇒ Object

Create a new command for the user to type. Not applicable for creating methods to develop the game with

pattern

(Regexp) Pattern that triggers the command to be run.

NOTE Must be unique and unambigious

help1

(String) An example of the command. E.g. “take item”

help2

(String) A short description of what the command does

&func

(Proc) Code executed when the player types the command in.

*NOTE* Must take one argument of type +Array+[+String+] which
contains what the player typed


177
178
179
180
# File 'lib/twisty/engine.rb', line 177

def define_command(pattern, help1, help2, &func)
	@commands[pattern] = Command.new(help1, help2, func)
	return nil
end

#define_item(id, name, desc, options = {}) ⇒ Object

Creates a new instance of Item in Engine.items indexed by id. Use this instead of Item.new().

id

(Symbol) Key within Engine.items

name

Name shown in “look” and used to “take” / “drop” the Item.

*NOTE* This MUST be a single word.
desc

(String) Long description shown when the player uses “look at”

options

(Hash=> +Any) Additional attributes of the Item

At present there are only two valid options that can be
passed via options:
fixed:: (+Boolean+) If set to true prevents "take" from
        working on the Item. Set to +false+ by default
storage:: (+Integer+) Indicates the number of other Items
          that this Item can contain. Set to +0+ by default


70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/twisty/engine.rb', line 70

def define_item(id, name, desc, options={})
	options = {fixed: false, storage: 0}.merge(options)

	fixed = options[:fixed] || false
	storage = options[:storage] || 0

	if @items[id] == nil
		@items[id] = Twisty::Item.new(id, name, desc, fixed, storage)
	else
		raise GameError.new "Item #{id} has already been defined"
	end

	return nil
end

#define_room(id, name, desc) ⇒ Object

Creates a new instance of Room in Engine.rooms indexed by id. Use this instead of Room.new().

id

(Symbol) Key for the Room in Engine.rooms

name

String (preferably one word) shown in the prompt when the player

is located in this Room
desc

(String) The long description of the player’s current location



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/twisty/engine.rb', line 93

def define_room(id, name, desc)
	room = Twisty::Room.new(id, name, desc)

	if @rooms[id] == nil
		@rooms[id] = room
	else
		raise GameError.new "Room #{id} has already been defined"
	end

	#First defined room is default starting point
	if @rooms.size == 1
		@current_room = id
	end

	return nil
end

#drop_item(name) ⇒ Object

The “drop item” command. Probably best not to call directly

name

(String) The name, typed by the player, of the item to be

dropped



334
335
336
337
338
339
340
341
342
# File 'lib/twisty/engine.rb', line 334

def drop_item(name)
	id = find_in_inventory(name)
	if @items[id].drop_event
		current_room.items << id
		@inventory.delete id
	end

	return nil
end

#end_loopObject

Ends the main loop of the game. Use this for win and loose conditions



397
398
399
400
# File 'lib/twisty/engine.rb', line 397

def end_loop
	@playing = false
	return nil
end

#find_in_current_room(name) ⇒ Object

(Symbol)

Returns Index of the Item of the same name in the current room



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/twisty/engine.rb', line 223

def find_in_current_room(name)
	current_items.each do |id|
		if @items.has_key? id
			if @items[id].name.downcase == name.downcase
				return id
			end
		else
			raise GameError.new "Invalid Item #{id} in #{@current_room}"
		end
	end

	#Could not be found
	raise PlayError.new "I see no #{name}"
	return :nil #Never reached
end

#find_in_inventory(name) ⇒ Object

(Symbol)

Returns Index of the Item of the same name in the inventory



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/twisty/engine.rb', line 243

def find_in_inventory(name)
	inventory.each do |id|
		if @items.has_key? id
			if @items[id].name.downcase == name.downcase
				return id
			end
		else
			raise GameError.new "Invalid Item #{id} in inventory"
		end
	end

	#Could not be found
	raise PlayError.new "You are not carrying that"
	return :nil
end

#give(id) ⇒ Object

Place an Item represented by the Symbol id. Unlike Engine.take_item_by_id() this does not remove the Item from any Room it may be in or trigger any events.

id

(Symbol) Key of the Item that will be added to the player’s

inventory


156
157
158
159
160
161
162
163
164
# File 'lib/twisty/engine.rb', line 156

def give(id)
	if @items.include? id
		@inventory << id
	else
		raise GameError.new "Invalid item: #{id}"
	end

	return nil
end

#goto(to) ⇒ Object

Called by the “walk door” command. Unlike current_room=(id) this triggers events and only moves the player if said events run successfully

id

(Symbol) Key in Engine.rooms of the Room that the player will

be moved to


351
352
353
354
355
356
357
358
359
360
361
# File 'lib/twisty/engine.rb', line 351

def goto(to)
	if @rooms.has_key? to
		if current_room.exit_event and @rooms[to].enter_event
			@current_room = to
		end
	else
		raise TwistyError.new "Room #{to} has not been defined"
	end

	return nil
end

#parse(line) ⇒ Object

Called by start_loop to process user inpu.



404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/twisty/engine.rb', line 404

def parse(line)
	#Strip double spaces and downcase
	tokens = line.downcase.split
	line = tokens.join(' ')

	if line == "" #Empty command
		return nil
	end

	@commands.each do |pattern, command|
		if line =~ pattern
			command.exec(tokens)
			return nil
		end
	end

	#Implicit error
	raise PlayError.new "I don't know how to #{line}"

	#Never reached
	return nil
end

#put_item(item, container) ⇒ Object

The “put item in item” command. Probably best not to call directly

item

(String) Name that the player has typed for an item to be

added to a container


313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/twisty/engine.rb', line 313

def put_item(item, container)
	iId = find_in_inventory(item)
	cId = find_in_current_room(container)

	if @items[cId].storage == 0
		raise PlayError.new "It won't fit in there"
	end

	if @items[cId].put_content_event(id) and @items[iId].drop_event
		@items[cId].add_item(iId)
		@inventory.delete iId
	end

	return nil
end

#start_loopObject

Starts the main loop of the game

NOTE This must be included once and only once at the end of the program



372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
# File 'lib/twisty/engine.rb', line 372

def start_loop
	@playing = true

	current_room.look
	puts

	while @playing == true
		printf "#{current_room.name} > "
		begin
			line = gets
			if line.class == NilClass
				@playing = false
				return nil
			end
			parse(line)
		rescue PlayError => e
			puts e.message
		end
	end

	return nil
end

#take_from(item, container) ⇒ Object

The “take item from item” command. Probably best not to call directly

item

(String) Name that the player has typed for an item to be

inventory
container

(String) Name of an Item that the player is looking to

remove added to the another Item from


287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/twisty/engine.rb', line 287

def take_from(item, container)
	cId = find_in_current_room(container) #Container ID

	@items[cId].contents.each do |iId|
		if @items.has_key? iId
			if @items[iId].name.downcase == item.downcase
				if @items[cId].take_content_event(iId) and @items[iId].take_event
					@items[cId].del_item iId
					@inventory << iId

					return nil
				end
			end
		else
			raise GameError.new "Invalid Item in container #{cId}"
		end
	end

	return nil
end

#take_item(name) ⇒ Object

The “take item” command. Probably best not to call directly

name

(String) Name of an Item the player has typed in



266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/twisty/engine.rb', line 266

def take_item(name)
	id = find_in_current_room(name)
	if @items[id].fixed
		raise PlayError.new "You can not move that"
	else
		if @items[id].take_event
			current_room.items.delete id
			@inventory << id
		end

		return nil
	end
end