Add checkpoint list parsing

This commit is contained in:
Emi Simpson 2023-02-12 11:10:07 -05:00
parent e188ff2210
commit c31b532a88
Signed by: Emi
GPG key ID: A12F2C2FFDC3D847
2 changed files with 73 additions and 6 deletions

10
main.py
View file

@ -4,21 +4,21 @@ from sys import argv
from operator import eq from operator import eq
from a_star import pathfind_multi from a_star import pathfind_multi
from read_in import load_world_from_paths from read_in import load_points, load_world_from_paths
from world import Point, World from world import Point, World
from write_out import save_map from write_out import save_map
def main(terrain_path: str, elevation_path: str, path_output: str, image_output: str): def main(terrain_path: str, elevation_path: str, checkpoints_path: str, image_output: str):
world = unwrap_r(load_world_from_paths(terrain_path, elevation_path)) world = unwrap_r(load_world_from_paths(terrain_path, elevation_path))
checkpoints = unwrap_r(load_points(checkpoints_path))
maybe_path = pathfind_multi( maybe_path = pathfind_multi(
world.neighbors, world.neighbors,
world.heuristic, world.heuristic,
[Point(200, 475), Point(200, 100)] checkpoints
) )
print(maybe_path)
path, cost = unwrap_opt(maybe_path) path, cost = unwrap_opt(maybe_path)
print(f'Path found! Estimated time: {cost//60000000} minutes') print(f'Path found! Estimated time: {cost//60000000} minutes')
save_map(path_output, world, path) save_map(image_output, world, path)
if __name__ == '__main__': if __name__ == '__main__':
main(*argv[1:]) main(*argv[1:])

View file

@ -1,6 +1,6 @@
from emis_funky_funktions import * from emis_funky_funktions import *
from world import Terrain, World from world import Point, Terrain, World
from PIL import Image from PIL import Image
@ -220,6 +220,73 @@ def load_world_from_paths(map_path: str, elevation_path: str) -> Result[World, U
load_image(map_path) load_image(map_path)
) )
def parse_point(s: str) -> Result[Point, str]:
"""
Parses a point from a string
The point is expected to be a string containing two integer values seperated by
whitespace.
Any errors in parsing the string will result in an `Err` being returned, containing
the original string.
>>> parse_point('230 327')
Ok((230, 327))
>>> parse_point('230327')
Err('230327')
>>> parse_point('23O 327')
Err('23O 327')
"""
match s.strip().split():
case [p1, p2]:
try:
return Ok(Point(int(p1), int(p2)))
except ValueError:
return Err(s)
case _:
return Err(s)
def parse_points(lines: Iterable[str]) -> Result[Sequence[Point], str]:
"""
Parse a series of points
Each point should be in the format specified by `parse_point()`, and each should be on
it's own "line" (aka, item in an iterable). Blank lines are ignored and dropped. If
any one of the lines in the input string fail to parse, the text of the first failed
line will be returned in an `Err`.
>>> parse_points('''
... 230 327
... 276 279
...
... 303 240
... '''.split('\\n'))
Ok([(230, 327), (276, 279), (303, 240)])
>>> parse_points('''
... 230 327
... 276 2BAD
... 3BAD 240
... '''.split('\\n'))
Err('276 2BAD')
"""
return sequence([
parse_point(line)
for line in lines
if len(line) and not line.isspace()
])
def load_points(path: str) -> Result[Sequence[Point], str]:
"""
Load a file full of points by passing the lines to `parse_points()`
See `parse_points()` for format specifications
"""
with open(path) as f:
return parse_points(f)
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod() doctest.testmod()