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
"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,
tiles: Sequence[Tuple[Terrain, int]],
width: int = 395,
@ -93,7 +100,11 @@ class World:
self.width = width
self.lon_scale = lon_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]]:
"""
@ -101,31 +112,31 @@ class World:
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
point, in millimeters.
point, in millimeters **AND SQUARED**.
This does not take into account the presence, value, or elevation of tiles
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
[((12, 11), 12762),
((13, 11), 7550),
((14, 11), 12762),
((12, 12), 10290),
((14, 12), 10290),
((12, 13), 12762),
((13, 13), 7550),
((14, 13), 12762)]
[((12, 11), 25),
((13, 11), 16),
((14, 11), 25),
((12, 12), 9),
((14, 12), 9),
((12, 13), 25),
((13, 13), 16),
((14, 13), 25)]
"""
return [
(Point(p.x - 1, p.y - 1), self._diag ),
(Point(p.x , p.y - 1), self.lat_scale),
(Point(p.x + 1, p.y - 1), self._diag ),
(Point(p.x - 1, p.y ), self.lon_scale),
(Point(p.x + 1, p.y ), self.lon_scale),
(Point(p.x - 1, p.y + 1), self._diag ),
(Point(p.x , p.y + 1), self.lat_scale),
(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_scale2),
(Point(p.x + 1, p.y - 1), self._diag2 ),
(Point(p.x - 1, p.y ), self._lon_scale2),
(Point(p.x + 1, p.y ), self._lon_scale2),
(Point(p.x - 1, p.y + 1), self._diag2 ),
(Point(p.x , p.y + 1), self._lat_scale2),
(Point(p.x + 1, p.y + 1), self._diag2 )
]
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!
"""
loc_terrain, loc_elevation = self[loc]
return [
(
adj_point,
(
# 2 * Movement speed (seconds / km = microseconds / millimeter)
(
self[loc][0] +
self[adj_point][0]
loc_terrain +
adj_terrain
)
# * Distance travelled (millimeters) = 2 * Time cost (microseconds)
* isqrt(
# Crow Distance Squared
(crow_distance * crow_distance)
crow_distance2
# + Elevation Change Squared = 3D distance squared
+ self.elevation_difference(loc, adj_point) ** 2
+ (loc_elevation - adj_elevation) ** 2
)
# / 2 = Time cost (microseconds)
// 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
and adj_point.y >= 0
and adj_point.x < self.width
and adj_point.y < len(self.tiles) // self.width
and adj_terrain < 4294967296
]
def heuristic(self, a: Point, b: Point) -> int: