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


123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/twisty/engine.rb', line 123

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



202
203
204
# File 'lib/twisty/engine.rb', line 202

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



211
212
213
# File 'lib/twisty/engine.rb', line 211

def current_items
  @rooms[@current_room].items
end

#current_roomObject

(Room)

The instance of Room that the player is currently in



194
195
196
# File 'lib/twisty/engine.rb', line 194

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



143
144
145
146
147
148
149
150
151
# File 'lib/twisty/engine.rb', line 143

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


181
182
183
184
# File 'lib/twisty/engine.rb', line 181

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

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

(Item)

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


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

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 @items[id]
end

#define_room(id, name, desc) ⇒ Object

(Room)

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



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/twisty/engine.rb', line 97

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 @rooms[id]
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



338
339
340
341
342
343
344
345
346
# File 'lib/twisty/engine.rb', line 338

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



403
404
405
406
# File 'lib/twisty/engine.rb', line 403

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



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/twisty/engine.rb', line 227

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



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/twisty/engine.rb', line 247

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


160
161
162
163
164
165
166
167
168
# File 'lib/twisty/engine.rb', line 160

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


355
356
357
358
359
360
361
362
363
364
365
# File 'lib/twisty/engine.rb', line 355

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.



410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
# File 'lib/twisty/engine.rb', line 410

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


317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/twisty/engine.rb', line 317

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(iId) 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



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/twisty/engine.rb', line 376

def start_loop
  @playing = true

  current_room.look
  puts
  @commands[/^inventory$/].exec(["inventory"])
  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


291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
# File 'lib/twisty/engine.rb', line 291

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



270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/twisty/engine.rb', line 270

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