Optimize search even further

This commit is contained in:
Emi Simpson 2023-02-12 17:55:06 -05:00
parent 5fac1d9c25
commit 4680fb6090
Signed by: Emi
GPG Key ID: A12F2C2FFDC3D847
1 changed files with 38 additions and 24 deletions

View File

@ -83,6 +83,13 @@ class World:
_diag: int _diag: int
"Real world distance represented by a diagonal movement, in millimeters" "Real world distance represented by a diagonal movement, in millimeters"
_lon_scale2: int
"Longitudinal scale squared"
_lat_scale2: int
"Latitudinal scale squared"
_diag2: int
"Diagonal scale squared"
def __init__(self, def __init__(self,
tiles: Sequence[Tuple[Terrain, int]], tiles: Sequence[Tuple[Terrain, int]],
width: int = 395, width: int = 395,
@ -93,7 +100,11 @@ class World:
self.width = width self.width = width
self.lon_scale = lon_scale self.lon_scale = lon_scale
self.lat_scale = lat_scale self.lat_scale = lat_scale
self._diag = isqrt(lon_scale * lon_scale + lat_scale * lat_scale)
self._lon_scale2 = lon_scale * lon_scale
self._lat_scale2 = lat_scale * lat_scale
self._diag2 = self._lon_scale2 + self._lat_scale2
self._diag = isqrt(self._diag2)
def _adjacency(self, p: Point) -> List[Tuple[Point, int]]: def _adjacency(self, p: Point) -> List[Tuple[Point, int]]:
""" """
@ -101,31 +112,31 @@ class World:
In addition to each point, a number is returned representing the distance as the In addition to each point, a number is returned representing the distance as the
crow flies between the center of the original point and the center of the adjacent crow flies between the center of the original point and the center of the adjacent
point, in millimeters. point, in millimeters **AND SQUARED**.
This does not take into account the presence, value, or elevation of tiles This does not take into account the presence, value, or elevation of tiles
represented on these points. represented on these points.
>>> world = World([], lon_scale=10_290, lat_scale=7_550) >>> world = World([], lon_scale=3, lat_scale=4)
>>> world._adjacency(Point(13, 12)) #doctest: +NORMALIZE_WHITESPACE >>> world._adjacency(Point(13, 12)) #doctest: +NORMALIZE_WHITESPACE
[((12, 11), 12762), [((12, 11), 25),
((13, 11), 7550), ((13, 11), 16),
((14, 11), 12762), ((14, 11), 25),
((12, 12), 10290), ((12, 12), 9),
((14, 12), 10290), ((14, 12), 9),
((12, 13), 12762), ((12, 13), 25),
((13, 13), 7550), ((13, 13), 16),
((14, 13), 12762)] ((14, 13), 25)]
""" """
return [ return [
(Point(p.x - 1, p.y - 1), self._diag ), (Point(p.x - 1, p.y - 1), self._diag2 ),
(Point(p.x , p.y - 1), self.lat_scale), (Point(p.x , p.y - 1), self._lat_scale2),
(Point(p.x + 1, p.y - 1), self._diag ), (Point(p.x + 1, p.y - 1), self._diag2 ),
(Point(p.x - 1, p.y ), self.lon_scale), (Point(p.x - 1, p.y ), self._lon_scale2),
(Point(p.x + 1, p.y ), self.lon_scale), (Point(p.x + 1, p.y ), self._lon_scale2),
(Point(p.x - 1, p.y + 1), self._diag ), (Point(p.x - 1, p.y + 1), self._diag2 ),
(Point(p.x , p.y + 1), self.lat_scale), (Point(p.x , p.y + 1), self._lat_scale2),
(Point(p.x + 1, p.y + 1), self._diag ) (Point(p.x + 1, p.y + 1), self._diag2 )
] ]
def __getitem__(self, loc: Point) -> Tuple[Terrain, int]: def __getitem__(self, loc: Point) -> Tuple[Terrain, int]:
@ -228,33 +239,36 @@ class World:
And there it is! The travel time returned by the `.neighbors` function! And there it is! The travel time returned by the `.neighbors` function!
""" """
loc_terrain, loc_elevation = self[loc]
return [ return [
( (
adj_point, adj_point,
( (
# 2 * Movement speed (seconds / km = microseconds / millimeter) # 2 * Movement speed (seconds / km = microseconds / millimeter)
( (
self[loc][0] + loc_terrain +
self[adj_point][0] adj_terrain
) )
# * Distance travelled (millimeters) = 2 * Time cost (microseconds) # * Distance travelled (millimeters) = 2 * Time cost (microseconds)
* isqrt( * isqrt(
# Crow Distance Squared # Crow Distance Squared
(crow_distance * crow_distance) crow_distance2
# + Elevation Change Squared = 3D distance squared # + Elevation Change Squared = 3D distance squared
+ self.elevation_difference(loc, adj_point) ** 2 + (loc_elevation - adj_elevation) ** 2
) )
# / 2 = Time cost (microseconds) # / 2 = Time cost (microseconds)
// 2 // 2
) )
) )
for (adj_point, crow_distance) in self._adjacency(loc) for (adj_point, crow_distance2) in self._adjacency(loc)
for (adj_terrain, adj_elevation) in (self[adj_point],)
if adj_point.x >= 0 if adj_point.x >= 0
and adj_point.y >= 0 and adj_point.y >= 0
and adj_point.x < self.width and adj_point.x < self.width
and adj_point.y < len(self.tiles) // self.width and adj_point.y < len(self.tiles) // self.width
and adj_terrain < 4294967296
] ]
def heuristic(self, a: Point, b: Point) -> int: def heuristic(self, a: Point, b: Point) -> int: