예제 #1
0
    def should_recalculate(self, state: PlayerState):
        # Don't recalculate if there are any un-executed urgent commands
        if self.has_urgent_commands() or self.has_processed_see_update:
            return False

        deadline_reached = self.deadline <= state.now()
        return deadline_reached or self.completion_criteria()
예제 #2
0
 def __init__(self,
              state: PlayerState,
              command_generator,
              completion_criteria=lambda: True,
              maximum_duration=1) -> None:
     self.command_generator = command_generator
     self.completion_criteria = completion_criteria
     self.deadline = state.now() + maximum_duration
     self.commands_executed = 0
     self.planned_commands: [Command] = []
     self.last_command_update_time = -1
     self.has_processed_see_update = False
예제 #3
0
def _dribble_objective(state: PlayerState):
    side = 1 if state.world_view.side == "l" else -1
    if not state.is_nearest_ball(1):
        state.mode = DEFAULT_MODE
        return determine_objective(state)

    if not state.is_near_ball(KICKABLE_MARGIN):
        return _rush_to_ball_objective(state)

    pos: Coordinate = state.position.get_value()
    if pos.euclidean_distance_from(Coordinate(52.5 * side, 0)) < 24:
        return Objective(
            state,
            lambda: actions.shoot_to(state, Coordinate(55 * side, 0), 100),
            lambda: True, 1)

    should_dribble = state.received_dribble_instruction.get_value() \
                     and state.received_dribble_instruction.last_updated_time >= state.now() - 100

    if not should_dribble:
        target = _choose_pass_target(state)
        if target is not None:
            return Objective(state,
                             lambda: actions.pass_to_player(state, target),
                             lambda: True, 1)
    else:
        state.received_dribble_instruction.set_value(False, state.now())

    if state.is_near_ball(
    ):  # todo temp: and state.action_history.has_looked_for_targets:
        target_coord: Coordinate = Coordinate(52.5 * side, 0)
        opposing_goal_dir = math.degrees(
            calculate_full_origin_angle_radians(target_coord,
                                                state.position.get_value()))
        state.action_history.has_looked_for_targets = False
        return Objective(
            state, lambda: actions.dribble(state, int(opposing_goal_dir)),
            lambda: False, 1)
    return _rush_to_ball_objective(state)
