Commit 64c02dc1 authored by u214892's avatar u214892
Browse files

Trainrun and Waypoint instead of WayPoint and TrainRun for readability

parent ca8dcd65
Pipeline #2837 passed with stages
in 48 minutes and 49 seconds
......@@ -6,7 +6,7 @@ import numpy as np
from flatland.core.grid.grid_utils import Vec2dOperations as Vec2d
from flatland.envs.rail_env import RailEnv, RailEnvActions
from flatland.envs.rail_env_shortest_paths import get_action_for_move
from flatland.envs.rail_train_run_data_structures import Wayoint, Trainrun, TrainrunWaypoint
from flatland.envs.rail_train_run_data_structures import Waypoint, Trainrun, TrainrunWaypoint
from flatland.utils.rendertools import RenderTool, AgentRenderVariant
# ---- ActionPlan ---------------
......@@ -35,7 +35,7 @@ class ControllerFromTrainruns():
self.action_plan: ActionPlanDict = [self._create_action_plan_for_agent(agent_id, chosen_path)
for agent_id, chosen_path in train_run_dict.items()]
def get_way_point_before_or_at_step(self, agent_id: int, step: int) -> Wayoint:
def get_way_point_before_or_at_step(self, agent_id: int, step: int) -> Waypoint:
"""
Get the way point point from which the current position can be extracted.
......@@ -53,13 +53,13 @@ class ControllerFromTrainruns():
entry_time_step = train_run[0].scheduled_at
# the agent has no position before and at choosing to enter the grid (one tick elapses before the agent enters the grid)
if step <= entry_time_step:
return Wayoint(position=None, direction=self.env.agents[agent_id].initial_direction)
return Waypoint(position=None, direction=self.env.agents[agent_id].initial_direction)
# the agent has no position as soon as the target is reached
exit_time_step = train_run[-1].scheduled_at
if step >= exit_time_step:
# agent loses position as soon as target cell is reached
return Wayoint(position=None, direction=train_run[-1].way_point.direction)
return Waypoint(position=None, direction=train_run[-1].way_point.direction)
way_point = None
for train_run_way_point in train_run:
......@@ -277,7 +277,7 @@ class ControllerFromTrainrunsReplayer():
i = 0
while not env.dones['__all__'] and i <= max_episode_steps:
for agent_id, agent in enumerate(env.agents):
way_point: Wayoint = ctl.get_way_point_before_or_at_step(agent_id, i)
way_point: Waypoint = ctl.get_way_point_before_or_at_step(agent_id, i)
assert agent.position == way_point.position, \
"before {}, agent {} at {}, expected {}".format(i, agent_id, agent.position,
way_point.position)
......
......@@ -10,7 +10,7 @@ from flatland.core.transition_map import GridTransitionMap
from flatland.envs.agent_utils import RailAgentStatus
from flatland.envs.distance_map import DistanceMap
from flatland.envs.rail_env import RailEnvNextAction, RailEnvActions, RailEnv
from flatland.envs.rail_train_run_data_structures import Wayoint
from flatland.envs.rail_train_run_data_structures import Waypoint
from flatland.utils.ordered_set import OrderedSet
......@@ -201,7 +201,7 @@ def get_action_for_move(
# N.B. get_shortest_paths is not part of distance_map since it refers to RailEnvActions (would lead to circularity!)
def get_shortest_paths(distance_map: DistanceMap, max_depth: Optional[int] = None, agent_handle: Optional[int] = None) \
-> Dict[int, Optional[List[Wayoint]]]:
-> Dict[int, Optional[List[Waypoint]]]:
"""
Computes the shortest path for each agent to its target and the action to be taken to do so.
The paths are derived from a `DistanceMap`.
......@@ -251,7 +251,7 @@ def get_shortest_paths(distance_map: DistanceMap, max_depth: Optional[int] = Non
best_next_action = next_action
distance = next_action_distance
shortest_paths[agent.handle].append(Wayoint(position, direction))
shortest_paths[agent.handle].append(Waypoint(position, direction))
depth += 1
# if there is no way to continue, the rail must be disconnected!
......@@ -263,7 +263,7 @@ def get_shortest_paths(distance_map: DistanceMap, max_depth: Optional[int] = Non
position = best_next_action.next_position
direction = best_next_action.next_direction
if max_depth is None or depth < max_depth:
shortest_paths[agent.handle].append(Wayoint(position, direction))
shortest_paths[agent.handle].append(Waypoint(position, direction))
if agent_handle is not None:
_shortest_path_for_agent(distance_map.agents[agent_handle])
......@@ -278,7 +278,7 @@ def get_k_shortest_paths(env: RailEnv,
source_position: Tuple[int, int],
source_direction: int,
target_position=Tuple[int, int],
k: int = 1, debug=False) -> List[Tuple[Wayoint]]:
k: int = 1, debug=False) -> List[Tuple[Waypoint]]:
"""
Computes the k shortest paths using modified Dijkstra
following pseudo-code https://en.wikipedia.org/wiki/K_shortest_path_routing
......@@ -304,7 +304,7 @@ def get_k_shortest_paths(env: RailEnv,
# P: set of shortest paths from s to t
# P =empty,
shortest_paths: List[Tuple[Wayoint]] = []
shortest_paths: List[Tuple[Waypoint]] = []
# countu: number of shortest paths found to node u
# countu = 0, for all u in V
......@@ -312,10 +312,10 @@ def get_k_shortest_paths(env: RailEnv,
# B is a heap data structure containing paths
# N.B. use OrderedSet to make result deterministic!
heap: OrderedSet[Tuple[Wayoint]] = OrderedSet()
heap: OrderedSet[Tuple[Waypoint]] = OrderedSet()
# insert path Ps = {s} into B with cost 0
heap.add((Wayoint(source_position, source_direction),))
heap.add((Waypoint(source_position, source_direction),))
# while B is not empty and countt < K:
while len(heap) > 0 and len(shortest_paths) < k:
......@@ -328,7 +328,7 @@ def get_k_shortest_paths(env: RailEnv,
if len(path) < cost:
pu = path
cost = len(path)
u: Wayoint = pu[-1]
u: Waypoint = pu[-1]
if debug:
print(" looking at pu={}".format(pu))
......@@ -360,7 +360,7 @@ def get_k_shortest_paths(env: RailEnv,
if debug:
print(" looking at neighbor v={}".format((*new_position, new_direction)))
v = Wayoint(position=new_position, direction=new_direction)
v = Waypoint(position=new_position, direction=new_direction)
# CAVEAT: do not allow for loopy paths
if v in pu:
continue
......
......@@ -6,13 +6,13 @@ from typing import NamedTuple, Tuple, List
# This induces a graph on top of the FLATland cells:
# - four possible way points per cell
# - edges are the possible transitions in the cell.
Wayoint = NamedTuple('Wayoint', [('position', Tuple[int, int]), ('direction', int)])
Waypoint = NamedTuple('Waypoint', [('position', Tuple[int, int]), ('direction', int)])
# A train run is represented by the waypoints traversed and the times of traversal
# The terminology follows https://github.com/crowdAI/train-schedule-optimisation-challenge-starter-kit/blob/master/documentation/output_data_model.md
TrainrunWaypoint = NamedTuple('TrainrunWaypoint', [
('scheduled_at', int),
('way_point', Wayoint)
('way_point', Waypoint)
])
# A train run is the list of an agent's way points and their scheduled time
Trainrun = List[TrainrunWaypoint]
......@@ -4,7 +4,7 @@ from flatland.core.grid.grid4 import Grid4TransitionsEnum
from flatland.envs.observations import GlobalObsForRailEnv
from flatland.envs.rail_env import RailEnv, RailEnvActions
from flatland.envs.rail_generators import rail_from_grid_transition_map
from flatland.envs.rail_train_run_data_structures import Wayoint
from flatland.envs.rail_train_run_data_structures import Waypoint
from flatland.envs.schedule_generators import random_schedule_generator
from flatland.utils.simple_rail import make_simple_rail
......@@ -32,25 +32,25 @@ def test_action_plan(rendering: bool = False):
for handle, agent in enumerate(env.agents):
print("[{}] {} -> {}".format(handle, agent.initial_position, agent.target))
chosen_path_dict = {0: [TrainrunWaypoint(scheduled_at=0, way_point=Wayoint(position=(3, 0), direction=3)),
TrainrunWaypoint(scheduled_at=2, way_point=Wayoint(position=(3, 1), direction=1)),
TrainrunWaypoint(scheduled_at=3, way_point=Wayoint(position=(3, 2), direction=1)),
TrainrunWaypoint(scheduled_at=14, way_point=Wayoint(position=(3, 3), direction=1)),
TrainrunWaypoint(scheduled_at=15, way_point=Wayoint(position=(3, 4), direction=1)),
TrainrunWaypoint(scheduled_at=16, way_point=Wayoint(position=(3, 5), direction=1)),
TrainrunWaypoint(scheduled_at=17, way_point=Wayoint(position=(3, 6), direction=1)),
TrainrunWaypoint(scheduled_at=18, way_point=Wayoint(position=(3, 7), direction=1)),
TrainrunWaypoint(scheduled_at=19, way_point=Wayoint(position=(3, 8), direction=1)),
TrainrunWaypoint(scheduled_at=20, way_point=Wayoint(position=(3, 8), direction=5))],
1: [TrainrunWaypoint(scheduled_at=0, way_point=Wayoint(position=(3, 8), direction=3)),
TrainrunWaypoint(scheduled_at=3, way_point=Wayoint(position=(3, 7), direction=3)),
TrainrunWaypoint(scheduled_at=5, way_point=Wayoint(position=(3, 6), direction=3)),
TrainrunWaypoint(scheduled_at=7, way_point=Wayoint(position=(3, 5), direction=3)),
TrainrunWaypoint(scheduled_at=9, way_point=Wayoint(position=(3, 4), direction=3)),
TrainrunWaypoint(scheduled_at=11, way_point=Wayoint(position=(3, 3), direction=3)),
TrainrunWaypoint(scheduled_at=13, way_point=Wayoint(position=(2, 3), direction=0)),
TrainrunWaypoint(scheduled_at=15, way_point=Wayoint(position=(1, 3), direction=0)),
TrainrunWaypoint(scheduled_at=17, way_point=Wayoint(position=(0, 3), direction=0))]}
chosen_path_dict = {0: [TrainrunWaypoint(scheduled_at=0, way_point=Waypoint(position=(3, 0), direction=3)),
TrainrunWaypoint(scheduled_at=2, way_point=Waypoint(position=(3, 1), direction=1)),
TrainrunWaypoint(scheduled_at=3, way_point=Waypoint(position=(3, 2), direction=1)),
TrainrunWaypoint(scheduled_at=14, way_point=Waypoint(position=(3, 3), direction=1)),
TrainrunWaypoint(scheduled_at=15, way_point=Waypoint(position=(3, 4), direction=1)),
TrainrunWaypoint(scheduled_at=16, way_point=Waypoint(position=(3, 5), direction=1)),
TrainrunWaypoint(scheduled_at=17, way_point=Waypoint(position=(3, 6), direction=1)),
TrainrunWaypoint(scheduled_at=18, way_point=Waypoint(position=(3, 7), direction=1)),
TrainrunWaypoint(scheduled_at=19, way_point=Waypoint(position=(3, 8), direction=1)),
TrainrunWaypoint(scheduled_at=20, way_point=Waypoint(position=(3, 8), direction=5))],
1: [TrainrunWaypoint(scheduled_at=0, way_point=Waypoint(position=(3, 8), direction=3)),
TrainrunWaypoint(scheduled_at=3, way_point=Waypoint(position=(3, 7), direction=3)),
TrainrunWaypoint(scheduled_at=5, way_point=Waypoint(position=(3, 6), direction=3)),
TrainrunWaypoint(scheduled_at=7, way_point=Waypoint(position=(3, 5), direction=3)),
TrainrunWaypoint(scheduled_at=9, way_point=Waypoint(position=(3, 4), direction=3)),
TrainrunWaypoint(scheduled_at=11, way_point=Waypoint(position=(3, 3), direction=3)),
TrainrunWaypoint(scheduled_at=13, way_point=Waypoint(position=(2, 3), direction=0)),
TrainrunWaypoint(scheduled_at=15, way_point=Waypoint(position=(1, 3), direction=0)),
TrainrunWaypoint(scheduled_at=17, way_point=Waypoint(position=(0, 3), direction=0))]}
expected_action_plan = [[
# take action to enter the grid
ActionPlanElement(0, RailEnvActions.MOVE_FORWARD),
......
......@@ -11,7 +11,7 @@ from flatland.envs.predictions import DummyPredictorForRailEnv, ShortestPathPred
from flatland.envs.rail_env import RailEnv, RailEnvActions
from flatland.envs.rail_env_shortest_paths import get_shortest_paths
from flatland.envs.rail_generators import rail_from_grid_transition_map
from flatland.envs.rail_train_run_data_structures import Wayoint
from flatland.envs.rail_train_run_data_structures import Waypoint
from flatland.envs.schedule_generators import random_schedule_generator
from flatland.utils.rendertools import RenderTool
from flatland.utils.simple_rail import make_simple_rail, make_simple_rail2, make_invalid_simple_rail
......@@ -147,12 +147,12 @@ def test_shortest_path_predictor(rendering=False):
paths = get_shortest_paths(env.distance_map)[0]
assert paths == [
Wayoint((5, 6), 0),
Wayoint((4, 6), 0),
Wayoint((3, 6), 0),
Wayoint((3, 7), 1),
Wayoint((3, 8), 1),
Wayoint((3, 9), 1)
Waypoint((5, 6), 0),
Waypoint((4, 6), 0),
Waypoint((3, 6), 0),
Waypoint((3, 7), 1),
Waypoint((3, 8), 1),
Waypoint((3, 9), 1)
]
# extract the data
......
......@@ -8,7 +8,7 @@ from flatland.envs.rail_env import RailEnv
from flatland.envs.rail_env_shortest_paths import get_shortest_paths, get_k_shortest_paths
from flatland.envs.rail_env_utils import load_flatland_environment_from_file
from flatland.envs.rail_generators import rail_from_grid_transition_map
from flatland.envs.rail_train_run_data_structures import Wayoint
from flatland.envs.rail_train_run_data_structures import Waypoint
from flatland.envs.schedule_generators import random_schedule_generator
from flatland.utils.rendertools import RenderTool
from flatland.utils.simple_rail import make_disconnected_simple_rail, make_simple_rail_with_alternatives
......@@ -47,45 +47,45 @@ def test_get_shortest_paths():
expected = {
0: [
Wayoint(position=(1, 1), direction=1),
Wayoint(position=(1, 2), direction=1),
Wayoint(position=(1, 3), direction=1),
Wayoint(position=(2, 3), direction=2),
Wayoint(position=(2, 4), direction=1),
Wayoint(position=(2, 5), direction=1),
Wayoint(position=(2, 6), direction=1),
Wayoint(position=(2, 7), direction=1),
Wayoint(position=(2, 8), direction=1),
Wayoint(position=(2, 9), direction=1),
Wayoint(position=(2, 10), direction=1),
Wayoint(position=(2, 11), direction=1),
Wayoint(position=(2, 12), direction=1),
Wayoint(position=(2, 13), direction=1),
Wayoint(position=(2, 14), direction=1),
Wayoint(position=(2, 15), direction=1),
Wayoint(position=(2, 16), direction=1),
Wayoint(position=(2, 17), direction=1),
Wayoint(position=(2, 18), direction=1)],
Waypoint(position=(1, 1), direction=1),
Waypoint(position=(1, 2), direction=1),
Waypoint(position=(1, 3), direction=1),
Waypoint(position=(2, 3), direction=2),
Waypoint(position=(2, 4), direction=1),
Waypoint(position=(2, 5), direction=1),
Waypoint(position=(2, 6), direction=1),
Waypoint(position=(2, 7), direction=1),
Waypoint(position=(2, 8), direction=1),
Waypoint(position=(2, 9), direction=1),
Waypoint(position=(2, 10), direction=1),
Waypoint(position=(2, 11), direction=1),
Waypoint(position=(2, 12), direction=1),
Waypoint(position=(2, 13), direction=1),
Waypoint(position=(2, 14), direction=1),
Waypoint(position=(2, 15), direction=1),
Waypoint(position=(2, 16), direction=1),
Waypoint(position=(2, 17), direction=1),
Waypoint(position=(2, 18), direction=1)],
1: [
Wayoint(position=(3, 18), direction=3),
Wayoint(position=(3, 17), direction=3),
Wayoint(position=(3, 16), direction=3),
Wayoint(position=(2, 16), direction=0),
Wayoint(position=(2, 15), direction=3),
Wayoint(position=(2, 14), direction=3),
Wayoint(position=(2, 13), direction=3),
Wayoint(position=(2, 12), direction=3),
Wayoint(position=(2, 11), direction=3),
Wayoint(position=(2, 10), direction=3),
Wayoint(position=(2, 9), direction=3),
Wayoint(position=(2, 8), direction=3),
Wayoint(position=(2, 7), direction=3),
Wayoint(position=(2, 6), direction=3),
Wayoint(position=(2, 5), direction=3),
Wayoint(position=(2, 4), direction=3),
Wayoint(position=(2, 3), direction=3),
Wayoint(position=(2, 2), direction=3),
Wayoint(position=(2, 1), direction=3)]
Waypoint(position=(3, 18), direction=3),
Waypoint(position=(3, 17), direction=3),
Waypoint(position=(3, 16), direction=3),
Waypoint(position=(2, 16), direction=0),
Waypoint(position=(2, 15), direction=3),
Waypoint(position=(2, 14), direction=3),
Waypoint(position=(2, 13), direction=3),
Waypoint(position=(2, 12), direction=3),
Waypoint(position=(2, 11), direction=3),
Waypoint(position=(2, 10), direction=3),
Waypoint(position=(2, 9), direction=3),
Waypoint(position=(2, 8), direction=3),
Waypoint(position=(2, 7), direction=3),
Waypoint(position=(2, 6), direction=3),
Waypoint(position=(2, 5), direction=3),
Waypoint(position=(2, 4), direction=3),
Waypoint(position=(2, 3), direction=3),
Waypoint(position=(2, 2), direction=3),
Waypoint(position=(2, 1), direction=3)]
}
for agent_handle in expected:
......@@ -102,12 +102,12 @@ def test_get_shortest_paths_max_depth():
expected = {
0: [
Wayoint(position=(1, 1), direction=1),
Wayoint(position=(1, 2), direction=1)
Waypoint(position=(1, 1), direction=1),
Waypoint(position=(1, 2), direction=1)
],
1: [
Wayoint(position=(3, 18), direction=3),
Wayoint(position=(3, 17), direction=3),
Waypoint(position=(3, 18), direction=3),
Waypoint(position=(3, 17), direction=3),
]
}
......@@ -126,78 +126,78 @@ def test_get_shortest_paths_agent_handle():
print(actual, file=sys.stderr)
expected = {6:
[Wayoint(position=(5, 5),
[Waypoint(position=(5, 5),
direction=0),
Wayoint(position=(4, 5),
Waypoint(position=(4, 5),
direction=0),
Wayoint(position=(3, 5),
Waypoint(position=(3, 5),
direction=0),
Wayoint(position=(2, 5),
Waypoint(position=(2, 5),
direction=0),
Wayoint(position=(1, 5),
Waypoint(position=(1, 5),
direction=0),
Wayoint(position=(0, 5),
Waypoint(position=(0, 5),
direction=0),
Wayoint(position=(0, 6),
Waypoint(position=(0, 6),
direction=1),
Wayoint(position=(0, 7), direction=1),
Wayoint(position=(0, 8),
Waypoint(position=(0, 7), direction=1),
Waypoint(position=(0, 8),
direction=1),
Wayoint(position=(0, 9),
Waypoint(position=(0, 9),
direction=1),
Wayoint(position=(0, 10),
Waypoint(position=(0, 10),
direction=1),
Wayoint(position=(1, 10),
Waypoint(position=(1, 10),
direction=2),
Wayoint(position=(2, 10),
Waypoint(position=(2, 10),
direction=2),
Wayoint(position=(3, 10),
Waypoint(position=(3, 10),
direction=2),
Wayoint(position=(4, 10),
Waypoint(position=(4, 10),
direction=2),
Wayoint(position=(5, 10),
Waypoint(position=(5, 10),
direction=2),
Wayoint(position=(6, 10),
Waypoint(position=(6, 10),
direction=2),
Wayoint(position=(7, 10),
Waypoint(position=(7, 10),
direction=2),
Wayoint(position=(8, 10),
Waypoint(position=(8, 10),
direction=2),
Wayoint(position=(9, 10),
Waypoint(position=(9, 10),
direction=2),
Wayoint(position=(10, 10),
Waypoint(position=(10, 10),
direction=2),
Wayoint(position=(11, 10),
Waypoint(position=(11, 10),
direction=2),
Wayoint(position=(12, 10),
Waypoint(position=(12, 10),
direction=2),
Wayoint(position=(13, 10),
Waypoint(position=(13, 10),
direction=2),
Wayoint(position=(14, 10),
Waypoint(position=(14, 10),
direction=2),
Wayoint(position=(15, 10),
Waypoint(position=(15, 10),
direction=2),
Wayoint(position=(16, 10),
Waypoint(position=(16, 10),
direction=2),
Wayoint(position=(17, 10),
Waypoint(position=(17, 10),
direction=2),
Wayoint(position=(18, 10),
Waypoint(position=(18, 10),
direction=2),
Wayoint(position=(19, 10),
Waypoint(position=(19, 10),
direction=2),
Wayoint(position=(20, 10),
Waypoint(position=(20, 10),
direction=2),
Wayoint(position=(20, 9),
Waypoint(position=(20, 9),
direction=3),
Wayoint(position=(20, 8),
Waypoint(position=(20, 8),
direction=3),
Wayoint(position=(21, 8),
Waypoint(position=(21, 8),
direction=2),
Wayoint(position=(21, 7),
Waypoint(position=(21, 7),
direction=3),
Wayoint(position=(21, 6),
Waypoint(position=(21, 6),
direction=3),
Wayoint(position=(21, 5),
Waypoint(position=(21, 5),
direction=3)
]}
......@@ -246,41 +246,41 @@ def test_get_k_shortest_paths(rendering=False):
expected = set([
(
Wayoint(position=(3, 1), direction=3),
Wayoint(position=(3, 0), direction=3),
Wayoint(position=(3, 1), direction=1),
Wayoint(position=(3, 2), direction=1),
Wayoint(position=(3, 3), direction=1),
Wayoint(position=(2, 3), direction=0),
Wayoint(position=(1, 3), direction=0),
Wayoint(position=(0, 3), direction=0),
Wayoint(position=(0, 4), direction=1),
Wayoint(position=(0, 5), direction=1),
Wayoint(position=(0, 6), direction=1),
Wayoint(position=(0, 7), direction=1),
Wayoint(position=(0, 8), direction=1),
Wayoint(position=(0, 9), direction=1),
Wayoint(position=(1, 9), direction=2),
Wayoint(position=(2, 9), direction=2),
Wayoint(position=(3, 9), direction=2)),
Waypoint(position=(3, 1), direction=3),
Waypoint(position=(3, 0), direction=3),
Waypoint(position=(3, 1), direction=1),
Waypoint(position=(3, 2), direction=1),
Waypoint(position=(3, 3), direction=1),
Waypoint(position=(2, 3), direction=0),
Waypoint(position=(1, 3), direction=0),
Waypoint(position=(0, 3), direction=0),
Waypoint(position=(0, 4), direction=1),
Waypoint(position=(0, 5), direction=1),
Waypoint(position=(0, 6), direction=1),
Waypoint(position=(0, 7), direction=1),
Waypoint(position=(0, 8), direction=1),
Waypoint(position=(0, 9), direction=1),
Waypoint(position=(1, 9), direction=2),
Waypoint(position=(2, 9), direction=2),
Waypoint(position=(3, 9), direction=2)),
(
Wayoint(position=(3, 1), direction=3),
Wayoint(position=(3, 0), direction=3),
Wayoint(position=(3, 1), direction=1),
Wayoint(position=(3, 2), direction=1),
Wayoint(position=(3, 3), direction=1),
Wayoint(position=(3, 4), direction=1),
Wayoint(position=(3, 5), direction=1),
Wayoint(position=(3, 6), direction=1),
Wayoint(position=(4, 6), direction=2),
Wayoint(position=(5, 6), direction=2),
Wayoint(position=(6, 6), direction=2),
Wayoint(position=(5, 6), direction=0),
Wayoint(position=(4, 6), direction=0),
Wayoint(position=(4, 7), direction=1),
Wayoint(position=(4, 8), direction=1),
Wayoint(position=(4, 9), direction=1),
Wayoint(position=(3, 9), direction=0))
Waypoint(position=(3, 1), direction=3),
Waypoint(position=(3, 0), direction=3),
Waypoint(position=(3, 1), direction=1),
Waypoint(position=(3, 2), direction=1),
Waypoint(position=(3, 3), direction=1),
Waypoint(position=(3, 4), direction=1),
Waypoint(position=(3, 5), direction=1),
Waypoint(position=(3, 6), direction=1),
Waypoint(position=(4, 6), direction=2),
Waypoint(position=(5, 6), direction=2),
Waypoint(position=(6, 6), direction=2),
Waypoint(position=(5, 6), direction=0),
Waypoint(position=(4, 6), direction=0),
Waypoint(position=(4, 7), direction=1),
Waypoint(position=(4, 8), direction=1),
Waypoint(position=(4, 9), direction=1),
Waypoint(position=(3, 9), direction=0))
])
assert actual == expected, "actual={},expected={}".format(actual, expected)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment