Browse Source

Strategická: Pathfinding

master
David Klement 2 years ago
parent
commit
0961d4161c
  1. 45
      klient/play.py

45
klient/play.py

@ -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…
Cancel
Save