예제 #4
0
def _choose_pass_target(state: PlayerState, must_pass: bool = False):
    print("choose pass target")
    """
    If uppaal has been generated recently -> Follow strat if applicable
    If free targets forward -> Pass forward
    If no free targets forward, but i am not marked -> dribble forward
    If no free targets forward, but free targets behind, and i am marked -> Pass back
    If no free targets and i am marked -> Try to dribble anyway
    :return: Parse target or None, if dribble
    """

    # For pass chain model, if an existing target is seen by player, pass ball
    if len(state.passchain_targets) > 0:
        print("passchain longer than 0")
        for target in state.passchain_targets:
            target: PrecariousData
            if target.last_updated_time > state.now() - 40:
                print("if target update time is later than 40 seconds ago")
                target = state.find_teammate_closest_to(target.get_value(),
                                                        max_distance_delta=8.0)
                if target is not None:
                    print("TORGET ACQUIRED : ", target)
                    return target

    debug_msg(str(state.now()) + "Choosing pass target", "DRIBBLE_PASS_MODEL")
    # Act according to Possession model
    if state.dribble_or_pass_strat.is_value_known():
        if state.dribble_or_pass_strat.is_value_known(state.now() - 8):
            debug_msg(
                "Following uppaal DribbleOrPass strategy :" +
                str(state.dribble_or_pass_strat.get_value()),
                "DRIBBLE_PASS_MODEL")
            strat = state.dribble_or_pass_strat.get_value()
            state.dribble_or_pass_strat = PrecariousData.unknown()
            if DRIBBLE_INDICATOR in strat:
                if not must_pass:
                    state.statistics.use_possession_strategy()
                    debug_msg(
                        str(state.now()) + " Dribble!", "DRIBBLE_PASS_MODEL")
                    return None

            else:
                match = re.match(r'.*\(([^,]*), ([^)]*)\)', strat)
                x = float(match.group(1))
                y = float(match.group(2))
                target = state.find_teammate_closest_to(Coordinate(x, y),
                                                        max_distance_delta=3.0)
                if target is not None:
                    debug_msg(
                        str(state.now()) +
                        " DRIBBLE_PASS_MODEL : Playing to :" +
                        str(Coordinate(x, y)), "DRIBBLE_PASS_MODEL")

                    # If target is outside the no no square then return target
                    i = -1 if state.world_view.side == "l" else 1
                    is_too_far_back = True if (state.world_view.side == "l" and target.coord.pos_x < -36) \
                                              or (state.world_view.side == "r" and target.coord.pos_x > 36) else False

                    if (not is_too_far_back) and (not is_offside(
                            state, target)) and (target.coord.pos_y > -20
                                                 or target.coord.pos_y > 20):
                        state.statistics.use_possession_strategy()
                        return target
                else:
                    debug_msg(
                        str(state.now()) + "No teammate matched :" +
                        str(Coordinate(x, y)) + " Visible: " +
                        str(state.world_view.get_teammates(
                            state.team_name, 10)), "DRIBBLE_PASS_MODEL")

        # Discard strategy
        state.statistics.discard_possession_strategy()
        state.dribble_or_pass_strat = PrecariousData.unknown()

    side = state.world_view.side
    """ # TODO : TESTING ONLY ----------------------------------------------------------
    teammates = state.world_view.get_teammates(state.team_name, 2)
    if len(teammates) is not 0:
        return choice(teammates)
    # todo -------------------------------------------------------------------------- """

    am_i_marked = state.world_view.is_marked(team=state.team_name,
                                             max_data_age=4,
                                             min_distance=4)

    # If free targets forward -> Pass forward
    forward_team_mates = state.world_view.get_non_offside_forward_team_mates(
        state.team_name,
        side,
        state.position.get_value(),
        max_data_age=4,
        min_distance_free=2,
        min_dist_from_me=2)

    if len(forward_team_mates) > 0:
        # If free team mates sort by closest to opposing teams goal
        opposing_team_goal: Coordinate = Coordinate(
            52.5, 0) if side == "l" else Coordinate(-52.5, 0)
        debug_msg("forward_team_mates: " + str(forward_team_mates),
                  "PASS_TARGET")
        good_target = list(
            sorted(forward_team_mates,
                   key=lambda p: p.coord.euclidean_distance_from(
                       opposing_team_goal),
                   reverse=False))[0]
        return good_target

    # If no free targets forward, but i am not marked -> dribble forward
    if len(forward_team_mates) < 1 and not am_i_marked:
        debug_msg("No free targets forward -> Dribble!", "PASS_TARGET")
        if must_pass:
            tms = state.world_view.get_teammates(state.team_name, 5)
            if len(tms) > 0:
                return random.choice(tms)
        return None

    # If no free targets forward, but free targets behind, and i am marked -> Pass back
    behind_team_mates = state.world_view.get_free_behind_team_mates(
        state.team_name,
        side,
        state.position.get_value(),
        max_data_age=3,
        min_distance_free=3,
        min_dist_from_me=3)
    if len(behind_team_mates) > 0:
        # Get the player furthest forward and free
        opposing_team_goal: Coordinate = Coordinate(
            52.5, 0) if side == "l" else Coordinate(-52.5, 0)
        debug_msg("Behind_team_mates: " + str(behind_team_mates),
                  "PASS_TARGET")
        good_target = list(
            sorted(behind_team_mates,
                   key=lambda p: p.coord.euclidean_distance_from(
                       opposing_team_goal),
                   reverse=False))[0]
        return good_target

    # If no free targets and i am marked -> Try to dribble anyway
    debug_msg("No free targets forward and i am marked -> Dribble anyway!",
              "PASS_TARGET")
    if must_pass:
        tms = state.world_view.get_player_observations(state.team_name, 3)
        if len(tms) > 0:
            return random.choice(tms)
    return None
