Browse Source

Strategická: Update pythoní templaty

master
Jiří Kalvoda 2 years ago
parent
commit
b6b062f2c2
  1. 211
      klient/play.py

211
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()
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]
# Třídy reprezentující hru
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,20 +104,70 @@ 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
def build_turn(members: Iterable[Member]) -> dict:
return {
"members": [
{"id": member.id, "action": str(member.action)}
for member in members
]
}
return Direction.STAY
# main (zde doplňte kód)
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)
def main() -> None:
global state
state = State(json.loads(sys.stdin.read()))
fields.append(fields_row)
return fields
# TODO: set actions for all yours members
# example: all members go up
for member in state.teams[1].members:
member.action = Direction.UP
print(json.dumps(state.build_turn()))
if __name__ == '__main__':
main()

Loading…
Cancel
Save