def utility_score(self, bot) -> float: car = bot.info.my_car ball = bot.info.ball my_hit_time = predict.time_till_reach_ball(car, ball) ball_soon = predict.ball_predict(bot, min(my_hit_time, 1.0)) close_to_ball_01 = clip01(1.0 - norm(car.pos - ball_soon.pos) / 3500) ** 0.5 # FIXME Not great reachable_ball = predict.ball_predict(bot, predict.time_till_reach_ball(bot.info.my_car, ball)) xy_ball_to_goal = xy(bot.info.opp_goal.pos - reachable_ball.pos) xy_car_to_ball = xy(reachable_ball.pos - bot.info.my_car.pos) in_position_01 = ease_out(clip01(dot(xy_ball_to_goal, xy_car_to_ball)), 0.5) # 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: 1, Objective.GO_FOR_IT: 1, Objective.FOLLOW_UP: 0, Objective.ROTATING: 0, Objective.SOLO: 1, }[bot.info.my_car.objective] return clip01(close_to_ball_01 * in_position_01 + kickoff_bias01) * obj_bonus
def utility(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) 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) # Chase ball right after kickoff. High right after kickoff kickoff_bias01 = max(0, 1 - bot.info.time_since_last_kickoff * 0.3) return clip01(own_half_01 + 0.1 * in_position + self.temp_utility_desire_boost + kickoff_bias01)
def utility_score(self, bot) -> float: car = bot.info.my_car if len(bot.info.teammates) == 0: team_committed01 = 0 no_defence01 = 1 else: mates = bot.info.teammates sum_pos = mates[0].pos + mates[0].vel * 0.5 for mate in mates[1:]: sum_pos += mate.pos + mate.vel * 0.5 avg_pos = sum_pos / len(mates) team_committed01 = clip01( norm(avg_pos - bot.info.own_goal.pos) / Field.LENGTH2) no_defence01 = clip01( argmin(mates, lambda mate: norm(mate.pos - bot.info.own_goal.pos))[1] / 1000) dist_to_ball01 = clip01( norm(car.pos - bot.info.ball.pos) / Field.LENGTH2) obj_bonus = { Objective.UNKNOWN: 1.0, Objective.GO_FOR_IT: 0, Objective.FOLLOW_UP: 0, Objective.ROTATING: 1.0, Objective.SOLO: 1.0, }[car.objective] return 0.85 * team_committed01 * dist_to_ball01 * no_defence01 * obj_bonus
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.13) ang = angle_between(head_dir, car_to_ball) ang_01 = clip01(1 - ang / (math.pi / 2)) xy_speed_delta_01 = lin_fall(norm(xy(car.vel - ball.vel)), 800) obj_bonus = { Objective.UNKNOWN: 0.8, Objective.GO_FOR_IT: 1.0, Objective.FOLLOW_UP: 0, Objective.ROTATING: 0, Objective.SOLO: 1.0, }[car.objective] return obj_bonus * clip01(xy_speed_delta_01 * ang_01 * dist_01 + self.is_dribbling * self.extra_utility_bias)
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 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 is_viable(self, car, current_time: float): up = car.up T = self.intercept_time - current_time xf = car.pos + car.vel * T + 0.5 * GRAVITY * T ** 2 vf = car.vel + GRAVITY * T if self.jumping: if self.jump_begin_time == -1: jump_elapsed = 0 else: jump_elapsed = current_time - self.jump_begin_time # How much longer we can press jump and still gain upward force tau = JUMP_MAX_DUR - jump_elapsed # Add jump pulse if jump_elapsed == 0: vf += up * JUMP_SPEED xf += up * JUMP_SPEED * T # Acceleration from holding jump vf += up * JUMP_ACCEL * tau xf += up * JUMP_ACCEL * tau * (T - 0.5 * tau) if self.do_second_jump: # Impulse from the second jump vf += up * JUMP_SPEED xf += up * JUMP_SPEED * (T - tau) delta_x = self.hit_pos - xf dir = normalize(delta_x) phi = angle_between(dir, car.forward) turn_time = 0.7 * (2 * math.sqrt(phi / 9)) tau1 = turn_time * clip(1 - 0.3 / phi, 0.02, 1) required_acc = (2 * norm(delta_x)) / ((T - tau1) ** 2) ratio = required_acc / BOOST_ACCEL tau2 = T - (T - tau1) * math.sqrt(1 - clip01(ratio)) velocity_estimate = vf + BOOST_ACCEL * (tau2 - tau1) * dir boost_estimate = (tau2 - tau1) * BOOST_PR_SEC enough_boost = boost_estimate < 0.95 * car.boost enough_time = abs(ratio) < 0.9 return norm(velocity_estimate) < 0.9 * MAX_SPEED and enough_boost and enough_time
def utility_score(self, bot) -> float: team_sign = bot.info.team_sign length = team_sign * Field.LENGTH2 ball_own_half_01 = clip01(remap(-length, length, -0.8, 1.8, 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: 1, Objective.GO_FOR_IT: 1, Objective.FOLLOW_UP: 0, Objective.ROTATING: 0, Objective.SOLO: 1.0, }[bot.info.my_car.objective] return ball_own_half_01 * in_position * obj_bonus
def utility_score(self, bot) -> float: car = bot.info.my_car ball = bot.info.ball follow_up_pos = bot.analyzer.ideal_follow_up_pos _, missing_follow_up_guy01 = argmin( bot.info.team_cars, lambda mate: 1.0 - clip01( norm(mate.pos - follow_up_pos) / 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.5, Objective.GO_FOR_IT: 0, Objective.FOLLOW_UP: 1, Objective.ROTATING: 0, Objective.SOLO: 0.9, }[car.objective] return attack_in_front * ball_in_front * missing_follow_up_guy01 * bot.info.my_car.onsite * obj_bonus
def exec(self, bot): if not self.announced_in_quick_chat: self.announced_in_quick_chat = True bot.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Information_IGotIt) ct = bot.info.time car = bot.info.my_car up = car.up controls = SimpleControllerState() # Time remaining till intercept time T = self.intercept_time - bot.info.time # Expected future position xf = car.pos + car.vel * T + 0.5 * GRAVITY * T ** 2 # Expected future velocity vf = car.vel + GRAVITY * T # Is set to false while jumping to avoid FeelsBackFlipMan rotate = True if self.jumping: if self.jump_begin_time == -1: jump_elapsed = 0 self.jump_begin_time = ct else: jump_elapsed = ct - self.jump_begin_time # How much longer we can press jump and still gain upward force tau = JUMP_MAX_DUR - jump_elapsed # Add jump pulse if jump_elapsed == 0: vf += up * JUMP_SPEED xf += up * JUMP_SPEED * T rotate = False # Acceleration from holding jump vf += up * JUMP_SPEED * tau xf += up * JUMP_SPEED * tau * (T - 0.5 * tau) if self.do_second_jump: # Impulse from the second jump vf += up * JUMP_SPEED xf += up * JUMP_SPEED * (T - tau) if jump_elapsed < JUMP_MAX_DUR: controls.jump = True else: controls.jump = False if self.do_second_jump: if self.jump_pause_counter < 4: # Do a 4-tick pause between jumps self.jump_pause_counter += 1 else: # Time to start second jump # we do this by resetting our jump counter and pretend and our aerial started in the air self.jump_begin_time = -1 self.jumping = True self.do_second_jump = False else: # We are done jumping self.jumping = False else: controls.jump = False delta_pos = self.hit_pos - xf direction = normalize(delta_pos) car_to_hit_pos = self.hit_pos - car.pos dodging = self.dodge_begin_time != -1 if dodging: controls.jump = True # We are not pressing jump, so let's align the car if rotate and not dodging: if self.do_dodge and norm(car_to_hit_pos) < Ball.RADIUS + 80: # Start dodge self.dodge_begin_time = ct hit_local = dot(car_to_hit_pos, car.rot) hit_local.z = 0 dodge_direction = normalize(hit_local) controls.roll = 0 controls.pitch = -dodge_direction.x controls.yaw = sign(car.rot.get(2, 2)) * direction.y controls.jump = True else: # Adjust orientation if norm(delta_pos) > 50: pd = bot.fly.align(bot, looking_in_dir(delta_pos)) else: if self.target_rot is not None: pd = bot.fly.align(bot, self.target_rot) else: pd = bot.fly.align(bot, looking_in_dir(self.hit_pos - car.pos)) controls.roll = pd.roll controls.pitch = pd.pitch controls.yaw = pd.yaw if not dodging and angle_between(car.forward, direction) < 0.3: if norm(delta_pos) > 40: controls.boost = 1 controls.throttle = 0 else: controls.boost = 0 controls.throttle = clip01(0.5 * THROTTLE_AIR_ACCEL * T ** 2) else: controls.boost = 0 controls.throttle = 0 prediction = predict.ball_predict(bot, T) self.done = T < 0 if norm(self.hit_pos - prediction.pos) > 50: # Jump shot failed self.done = True bot.send_quick_chat(QuickChats.CHAT_EVERYONE, QuickChats.Apologies_Cursing) if bot.do_rendering: car_to_hit_dir = normalize(self.hit_pos - car.pos) color = bot.renderer.pink() rendering.draw_cross(bot, self.hit_pos, color, arm_length=100) rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.25), car_to_hit_dir, 40, 12, color) rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.5), car_to_hit_dir, 40, 12, color) rendering.draw_circle(bot, lerp(car.pos, self.hit_pos, 0.75), car_to_hit_dir, 40, 12, color) bot.renderer.draw_line_3d(car.pos, self.hit_pos, color) return controls
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.shoot.can_shoot: aim_cone.draw(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: draw.cross(point_in_front_of_mate, draw.green()) return shot_ctrls # Atba with bias I guess draw.line(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: draw.bezier([ bot.info.my_car.pos, bot.shoot.curve_point, bot.shoot.ball_when_hit.pos ]) return shot_ctrls
def lin_fall(x, max): """f(0)=1. Linear fall off. Hits 0 at max.""" return clip01((max - x) / x)