def utility_score(self, bot) -> float: if self.temp_utility_desire_boost > 0: self.temp_utility_desire_boost = max(0, self.temp_utility_desire_boost - bot.info.dt) elif self.temp_utility_desire_boost < 0: self.temp_utility_desire_boost = min(0, self.temp_utility_desire_boost + bot.info.dt) car = bot.info.my_car ball_soon = predict.ball_predict(bot, 1) arena_length2 = bot.info.team_sign * Field.LENGTH2 own_half_01 = clip01(remap(arena_length2, -arena_length2, 0.0, 1.1, ball_soon.pos.y)) close_to_ball01 = clip01(1.0 - norm(car.pos - ball_soon.pos) / 3500) ** 0.5 reachable_ball = predict.ball_predict(bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball)) self.ball_to_goal_right = bot.info.opp_goal.right_post - reachable_ball.pos self.ball_to_goal_left = bot.info.opp_goal.left_post - reachable_ball.pos self.aim_cone = AimCone(self.ball_to_goal_right, self.ball_to_goal_left) car_to_ball = reachable_ball.pos - bot.info.my_car.pos in_position = self.aim_cone.contains_direction(car_to_ball) # Chase ball right after kickoff. High right after kickoff kickoff_bias01 = max(0, 1 - bot.info.time_since_last_kickoff * 0.3) * float(bot.info.my_car.objective == Objective.UNKNOWN) obj_bonus = { Objective.UNKNOWN: 0, Objective.GO_FOR_IT: 0.2, Objective.FOLLOW_UP: 0, Objective.ROTATE_BACK_OR_DEF: -0.2, }[bot.info.my_car.objective] return clip01(close_to_ball01 * own_half_01 + 0.1 * in_position + self.temp_utility_desire_boost + kickoff_bias01) + obj_bonus
def exec(self, bot) -> SimpleControllerState: car = bot.info.my_car shoot_controls = bot.shoot.with_aiming( bot, self.aim_cone, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball)) hit_pos = bot.shoot.ball_when_hit.pos if bot.do_rendering: self.aim_cone.draw(bot, hit_pos, r=0, g=170, b=255) if bot.shoot.can_shoot: if bot.shoot.using_curve and bot.do_rendering: rendering.draw_bezier( bot, [car.pos, bot.shoot.curve_point, hit_pos]) return shoot_controls else: # go home-ish own_goal = lerp(bot.info.own_goal, bot.info.ball.pos, 0.5) return bot.drive.go_towards_point(bot, own_goal, target_vel=1460, slide=True, boost_min=0, can_keep_speed=True)
def update(self, bot): ball = bot.info.ball # Find closest foe to ball self.opp_closest_to_ball, self.opp_closest_to_ball_dist = argmin(bot.info.opponents, lambda opp: norm(opp.pos - ball.pos)) # Possession and on/off-site self.car_with_possession = None self.ally_with_possession = None self.opp_with_possession = None for car in bot.info.cars: # On site own_goal = bot.info.goals[car.team] ball_to_goal = own_goal.pos - ball.pos car_to_ball = ball.pos - car.pos car.onsite = dot(ball_to_goal, car_to_ball) < 0.1 # Reach ball time car.reach_ball_time = predict.time_till_reach_ball(car, ball) reach01 = clip01((5 - car.reach_ball_time) / 5) # Possession point_in_front = car.pos + car.vel * 0.6 ball_point_dist = norm(ball.pos - point_in_front) dist01 = 1500 / (1500 + ball_point_dist) # Halves every 1500 uu of dist car_to_ball = bot.info.ball.pos - car.pos car_to_ball_unit = normalize(car_to_ball) in_front01 = dot(car.forward, car_to_ball_unit) car.possession = dist01 * in_front01 * reach01 * 3 if self.car_with_possession is None or car.possession > self.car_with_possession.possession: self.car_with_possession = car if car.team == bot.team and (self.ally_with_possession is None or car.possession > self.ally_with_possession.possession): self.ally_with_possession = car if car.team != bot.team and (self.opp_with_possession is None or car.possession > self.opp_with_possession.possession): self.opp_with_possession = car # Objectives for car in bot.info.cars: car.last_objective = car.objective car.objective = Objective.UNKNOWN thirdman_index, _ = argmin(bot.info.team_cars, lambda ally: norm(ally.pos - bot.info.own_goal.pos)) attacker, attacker_score = argmax(bot.info.team_cars, lambda ally: ((0.09 if ally.last_objective == Objective.GO_FOR_IT else 0) + ally.boost / 490 - (0.21 if ally.index == thirdman_index else 0) - (0.4 if not ally.onsite else 0) + ally.possession * (10_000 - ally.team_sign * ally.pos.y) / 20_000)**2) attacker.objective = Objective.GO_FOR_IT follower_expected_pos = (ball.pos + bot.info.own_goal.pos) * 0.5 follower, follower_score = argmin([ally for ally in bot.info.team_cars if ally.objective == Objective.UNKNOWN], lambda ally: (-500 if ally.last_objective == Objective.FOLLOW_UP else 0) - ally.boost * 2 + (1100 if ally.index == thirdman_index else 0) + (200 if not ally.onsite else 0) + norm(ally.pos - follower_expected_pos)) follower.objective = Objective.FOLLOW_UP for car in bot.info.team_cars: if car.objective == Objective.UNKNOWN: car.objective = Objective.ROTATE_BACK_OR_DEF
def utility(self, bot) -> float: team_sign = bot.info.team_sign length = team_sign * Field.LENGTH / 2 ball_own_half_01 = clip01( remap(-length, length, -0.2, 1.2, bot.info.ball.pos.y)) reachable_ball = predict.ball_predict( bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball)) car_to_ball = reachable_ball.pos - bot.info.my_car.pos in_position = self.aim_cone.contains_direction(car_to_ball, math.pi / 8) return ball_own_half_01 * in_position
def utility(self, bot) -> float: ball_soon = predict.ball_predict(bot, 1) arena_length2 = bot.info.team_sign * Field.LENGTH / 2 own_half_01 = clip01( remap(arena_length2, -arena_length2, 0.0, 1.1, ball_soon.pos.y)) reachable_ball = predict.ball_predict( bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball)) self.ball_to_goal_right = bot.info.enemy_goal_right - reachable_ball.pos self.ball_to_goal_left = bot.info.enemy_goal_left - reachable_ball.pos self.aim_cone = AimCone(self.ball_to_goal_right, self.ball_to_goal_left) car_to_ball = reachable_ball.pos - bot.info.my_car.pos in_position = self.aim_cone.contains_direction(car_to_ball) return clip01(own_half_01 + 0.1 * in_position)
def utility_score(self, bot) -> float: team_sign = bot.info.team_sign length = team_sign * Field.LENGTH / 2 ball_own_half_01 = clip01( remap(-length, length, -0.2, 1.2, bot.info.ball.pos.y)) reachable_ball = predict.ball_predict( bot, predict.time_till_reach_ball(bot.info.my_car, bot.info.ball)) car_to_ball = reachable_ball.pos - bot.info.my_car.pos in_position = self.aim_cone.contains_direction(car_to_ball, math.pi / 8) obj_bonus = { Objective.UNKNOWN: 0, Objective.GO_FOR_IT: 0.15, Objective.FOLLOW_UP: 0, Objective.ROTATE_BACK_OR_DEF: 0.0, }[bot.info.my_car.objective] return ball_own_half_01 * in_position + obj_bonus
def exec(self, bot) -> SimpleControllerState: car = bot.info.my_car ball = bot.info.ball hits_goal_prediction = predict.will_ball_hit_goal(bot) reach_time = clip(predict.time_till_reach_ball(car, ball), 0, hits_goal_prediction.time - 0.5) reachable_ball = predict.ball_predict(bot, reach_time) self.ball_to_goal_right = self.own_goal_right - reachable_ball.pos self.ball_to_goal_left = self.own_goal_left - reachable_ball.pos self.aim_cone = AimCone(self.ball_to_goal_left, self.ball_to_goal_right) self.aim_cone.draw(bot, reachable_ball.pos, r=200, g=0, b=160) shoot_controls = bot.shoot.with_aiming(bot, self.aim_cone, reach_time) if not bot.shoot.can_shoot: # Go home return bot.drive.go_home(bot) else: return shoot_controls
def run(self, bot) -> SimpleControllerState: car = bot.info.my_car ball = bot.info.ball my_hit_time = predict.time_till_reach_ball(car, ball) shoot_controls = bot.shoot.with_aiming(bot, self.aim_cone, my_hit_time) hit_pos = bot.shoot.ball_when_hit.pos dist = norm(car.pos - hit_pos) closest_enemy, enemy_dist = bot.info.closest_enemy(0.5 * (hit_pos + ball.pos)) if not bot.shoot.can_shoot and is_closer_to_goal_than(car.pos, hit_pos, bot.info.team): # Can't shoot but or at least on the right side: Chase goal_to_ball = normalize(hit_pos - bot.info.opp_goal.pos) offset_ball = hit_pos + goal_to_ball * Ball.RADIUS * 0.9 enemy_hit_time = predict.time_till_reach_ball(closest_enemy, ball) enemy_hit_pos = predict.ball_predict(bot, enemy_hit_time).pos if enemy_hit_time < 1.5 * my_hit_time: self.temp_utility_desire_boost -= bot.info.dt if bot.do_rendering: bot.renderer.draw_line_3d(closest_enemy.pos, enemy_hit_pos, bot.renderer.red()) return bot.drive.home(bot) if bot.do_rendering: bot.renderer.draw_line_3d(car.pos, offset_ball, bot.renderer.yellow()) return bot.drive.towards_point(bot, offset_ball, target_vel=2200, slide=False, boost_min=0) elif len(bot.info.teammates) == 0 and not bot.shoot.aim_is_ok and hit_pos.y * -bot.info.team_sign > 4250 and abs(hit_pos.x) > 900 and not dist < 420: # hit_pos is an enemy corner and we are not close: Avoid enemy corners in 1s and just wait enemy_to_ball = normalize(hit_pos - closest_enemy.pos) wait_point = hit_pos + enemy_to_ball * enemy_dist # a point 50% closer to the center of the field wait_point = lerp(wait_point, ball.pos + Vec3(0, bot.info.team_sign * 3000, 0), 0.5) if bot.do_rendering: bot.renderer.draw_line_3d(car.pos, wait_point, bot.renderer.yellow()) return bot.drive.towards_point(bot, wait_point, norm(car.pos - wait_point), slide=False, can_keep_speed=True, can_dodge=False) elif bot.shoot.can_shoot: # Shoot ! if bot.do_rendering: self.aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, r=0, b=0) if bot.shoot.using_curve: rendering.draw_bezier(bot, [car.pos, bot.shoot.curve_point, hit_pos]) return shoot_controls else: # We can't shoot at goal reliably # How about a shot to the corners then? corners = [ Vec3(-Field.WIDTH2, -bot.info.team_sign * Field.LENGTH2, 0), Vec3(Field.WIDTH2, -bot.info.team_sign * Field.LENGTH2, 0), ] for corner in corners: ctrls = bot.shoot.towards(bot, corner, bot.info.my_car.reach_ball_time) if bot.shoot.can_shoot: self.aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, b=0) if bot.shoot.using_curve: rendering.draw_bezier(bot, [car.pos, bot.shoot.curve_point, hit_pos]) return ctrls enemy_to_ball = normalize(xy(ball.pos - closest_enemy.pos)) ball_to_my_goal = normalize(xy(bot.info.own_goal.pos - ball.pos)) dot_threat = dot(enemy_to_ball, ball_to_my_goal) # 1 = enemy is in position, -1 = enemy is NOT in position if car.boost <= 10 and ball.pos.y * bot.info.team_sign < 0 and dot_threat < 0.15: collect_center = ball.pos.y * bot.info.team_sign <= 0 collect_small = closest_enemy.pos.y * bot.info.team_sign <= 0 or enemy_dist < 900 pads = filter_pads(bot, bot.info.big_boost_pads, big_only=not collect_small, enemy_side=False, center=collect_center) bot.maneuver = CollectClosestBoostManeuver(bot, pads) # return home-ish return bot.drive.stay_at(bot, lerp(bot.info.own_goal.pos, ball.pos, 0.2), ball.pos)
def exec(self, bot) -> SimpleControllerState: car = bot.info.my_car ball = bot.info.ball shoot_controls = bot.shoot.with_aiming( bot, self.aim_cone, predict.time_till_reach_ball(car, ball)) if bot.do_rendering: self.aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, b=0) hit_pos = bot.shoot.ball_when_hit.pos dist = norm(car.pos - hit_pos) closest_enemy, enemy_dist = bot.info.closest_enemy( 0.5 * (hit_pos + ball.pos)) if not bot.shoot.can_shoot and is_closer_to_goal_than( car.pos, hit_pos, bot.info.team): # Can't shoot but or at least on the right side: Chase goal_to_ball = normalize(hit_pos - bot.info.enemy_goal) offset_ball = hit_pos + goal_to_ball * Ball.RADIUS * 0.9 if bot.do_rendering: bot.renderer.draw_line_3d(car.pos, offset_ball, bot.renderer.yellow()) return bot.drive.go_towards_point(bot, offset_ball, target_vel=2200, slide=False, boost_min=0) elif not bot.shoot.aim_is_ok and hit_pos.y * -bot.info.team_sign > 4350 and abs( hit_pos.x) > 900 and not dist < 450: # hit_pos is an enemy corner and we are not close: Avoid enemy corners and just wait enemy_to_ball = normalize(hit_pos - closest_enemy.pos) wait_point = hit_pos + enemy_to_ball * enemy_dist # a point 50% closer to the center of the field wait_point = lerp(wait_point, ball.pos + Vec3(0, bot.info.team_sign * 3000, 0), 0.5) if bot.do_rendering: bot.renderer.draw_line_3d(car.pos, wait_point, bot.renderer.yellow()) return bot.drive.go_towards_point(bot, wait_point, norm(car.pos - wait_point), slide=False, can_keep_speed=True, can_dodge=False) elif not bot.shoot.can_shoot: if car.boost == 0: collect_center = ball.pos.y * bot.info.team_sign <= 0 collect_small = closest_enemy.pos.y * bot.info.team_sign <= 0 pads = filter_pads(bot, bot.info.big_boost_pads, big_only=not collect_small, enemy_side=False, center=collect_center) bot.maneuver = CollectClosestBoostManeuver(bot, pads) # return home return bot.drive.go_home(bot) else: # Shoot ! if bot.shoot.using_curve and bot.do_rendering: rendering.draw_bezier( bot, [car.pos, bot.shoot.curve_point, hit_pos]) return shoot_controls