Made depth-first map display mechanism
This commit is contained in:
parent
6c2722a3f2
commit
2b61637d61
2 changed files with 177 additions and 125 deletions
|
|
@ -170,7 +170,7 @@ class MapNode:
|
||||||
# This catches eventual longer link chains that would otherwise be lost
|
# This catches eventual longer link chains that would otherwise be lost
|
||||||
# {startdirection: [direction, ...], ...}
|
# {startdirection: [direction, ...], ...}
|
||||||
# where the directional path-lists also include the start-direction
|
# where the directional path-lists also include the start-direction
|
||||||
self.xy_steps_in_direction = {}
|
self.xy_steps_to_node = {}
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"<MapNode '{self.symbol}' {self.node_index} XY=({round(self.X)},{round(self.Y)})"
|
return f"<MapNode '{self.symbol}' {self.node_index} XY=({round(self.X)},{round(self.Y)})"
|
||||||
|
|
@ -207,12 +207,13 @@ class MapNode:
|
||||||
if end_node:
|
if end_node:
|
||||||
# the link could be followed to an end node!
|
# the link could be followed to an end node!
|
||||||
node_index = end_node.node_index
|
node_index = end_node.node_index
|
||||||
self.links[direction] = end_node
|
|
||||||
self.weights[node_index] = weight
|
self.weights[node_index] = weight
|
||||||
|
self.links[direction] = end_node
|
||||||
|
# this is useful for map building later - there could be multiple
|
||||||
|
# links tied together until getting to the node
|
||||||
|
self.xy_steps_to_node[direction] = steps
|
||||||
|
|
||||||
# this is useful for map building later
|
# used for building the shortest path
|
||||||
self.xy_steps_in_direction[direction] = steps
|
|
||||||
|
|
||||||
cheapest = self.cheapest_to_node.get(node_index, ("", _BIG))[1]
|
cheapest = self.cheapest_to_node.get(node_index, ("", _BIG))[1]
|
||||||
if weight < cheapest:
|
if weight < cheapest:
|
||||||
self.cheapest_to_node[node_index] = (direction, weight)
|
self.cheapest_to_node[node_index] = (direction, weight)
|
||||||
|
|
@ -253,18 +254,16 @@ class MapNode:
|
||||||
|
|
||||||
class MapLink:
|
class MapLink:
|
||||||
"""
|
"""
|
||||||
This represents a link between up to 8 nodes. A link is always
|
This represents a link between up to 8 nodes. A Link can be placed
|
||||||
located on a (.5, .5) location on the map like (1.5, 2.5).
|
on any location in the grid, but when on an integer XY position they
|
||||||
|
don't represent an actual in-game place but just a link between such
|
||||||
|
places (nodes).
|
||||||
|
|
||||||
Each link has a 'weight' from 1...inf, whis indicates how 'slow'
|
Each link has a 'weight' >=1, this indicates how 'slow'
|
||||||
it is to traverse that link. This is used by the Dijkstra algorithm
|
it is to traverse that link. This is used by the Dijkstra algorithm
|
||||||
to find the 'fastest' route to a point. By default this weight is 1
|
to find the 'fastest' route to a point. By default this weight is 1
|
||||||
for every link, but a locked door, terrain etc could increase this
|
for every link, but a locked door, terrain etc could increase this
|
||||||
and have the algorithm prefer to use another route.
|
and have the shortest-path algorithm prefer to use another route.
|
||||||
|
|
||||||
It is usually bidirectional, but could also be one-directional.
|
|
||||||
It is also possible for a link to have some sort of blockage, like
|
|
||||||
a door.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# link setup
|
# link setup
|
||||||
|
|
@ -312,7 +311,7 @@ class MapLink:
|
||||||
def get_visually_connected(self, xygrid, directions=None):
|
def get_visually_connected(self, xygrid, directions=None):
|
||||||
"""
|
"""
|
||||||
A helper to get all directions to which there appears to be a
|
A helper to get all directions to which there appears to be a
|
||||||
visual link/node. This does not trace the link and check weights etc.
|
visual link/node. This does not trace the length of the link and check weights etc.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
link (MapLink): Currently active link.
|
link (MapLink): Currently active link.
|
||||||
|
|
@ -620,7 +619,7 @@ class Map:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
mapcorner_symbol = '+'
|
mapcorner_symbol = '+'
|
||||||
max_pathfinding_length = 1000
|
max_pathfinding_length = 500
|
||||||
empty_symbol = ' '
|
empty_symbol = ' '
|
||||||
# we normally only accept one single character for the legend key
|
# we normally only accept one single character for the legend key
|
||||||
legend_key_exceptions = ("\\")
|
legend_key_exceptions = ("\\")
|
||||||
|
|
@ -675,7 +674,57 @@ class Map:
|
||||||
return "\n".join("".join(line) for line in self.display_map[::-1])
|
return "\n".join("".join(line) for line in self.display_map[::-1])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"<Map {self.max_X}x{self.max_Y}, {len(self.node_index_map)} nodes>"
|
return f"<Map {self.max_X + 1}x{self.max_Y + 1}, {len(self.node_index_map)} nodes>"
|
||||||
|
|
||||||
|
def _get_topology_around_coord(self, coord, dist=2):
|
||||||
|
"""
|
||||||
|
Get all links and nodes up to a certain distance from an XY coordinate.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
coord (tuple), the X,Y coordinate of the center point.
|
||||||
|
dist (int): How many nodes away from center point to find paths for.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: A tuple of 5 elements `(coords, xmin, xmax, ymin, ymax)`, where the
|
||||||
|
first element is a list of xy-coordinates (on xygrid) for all linked nodes within
|
||||||
|
range. This is meant to be used with the xygrid for extracting a subset
|
||||||
|
for display purposes. The others are the minimum size of the rectangle
|
||||||
|
surrounding the area containing `coords`.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
This performs a depth-first pass down the the given dist.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def _scan_neighbors(start_node, points, dist=2,
|
||||||
|
xmin=_BIG, ymin=_BIG, xmax=0, ymax=0, depth=0):
|
||||||
|
|
||||||
|
x0, y0 = start_node.x, start_node.y
|
||||||
|
points.append((x0, y0))
|
||||||
|
xmin, xmax = min(xmin, x0), max(xmax, x0)
|
||||||
|
ymin, ymax = min(ymin, y0), max(ymax, y0)
|
||||||
|
|
||||||
|
if depth < dist:
|
||||||
|
# keep stepping
|
||||||
|
for direction, end_node in start_node.links.items():
|
||||||
|
x, y = x0, y0
|
||||||
|
for stepdirection in start_node.xy_steps_to_node[direction]:
|
||||||
|
dx, dy = _MAPSCAN[stepdirection]
|
||||||
|
|
||||||
|
x, y = x + dx, y + dy
|
||||||
|
points.append((x, y))
|
||||||
|
xmin, xmax = min(xmin, x), max(xmax, x)
|
||||||
|
ymin, ymax = min(ymin, y), max(ymax, y)
|
||||||
|
|
||||||
|
points, xmin, xmax, ymin, ymax = _scan_neighbors(
|
||||||
|
end_node, points, dist=dist,
|
||||||
|
xmin=xmin, ymin=ymin, xmax=xmax, ymax=ymax,
|
||||||
|
depth=depth + 1)
|
||||||
|
|
||||||
|
return points, xmin, xmax, ymin, ymax
|
||||||
|
|
||||||
|
center_node = self.get_node_from_coord(coord)
|
||||||
|
points, xmin, xmax, ymin, ymax = _scan_neighbors(center_node, [], dist=dist)
|
||||||
|
return list(set(points)), xmin, xmax, ymin, ymax
|
||||||
|
|
||||||
def _calculate_path_matrix(self):
|
def _calculate_path_matrix(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -695,7 +744,7 @@ class Map:
|
||||||
# solve using Dijkstra's algorithm
|
# solve using Dijkstra's algorithm
|
||||||
self.dist_matrix, self.pathfinding_routes = dijkstra(
|
self.dist_matrix, self.pathfinding_routes = dijkstra(
|
||||||
pathfinding_matrix, directed=True,
|
pathfinding_matrix, directed=True,
|
||||||
return_predecessors=True, limit=1000)
|
return_predecessors=True, limit=self.max_pathfinding_length)
|
||||||
|
|
||||||
def _parse(self):
|
def _parse(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -958,14 +1007,17 @@ class Map:
|
||||||
Display the map centered on a point and everything around it within a certain distance.
|
Display the map centered on a point and everything around it within a certain distance.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
coord (tuple): (X,Y) in-world coordinate location.
|
coord (tuple): (X,Y) in-world coordinate location. If this is not the location
|
||||||
|
of a node on the grid, the `character` or the empty-space symbol (by default
|
||||||
|
an empty space) will be shown.
|
||||||
dist (int, optional): Number of gridpoints distance to show. Which
|
dist (int, optional): Number of gridpoints distance to show. Which
|
||||||
grid to use depends on the setting of `only_nodes`.
|
grid to use depends on the setting of `only_nodes`.
|
||||||
mode (str, optional): One of 'scan' or 'nodes'. In 'scan' mode, dist measure
|
mode (str, optional): One of 'scan' or 'nodes'. In 'scan' mode, dist measure
|
||||||
number of xy grid points in all directions. If 'nodes', distance
|
number of xy grid points in all directions and doesn't care about if visible
|
||||||
measure how many full nodes away to display.
|
nodes are reachable or not. If 'nodes', distance measure how many linked nodes
|
||||||
|
away from the center coordinate to display.
|
||||||
character (str, optional): Place this symbol at the `coord` position
|
character (str, optional): Place this symbol at the `coord` position
|
||||||
of the displayed map. Ignored if falsy.
|
of the displayed map. The center node' symbol is shown if this is falsy.
|
||||||
max_size (tuple, optional): A max `(width, height)` to crop the displayed
|
max_size (tuple, optional): A max `(width, height)` to crop the displayed
|
||||||
return to. Make both odd numbers to get a perfect center.
|
return to. Make both odd numbers to get a perfect center.
|
||||||
If unset, display-size can grow up to the full size of the grid.
|
If unset, display-size can grow up to the full size of the grid.
|
||||||
|
|
@ -1013,63 +1065,18 @@ class Map:
|
||||||
ix, iy = max(0, min(iX * 2, width)), max(0, min(iY * 2, height))
|
ix, iy = max(0, min(iX * 2, width)), max(0, min(iY * 2, height))
|
||||||
display_map = self.display_map
|
display_map = self.display_map
|
||||||
|
|
||||||
if dist <= 0:
|
if dist <= 0 or not self.get_node_from_coord(coord):
|
||||||
# show nothing but ourselves
|
# There is no node at these coordinates. Show
|
||||||
return character if character else ' '
|
# nothing but ourselves or emptiness
|
||||||
|
return character if character else self.empty_symbol
|
||||||
|
|
||||||
if mode == 'nodes':
|
if mode == 'nodes':
|
||||||
# dist measures only full, reachable nodes.
|
# dist measures only full, reachable nodes.
|
||||||
# this requires a series of shortest-path
|
# this requires a series of shortest-path
|
||||||
# Steps from on the pre-calulcated grid.
|
# Steps from on the pre-calulcated grid.
|
||||||
|
# from evennia import set_trace;set_trace()
|
||||||
|
|
||||||
if not self.dist_matrix:
|
points, xmin, xmax, ymin, ymax = self._get_topology_around_coord(coord, dist=dist)
|
||||||
self._calculate_path_matrix()
|
|
||||||
|
|
||||||
xmin, ymin = width, height
|
|
||||||
xmax, ymax = 0, 0
|
|
||||||
# adjusted center of map section
|
|
||||||
ixc, iyc = ix, iy
|
|
||||||
|
|
||||||
center_node = self.get_node_from_coord((iX, iY))
|
|
||||||
if not center_node:
|
|
||||||
# there is nothing at this grid location
|
|
||||||
return character if character else ' '
|
|
||||||
|
|
||||||
# the points list coordinates on the xygrid to show.
|
|
||||||
points = [(ix, iy)]
|
|
||||||
node_index_map = self.node_index_map
|
|
||||||
|
|
||||||
# find all reachable nodes within a (weighted) distance of `dist`
|
|
||||||
for inode, node_dist in enumerate(self.dist_matrix[center_node.node_index]):
|
|
||||||
|
|
||||||
if node_dist > dist:
|
|
||||||
continue
|
|
||||||
|
|
||||||
# we have a node within 'dist' from us, get, the route to it
|
|
||||||
node = node_index_map[inode]
|
|
||||||
_, path = self.get_shortest_path((iX, iY), (node.X, node.Y))
|
|
||||||
# follow directions to figure out which map coords to display
|
|
||||||
node0 = node
|
|
||||||
ix0, iy0 = ix, iy
|
|
||||||
for path_element in path:
|
|
||||||
# we don't need the start node since we know it already
|
|
||||||
if isinstance(path_element, str):
|
|
||||||
# a direction - this can lead to following
|
|
||||||
# a longer link-chain chain
|
|
||||||
for dstep in node0.xy_steps_in_direction[path_element]:
|
|
||||||
dx, dy = _MAPSCAN[dstep]
|
|
||||||
ix0, iy0 = ix0 + dx, iy0 + dy
|
|
||||||
points.append((ix0, iy0))
|
|
||||||
xmin, ymin = min(xmin, ix0), min(ymin, iy0)
|
|
||||||
xmax, ymax = max(xmax, ix0), max(ymax, iy0)
|
|
||||||
else:
|
|
||||||
# a Mapnode
|
|
||||||
node0 = path_element
|
|
||||||
ix0, iy0 = node0.x, node0.y
|
|
||||||
if (ix0, iy0) != (ix, iy):
|
|
||||||
points.append((ix0, iy0))
|
|
||||||
xmin, ymin = min(xmin, ix0), min(ymin, iy0)
|
|
||||||
xmax, ymax = max(xmax, ix0), max(ymax, iy0)
|
|
||||||
|
|
||||||
ixc, iyc = ix - xmin, iy - ymin
|
ixc, iyc = ix - xmin, iy - ymin
|
||||||
# note - override width/height here since our grid is
|
# note - override width/height here since our grid is
|
||||||
|
|
@ -1079,6 +1086,63 @@ class Map:
|
||||||
for (ix0, iy0) in points:
|
for (ix0, iy0) in points:
|
||||||
gridmap[iy0 - ymin][ix0 - xmin] = display_map[iy0][ix0]
|
gridmap[iy0 - ymin][ix0 - xmin] = display_map[iy0][ix0]
|
||||||
|
|
||||||
|
# if not self.dist_matrix:
|
||||||
|
# self._calculate_path_matrix()
|
||||||
|
#
|
||||||
|
# xmin, ymin = width, height
|
||||||
|
# xmax, ymax = 0, 0
|
||||||
|
# # adjusted center of map section
|
||||||
|
# ixc, iyc = ix, iy
|
||||||
|
#
|
||||||
|
# center_node = self.get_node_from_coord((iX, iY))
|
||||||
|
# if not center_node:
|
||||||
|
# # there is nothing at this grid location
|
||||||
|
# return character if character else ' '
|
||||||
|
#
|
||||||
|
# # the points list coordinates on the xygrid to show.
|
||||||
|
# points = [(ix, iy)]
|
||||||
|
# node_index_map = self.node_index_map
|
||||||
|
#
|
||||||
|
# # find all reachable nodes within a (weighted) distance of `dist`
|
||||||
|
# for inode, node_dist in enumerate(self.dist_matrix[center_node.node_index]):
|
||||||
|
#
|
||||||
|
# if node_dist > dist:
|
||||||
|
# continue
|
||||||
|
#
|
||||||
|
# # we have a node within 'dist' from us, get, the route to it
|
||||||
|
# node = node_index_map[inode]
|
||||||
|
# _, path = self.get_shortest_path((iX, iY), (node.X, node.Y))
|
||||||
|
# # follow directions to figure out which map coords to display
|
||||||
|
# node0 = node
|
||||||
|
# ix0, iy0 = ix, iy
|
||||||
|
# for path_element in path:
|
||||||
|
# # we don't need the start node since we know it already
|
||||||
|
# if isinstance(path_element, str):
|
||||||
|
# # a direction - this can lead to following
|
||||||
|
# # a longer link-chain chain
|
||||||
|
# for dstep in node0.xy_steps_to_noden[path_element]:
|
||||||
|
# dx, dy = _MAPSCAN[dstep]
|
||||||
|
# ix0, iy0 = ix0 + dx, iy0 + dy
|
||||||
|
# points.append((ix0, iy0))
|
||||||
|
# xmin, ymin = min(xmin, ix0), min(ymin, iy0)
|
||||||
|
# xmax, ymax = max(xmax, ix0), max(ymax, iy0)
|
||||||
|
# else:
|
||||||
|
# # a Mapnode
|
||||||
|
# node0 = path_element
|
||||||
|
# ix0, iy0 = node0.x, node0.y
|
||||||
|
# if (ix0, iy0) != (ix, iy):
|
||||||
|
# points.append((ix0, iy0))
|
||||||
|
# xmin, ymin = min(xmin, ix0), min(ymin, iy0)
|
||||||
|
# xmax, ymax = max(xmax, ix0), max(ymax, iy0)
|
||||||
|
#
|
||||||
|
# ixc, iyc = ix - xmin, iy - ymin
|
||||||
|
# # note - override width/height here since our grid is
|
||||||
|
# # now different from the original for future cropping
|
||||||
|
# width, height = xmax - xmin + 1, ymax - ymin + 1
|
||||||
|
# gridmap = [[" "] * width for _ in range(height)]
|
||||||
|
# for (ix0, iy0) in points:
|
||||||
|
# gridmap[iy0 - ymin][ix0 - xmin] = display_map[iy0][ix0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# scan-mode (default) - dist measures individual grid points
|
# scan-mode (default) - dist measures individual grid points
|
||||||
if dist is None:
|
if dist is None:
|
||||||
|
|
|
||||||
|
|
@ -62,19 +62,7 @@ MAP2_DISPLAY = """
|
||||||
#-#-#-#
|
#-#-#-#
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
MAP4 = r"""
|
MAP3 = r"""
|
||||||
|
|
||||||
+ 0 1
|
|
||||||
|
|
||||||
1 #-#
|
|
||||||
|\|
|
|
||||||
0 #-#
|
|
||||||
|
|
||||||
+ 0 1
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
MAP4 = r"""
|
|
||||||
|
|
||||||
+ 0 1 2 3 4 5
|
+ 0 1 2 3 4 5
|
||||||
|
|
||||||
|
|
@ -94,7 +82,7 @@ MAP4 = r"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAP4_DISPLAY = r"""
|
MAP3_DISPLAY = r"""
|
||||||
#-#---# #
|
#-#---# #
|
||||||
| / \ /
|
| / \ /
|
||||||
# / #
|
# / #
|
||||||
|
|
@ -108,7 +96,7 @@ MAP4_DISPLAY = r"""
|
||||||
# #---#-#
|
# #---#-#
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
MAP5 = r"""
|
MAP4 = r"""
|
||||||
|
|
||||||
+ 0 1 2 3 4
|
+ 0 1 2 3 4
|
||||||
|
|
||||||
|
|
@ -126,7 +114,7 @@ MAP5 = r"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAP5_DISPLAY = r"""
|
MAP4_DISPLAY = r"""
|
||||||
#-# #---#
|
#-# #---#
|
||||||
x /
|
x /
|
||||||
#-#-#
|
#-#-#
|
||||||
|
|
@ -138,7 +126,7 @@ MAP5_DISPLAY = r"""
|
||||||
#---#
|
#---#
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
MAP6 = r"""
|
MAP5 = r"""
|
||||||
|
|
||||||
+ 0 1 2
|
+ 0 1 2
|
||||||
|
|
||||||
|
|
@ -152,7 +140,7 @@ MAP6 = r"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAP6_DISPLAY = r"""
|
MAP5_DISPLAY = r"""
|
||||||
#-#
|
#-#
|
||||||
| |
|
| |
|
||||||
#>#
|
#>#
|
||||||
|
|
@ -160,7 +148,7 @@ MAP6_DISPLAY = r"""
|
||||||
#>#
|
#>#
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
MAP7 = r"""
|
MAP6 = r"""
|
||||||
|
|
||||||
+ 0 1 2 3 4
|
+ 0 1 2 3 4
|
||||||
|
|
||||||
|
|
@ -178,7 +166,7 @@ MAP7 = r"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAP7_DISPLAY = r"""
|
MAP6_DISPLAY = r"""
|
||||||
#-#-#-#
|
#-#-#-#
|
||||||
^ |
|
^ |
|
||||||
| #>#
|
| #>#
|
||||||
|
|
@ -191,7 +179,7 @@ MAP7_DISPLAY = r"""
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
|
|
||||||
MAP8 = r"""
|
MAP7 = r"""
|
||||||
+ 0 1 2
|
+ 0 1 2
|
||||||
|
|
||||||
2 #-#
|
2 #-#
|
||||||
|
|
@ -204,7 +192,7 @@ MAP8 = r"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAP8_DISPLAY = r"""
|
MAP7_DISPLAY = r"""
|
||||||
#-#
|
#-#
|
||||||
|
|
|
|
||||||
#-o-#
|
#-o-#
|
||||||
|
|
@ -213,7 +201,7 @@ MAP8_DISPLAY = r"""
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
|
|
||||||
MAP9 = r"""
|
MAP8 = r"""
|
||||||
+ 0 1 2 3 4 5
|
+ 0 1 2 3 4 5
|
||||||
|
|
||||||
4 #-#-o o o-o
|
4 #-#-o o o-o
|
||||||
|
|
@ -230,7 +218,7 @@ MAP9 = r"""
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
MAP9_DISPLAY = r"""
|
MAP8_DISPLAY = r"""
|
||||||
#-#-o o o-o
|
#-#-o o o-o
|
||||||
| \|/| | |
|
| \|/| | |
|
||||||
#-o-o-# o-#
|
#-o-o-# o-#
|
||||||
|
|
@ -315,7 +303,7 @@ class TestMap1(TestCase):
|
||||||
((0, 1), 1, '@-#\n| \n# '),
|
((0, 1), 1, '@-#\n| \n# '),
|
||||||
((1, 0), 1, ' #\n |\n#-@'),
|
((1, 0), 1, ' #\n |\n#-@'),
|
||||||
((1, 1), 1, '#-@\n |\n #'),
|
((1, 1), 1, '#-@\n |\n #'),
|
||||||
((0, 0), 2, ''),
|
((0, 0), 2, '#-#\n| |\n@-#'),
|
||||||
|
|
||||||
])
|
])
|
||||||
def test_get_map_display__nodes__character(self, coord, dist, expected):
|
def test_get_map_display__nodes__character(self, coord, dist, expected):
|
||||||
|
|
@ -387,7 +375,7 @@ class TestMap2(TestCase):
|
||||||
"""
|
"""
|
||||||
node = self.map.get_node_from_coord((4, 1))
|
node = self.map.get_node_from_coord((4, 1))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
node.xy_steps_in_direction,
|
node.xy_steps_to_node,
|
||||||
{'e': ['e'],
|
{'e': ['e'],
|
||||||
's': ['s'],
|
's': ['s'],
|
||||||
'w': ['w', 'w', 'w']}
|
'w': ['w', 'w', 'w']}
|
||||||
|
|
@ -400,7 +388,7 @@ class TestMap2(TestCase):
|
||||||
"""
|
"""
|
||||||
node = self.map.get_node_from_coord((2, 2))
|
node = self.map.get_node_from_coord((2, 2))
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
node.xy_steps_in_direction,
|
node.xy_steps_to_node,
|
||||||
{'n': ['n', 'n', 'n'],
|
{'n': ['n', 'n', 'n'],
|
||||||
'e': ['e'],
|
'e': ['e'],
|
||||||
's': ['s'],
|
's': ['s'],
|
||||||
|
|
@ -434,18 +422,18 @@ class TestMap2(TestCase):
|
||||||
self.assertEqual(expected, mapstr)
|
self.assertEqual(expected, mapstr)
|
||||||
|
|
||||||
|
|
||||||
class TestMap4(TestCase):
|
class TestMap3(TestCase):
|
||||||
"""
|
"""
|
||||||
Test Map4 - Map with diaginal links
|
Test Map3 - Map with diagonal links
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = mapsystem.Map({"map": MAP4})
|
self.map = mapsystem.Map({"map": MAP3})
|
||||||
|
|
||||||
def test_str_output(self):
|
def test_str_output(self):
|
||||||
"""Check the display_map"""
|
"""Check the display_map"""
|
||||||
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
||||||
self.assertEqual(MAP4_DISPLAY, stripped_map)
|
self.assertEqual(MAP3_DISPLAY, stripped_map)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
((0, 0), (1, 0), ()), # no node at (1, 0)!
|
((0, 0), (1, 0), ()), # no node at (1, 0)!
|
||||||
|
|
@ -472,7 +460,7 @@ class TestMap4(TestCase):
|
||||||
((2, 2), 2, None,
|
((2, 2), 2, None,
|
||||||
' # \n / \n # / \n |/ \n # #\n \\ / '
|
' # \n / \n # / \n |/ \n # #\n \\ / '
|
||||||
'\n # @-# \n |/ \\ \n # #\n / \\ \n# # '),
|
'\n # @-# \n |/ \\ \n # #\n / \\ \n# # '),
|
||||||
((5, 2), 2, None, '')
|
((5, 2), 2, None, ' # \n | \n # \n / \\ \n# @\n \\ / \n # \n | \n # ')
|
||||||
])
|
])
|
||||||
def test_get_map_display__nodes__character(self, coord, dist, max_size, expected):
|
def test_get_map_display__nodes__character(self, coord, dist, max_size, expected):
|
||||||
"""
|
"""
|
||||||
|
|
@ -481,21 +469,21 @@ class TestMap4(TestCase):
|
||||||
"""
|
"""
|
||||||
mapstr = self.map.get_map_display(coord, dist=dist, mode='nodes', character='@',
|
mapstr = self.map.get_map_display(coord, dist=dist, mode='nodes', character='@',
|
||||||
max_size=max_size)
|
max_size=max_size)
|
||||||
# print(repr(mapstr))
|
print(f"\n\n{expected}\n\n{mapstr}\n\n{repr(mapstr)}")
|
||||||
self.assertEqual(expected, mapstr)
|
self.assertEqual(expected, mapstr)
|
||||||
|
|
||||||
class TestMap5(TestCase):
|
class TestMap4(TestCase):
|
||||||
"""
|
"""
|
||||||
Test Map5 - Map with + and x crossing links
|
Test Map4 - Map with + and x crossing links
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = mapsystem.Map({"map": MAP5})
|
self.map = mapsystem.Map({"map": MAP4})
|
||||||
|
|
||||||
def test_str_output(self):
|
def test_str_output(self):
|
||||||
"""Check the display_map"""
|
"""Check the display_map"""
|
||||||
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
||||||
self.assertEqual(MAP5_DISPLAY, stripped_map)
|
self.assertEqual(MAP4_DISPLAY, stripped_map)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
((1, 0), (1, 2), ('n',)), # cross + vertically
|
((1, 0), (1, 2), ('n',)), # cross + vertically
|
||||||
|
|
@ -514,18 +502,18 @@ class TestMap5(TestCase):
|
||||||
self.assertEqual(expected_directions, tuple(directions))
|
self.assertEqual(expected_directions, tuple(directions))
|
||||||
|
|
||||||
|
|
||||||
class TestMap6(TestCase):
|
class TestMap5(TestCase):
|
||||||
"""
|
"""
|
||||||
Test Map6 - Small map with one-way links
|
Test Map5 - Small map with one-way links
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = mapsystem.Map({"map": MAP6})
|
self.map = mapsystem.Map({"map": MAP5})
|
||||||
|
|
||||||
def test_str_output(self):
|
def test_str_output(self):
|
||||||
"""Check the display_map"""
|
"""Check the display_map"""
|
||||||
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
||||||
self.assertEqual(MAP6_DISPLAY, stripped_map)
|
self.assertEqual(MAP5_DISPLAY, stripped_map)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
((0, 0), (1, 0), ('e',)), # cross one-way
|
((0, 0), (1, 0), ('e',)), # cross one-way
|
||||||
|
|
@ -542,18 +530,18 @@ class TestMap6(TestCase):
|
||||||
self.assertEqual(expected_directions, tuple(directions))
|
self.assertEqual(expected_directions, tuple(directions))
|
||||||
|
|
||||||
|
|
||||||
class TestMap7(TestCase):
|
class TestMap6(TestCase):
|
||||||
"""
|
"""
|
||||||
Test Map6 - Bigger map with one-way links in different directions
|
Test Map6 - Bigger map with one-way links in different directions
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = mapsystem.Map({"map": MAP7})
|
self.map = mapsystem.Map({"map": MAP6})
|
||||||
|
|
||||||
def test_str_output(self):
|
def test_str_output(self):
|
||||||
"""Check the display_map"""
|
"""Check the display_map"""
|
||||||
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
||||||
self.assertEqual(MAP7_DISPLAY, stripped_map)
|
self.assertEqual(MAP6_DISPLAY, stripped_map)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
((0, 0), (2, 0), ('e', 'e')), # cross one-way
|
((0, 0), (2, 0), ('e', 'e')), # cross one-way
|
||||||
|
|
@ -574,18 +562,18 @@ class TestMap7(TestCase):
|
||||||
self.assertEqual(expected_directions, tuple(directions))
|
self.assertEqual(expected_directions, tuple(directions))
|
||||||
|
|
||||||
|
|
||||||
class TestMap8(TestCase):
|
class TestMap7(TestCase):
|
||||||
"""
|
"""
|
||||||
Test Map6 - Small test of dynamic link node
|
Test Map7 - Small test of dynamic link node
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = mapsystem.Map({"map": MAP8})
|
self.map = mapsystem.Map({"map": MAP7})
|
||||||
|
|
||||||
def test_str_output(self):
|
def test_str_output(self):
|
||||||
"""Check the display_map"""
|
"""Check the display_map"""
|
||||||
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
||||||
self.assertEqual(MAP8_DISPLAY, stripped_map)
|
self.assertEqual(MAP7_DISPLAY, stripped_map)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
((1, 0), (1, 2), ('n', )),
|
((1, 0), (1, 2), ('n', )),
|
||||||
|
|
@ -599,21 +587,21 @@ class TestMap8(TestCase):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
directions, _ = self.map.get_shortest_path(startcoord, endcoord)
|
directions, _ = self.map.get_shortest_path(startcoord, endcoord)
|
||||||
self.assertequal(expected_directions, tuple(directions))
|
self.assertEqual(expected_directions, tuple(directions))
|
||||||
|
|
||||||
|
|
||||||
class TestMap9(TestCase):
|
class TestMap8(TestCase):
|
||||||
"""
|
"""
|
||||||
Test Map6 - Small test of dynamic link node
|
Test Map8 - Small test of dynamic link node
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.map = mapsystem.Map({"map": MAP9})
|
self.map = mapsystem.Map({"map": MAP8})
|
||||||
|
|
||||||
def test_str_output(self):
|
def test_str_output(self):
|
||||||
"""Check the display_map"""
|
"""Check the display_map"""
|
||||||
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
stripped_map = "\n".join(line.rstrip() for line in str(self.map).split('\n'))
|
||||||
self.assertEqual(MAP9_DISPLAY, stripped_map)
|
self.assertEqual(MAP8_DISPLAY, stripped_map)
|
||||||
|
|
||||||
@parameterized.expand([
|
@parameterized.expand([
|
||||||
((2, 0), (2, 2), ('n',)),
|
((2, 0), (2, 2), ('n',)),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue