-
Notifications
You must be signed in to change notification settings - Fork 0
/
location.rb
128 lines (103 loc) · 4.55 KB
/
location.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# lib/explore/models/location.rb
require 'controllers/action_delegate'
require 'util/argument_validator'
require 'util/text_processor'
require 'explore/models/edge'
require 'explore/parsers/location_parser'
module Explore::Models
# A Location is a node in the graph of explorable spaces. Each location has
# zero or more actions that can be performed on it directly, zero or more
# delegates that also respond to actions, and zero or more edges that connect
# to other nodes. Each location belongs to a Region.
class Location < RoundTable::Controllers::ActionDelegate
include RoundTable::Util::ArgumentValidator
def initialize(slug, params = nil, &block)
# @param slug : the name of the location. Must be a string or a symbol.
# @param params : additional initialization information. Must be a hash.
# @key :region (optional) : the region containing this location. Must
# be a Explore::Models::Region
# @key :name (optional) : the human-readable name of the location. If
# omitted, the name is automatically generated from the slug.
# @key :description (optional) : a short string displayed to the player
# when entering the location. Can be a string or a block, which will
# be evaluated in the context of the location instance and must
# return a string.
# @param &block (optional) : a block evaluated by a generated
# LocationParser (to avoid namespace collisions). Location can also be
# populated manually.
validate_argument slug, :as => "slug", :type => [String, Symbol]
validate_argument params, :as => "params", :type => Hash, :allow_nil? => true
config = { :name => nil }
config.update(params) if params.is_a? Hash
@slug = RoundTable::Util::TextProcessor.to_snake_case(slug.to_s).intern
@name = config[:name] || @slug.to_s.split("_").map { |str| str.capitalize }.join(" ")
@region = config[:region]
@edges = Hash.new
self.description = config[:description] || "A rather generic-looking location. Nothing to see here."
if block_given?
parser = Explore::Parsers::LocationParser.new(self)
parser.instance_eval &block
end # if
end # constructor
#################
# Other Locations
attr_reader :edges
# Adds a directed (outgoing) connection to another location that the player
# can navigate, e.g. through the "go" action.
#
# @param location: the name of the other location.
# @param params: additional parameters; see Edge.new for full details.
def add_edge(location, params = {})
if self.has_edge? location
self.edges[location].update(params)
else
edge = Explore::Models::Edge.new location, params
@edges[edge.location] = edge
end # if-else
end # method add_edge
def has_edge?(name)
@edges.has_key? name
end # method has_edge?
def has_direction?(name)
self.directions.include? name
end # method has_direction?
def has_location?(name)
self.locations.include? name
end # method has_location?
def directions
directions = Hash.new
self.edges.each do |key, loc|
directions.update({ loc.direction => key }) unless loc.direction.nil?
end # each
return directions
end # method directions
def locations
locations = Hash.new
self.edges.each do |key, loc|
locations.update({ loc.name => key }) unless loc.name.nil?
end # each
return locations
end # method locations
########################
# Accessors and Mutators
attr_reader :name, :region, :slug
def continent
self.region.continent
end # method continent
def description
@description.respond_to?(:call) ? self.instance_eval(&@description) : @description
end # accessor description
def description=(value)
raise ArgumentError.new "expected String or Proc, received #{value.class}" unless value.is_a?(String) or value.respond_to?(:call)
@description = value
end # mutator description=
def name=(value)
raise ArgumentError.new "expected String, received #{value.class}" unless value.is_a? String
@name = value
end # mutator name=
def region=(value)
raise ArgumentError.new "expected Explore::Models::Region, received #{value.class}" unless value.is_a? Explore::Models::Region
@region = value
end # mutator region=
end # class Location
end # module Explore::Models