예제 #5
0
def determine_objective_field_default(state: PlayerState):
    state.intercepting = False
    # If lost orientation -> blind orient
    if _lost_orientation(state):
        return Objective(state, lambda: actions.blind_orient(state),
                         lambda: True, 1)

    opponent_side = "r" if state.world_view.side == "l" else "l"
    # If game not started or other team starting -> Idle orientation
    if state.world_view.game_state == 'before_kick_off' or state.world_view.game_state == "kick_off_{0}".format(
            opponent_side) or "goal" in state.world_view.game_state:
        return Objective(state, lambda: actions.idle_orientation(state),
                         lambda: True, 1)

    # If some fault has been made by our team -> position optimally
    if "fault_{0}".format(
            state.world_view.side) in state.world_view.game_state:
        return _position_optimally_objective(state)

    # If we have a free kick, corner_kick, kick_in or kick_off
    #   If closest -> Go to ball and pass, else position optimally
    if state.world_view.game_state == "free_kick_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "corner_kick_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "kick_in_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "kick_off_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "offside_{0}".format(opponent_side):
        if _ball_unknown(state):
            return _locate_ball_objective(state)
        if state.is_near_ball(KICKABLE_MARGIN):
            if state.world_view.sim_time - state.action_history.last_look_for_pass_targets > 2:
                return Objective(state,
                                 lambda: actions.look_for_pass_target(state),
                                 lambda: True, 2)
            if _choose_pass_target(state, must_pass=True) is not None:
                return Objective(
                    state, lambda: actions.pass_to_player(
                        state, _choose_pass_target(state, must_pass=True)),
                    lambda: True, 1)
            else:
                return Objective(state,
                                 lambda: actions.look_for_pass_target(state),
                                 lambda: True, 2)
        elif state.is_nearest_ball(1):
            return _jog_to_ball_objective(state)
        else:
            return _position_optimally_objective(state)

    # If in dribbling mode -> Dribble
    if state.mode is DRIBBLING_MODE:
        return _dribble_objective(state)

    # If in possession mode -> Pass
    if state.mode is POSSESSION_MODE:
        return _pass_objective(state)

    # If position known, but ball not -> Locate ball
    if _ball_unknown(state):
        return _locate_ball_objective(state)

    # If in possession of ball -> dribble!
    if state.is_near_ball() and state.is_nearest_ball(1):
        state.mode = DRIBBLING_MODE
        return _dribble_objective(state)

    required_degree = calculate_required_degree(state)
    if state.is_nearest_ball(required_degree):
        intercept_actions = actions.intercept_2(state)
        state.intercepting = True
        if intercept_actions is not None:
            return Objective(state, lambda: intercept_actions)
        else:
            return _rush_to_ball_objective(state)

    # If ball not incoming -> Position optimally while looking at ball
    if not state.ball_incoming() and not configurations.USING_PASS_CHAIN_STRAT:
        if state.is_test_player():
            debug_msg(str(state.now()) + " Position optimally!", "ACTIONS")
        return _position_optimally_objective(state)

    if state.is_test_player():
        debug_msg(str(state.now()) + " Idle orientation!", "ACTIONS")

    return Objective(state, lambda: actions.idle_orientation(state),
                     lambda: True, 1)
