class Twisty::Engine
Main class within Twisty
.
Attributes
(Hash
[Command
]) Hash of user typeable commands indexed by regular expression
(Array
[Symbol
]) Keys of the Items the player is carrying
(Hash
{Symbol
=> Item
}) All Items in the game regardless of if they have been placed anywhere
(Hash
{Symbol
=> Room
}) All Rooms in the game regardless of if they can be reached
Public Class Methods
Initialiser. As this class is a singleton use Engine.instance instead
# 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
Public Instance Methods
Creates an exit from one Room
to another
- from
-
(
Symbol
) Key for theRoom
where the player is before using “walk” - to
-
(
Symbol
) Key for theRoom
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
# 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
(Hash
{Symbol
=> String
})
Exits of the Room
the player is currently in
# File lib/twisty/engine.rb, line 202 def current_doors @rooms[@current_room].doors end
(Array
[Symbol
])
Keys of the Items present in the Room
where the player is currently located
# File lib/twisty/engine.rb, line 211 def current_items @rooms[@current_room].items end
(Room
)
The instance of Room
that the player is currently in
# File lib/twisty/engine.rb, line 194 def current_room @rooms[@current_room] end
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 theRoom
where the player will go to
# 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
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 typeArray
[String
] which contains what the player typed
# File lib/twisty/engine.rb, line 181 def define_command(pattern, help1, help2, &func) @commands[pattern] = Command.new(help1, help2, func) return nil end
(Item
)
Creates a new instance of Item
in Engine.items
indexed by id. Use this instead of Item.new()
.
- id
-
(
Symbol
) Key withinEngine.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
{Symbol
=> +Any}) Additional attributes of theItem
At present there are only two valid options that can be passed via options:
# 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
(Room
)
Creates a new instance of Room
in Engine.rooms
indexed by id. Use this instead of Room.new()
.
- id
-
(
Symbol
) Key for theRoom
inEngine.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
# 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
The “drop item” command. Probably best not to call directly
- name
-
(
String
) The name, typed by the player, of the item to be
dropped
# 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
Ends the main loop of the game. Use this for win and loose conditions
# File lib/twisty/engine.rb, line 403 def end_loop @playing = false return nil end
(Symbol
)
Returns Index of the Item
of the same name in the current room
# 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
(Symbol
)
Returns Index of the Item
of the same name in the inventory
# 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
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 theItem
that will be added to the player's inventory
# 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
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 inEngine.rooms
of theRoom
that the player will be moved to
# 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
Called by start_loop
to process user inpu.
# 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
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
# 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
Starts the main loop of the game
NOTE This must be included once and only once at the end of the program
# 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
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 anItem
that the player is looking to remove added to the anotherItem
from
# 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
The “take item” command. Probably best not to call directly
- name
-
(
String
) Name of anItem
the player has typed in
# 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