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
|
||||
from __future__ import annotations
|
||||
from enum import Enum
|
||||
from typing import Callable, Iterable, List, Optional
|
||||
from typing import Callable, Iterable, Optional, List, Set
|
||||
import collections
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
@ -13,6 +14,17 @@ class Action(Enum):
|
|||
RIGHT = "right"
|
||||
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:
|
||||
def __init__(self, state: dict) -> None:
|
||||
|
@ -44,6 +56,12 @@ class Field:
|
|||
self.home_for_team = home_for_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:
|
||||
if action == Action.UP:
|
||||
neighbour_i = self.i - 1
|
||||
|
@ -111,6 +129,31 @@ def find_team_members(team_id: int) -> List[Member]:
|
|||
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:
|
||||
return {
|
||||
"members": [
|
||||
|
|
Loading…
Reference in a new issue