예제 #6
0
def determine_objective_goalie_default(state: PlayerState):
    opponent_side = "r" if state.world_view.side == "l" else "l"
    # If goalie and goal_kick -> Go to ball and pass
    if state.world_view.game_state == "goal_kick_{0}".format(
            state.world_view.side) and state.num == 1:
        debug_msg(
            str(state.now()) + " | goal kick -> got to ball and pass",
            "GOALIE")
        if state.is_near_ball(KICKABLE_MARGIN):
            return _pass_objective(state, must_pass=True)
        else:
            return _jog_to_ball_objective(state)

    # If game not started or other team starting -> Idle orientation
    if state.world_view.game_state == 'before_kick_off' or state.world_view.game_state == "kick_off_{0}".format(
            opponent_side) or ("goal_r" == state.world_view.game_state
                               or "goal_l" == state.world_view.game_state):
        debug_msg(
            str(state.now()) +
            " | If game not started or other team starting -> Idle orientation",
            "GOALIE")
        return Objective(state, lambda: actions.idle_orientation(state),
                         lambda: True, 1)

    # If lost_orientation -> blind orient
    if _lost_orientation(state):
        debug_msg(
            str(state.now()) + " | lost orientation -> blind orient", "GOALIE")
        return Objective(state, lambda: actions.blind_orient(state),
                         lambda: True, 1)

    # If ball unknown -> locate ball
    if _ball_unknown(state):
        debug_msg(
            str(state.now()) + " | ball unknown -> locate ball", "GOALIE")
        return Objective(state, lambda: actions.locate_ball(state),
                         lambda: True, 1)

    # If some fault has been made by our team -> Position optimally
    if "fault_{0}".format(
            state.world_view.side) in state.world_view.game_state:
        debug_msg(
            str(state.now()) + " | Team made fault -> position optimally",
            "GOALIE")
        return _position_optimally_objective_goalie(state)

    # If we have a free kick, corner_kick, kick_in, kick_off or goal_kick
    # If closest -> Go to ball and pass, else position optimally
    if state.world_view.game_state == "free_kick_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "corner_kick_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "kick_in_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "goal_kick_{0}".format(state.world_view.side) \
            or state.world_view.game_state == "offside_{0}".format(opponent_side):
        debug_msg(
            str(state.now()) +
            " | free_kick, corner_kick, kick_in, kick_off, goal_kick, offside -> go to ball or position optimally",
            "GOALIE")
        if _ball_unknown(state):
            return _locate_ball_objective(state)
        if state.is_near_ball(KICKABLE_MARGIN):
            if state.world_view.sim_time - state.action_history.last_look_for_pass_targets > 2:
                return Objective(state,
                                 lambda: actions.look_for_pass_target(state),
                                 lambda: True, 2)
            if _choose_pass_target(state, must_pass=True) is not None:
                return Objective(
                    state, lambda: actions.pass_to_player(
                        state, _choose_pass_target(state, must_pass=True)),
                    lambda: True, 1)
            else:
                return Objective(state,
                                 lambda: actions.look_for_pass_target(state),
                                 lambda: True, 2)
        elif state.is_nearest_ball(1):
            return _jog_to_ball_objective(state)
        else:
            return _position_optimally_objective_goalie(state)

    ball: Ball = state.world_view.ball.get_value()

    # If in possession of the ball -> Pass to team mate
    if state.is_near_ball(KICKABLE_MARGIN):
        pass_target = _choose_pass_target(state)
        if pass_target is not None:
            debug_msg(
                str(state.now()) +
                " | in possession, pass target found -> pass to teammate",
                "GOALIE")
            return Objective(
                state, lambda: actions.pass_to_player(
                    state, _choose_pass_target(state)), lambda: True, 1)
        # No suitable pass target
        debug_msg(
            str(state.now()) +
            " | in possession, pass target not found -> look for pass target",
            "GOALIE")
        return Objective(state, lambda: actions.look_for_pass_target(state),
                         lambda: True, 1)

    # If ball coming to goalie inside box -> Catch ball
    positions = ball.project_ball_position(2, 0)
    if positions is not None and state.is_inside_own_box():
        debug_msg(
            str(state.now()) + " | Ball incoming inside box -> Catch ball",
            "GOALIE")
        ball_pos_1_tick: Coordinate = positions[0]
        if ball_pos_1_tick.euclidean_distance_from(
                state.position.get_value()) < CATCHABLE_MARGIN:
            return Objective(
                state, lambda: actions.catch_ball(state, ball_pos_1_tick),
                lambda: True, 1)

    # If ball coming towards us or ball will hit goal soon -> Intercept
    if (ball.will_hit_goal_within(ticks=5)
            or (state.is_nearest_ball(1) and state.is_ball_inside_own_box())):
        debug_msg(
            str(state.now()) +
            " | ball coming towards us or ball will hit goal soon -> run to ball and catch!",
            "GOALIE")
        intercept_actions = actions.intercept_2(state, "catch")
        if intercept_actions is not None:
            return Objective(state, lambda: intercept_actions)
        else:
            return _rush_to_ball_objective(state)

    # If position not alligned with ball y-position -> Adjust y-position
    if state.position.is_value_known(
    ) and state.world_view.ball.is_value_known(
    ) and not configurations.USING_PASS_CHAIN_STRAT:
        debug_msg(
            str(state.now()) + " | Position not optimal -> adjust position",
            "GOALIE")
        return _position_optimally_objective_goalie(state)

    # If nothing to do -> Face ball
    debug_msg(str(state.now()) + " | Nothing to do -> Face ball", "GOALIE")
    return Objective(state, lambda: actions.face_ball(state), lambda: True, 1)
예제 #7
0
def _find_applicable_strat_player(state: PlayerState) -> _StrategyGenerator:
    # Matches the current state of the game to a uppaal model, if applicable

    # Check if dribble strategy model can be applied
    if state.team_name in DRIBBLE_OR_PASS_TEAMS and state.needs_dribble_or_pass_strat(
    ):
        print(state.now(), " DRIBBLE STRAT - Player : ", state.num)

        possession_dir = Path(__file__).parent / "models" / "possessionmodel"
        if not possession_dir.exists():
            os.makedirs(possession_dir)

        original_pos_model = Path(
            possession_dir).parent / "PassOrDribbleModel.xml"
        model_name = "possessionmodel{0}{1}.xml".format(
            state.world_view.side, state.num)
        new_pos_file = possession_dir / model_name

        if not new_pos_file.exists():
            f = open(new_pos_file, "x")
            copyfile(original_pos_model, new_pos_file)
            f.close()

        return _StrategyGenerator(
            "/possessionmodel/possessionmodel{0}{1}".format(
                state.world_view.side, state.num),
            _update_dribble_or_pass_model, _extract_pass_or_dribble_strategy)

    # Check if stamina strategy model can be applied
    if state.team_name in STAMINA_MODEL_TEAMS and (
            state.now() % 121) == (state.num + 1) * 10:
        print(state.num, state.team_name)
        return _StrategyGenerator(
            "/staminamodel/staminamodel{0}{1}".format(state.world_view.side,
                                                      state.num),
            _update_stamina_model_simple, _extract_stamina_solution_simple)

    # Check if the goalie defence model can be applied
    if state.team_name in GOALIE_MODEL_TEAMS and state.player_type == "goalie":
        ball_possessor = state.get_ball_possessor()

        if ball_possessor is not None and ball_possessor.coord is not None:
            side = 1 if state.world_view.side == "r" else -1
            steps_per_meter = goalie_strategy.STEPS_PER_METER
            # Convert coordinate to fit the squares from the strategy
            possessor_new_x = math.floor(ball_possessor.coord.pos_x * side /
                                         steps_per_meter) * steps_per_meter
            possessor_new_y = math.floor(
                ball_possessor.coord.pos_y / steps_per_meter) * steps_per_meter
            goalie_new_x = math.floor(state.position.get_value().pos_x * side /
                                      steps_per_meter) * steps_per_meter
            goalie_new_y = math.floor(state.position.get_value().pos_y /
                                      steps_per_meter) * steps_per_meter

            if abs(state.position.get_value().pos_x) > 52.5:
                goalie_new_x = 52 * side

            # Example: "(36.5, -19.5),(47.5, -8.5)" -> "(goalie_x, goalie_y),(player_x, player_y)"
            key = "({0}.0, {1}.0),({2}.0, {3}.0)".format(
                str(goalie_new_x), str(goalie_new_y), str(possessor_new_x),
                str(possessor_new_y))
            if key in state.goalie_position_dict.keys():
                result = state.goalie_position_dict[key]
                optimal_x = int(goalie_new_x * side + result[0] * side)
                optimal_y = int(goalie_new_y + result[1])
                optimal_coord = Coordinate(optimal_x, optimal_y)
                state.goalie_position_strategy = optimal_coord

    return None
