def utility(self, bot): 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(self, bot): 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 execute(self, bot): 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 bot.controls = bot.drive.go_home(bot) else: bot.controls = shoot_controls
def with_aiming(self, bot, aim_cone: AimCone, time: float, dodge_hit: bool = True): # aim: | | | | # ball | bad | ok | good | # z pos: | | | | # -----------+-----------+-----------+-----------+ # too high | give | give | wait/ | # | up | up | improve | # -----------+ - - - - - + - - - - - + - - - - - + # medium | give | improve | aerial | # | up | aim | | # -----------+ - - - - - + - - - - - + - - - - - + # soon on | improve | slow | small | # ground | aim | curve | jump | # -----------+ - - - - - + - - - - - + - - - - - + # on ground | improve | fast | fast | # | aim?? | curve | straight | # -----------+ - - - - - + - - - - - + - - - - - + # FIXME if the ball is not on the ground we treat it as 'soon on ground' in all other cases self.controls = SimpleControllerState() self.aim_is_ok = False self.waits_for_fall = False self.ball_is_flying = False self.can_shoot = False self.using_curve = False self.curve_point = None self.ball_when_hit = None car = bot.info.my_car ball_soon = ball_predict(bot, time) car_to_ball_soon = ball_soon.pos - car.pos if ball_soon.pos[Z] < 110 or ( ball_soon.pos[Z] < 475 and ball_soon.vel[Z] <= 0) or True: #FIXME Always true # The ball is on the ground or soon on the ground if 275 < ball_soon.pos[Z] < 475 and aim_cone.contains_direction( car_to_ball_soon): # Can we hit it if we make a small jump? vel_f = proj_onto_size(car.vel, xy(car_to_ball_soon)) car_expected_pos = car.pos + car.vel * time ball_soon_flat = xy(ball_soon.pos) diff = norm(car_expected_pos - ball_soon_flat) if bot.do_rendering: bot.renderer.draw_line_3d(car.pos, car_expected_pos, bot.renderer.lime()) bot.renderer.draw_rect_3d(car_expected_pos, 12, 12, True, bot.renderer.lime()) if vel_f > 400: if diff < 150: bot.plan = SmallJumpPlan(lambda b: b.info.ball.pos) if 110 < ball_soon.pos[Z]: # and ball_soon.vel[Z] <= 0: # The ball is slightly in the air, lets wait just a bit more self.waits_for_fall = True ball_landing = next_ball_landing(bot, ball_soon, size=100) time = time + ball_landing.time ball_soon = ball_predict(bot, time) car_to_ball_soon = ball_soon.pos - car.pos self.ball_when_hit = ball_soon # The ball is on the ground, are we in position for a shot? if aim_cone.contains_direction(car_to_ball_soon): # Straight shot self.aim_is_ok = True self.can_shoot = True if norm(car_to_ball_soon ) < 240 + BALL_RADIUS and aim_cone.contains_direction( car_to_ball_soon): bot.drive.start_dodge() offset_point = xy( ball_soon.pos) - 50 * aim_cone.get_center_dir() speed = self.determine_speed(norm(car_to_ball_soon), time) self.controls = bot.drive.go_towards_point( bot, offset_point, target_vel=speed, slide=True, boost=True, can_keep_speed=False) return self.controls elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 5): # Curve shot self.aim_is_ok = True self.using_curve = True self.can_shoot = True offset_point = xy( ball_soon.pos) - 50 * aim_cone.get_center_dir() closest_dir = aim_cone.get_closest_dir_in_cone( car_to_ball_soon) self.curve_point = curve_from_arrival_dir( car.pos, offset_point, closest_dir) self.curve_point[X] = clip(self.curve_point[X], -FIELD_WIDTH / 2, FIELD_WIDTH / 2) self.curve_point[Y] = clip(self.curve_point[Y], -FIELD_LENGTH / 2, FIELD_LENGTH / 2) if dodge_hit and norm(car_to_ball_soon ) < 240 + BALL_RADIUS and angle_between( car.forward(), car_to_ball_soon ) < 0.5 and aim_cone.contains_direction( car_to_ball_soon): bot.drive.start_dodge() speed = self.determine_speed(norm(car_to_ball_soon), time) self.controls = bot.drive.go_towards_point( bot, self.curve_point, target_vel=speed, slide=True, boost=True, can_keep_speed=False) return self.controls else: # We are NOT in position! self.aim_is_ok = False pass else: if aim_cone.contains_direction(car_to_ball_soon): self.waits_for_fall = True self.aim_is_ok = True #self.can_shoot = False pass # Allow small aerial (wait if ball is too high) elif aim_cone.contains_direction(car_to_ball_soon, math.pi / 4): self.ball_is_flying = True pass # Aim is ok, but ball is in the air