def update(self, fsm, rs):
        # update ball predictions
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)
        # print(f"Ball prediction for {predict_time} ticks: {predicted_ball}")

        rs.out = move_to_point(rs, predicted_ball[0], predicted_ball[1], False)
        distance = sqrt(
            pow(rs.ball_pos[0] - rs.agent_pos[0], 2) +
            pow(rs.ball_pos[1] - rs.agent_pos[1], 2))
        if abs(rs.ball_pos[0]
               ) > SIDE_THRESH or rs.ball_pos[1] < BEHIND_THRESH - GOAL_DIST:
            fsm.change_state(rs, StateMidIdle())
            return
        if distance <= CHASE_TO_CIRCLE:
            fsm.change_state(rs, StateMidCircle())
            return
        if rs.ball_pos[1] < BEHIND_THRESH - GOAL_DIST:
            fsm.change_state(rs, StateMidHover())
            return
    def update(self, fsm, rs):
        # update ball predictions
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)
        # print(f"Ball prediction for {predict_time} ticks: {predicted_ball}")

        ball_speed = sqrt(pow(ball_vel[0], 2) + pow(ball_vel[1], 2))
        rs.out = move_to_point(
            rs, HOVER_DIST * (rs.ball_pos[0] / (rs.ball_pos[1] + GOAL_DIST)),
            HOVER_DIST - GOAL_DIST, False)
        distance = predicted_ball[1] + GOAL_DIST
        if abs(rs.ball_pos[0]
               ) > SIDE_THRESH or rs.ball_pos[1] < BEHIND_THRESH - GOAL_DIST:
            fsm.change_state(rs, StateMidIdle())
            return
        if distance < HOVER_TO_PUSH or distance < BEHIND_THRESH:
            if ball_speed < BALL_VEL_THRESH:
                fsm.change_state(rs, StateMidChase())
            else:
                fsm.change_state(rs, StateMidPush())
            return
    def update(self, fsm, rs):
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)

        rs.out = move_to_point(rs, rs.ball_pos[0], rs.ball_pos[1], False)
        if ball_dist <= CHASE_TO_CIRCLE:
            fsm.change_state(rs, StateAttackCircle())
            return
 def update(self, fsm, rs):
     distance = sqrt(
         pow(rs.ball_pos[0] - rs.agent_pos[0], 2) +
         pow(rs.ball_pos[1] - rs.agent_pos[1], 2))
     direction = atan2(rs.ball_pos[1] - rs.agent_pos[1],
                       rs.ball_pos[0] - rs.agent_pos[0]) - pi / 2
     rs.out = move_to_point(rs, rs.ball_pos[0], rs.ball_pos[1], False)
     if abs(rs.ball_pos[0]
            ) > SIDE_THRESH or rs.ball_pos[1] < BEHIND_THRESH - GOAL_DIST:
         fsm.change_state(rs, StateMidIdle())
         return
     if distance >= CIRCLE_TO_CHASE or (abs(direction) > MID_ANGLE_EXIT):
         fsm.change_state(rs, StateMidCircle())
         return
    def update(self, fsm, rs):
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)

        mag = sqrt(pow(rs.ball_pos[0], 2) + pow(rs.ball_pos[1], 2))
        rs.out = move_to_point(rs, 0.2 * (predicted_ball[0] / mag),
                               0.2 * (predicted_ball[1] / mag), False)
        if abs(rs.ball_pos[0]
               ) < SIDE_THRESH and rs.ball_pos[1] > BEHIND_THRESH - GOAL_DIST:
            fsm.change_state(rs, StateMidHover())
            return
    def update(self, fsm, rs):
        # update ball predictions
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        actual_ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(actual_ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)
        #print(f"Ball prediction for {predict_time} ticks: {predicted_ball}")

        rs.out = move_to_point(rs, predicted_ball[0], predicted_ball[1], False)
        ball_dist = rs.ball_pos[1] + GOAL_DIST
        robot_dist = rs.agent_pos[1] + GOAL_DIST
        if ball_dist >= BALL_SAFE_DIST or robot_dist >= SURGE_DIST:
            fsm.change_state(rs, StateDefendHover())
            return
    def update(self, fsm, rs):
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)

        goal_angle = atan2(GOAL_DIST - rs.agent_pos[1], -rs.agent_pos[0])
        direction = atan2(rs.ball_pos[1] - rs.agent_pos[1],
                          rs.ball_pos[0] - rs.agent_pos[0]) - goal_angle
        rs.out = move_to_point(rs, predicted_ball[0], predicted_ball[1], False)
        if ball_dist >= CIRCLE_TO_CHASE or (abs(direction) >
                                            FORWARD_ANGLE_EXIT):
            fsm.change_state(rs, StateAttackCircle())
            return
    def update(self, fsm, rs):
        # update ball predictions
        ball_vel = rs.ball_predictor.push_measurement(rs.ball_pos,
                                                      rs.simulation_time)
        ball_dist = sqrt(
            pow(rs.agent_pos[0] - rs.ball_pos[0], 2) +
            pow(rs.agent_pos[1] - rs.ball_pos[1], 2))
        predict_time = predict_time_func(ball_dist)
        predicted_ball = predict_object(rs.ball_pos, ball_vel, predict_time)
        #print(f"Ball prediction for {predict_time} ticks: {predicted_ball}")

        # direction = atan2(predicted_ball[1] - rs.agent_pos[1], predicted_ball[0] - rs.agent_pos[0])
        rs.out = move_to_point(
            rs, IDLE_DIST * (rs.ball_pos[0] / (rs.ball_pos[1] + GOAL_DIST)),
            IDLE_DIST - GOAL_DIST, False)
        distance = predicted_ball[1] + GOAL_DIST
        if distance < SURGE_THRESH:
            fsm.change_state(rs, StateDefendSurge())
            return
 def update(self, fsm, rs):
     rs.out = move_to_point(rs, rs.ball_pos[0], rs.ball_pos[1], False)
     if rs.simulation_time > 3008:
         fsm.change_state(rs, StateAttackChase())
         return