mirror of
https://github.com/evennia/evennia.git
synced 2026-03-26 01:36:32 +01:00
Experiment with coloring paths
This commit is contained in:
parent
c8b5db1b25
commit
0406e272d5
2 changed files with 74 additions and 100 deletions
|
|
@ -1001,28 +1001,42 @@ class Map:
|
|||
|
||||
return directions, path
|
||||
|
||||
def get_map_display(self, coord, dist=2, mode='scan',
|
||||
character='@', max_size=None, return_str=True):
|
||||
def get_visual_range(self, coord, dist=2, mode='nodes',
|
||||
character='@',
|
||||
target=None, path_styler="|y{display_symbol}|n",
|
||||
max_size=None,
|
||||
return_str=True):
|
||||
"""
|
||||
Display the map centered on a point and everything around it within a certain distance.
|
||||
Get a part of the grid centered on a specific point and extended a certain number
|
||||
of nodes or grid points in every direction.
|
||||
|
||||
Args:
|
||||
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
|
||||
grid to use depends on the setting of `only_nodes`.
|
||||
grid to use depends on the setting of `only_nodes`. Set to `None` to
|
||||
always show the entire grid.
|
||||
mode (str, optional): One of 'scan' or 'nodes'. In 'scan' mode, dist measure
|
||||
number of xy grid points in all directions and doesn't care about if visible
|
||||
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
|
||||
of the displayed map. The center node' symbol is shown if this is falsy.
|
||||
target (tuple, optional): A target XY coordinate to go to. The path to this
|
||||
(or the beginning of said path, if outside of visual range) will be
|
||||
marked according to `path_style`.
|
||||
path_styler (str or callable, optional): This is use for marking the path
|
||||
found when `path_to_coord` is given. If a string, it accepts a formatting marker
|
||||
`display_symbol` which will be filled with the `display_symbol` of each node/link
|
||||
the path passes through. This allows e.g. to color the path. If a callable, this
|
||||
will receive the MapNode or MapLink object for every step of the path and and
|
||||
must return the suitable string to display at the position of the node/link.
|
||||
max_size (tuple, optional): A max `(width, height)` to crop the displayed
|
||||
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.
|
||||
return_str (bool, optional): Return result as an
|
||||
already formatted string.
|
||||
return_str (bool, optional): Return result as an already formatted string
|
||||
or a 2D list.
|
||||
|
||||
Returns:
|
||||
str or list: Depending on value of `return_str`. If a list,
|
||||
|
|
@ -1064,18 +1078,20 @@ class Map:
|
|||
width, height = self.max_x + 1, self.max_y + 1
|
||||
ix, iy = max(0, min(iX * 2, width)), max(0, min(iY * 2, height))
|
||||
display_map = self.display_map
|
||||
xmin, xmax, ymin, ymax = 0, width - 1, 0, height - 1
|
||||
|
||||
if dist <= 0 or not self.get_node_from_coord(coord):
|
||||
if dist is None:
|
||||
# show the entire grid
|
||||
gridmap = self.display_map
|
||||
ixc, iyc = ix, iy
|
||||
|
||||
elif dist is None or dist <= 0 or not self.get_node_from_coord(coord):
|
||||
# There is no node at these coordinates. Show
|
||||
# nothing but ourselves or emptiness
|
||||
return character if character else self.empty_symbol
|
||||
|
||||
if mode == 'nodes':
|
||||
elif mode == 'nodes':
|
||||
# dist measures only full, reachable nodes.
|
||||
# this requires a series of shortest-path
|
||||
# Steps from on the pre-calulcated grid.
|
||||
# from evennia import set_trace;set_trace()
|
||||
|
||||
points, xmin, xmax, ymin, ymax = self._get_topology_around_coord(coord, dist=dist)
|
||||
|
||||
ixc, iyc = ix - xmin, iy - ymin
|
||||
|
|
@ -1086,83 +1102,41 @@ class Map:
|
|||
for (ix0, iy0) in points:
|
||||
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]
|
||||
elif mode == 'scans':
|
||||
# scan-mode - dist measures individual grid points
|
||||
|
||||
xmin, xmax = max(0, ix - dist), min(width, ix + dist + 1)
|
||||
ymin, ymax = max(0, iy - dist), min(height, iy + dist + 1)
|
||||
ixc, iyc = ix - xmin, iy - ymin
|
||||
gridmap = [line[xmin:xmax] for line in display_map[ymin:ymax]]
|
||||
|
||||
else:
|
||||
# scan-mode (default) - dist measures individual grid points
|
||||
if dist is None:
|
||||
gridmap = self.display_map
|
||||
ixc, iyc = ix, iy
|
||||
else:
|
||||
left, right = max(0, ix - dist), min(width, ix + dist + 1)
|
||||
bottom, top = max(0, iy - dist), min(height, iy + dist + 1)
|
||||
ixc, iyc = ix - left, iy - bottom
|
||||
gridmap = [line[left:right] for line in display_map[bottom:top]]
|
||||
|
||||
raise MapError(f"Map.get_visual_range 'mode' was '{mode}' "
|
||||
"- it must be either 'scan' or 'nodes'.")
|
||||
if character:
|
||||
gridmap[iyc][ixc] = character # correct indexing; it's a list of lines
|
||||
|
||||
if max_size:
|
||||
# crop grid to make sure it doesn't grow too far
|
||||
max_x, max_y = max_size
|
||||
left, right = max(0, ixc - max_x // 2), min(width, ixc + max_x // 2 + 1)
|
||||
bottom, top = max(0, iyc - max_y // 2), min(height, iyc + max_y // 2 + 1)
|
||||
gridmap = [line[left:right] for line in gridmap[bottom:top]]
|
||||
xmin, xmax = max(0, ixc - max_x // 2), min(width, ixc + max_x // 2 + 1)
|
||||
ymin, ymax = max(0, iyc - max_y // 2), min(height, iyc + max_y // 2 + 1)
|
||||
gridmap = [line[xmin:xmax] for line in gridmap[ymin:ymax]]
|
||||
|
||||
if target:
|
||||
# stylize path to target
|
||||
|
||||
def _path_styler(node):
|
||||
return path_styler
|
||||
|
||||
if not callable(path_styler):
|
||||
path_styler = _path_styler
|
||||
|
||||
path, _ = self.get_shortest_path(coord, target)
|
||||
for node_or_link in path[1:]:
|
||||
ix, iy = node_or_link.x, node_or_link.y
|
||||
if xmin <= ix <= xmax and ymin <= iy <= ymax:
|
||||
gridmap[iy - ymin][ix - xmin] = path_styler(node_or_link)
|
||||
|
||||
if return_str:
|
||||
# we must flip the y-axis before returning the string
|
||||
|
|
|
|||
|
|
@ -270,13 +270,13 @@ class TestMap1(TestCase):
|
|||
((1, 1), "-#\n |", [["-", "#"], [" ", "|"]]),
|
||||
|
||||
])
|
||||
def test_get_map_display(self, coord, expectstr, expectlst):
|
||||
def test_get_visual_range(self, coord, expectstr, expectlst):
|
||||
"""
|
||||
Test displaying a part of the map around a central point.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=1, character=None)
|
||||
maplst = self.map.get_map_display(coord, dist=1, return_str=False, character=None)
|
||||
mapstr = self.map.get_visual_range(coord, dist=1, character=None)
|
||||
maplst = self.map.get_visual_range(coord, dist=1, return_str=False, character=None)
|
||||
self.assertEqual(expectstr, mapstr)
|
||||
self.assertEqual(expectlst, maplst[::-1])
|
||||
|
||||
|
|
@ -287,14 +287,14 @@ class TestMap1(TestCase):
|
|||
((1, 1), "-@\n |", [["-", "@"], [" ", "|"]]),
|
||||
|
||||
])
|
||||
def test_get_map_display__character(self, coord, expectstr, expectlst):
|
||||
def test_get_visual_range__character(self, coord, expectstr, expectlst):
|
||||
"""
|
||||
Test displaying a part of the map around a central point, showing the
|
||||
character @-symbol in that spot.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=1, character='@')
|
||||
maplst = self.map.get_map_display(coord, dist=1, return_str=False, character='@')
|
||||
mapstr = self.map.get_visual_range(coord, dist=1, character='@')
|
||||
maplst = self.map.get_visual_range(coord, dist=1, return_str=False, character='@')
|
||||
self.assertEqual(expectstr, mapstr)
|
||||
self.assertEqual(expectlst, maplst[::-1]) # flip y-axis to match print direction
|
||||
|
||||
|
|
@ -306,12 +306,12 @@ class TestMap1(TestCase):
|
|||
((0, 0), 2, '#-#\n| |\n@-#'),
|
||||
|
||||
])
|
||||
def test_get_map_display__nodes__character(self, coord, dist, expected):
|
||||
def test_get_visual_range__nodes__character(self, coord, dist, expected):
|
||||
"""
|
||||
Get sub-part of map with node-mode.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=dist, mode='nodes', character='@')
|
||||
mapstr = self.map.get_visual_range(coord, dist=dist, mode='nodes', character='@')
|
||||
self.assertEqual(expected, mapstr)
|
||||
|
||||
class TestMap2(TestCase):
|
||||
|
|
@ -360,12 +360,12 @@ class TestMap2(TestCase):
|
|||
((4, 5), '#-#-@ \n| | \n#---# \n| | \n| #-#'),
|
||||
((5, 2), '--# \n | \n #-#\n |\n#---@\n \n--#-#\n | \n#-# '),
|
||||
])
|
||||
def test_get_map_display__scan__character(self, coord, expected):
|
||||
def test_get_visual_range__scan__character(self, coord, expected):
|
||||
"""
|
||||
Test showing smaller part of grid, showing @-character in the middle.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=4, character='@')
|
||||
mapstr = self.map.get_visual_range(coord, dist=4, character='@')
|
||||
self.assertEqual(expected, mapstr)
|
||||
|
||||
def test_extended_path_tracking__horizontal(self):
|
||||
|
|
@ -412,13 +412,13 @@ class TestMap2(TestCase):
|
|||
((2, 2), 4, (3, 3), ' | \n-@-\n | '),
|
||||
((2, 2), 4, (1, 1), '@')
|
||||
])
|
||||
def test_get_map_display__nodes__character(self, coord, dist, max_size, expected):
|
||||
def test_get_visual_range__nodes__character(self, coord, dist, max_size, expected):
|
||||
"""
|
||||
Get sub-part of map with node-mode.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=dist, mode='nodes', character='@',
|
||||
max_size=max_size)
|
||||
mapstr = self.map.get_visual_range(coord, dist=dist, mode='nodes', character='@',
|
||||
max_size=max_size)
|
||||
self.assertEqual(expected, mapstr)
|
||||
|
||||
|
||||
|
|
@ -462,13 +462,13 @@ class TestMap3(TestCase):
|
|||
'\n # @-# \n |/ \\ \n # #\n / \\ \n# # '),
|
||||
((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_visual_range__nodes__character(self, coord, dist, max_size, expected):
|
||||
"""
|
||||
Get sub-part of map with node-mode.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=dist, mode='nodes', character='@',
|
||||
max_size=max_size)
|
||||
mapstr = self.map.get_visual_range(coord, dist=dist, mode='nodes', character='@',
|
||||
max_size=max_size)
|
||||
print(f"\n\n{expected}\n\n{mapstr}\n\n{repr(mapstr)}")
|
||||
self.assertEqual(expected, mapstr)
|
||||
|
||||
|
|
@ -624,12 +624,12 @@ class TestMap8(TestCase):
|
|||
((2, 2), 1, None, ' #-o \n | \n# o \n| | \no-o-@-#\n '
|
||||
'| \n o \n | \n # '),
|
||||
])
|
||||
def test_get_map_display__nodes__character(self, coord, dist, max_size, expected):
|
||||
def test_get_visual_range__nodes__character(self, coord, dist, max_size, expected):
|
||||
"""
|
||||
Get sub-part of map with node-mode.
|
||||
|
||||
"""
|
||||
mapstr = self.map.get_map_display(coord, dist=dist, mode='nodes', character='@',
|
||||
max_size=max_size)
|
||||
mapstr = self.map.get_visual_range(coord, dist=dist, mode='nodes', character='@',
|
||||
max_size=max_size)
|
||||
print(repr(mapstr))
|
||||
self.assertEqual(expected, mapstr)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue