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