def exec(self, bot): goal_to_ball = bot.info.ball.pos - bot.info.own_goal.pos goal_to_car = bot.info.my_car.pos - bot.info.own_goal.pos car_prj = proj_onto(goal_to_car, goal_to_ball) target = lerp(bot.info.own_goal.pos + car_prj, lerp(bot.info.ball.pos, bot.info.opp_goal.pos, 0.4), 0.08) if bot.do_rendering: bot.renderer.draw_line_3d(bot.info.my_car.pos, target, bot.renderer.purple()) speed = max( (norm(bot.info.my_car.pos - bot.info.ball.pos) - 900) * 0.6, 100) return bot.drive.towards_point( bot, target, target_vel=speed, slide=True, boost_min=0, can_keep_speed=norm(bot.info.my_car.pos - bot.info.ball.pos) > 3000, can_dodge=True, wall_offset_allowed=125)
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 utility_score(self, bot) -> float: car = bot.info.my_car ball = bot.info.ball car_to_ball = car.pos - ball.pos bouncing_b = ball.pos.z > 130 or abs(ball.vel.z) > 300 if not bouncing_b: return 0 dist_01 = clip01(1 - norm(car_to_ball) / 3000) head_dir = lerp(Vec3(0, 0, 1), car.forward, 0.1) ang = angle_between(head_dir, car_to_ball) ang_01 = clip01(1 - ang / (math.pi / 2)) obj_bonus = { Objective.UNKNOWN: 0, Objective.GO_FOR_IT: 0.2, Objective.FOLLOW_UP: 0, Objective.ROTATE_BACK_OR_DEF: 0, }[car.objective] return clip01(0.6 * ang_01 + 0.4 * dist_01 # - 0.3 * bot.analyzer.team_mate_has_ball_01 + self.is_dribbling * self.extra_utility_bias + obj_bonus)
def time_till_reach_ball(car, ball): """ Rough estimate about when we can reach the ball in 2d. """ car_to_ball = xy(ball.pos - car.pos) dist = norm(car_to_ball) - Ball.RADIUS / 2 vel_c_f = proj_onto_size(car.vel, car_to_ball) vel_b_f = proj_onto_size(ball.vel, car_to_ball) vel_c_amp = lerp(vel_c_f, norm(car.vel), 0.58) vel_f = vel_c_amp - vel_b_f dist_long_01 = clip01(dist / 10_000.0) time_normal = dist / max(220, vel_f) time_long = dist / max(norm(car.vel), 1410) time = lerp(time_normal, time_long, dist_long_01) arrive_time = time * 0.95 # Combine slightly with old prediction to negative rapid changes result = lerp(arrive_time, car.last_expected_time_till_reach_ball, 0.22) car.last_expected_time_till_reach_ball = arrive_time return result
def approach_defensively(self, bot) -> SimpleControllerState: car = bot.data.my_car ball = bot.data.ball goal = Vec3(y=5400 * bot.data.team_sign) self.target = lerp(ball.pos, goal, 0.8) self.target_vel = norm(self.target - car.pos) return super().exec(bot)
def run(self, bot) -> SimpleControllerState: car = bot.info.my_car ball = bot.info.ball half_way = lerp(bot.info.own_goal.pos, ball.pos, 0.5) dist_ball = norm(car.pos - ball.pos) return bot.drive.towards_point( bot, half_way, target_vel=dist_ball * 0.3, slide=dist_ball > 1500, can_dodge=False )
def utility_score(self, bot) -> float: car = bot.info.my_car ball = bot.info.ball half_way = lerp(bot.info.own_goal.pos, ball.pos, 0.5) _, missing_center_guy01 = argmin(bot.info.team_cars, lambda mate: 1.0 - clip01(norm(mate.pos - half_way) / Field.LENGTH2)) attack_in_front = any(is_closer_to_goal_than(car.pos, mate.pos, car.team) for mate in bot.info.teammates if mate.objective == Objective.GO_FOR_IT) ball_in_front = is_closer_to_goal_than(car.pos, ball.pos, car.team) obj_bonus = { Objective.UNKNOWN: 0, Objective.GO_FOR_IT: 0, Objective.FOLLOW_UP: 0.23, Objective.ROTATE_BACK_OR_DEF: 0, }[car.objective] return attack_in_front * ball_in_front * missing_center_guy01 + obj_bonus
def utility(self, bot) -> float: car = bot.info.my_car ball = bot.info.ball car_to_ball = car.pos - ball.pos bouncing_b = ball.pos.z > 130 or abs(ball.vel.z) > 300 if not bouncing_b: return 0 dist_01 = clip01(1 - norm(car_to_ball) / 3000) head_dir = lerp(Vec3(0, 0, 1), car.forward, 0.1) ang = angle_between(head_dir, car_to_ball) ang_01 = clip01(1 - ang / (math.pi / 2)) return clip01(0.6 * ang_01 + 0.4 * dist_01 # - 0.3 * bot.analyzer.team_mate_has_ball_01 + self.is_dribbling * self.extra_utility_bias)
def towards_point(self, bot, point: Vec3, target_vel=1430, slide=False, boost_min=101, can_keep_speed=True, can_dodge=True, wall_offset_allowed=125) -> SimpleControllerState: REQUIRED_ANG_FOR_SLIDE = 1.65 REQUIRED_VELF_FOR_DODGE = 1100 car = bot.info.my_car # Dodge is done if self.dodge is not None and self.dodge.done: self.dodge = None self.last_dodge_end_time = bot.info.time # Continue dodge elif self.dodge is not None: self.dodge.target = point return self.dodge.exec(bot) # Begin recovery if not car.on_ground: bot.maneuver = RecoveryManeuver(bot) return self.controls # Get down from wall by choosing a point close to ground if not is_near_wall(point, wall_offset_allowed) and angle_between( car.up, Vec3(0, 0, 1)) > math.pi * 0.31: point = lerp(xy(car.pos), xy(point), 0.5) # If the car is in a goal, avoid goal posts self._avoid_goal_post(bot, point) car_to_point = point - car.pos # The vector from the car to the point in local coordinates: # point_local.x: how far in front of my car # point_local.y: how far to the left of my car # point_local.z: how far above my car point_local = dot(point - car.pos, car.rot) # Angle to point in local xy plane and other stuff angle = math.atan2(point_local.y, point_local.x) dist = norm(point_local) vel_f = proj_onto_size(car.vel, car.forward) vel_towards_point = proj_onto_size(car.vel, car_to_point) # Start dodge if can_dodge and abs(angle) <= 0.02 and vel_towards_point > REQUIRED_VELF_FOR_DODGE\ and dist > vel_towards_point + 500 + 900 and bot.info.time > self.last_dodge_end_time + self.dodge_cooldown: self.dodge = DodgeManeuver(bot, point) # Start half-flip elif can_dodge and abs(angle) >= 3 and vel_towards_point < 50\ and dist > -vel_towards_point + 500 + 900 and bot.info.time > self.last_dodge_end_time + self.dodge_cooldown: self.dodge = HalfFlipManeuver(bot, boost=car.boost > boost_min + 10) # Is point right behind? Maybe reverse instead if -100 < point_local.x < 0 and abs(point_local.y) < 50: #bot.print("Reversing?") pass # Is in turn radius deadzone? tr = turn_radius(abs(vel_f + 50)) # small bias tr_side = sign(angle) tr_center_local = Vec3(0, tr * tr_side, 10) point_is_in_turn_radius_deadzone = norm(point_local - tr_center_local) < tr # Draw turn radius deadzone if car.on_ground and bot.do_rendering: tr_center_world = car.pos + dot(car.rot, tr_center_local) tr_center_world_2 = car.pos + dot(car.rot, -1 * tr_center_local) rendering.draw_circle(bot, tr_center_world, car.up, tr, 22) rendering.draw_circle(bot, tr_center_world_2, car.up, tr, 22) if point_is_in_turn_radius_deadzone: # Hard turn self.controls.steer = sign(angle) self.controls.boost = False self.controls.throttle = 0 if vel_f > 150 else 0.1 if point_local.x < 110 and point_local.y < 400 and norm( car.vel) < 300: # Brake or go backwards when the point is really close but not in front of us self.controls.throttle = clip(-0.25 + point_local.x / -110.0, 0, -1) self.controls.steer = -0.5 * sign(angle) else: # Should drop speed or just keep up the speed? if can_keep_speed and target_vel < vel_towards_point: target_vel = vel_towards_point else: # Small lerp adjustment target_vel = lerp(vel_towards_point, target_vel, 1.1) # Turn and maybe slide self.controls.steer = clip(angle + (2.5 * angle)**3, -1.0, 1.0) if slide and abs(angle) > REQUIRED_ANG_FOR_SLIDE: self.controls.handbrake = True self.controls.steer = sign(angle) else: self.controls.handbrake = False # Overshoot target vel for quick adjustment target_vel = lerp(vel_towards_point, target_vel, 1.2) # Find appropriate throttle/boost if vel_towards_point < target_vel: self.controls.throttle = 1 if boost_min < car.boost and vel_towards_point + 80 < target_vel and target_vel > 1400 \ and not self.controls.handbrake and is_heading_towards(angle, dist): self.controls.boost = True else: self.controls.boost = False else: vel_delta = target_vel - vel_towards_point self.controls.throttle = clip(0.2 + vel_delta / 500, 0, -1) self.controls.boost = False if self.controls.handbrake: self.controls.throttle = min(0.4, self.controls.throttle) # Saved if something outside calls start_dodge() in the meantime self.last_point = point return self.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): pred_ball = predict.ball_predict(bot, bot.info.my_car.reach_ball_time) # On a scale from 0 to 1, how much is this a clear? clear01 = clip01( norm(bot.info.opp_goal.pos - pred_ball.pos) / Field.LENGTH)**2 ts = bot.info.team_sign right = lerp(bot.info.opp_goal.right_post, Vec3(ts * Field.WIDTH2, ts * (Field.LENGTH2 + 300), 0), clear01) left = lerp(bot.info.opp_goal.left_post, Vec3(-ts * Field.WIDTH2, ts * (Field.LENGTH2 + 300), 0), clear01) ball_to_right = right - pred_ball.pos ball_to_left = left - pred_ball.pos aim_cone = AimCone(ball_to_right, ball_to_left) shot_ctrls = bot.shoot.with_aiming(bot, aim_cone, bot.info.my_car.reach_ball_time) if bot.do_rendering: if bot.shoot.can_shoot: aim_cone.draw(bot, bot.shoot.ball_when_hit.pos, b=0, r=0) if not bot.shoot.can_shoot: # We can't shoot on target if len(bot.info.teammates) != 0: # Consider passing for mate in bot.info.teammates: point_in_front_of_mate = lerp(mate.pos, bot.info.opp_goal.pos, 0.5) shot_ctrls = bot.shoot.towards( bot, point_in_front_of_mate, bot.info.my_car.reach_ball_time) if bot.shoot.can_shoot: if bot.do_rendering: rendering.draw_cross(bot, point_in_front_of_mate, bot.renderer.green()) return shot_ctrls # Atba with bias I guess if bot.do_rendering: bot.renderer.draw_line_3d(bot.info.my_car.pos, pred_ball.pos, bot.renderer.red()) return bot.shoot.any_touch(bot, bot.info.my_car.reach_ball_time) # # We are out of position, start rotating back # own_goal = lerp(bot.info.own_goal.pos, bot.info.ball.pos, 0.5) # return bot.drive.towards_point( # bot, # own_goal, # target_vel=1460, # slide=False, # boost_min=0, # can_keep_speed=True # ) else: # Shoot! if bot.shoot.using_curve and bot.do_rendering: rendering.draw_bezier(bot, [ bot.info.my_car.pos, bot.shoot.curve_point, bot.shoot.ball_when_hit.pos ]) return shot_ctrls
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