예제 #8
0
def _update_dribble_or_pass_model(state: PlayerState, model: UppaalModel):
    # This function edits the UPPAAL file to represent the current state of the game

    # Amount of ticks to forecast game state
    # This should be the expected time that it takes to generate the strategy
    FORECAST_TICKS = 6

    team_mates = state.world_view.get_teammates_precarious(state.team_name,
                                                           10,
                                                           min_dist=5)
    opponents = state.world_view.get_opponents_precarious(state.team_name,
                                                          10,
                                                          min_dist=0)

    # Forecast position of the ball possessor
    if state.get_y_north_velocity_vector() is not None:
        possessor_forecasted = (
            state.position.get_value().vector() +
            state.get_y_north_velocity_vector() * FORECAST_TICKS).coord()
    else:
        possessor_forecasted = state.position.get_value()

    # Forecast position of other players
    forecasted_team_positions = list(
        map(
            lambda p: p.get_value().forecasted_position(
                (state.now() - p.last_updated_time) + FORECAST_TICKS),
            team_mates))
    forecasted_opponent_positions = list(
        map(
            lambda p: p.get_value().forecasted_position(
                (state.now() - p.last_updated_time) + FORECAST_TICKS),
            opponents))
    if state.players_close_behind > 0:
        forecasted_opponent_positions.append(
            Coordinate(
                possessor_forecasted.pos_x - 1,
                possessor_forecasted.pos_y,
            ))

    # Convert to textual format understandable by uppaal
    team_pos_value = _to_3d_double_array_coordinate(forecasted_team_positions)
    opponent_pos_value = _to_3d_double_array_coordinate(
        forecasted_opponent_positions)
    possessor_val = _to_2d_double_array_coordinate(possessor_forecasted)

    model.set_global_declaration_value("TEAM_MATES",
                                       len(forecasted_team_positions))
    model.set_global_declaration_value("OPPONENTS",
                                       len(forecasted_opponent_positions))
    model.set_global_declaration_value("team_pos[TEAM_MATES][2]",
                                       team_pos_value)
    model.set_global_declaration_value("opponent_pos[OPPONENTS][2]",
                                       opponent_pos_value)
    model.set_global_declaration_value("possessor[2]", possessor_val)

    if state.is_test_player():  # Debugging
        all_posis = list(
            map(lambda p: p.get_value().coord, state.world_view.other_players))
        debug_msg(
            str(state.now()) + " All positions: " + str(all_posis),
            "DRIBBLE_PASS_MODEL")
        debug_msg(
            str(state.now()) + " Forecasted team positions: " +
            str(team_pos_value), "DRIBBLE_PASS_MODEL")
        debug_msg(
            str(state.now()) + " Forecasted opponent positions: " +
            str(opponent_pos_value), "DRIBBLE_PASS_MODEL")
        debug_msg(
            str(state.now()) + " Forecasted possessor position: " +
            str(possessor_val), "DRIBBLE_PASS_MODEL")

    return forecasted_team_positions