Strategická: Pathfinding
This commit is contained in:
parent
36c1072d40
commit
0961d4161c
1 changed files with 44 additions and 1 deletions
|
@ -1,7 +1,8 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import Callable, Iterable, List, Optional
|
from typing import Callable, Iterable, Optional, List, Set
|
||||||
|
import collections
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -13,6 +14,17 @@ class Action(Enum):
|
||||||
RIGHT = "right"
|
RIGHT = "right"
|
||||||
STAY = None
|
STAY = None
|
||||||
|
|
||||||
|
def invert(self) -> Action:
|
||||||
|
if self == Action.UP:
|
||||||
|
return Action.DOWN
|
||||||
|
if self == Action.DOWN:
|
||||||
|
return Action.UP
|
||||||
|
if self == Action.LEFT:
|
||||||
|
return Action.RIGHT
|
||||||
|
if self == Action.RIGHT:
|
||||||
|
return Action.LEFT
|
||||||
|
return Action.STAY
|
||||||
|
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
def __init__(self, state: dict) -> None:
|
def __init__(self, state: dict) -> None:
|
||||||
|
@ -44,6 +56,12 @@ class Field:
|
||||||
self.home_for_team = home_for_team
|
self.home_for_team = home_for_team
|
||||||
self.occupied_by_team = occupied_by_team
|
self.occupied_by_team = occupied_by_team
|
||||||
|
|
||||||
|
def __eq__(self, other: Field) -> bool:
|
||||||
|
return (self.i, self.j) == (other.i, other.j)
|
||||||
|
|
||||||
|
def __hash__(self) -> int:
|
||||||
|
return hash((self.i, self.j))
|
||||||
|
|
||||||
def get_neighbour_field(self, action: Action) -> Field:
|
def get_neighbour_field(self, action: Action) -> Field:
|
||||||
if action == Action.UP:
|
if action == Action.UP:
|
||||||
neighbour_i = self.i - 1
|
neighbour_i = self.i - 1
|
||||||
|
@ -111,6 +129,31 @@ def find_team_members(team_id: int) -> List[Member]:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def pathfind(member: Member, goal: Field) -> Action:
|
||||||
|
"""Find the shortest path from member position to goal.
|
||||||
|
|
||||||
|
Returns the first action to take.
|
||||||
|
If there is no path, returns Action.STAY.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# BFS from goal to member
|
||||||
|
# this direction makes it easier to realize that no path exists
|
||||||
|
explored: Set[Field] = set()
|
||||||
|
queue = collections.deque([goal])
|
||||||
|
while queue:
|
||||||
|
field = queue.popleft()
|
||||||
|
for action in Action:
|
||||||
|
neighbour = field.get_neighbour_field(action)
|
||||||
|
if (neighbour in explored or
|
||||||
|
not neighbour.is_accessible(member.team)):
|
||||||
|
continue
|
||||||
|
if field == member.field:
|
||||||
|
return action.invert()
|
||||||
|
queue.append(neighbour)
|
||||||
|
explored.add(field)
|
||||||
|
return Action.STAY
|
||||||
|
|
||||||
|
|
||||||
def build_turn(members: Iterable[Member]) -> dict:
|
def build_turn(members: Iterable[Member]) -> dict:
|
||||||
return {
|
return {
|
||||||
"members": [
|
"members": [
|
||||||
|
|
Loading…
Reference in a new issue