From c31b532a886b5b57649f4e82dac651661e77655a Mon Sep 17 00:00:00 2001 From: Emi Simpson Date: Sun, 12 Feb 2023 11:10:07 -0500 Subject: [PATCH] Add checkpoint list parsing --- main.py | 10 ++++---- read_in.py | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/main.py b/main.py index f05b14d..9c199bd 100644 --- a/main.py +++ b/main.py @@ -4,21 +4,21 @@ from sys import argv from operator import eq 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 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)) + checkpoints = unwrap_r(load_points(checkpoints_path)) maybe_path = pathfind_multi( world.neighbors, world.heuristic, - [Point(200, 475), Point(200, 100)] + checkpoints ) - print(maybe_path) path, cost = unwrap_opt(maybe_path) print(f'Path found! Estimated time: {cost//60000000} minutes') - save_map(path_output, world, path) + save_map(image_output, world, path) if __name__ == '__main__': main(*argv[1:]) \ No newline at end of file diff --git a/read_in.py b/read_in.py index afffe5f..f7c79a7 100644 --- a/read_in.py +++ b/read_in.py @@ -1,6 +1,6 @@ from emis_funky_funktions import * -from world import Terrain, World +from world import Point, Terrain, World 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) ) +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__': import doctest doctest.testmod() \ No newline at end of file