Strategická: Update pythoní templaty
This commit is contained in:
parent
c2c343697d
commit
b6b062f2c2
1 changed files with 115 additions and 94 deletions
209
klient/play.py
209
klient/play.py
|
@ -7,36 +7,42 @@ import json
|
|||
import sys
|
||||
|
||||
|
||||
class Action(enum.Enum):
|
||||
UP = enum.auto()
|
||||
DOWN = enum.auto()
|
||||
LEFT = enum.auto()
|
||||
RIGHT = enum.auto()
|
||||
STAY = enum.auto()
|
||||
# Třídy reprezentující hru
|
||||
|
||||
def invert(self) -> Action:
|
||||
INVERSIONS = {
|
||||
Action.UP: Action.DOWN,
|
||||
Action.DOWN: Action.UP,
|
||||
Action.LEFT: Action.RIGHT,
|
||||
Action.RIGHT: Action.LEFT,
|
||||
Action.STAY: Action.STAY,
|
||||
}
|
||||
return INVERSIONS[self]
|
||||
class Direction(enum.Enum):
|
||||
UP = 0
|
||||
LEFT = 1
|
||||
DOWN = 2
|
||||
RIGHT = 3
|
||||
STAY = None
|
||||
|
||||
def combine(self, other) -> Direction:
|
||||
return Direction((self.value + other.value)%4)
|
||||
|
||||
def invert(self) -> Direction:
|
||||
if self == Direction.STAY:
|
||||
return self
|
||||
return self.combine(Direction.DOWN)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name.lower()
|
||||
|
||||
|
||||
class State:
|
||||
def __init__(self, state: dict) -> None:
|
||||
self.world = parse_world(state["state"]["world"])
|
||||
self.my_team_id: int = state["team_id"]
|
||||
self.round_number: int = state["round"]
|
||||
self.time_to_response: Optional[int] = state["time_to_response"]
|
||||
class Team:
|
||||
home: 'Field'
|
||||
|
||||
def __init__(self, id: int, is_me: bool) -> None:
|
||||
self.id: int = id
|
||||
self.is_me = is_me
|
||||
self.protected_fields: List[Field] = []
|
||||
self.occupied: List[Field] = []
|
||||
self.members: List[Member] = []
|
||||
|
||||
state: State
|
||||
def __eq__(self, other: Field) -> bool:
|
||||
return (self.id) == (other.id)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(self.id)
|
||||
|
||||
|
||||
class Member:
|
||||
|
@ -44,22 +50,22 @@ class Member:
|
|||
self.field = field
|
||||
self.team = team
|
||||
self.id = id
|
||||
self.action = Action.STAY
|
||||
self.action = Direction.STAY
|
||||
|
||||
|
||||
class Field:
|
||||
members: List[Member]
|
||||
|
||||
def __init__(self, i: int, j: int, hill: bool,
|
||||
home_for_team: Optional[int],
|
||||
occupied_by_team: Optional[int],
|
||||
protected_for_team: Optional[int],) -> None:
|
||||
self.i = i
|
||||
self.j = j
|
||||
self.hill = hill
|
||||
self.home_for_team = home_for_team
|
||||
self.occupied_by_team = occupied_by_team
|
||||
self.protected_for_team = protected_for_team
|
||||
home_for_team: Optional[Team],
|
||||
occupied_by_team: Optional[Team],
|
||||
protected_for_team: Optional[Team],) -> None:
|
||||
self.i: int = i
|
||||
self.j: int = j
|
||||
self.hill: bool = hill
|
||||
self.home_for_team: Optional[Team] = home_for_team
|
||||
self.occupied_by_team: Optional[Team] = occupied_by_team
|
||||
self.protected_for_team: Optional[Team] = protected_for_team
|
||||
|
||||
def __eq__(self, other: Field) -> bool:
|
||||
return (self.i, self.j) == (other.i, other.j)
|
||||
|
@ -67,17 +73,17 @@ class Field:
|
|||
def __hash__(self) -> int:
|
||||
return hash((self.i, self.j))
|
||||
|
||||
def get_neighbour_field(self, action: Action) -> Field:
|
||||
if action == Action.UP:
|
||||
def get_neighbour_field(self, action: Direction) -> Field:
|
||||
if action == Direction.UP:
|
||||
neighbour_i = self.i - 1
|
||||
neighbour_j = self.j
|
||||
elif action == Action.DOWN:
|
||||
elif action == Direction.DOWN:
|
||||
neighbour_i = self.i + 1
|
||||
neighbour_j = self.j
|
||||
elif action == Action.LEFT:
|
||||
elif action == Direction.LEFT:
|
||||
neighbour_i = self.i
|
||||
neighbour_j = self.j - 1
|
||||
elif action == Action.RIGHT:
|
||||
elif action == Direction.RIGHT:
|
||||
neighbour_i = self.i
|
||||
neighbour_j = self.j + 1
|
||||
else:
|
||||
|
@ -88,7 +94,7 @@ class Field:
|
|||
neighbour_j %= len(state.world[0])
|
||||
return state.world[neighbour_i][neighbour_j]
|
||||
|
||||
def is_accessible(self, team: int) -> bool:
|
||||
def is_accessible(self, team: Team) -> bool:
|
||||
"""If this field is accessible for the given team."""
|
||||
|
||||
if self.hill:
|
||||
|
@ -98,19 +104,69 @@ class Field:
|
|||
return False
|
||||
return True
|
||||
|
||||
# Celý stav hry včetně parsování a vypisování
|
||||
|
||||
def main() -> None:
|
||||
global state
|
||||
state = State(json.loads(sys.stdin.read()))
|
||||
my_members = find_team_members(state.my_team_id)
|
||||
class State:
|
||||
def __init__(self, state: dict) -> None:
|
||||
self.teams = [Team(i, i==state["team_id"]) for i in range(state["teams_count"])]
|
||||
self.world = self._parse_world(state["state"]["world"])
|
||||
self.my_team: Team = self.teams[state["team_id"]]
|
||||
self.round_number: int = state["round"]
|
||||
self.time_to_response: Optional[int] = state["time_to_response"]
|
||||
|
||||
# TODO: set actions for all members
|
||||
# example: all members go up
|
||||
for member in my_members:
|
||||
member.action = Action.UP
|
||||
def _parse_world(self, world: dict) -> List[List[Field]]:
|
||||
def get_team(team_id):
|
||||
return None if team_id is None else self.teams[team_id]
|
||||
|
||||
print(json.dumps(build_turn(my_members)))
|
||||
fields = []
|
||||
for i, row in enumerate(world):
|
||||
fields_row = []
|
||||
for j, field in enumerate(row):
|
||||
parsed_field = Field(
|
||||
i, j,
|
||||
field["hill"],
|
||||
get_team(field["home_for_team"]),
|
||||
get_team(field["occupied_by_team"]),
|
||||
get_team(field["protected_for_team"]),
|
||||
)
|
||||
if parsed_field.home_for_team:
|
||||
parsed_field.home_for_team.home = parsed_field
|
||||
if parsed_field.occupied_by_team:
|
||||
parsed_field.occupied_by_team.occupied.append(parsed_field)
|
||||
if parsed_field.protected_for_team:
|
||||
parsed_field.protected_for_team.protected_fields.append(parsed_field)
|
||||
members = []
|
||||
for member in field["members"]:
|
||||
m = Member(
|
||||
parsed_field,
|
||||
self.teams[member["team"]],
|
||||
member["id"],
|
||||
)
|
||||
members.append(m)
|
||||
m.team.members.append(m)
|
||||
parsed_field.members = members
|
||||
fields_row.append(parsed_field)
|
||||
|
||||
fields.append(fields_row)
|
||||
return fields
|
||||
|
||||
|
||||
def build_turn(self) -> dict:
|
||||
for team in self.teams:
|
||||
if not team.is_me:
|
||||
for member in team.members:
|
||||
if member.action is not Direction.STAY:
|
||||
raise Exception("Akce přiřazena cizímu týmu")
|
||||
return {
|
||||
"members": [
|
||||
{"id": member.id, "action": str(member.action)}
|
||||
for member in self.my_team.members
|
||||
]
|
||||
}
|
||||
|
||||
state: State
|
||||
|
||||
# Algoritmy
|
||||
|
||||
def find_fields(predicate: Callable[[Field], bool]) -> List[Field]:
|
||||
"""Find all fields that satisfy the given predicate."""
|
||||
|
@ -123,19 +179,7 @@ def find_fields(predicate: Callable[[Field], bool]) -> List[Field]:
|
|||
return result
|
||||
|
||||
|
||||
def find_team_members(team_id: int) -> List[Member]:
|
||||
"""Find all members that belong to the given team."""
|
||||
|
||||
result = []
|
||||
for row in state.world:
|
||||
for field in row:
|
||||
for member in field.members:
|
||||
if member.team == team_id:
|
||||
result.append((member))
|
||||
return result
|
||||
|
||||
|
||||
def pathfind(member: Member, goal: Field) -> Action:
|
||||
def pathfind(member: Member, goal: Field) -> Direction:
|
||||
"""Find the shortest path from member position to goal.
|
||||
|
||||
Returns the first action to take.
|
||||
|
@ -148,7 +192,7 @@ def pathfind(member: Member, goal: Field) -> Action:
|
|||
queue = collections.deque([goal])
|
||||
while queue:
|
||||
field = queue.popleft()
|
||||
for action in Action:
|
||||
for action in Direction:
|
||||
neighbour = field.get_neighbour_field(action)
|
||||
if (neighbour in explored or
|
||||
not neighbour.is_accessible(member.team)):
|
||||
|
@ -157,43 +201,20 @@ def pathfind(member: Member, goal: Field) -> Action:
|
|||
return action.invert()
|
||||
queue.append(neighbour)
|
||||
explored.add(neighbour)
|
||||
return Action.STAY
|
||||
return Direction.STAY
|
||||
|
||||
# main (zde doplňte kód)
|
||||
|
||||
def build_turn(members: Iterable[Member]) -> dict:
|
||||
return {
|
||||
"members": [
|
||||
{"id": member.id, "action": str(member.action)}
|
||||
for member in members
|
||||
]
|
||||
}
|
||||
def main() -> None:
|
||||
global state
|
||||
state = State(json.loads(sys.stdin.read()))
|
||||
|
||||
# TODO: set actions for all yours members
|
||||
# example: all members go up
|
||||
for member in state.teams[1].members:
|
||||
member.action = Direction.UP
|
||||
|
||||
def parse_world(world: dict) -> List[List[Field]]:
|
||||
fields = []
|
||||
for i, row in enumerate(world):
|
||||
fields_row = []
|
||||
for j, field in enumerate(row):
|
||||
parsed_field = Field(
|
||||
i, j,
|
||||
field["hill"],
|
||||
field["home_for_team"],
|
||||
field["occupied_by_team"],
|
||||
field["protected_for_team"],
|
||||
)
|
||||
members = []
|
||||
for member in field["members"]:
|
||||
members.append(Member(
|
||||
parsed_field,
|
||||
member["team"],
|
||||
member["id"],
|
||||
))
|
||||
parsed_field.members = members
|
||||
fields_row.append(parsed_field)
|
||||
|
||||
fields.append(fields_row)
|
||||
return fields
|
||||
|
||||
print(json.dumps(state.build_turn()))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
Loading…
Reference in a new issue