diff --git a/world.py b/world.py index a0c7970..9d6b0b3 100644 --- a/world.py +++ b/world.py @@ -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: