diff --git a/klient/play.py b/klient/play.py index 846588c..780d180 100755 --- a/klient/play.py +++ b/klient/play.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import argparse import time +from typing import Callable, List, Optional, Tuple from client import get_state, send_turn, logger, TIME_BEFORE_RETRY @@ -12,6 +13,27 @@ parser.add_argument("--log_level", type=str, default="WARNING", choices=["ERROR" # you can add your own arguments, the strategy function will get them +Coords = Tuple[int, int] + + +class Member: + def __init__(self, team: int, id: int, remaining_rounds: int): + self.team = team + self.id = id + self.remaining_rounds = remaining_rounds + self.action: Optional[str] = None + + +class Field: + def __init__(self, home_for_team: Optional[int], + occupied_by_team: Optional[int], + hill: bool, members: List[Member]): + self.home_for_team = home_for_team + self.occupied_by_team = occupied_by_team + self.hill = hill + self.members = members + + def strategy(team_id: int, state: dict, args: argparse.Namespace) -> dict: """Finds the best move for the given state. @@ -46,7 +68,75 @@ def strategy(team_id: int, state: dict, args: argparse.Namespace) -> dict: } ``` """ - return {} + + world = parse_world(state["map"]) + home = find_fields(world, lambda f: f.home_for_team == team_id)[0][1] + members = find_members(world, lambda m: m.team == team_id) + + # TODO: implement your strategy here + for member, coords in members: + member.action = "up" + return build_turn(members) + + +def find_fields( + world: List[List[Field]], + predicate: Callable[[Field], bool] +) -> List[Tuple[Field, Coords]]: + """Finds all fields that satisfy the given predicate.""" + + result = [] + for y, row in enumerate(world): + for x, field in enumerate(row): + if predicate(field): + result.append((field, (x, y))) + return result + + +def find_members( + world: List[List[Field]], + predicate: Callable[[Member], bool] +) -> List[Tuple[Member, Coords]]: + """Finds all members that satisfy the given predicate.""" + + result = [] + for y, row in enumerate(world): + for x, field in enumerate(row): + for member in field.members: + if predicate(member): + result.append((member, (x, y))) + return result + + +def build_turn(members: List[Member]) -> dict: + return { + "members": [ + {"id": member.id, "action": member.action} + for member in members + ] + } + + +def parse_world(world: dict) -> List[List[Field]]: + fields = [] + for row in world: + fields_row = [] + for field in row: + members = [] + for member in field["members"]: + members.append(Member( + member["team"], + member["id"], + member["remaining_rounds"] + )) + fields_row.append(Field( + field["home_for_team"], + field["occupied_by_team"], + field["hill"], + members + )) + fields.append(fields_row) + return fields def main(args: argparse.Namespace):