Class: Map

Inherits:
Object
  • Object
show all
Includes:
MapDungeon, MapEntity, MapPoint
Defined in:
lib/map/map.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeMap

Returns a new instance of Map.



11
12
13
14
# File 'lib/map/map.rb', line 11

def initialize()
  @map_nodes = Hash.new()
  @adjacencies = Hash.new()
end

Instance Attribute Details

#adjacenciesObject (readonly)

Attribute access



17
18
19
# File 'lib/map/map.rb', line 17

def adjacencies
  @adjacencies
end

#map_nodesObject (readonly)

Attribute access



17
18
19
# File 'lib/map/map.rb', line 17

def map_nodes
  @map_nodes
end

Instance Method Details

#add_entity(point, entity) ⇒ Object

Adds a new entity to the node



107
108
109
# File 'lib/map/map.rb', line 107

def add_entity(point, entity)
  @map_nodes[point].add_entity(entity, entity.type())
end

#add_new_adjacent(point, newAdjacent) ⇒ Object

Adds a new adjacent to point only if it belongs to the map



93
94
95
96
97
98
# File 'lib/map/map.rb', line 93

def add_new_adjacent(point, newAdjacent)
  if((@map_nodes[point] != nil) && !(is_adjacent?(point, newAdjacent)) && (@map_nodes[newAdjacent] != nil))
    @adjacencies[point] << newAdjacent
    @adjacencies[newAdjacent] << point
  end 
end

#add_new_node(point, node, adjacencies = []) ⇒ Object

Allows user to add a new node after building the map



75
76
77
78
79
80
81
82
83
# File 'lib/map/map.rb', line 75

def add_new_node(point, node, adjacencies = [])
  @map_nodes[point] = node
  @adjacencies[point] = adjacencies
  adjacencies.each do |p| 
    if((@adjacencies[p] != nil) && !(is_adjacent?(p, point)))
      @adjacencies[p] << point
    end
  end
end

#build_map(filePath, pointBuilder = "", dungeonBuilder = "", entityBuilder = "") ⇒ Object

Builds the map structure from XML specification



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/map/map.rb', line 20

def build_map(filePath, pointBuilder = "", dungeonBuilder = "", entityBuilder = "")
  if(filePath.include?('http'))
    doc = parse_from_URL(filePath)
  else
    doc = parse_from_XML(filePath)
  end
  doc.remove_namespaces!
  doc.xpath("//node").each() do |node|
    coords = node.xpath("point//*")
    point = build_point(coords, pointBuilder)
    dungeonElements = node.xpath("dungeon//*[not(name()='entity') and not(ancestor-or-self::entity)]")
    dungeon = build_dungeon(node, dungeonElements, dungeonBuilder, entityBuilder)
    @map_nodes[point] = dungeon
    build_adjacent(point, node, pointBuilder)  
  end
  p = @map_nodes.keys().sample() #Get random key
  if(@map_nodes.length() != check_connectivity(p))
    raise MapExceptions::MalformedMapException.new()
  end
end

#check_connectivity(point, visited = Hash.new()) ⇒ Object

Checks if the map generated is fully connected



122
123
124
125
126
127
128
129
130
# File 'lib/map/map.rb', line 122

def check_connectivity(point, visited = Hash.new())
  visited[point] = 1
  @adjacencies[point].each do |nextPoint|
    if(!visited.has_key?(nextPoint))
      check_connectivity(nextPoint, visited)
    end
  end
  return visited.length()
end

#delete_adjacent(point, adjacent) ⇒ Object

Delete a single element from the adjacent list of point



101
102
103
104
# File 'lib/map/map.rb', line 101

def delete_adjacent(point, adjacent)
  @adjacencies[point].delete(adjacent)
  @adjacencies[adjacent].delete(point)
end

#delete_node(point) ⇒ Object

Allows user to delete a node of the map



86
87
88
89
90
# File 'lib/map/map.rb', line 86

def delete_node(point)
  @map_nodes.delete(point)
  @adjacencies.delete(point)
  @adjacencies.each { |k, v| @adjacencies[k].delete(point) }
end

#each_adjacencyObject

Iterates over the adjacency hash



68
69
70
71
72
# File 'lib/map/map.rb', line 68

def each_adjacency()
  @adjacencies.each { |key, value|
    value.each { |adjacent| yield adjacent }
  }
end

#get_node(point) ⇒ Object

Returns the node with that coordinates



63
64
65
# File 'lib/map/map.rb', line 63

def get_node(point)
  @map_nodes[point]
end

#has_entity?(point, entity) ⇒ Boolean

Checks if there is an entity on the node

Returns:

  • (Boolean)


117
118
119
# File 'lib/map/map.rb', line 117

def has_entity?(point, entity)
  @map_nodes[point].has_entity?(entity, entity.type())
end

#is_adjacent?(point1, point2) ⇒ Boolean

Check if point2 is in the adjacent list of point1

Returns:

  • (Boolean)


58
59
60
# File 'lib/map/map.rb', line 58

def is_adjacent?(point1, point2)
  @adjacencies[point1].find { |p| point2 == p }  
end

#move(point, entity, movX = 0, movY = 0, movZ = 0) ⇒ Object

Allows to make a movement without creating a explicit Point object



42
43
44
45
# File 'lib/map/map.rb', line 42

def move(point, entity, movX = 0, movY = 0, movZ = 0)
  toPoint = Point.new(point.x()+movX, point.y()+movY, point.z()+movZ)
  movement(point, toPoint, entity)
end

#movement(fromPoint, toPoint, entity) ⇒ Object

Puts move the entity from one point to an adjacent



48
49
50
51
52
53
54
55
# File 'lib/map/map.rb', line 48

def movement(fromPoint, toPoint, entity)
  if(is_adjacent?(fromPoint, toPoint))
      remove_entity(fromPoint, entity)
      add_entity(toPoint, entity)
  else
    raise MapExceptions::NotAdjacentException.new(fromPoint,toPoint)
  end
end

#remove_entity(point, entity) ⇒ Object

Removes an entity



112
113
114
# File 'lib/map/map.rb', line 112

def remove_entity(point, entity)
  @map_nodes[point].remove_entity(entity, entity.type())
end

#shortest_path(initial, destination) ⇒ Object

Shortest path from initial to destination



133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/map/map.rb', line 133

def shortest_path(initial, destination)
  distance = Hash.new()
  visited = Hash.new()
  @adjacencies.each_key do |point|
    if(is_adjacent?(initial, point))
      distance[point] = 1
    else
      distance[point] = (2**(0.size * 8 - 2) - 1)
    end
  end
  visited[initial] = true
  distance.delete(initial)
  until(visited.length == @adjacencies.length) do
    if((value = distance.values.min) != nil)
      if(!(visited.has_key?(distance.key(value))))
        nextNode = distance.key(value)
        visited[nextNode] = true
        if(nextNode == destination)
          break;
        end
        @adjacencies[nextNode].each do |a|
          alt = distance[nextNode] + 1
          if(!(visited.has_key?(a)) && alt < distance[a])
            distance[a] = alt
          end
        end
        distance.delete(nextNode)
      end
    end
  end
  return distance[destination]
end