Optimize search even further
This commit is contained in:
parent
5fac1d9c25
commit
4680fb6090
62
world.py
62
world.py
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue