def execute_dribbling(self): # Grab best pass self.pass_target, self.pass_score = evaluation.passing_positioning.eval_best_receive_point( main.ball().pos, main.our_robots(), AdaptiveFormation.FIELD_POS_WEIGHTS, AdaptiveFormation.NELDER_MEAD_ARGS, AdaptiveFormation.PASSING_WEIGHTS) # Grab shot chance self.shot_chance = evaluation.shooting.eval_shot(main.ball().pos) # Recalculate dribbler pos self.check_dribbling_timer += 1 if (self.check_dribbling_timer > self.check_dribbling_timer_cutoff): self.check_dribbling_timer = 0 self.dribbler.pos, _ = evaluation.passing_positioning.eval_best_receive_point( main.ball().pos, main.our_robots(), AdaptiveFormation.FIELD_POS_WEIGHTS, AdaptiveFormation.NELDER_MEAD_ARGS, AdaptiveFormation.DRIBBLING_WEIGHTS) # TODO: Get list of top X pass positions and have robots in good positions to reach them # Good positions can be definied by offensive / defensive costs # Offensive positions move onto the ball in the direction of the goal # Defensive cover the center of the field # Setup previous values (Basic complementary filter) c = .8 self.prev_shot_chance = c * self.shot_chance + \ (1 - c) * self.prev_shot_chance self.prev_pass_score = c * self.pass_score + \ (1 - c) * self.prev_pass_score
def on_enter_shoot(self): self.remove_all_subbehaviors() #Depending on shot and pass chances, #the striker will shoot #or #the striker will pass to the distractor and the distractor will shoot pass_striker_to_distractor_chance = evaluation.passing.eval_pass( self.striker_point, self.Distraction_recieve_pass_point, main.our_robots()) shot_of_striker_chance = evaluation.shooting.eval_shot( self.striker_point, main.our_robots()) shot_of_distractor_chance = evaluation.shooting.eval_shot( self.Distraction_recieve_pass_point, main.our_robots()) if pass_striker_to_distractor_chance * shot_of_distractor_chance > shot_of_striker_chance: dont_shoot = True self.add_subbehavior( skills.move.Move(self.Distraction_recieve_pass_point), 'make first distractor stay again', required=True) self.add_subbehavior( skills.move.Move(self.Distraction_point), 'make distracor stay', required=False, priority=10) self.add_subbehavior( skills.pivot_kick.PivotKick(), 'shooting', required=True)
def __init__(self): super().__init__(continuous=True) self.add_transition(behavior.Behavior.State.start, behavior.Behavior.State.running, lambda: True, 'immediately') # Add a center blocker self.add_subbehavior( tactics.stopped.circle_on_center.CircleOnCenter( # TODO find a way to do this without hard coding 3 # defense/goalie robots (or make those constants) min_robots=1 if (main.our_robots() is not None) and len( main.our_robots()) > 3 else 0), 'circle_up', priority=15, required=True) # Add two marker robots (with lower than defense priority) mark_one = skills.mark.Mark() self.add_subbehavior(mark_one, 'mark_one', priority=planning_priority.PIVOT_KICK + 1, required=False) mark_two = skills.mark.Mark() self.add_subbehavior(mark_two, 'mark_two', priority=planning_priority.PIVOT_KICK, required=False)
def on_enter_strategizing(self): #pick a robot to talk to target_bot = random.randint(0, ((len(main.our_robots()) - 1) if (main.our_robots() is not None) else 0)) self.subbehavior_with_name('coach').pos = ( main.our_robots()[target_bot].pos + robocup.Point( -constants.Robot.Radius * 2, constants.Robot.Radius * 2)) self.subbehavior_with_name( 'coach').threshold = constants.Robot.Radius * 2 print("\n\n Alright Number " + str(target_bot) + " here is the plan:")
def can_collect_ball_before_opponent(our_robots_to_check=None, their_robots_to_check=None, our_robots_to_dodge=None, their_robots_to_dodge=None, valid_error_percent=0.05): if our_robots_to_check is None: our_robots_to_check = main.our_robots() if their_robots_to_check is None: their_robots_to_check = main.their_robots() if our_robots_to_dodge is None: our_robots_to_dodge = main.our_robots() if their_robots_to_dodge is None: their_robots_to_dodge = main.their_robots() shortest_opp_time = float("inf") shortest_our_time = float("inf") dodge_dist = constants.Robot.Radius closest_robot = None # TODO: Do some sort of prediction as the ball moves target_pos = main.ball().pos # TODO: Take velocity and acceleration into account # Find closest opponent robot for bot in their_robots_to_check: dist = estimate_path_length(bot.pos, target_pos, our_robots_to_dodge, dodge_dist) target_dir = (target_pos - bot.pos).normalized() time = robocup.get_trapezoidal_time( dist, dist, 2.2, 1, target_dir.dot(bot.vel) / target_dir.mag(), 0) if (time < shortest_opp_time): shortest_opp_time = time # Find closest robot on our team for bot in our_robots_to_check: dist = estimate_path_length(bot.pos, target_pos, their_robots_to_dodge, dodge_dist) target_dir = (target_pos - bot.pos).normalized() time = robocup.get_trapezoidal_time( dist, dist, 2.2, 1, target_dir.dot(bot.vel) / target_dir.mag(), 0) if (time < shortest_our_time): shortest_our_time = time closest_robot = bot # Greater than 1 when we are further away print(shortest_our_time) print(shortest_opp_time) return shortest_our_time < shortest_opp_time * ( 1 + valid_error_percent), closest_robot
def on_exit_restart_play_began(self): for bot in main.our_robots(): if self._touching_ball(bot): self.kicker_shell_id = bot.shell_id() return if main.ball().valid: # pick our closest robot ball_pos = self.pre_ball_pos if not ball_pos: ball_pos = main.ball().pos bot = min(main.our_robots(), key=lambda bot: bot.pos.dist_to(ball_pos)) self.kicker_shell_id = bot.shell_id()
def can_collect_ball_before_opponent(our_robots_to_check=None, their_robots_to_check=None, our_robots_to_dodge=None, their_robots_to_dodge=None, valid_error_percent=0.05): if our_robots_to_check is None: our_robots_to_check = main.our_robots() if their_robots_to_check is None: their_robots_to_check = main.their_robots() if our_robots_to_dodge is None: our_robots_to_dodge = main.our_robots() if their_robots_to_dodge is None: their_robots_to_dodge = main.their_robots() shortest_opp_time = float("inf") shortest_our_time = float("inf") dodge_dist = constants.Robot.Radius closest_robot = None # TODO: Do some sort of prediction as the ball moves target_pos = main.ball().pos # TODO: Take velocity and acceleration into account # Find closest opponent robot for bot in their_robots_to_check: dist = estimate_path_length(bot.pos, target_pos, our_robots_to_dodge, dodge_dist) target_dir = (target_pos - bot.pos).normalized() time = robocup.get_trapezoidal_time(dist, dist, 2.2, 1, target_dir.dot(bot.vel) / target_dir.mag(), 0) if (time < shortest_opp_time): shortest_opp_time = time # Find closest robot on our team for bot in our_robots_to_check: dist = estimate_path_length(bot.pos, target_pos, their_robots_to_dodge, dodge_dist) target_dir = (target_pos - bot.pos).normalized() time = robocup.get_trapezoidal_time(dist, dist, 2.2, 1, target_dir.dot(bot.vel) / target_dir.mag(), 0) if (time < shortest_our_time): shortest_our_time = time closest_robot = bot return shortest_our_time < shortest_opp_time * (1 + valid_error_percent ), closest_robot
def add_shot_obstacle(self, excluded_robots=[]): pt = self.aim_target_point if pt != None: # segment centered at the target point that's @width wide and perpendicular to the shot shot_perp = (main.ball().pos - pt).perp_ccw().normalized() # Make the shot triangle obstacle a fixed width at the end unless # we're aiming at a segment. In that case, just use the length of # the segment. width = 0.5 if isinstance(self.target, robocup.Segment): width = self.target.length() a = pt + shot_perp * width / 2.0 b = pt - shot_perp * width / 2.0 # build the obstacle polygon obs = robocup.Polygon() obs.add_vertex(main.ball().pos) obs.add_vertex(a) obs.add_vertex(b) # tell the bots to not go there for bot in main.our_robots(): if bot not in excluded_robots + [self.robot]: bot.add_local_obstacle(obs)
def __init__(self): super().__init__(continuous=True) goalie = submissive_goalie.SubmissiveGoalie() goalie.shell_id = main.root_play().goalie_id self.add_subbehavior(goalie, "goalie", required=True) self.add_state(WingerWall.State.defending, behavior.Behavior.State.running) self.add_transition(behavior.Behavior.State.start, WingerWall.State.defending, lambda: True, "immediately") self.aggression = 1 self.kick_eval = robocup.KickEvaluator(main.system_state()) self.wingers = [] self.forwards = [] self.max_wingers = 3 self.max_wall = 3 self.assigned_wingers = 0 # List of tuples of (class score, robot obj) self.kick_eval.excluded_robots.clear() for bot in main.our_robots(): self.kick_eval.add_excluded_robot(bot)
def __init__(self): super().__init__(start_state=DoubleTouchTracker.State.start) for state in DoubleTouchTracker.State: self.add_state(state) # FIXME: is it only restart plays? self.add_transition(DoubleTouchTracker.State.start, DoubleTouchTracker.State.restart_play_began, lambda: (main.root_play().play != None and main.root_play().play.__class__.is_restart() and main.game_state().is_our_restart()), 'we start running an offensive restart play') self.add_transition(DoubleTouchTracker.State.restart_play_began, DoubleTouchTracker.State.kicking, lambda: any(bot.has_ball() for bot in main.our_robots()), 'one of our bots has the ball') self.add_transition(DoubleTouchTracker.State.kicking, DoubleTouchTracker.State.kicker_forbidden, lambda: not self.kicker_has_possession(), 'kicker kicks or fumbles ball') self.add_transition(DoubleTouchTracker.State.kicker_forbidden, DoubleTouchTracker.State.other_robot_touched, lambda: self.other_robot_touching_ball(), 'another robot has touched the ball')
def execute_pass_set(self): # gets the best position to travel to for ball reception best_point = self.passing_point # sets the second point alt_point, value2 = evaluation.passing_positioning.eval_best_receive_point( self.passing_point, main.our_robots(), AdvanceZoneMidfielder.FIELD_POS_WEIGHTS, AdvanceZoneMidfielder.NELDER_MEAD_ARGS, AdvanceZoneMidfielder.PASSING_WEIGHTS) # check for futile position i.e the alternate position is in the way of a shot from best position if self.in_shot_triangle(best_point, alt_point): alt_point = self.remove_obstruction(best_point, alt_point) points = [best_point, alt_point] # moves the robots and assigns information for i in range(len(points)): if (self.moves[i] is None): self.moves[i] = skills.move.Move(points[i]) self.add_subbehavior(self.moves[i], self.names[i], required=False, priority=self.priorities[i]) else: self.moves[i].pos = points[i]
def __init__(self): super().__init__(start_state=DoubleTouchTracker.State.start) for state in DoubleTouchTracker.State: self.add_state(state) # FIXME: is it only restart plays? self.add_transition( DoubleTouchTracker.State.start, DoubleTouchTracker.State.restart_play_began, lambda: (main.root_play().play != None and main.root_play().play.__class__. is_restart() and main.game_state().is_our_restart()), 'we start running an offensive restart play') self.add_transition( DoubleTouchTracker.State.restart_play_began, DoubleTouchTracker.State.kicking, lambda: any(bot.has_ball() for bot in main.our_robots()), 'one of our bots has the ball') self.add_transition(DoubleTouchTracker.State.kicking, DoubleTouchTracker.State.kicker_forbidden, lambda: not self.kicker_has_possession(), 'kicker kicks or fumbles ball') self.add_transition(DoubleTouchTracker.State.kicker_forbidden, DoubleTouchTracker.State.other_robot_touched, lambda: self.other_robot_touching_ball(), 'another robot has touched the ball')
def kicker_has_possession(self): if self.kicker_shell_id != None: for bot in main.our_robots(): if bot.shell_id() == self.kicker_shell_id: # we use two methods here because the ball-sensor output is often jittery return bot.has_ball() or evaluation.ball.robot_has_ball(bot) return False
def __init__(self): super().__init__(continuous=True) self.ball_pos = self.get_ball_pos() self.add_state(FollowBall.State.ball_moved, behavior.Behavior.State.running) self.add_state(FollowBall.State.nothing, behavior.Behavior.State.running) ball_has_moved = (lambda: (self.get_ball_pos().x != self.ball_pos.x) or (self.get_ball_pos().y != self.ball_pos.y)) #in_ball_radius = (lambda : False) print(main.our_robots()[1].shell_id) self.add_transition(behavior.Behavior.State.start, self.State.nothing, lambda: True, 'immediately') self.add_transition(self.State.ball_moved, self.State.nothing, lambda: True, 'ball staying still') self.add_transition(self.State.nothing, self.State.ball_moved, ball_has_moved, 'ball moved')
def __init__(self): super().__init__(start_state=DoubleTouchTracker.State.start) for state in DoubleTouchTracker.State: self.add_state(state) # FIXME: is it only restart plays? self.add_transition( DoubleTouchTracker.State.start, DoubleTouchTracker.State.restart_play_began, lambda: (main.root_play().play is not None and main.root_play().play.__class__.is_restart() and main.game_state().is_our_restart()), 'we start running an offensive restart play') self.add_transition( DoubleTouchTracker.State.restart_play_began, DoubleTouchTracker.State.kicking, lambda: ((any(self._touching_ball(bot) for bot in main.our_robots())) or main.game_state().is_playing()) and not main.game_state().is_placement(), 'one of our bots has the ball or the ball was kicked') self.add_transition(DoubleTouchTracker.State.kicking, DoubleTouchTracker.State.kicker_forbidden, # The ball is no longer in restart, we have begun playing (lambda: main.game_state().is_playing() or # We aren't in a restart anymore main.root_play().play is None or not main.root_play().play.__class__.is_restart()), 'ball has moved and is now in play') self.add_transition(DoubleTouchTracker.State.kicker_forbidden, DoubleTouchTracker.State.other_robot_touched, lambda: self.other_robot_touching_ball(), 'another robot has touched the ball')
def execute_pass_set(self): # gets the best position to travel to for ball reception best_point = self.passing_point # sets the second point alt_point, value2 = evaluation.passing_positioning.eval_best_receive_point( self.passing_point, main.our_robots(), AdvanceZoneMidfielder.FIELD_POS_WEIGHTS, AdvanceZoneMidfielder.NELDER_MEAD_ARGS, AdvanceZoneMidfielder.PASSING_WEIGHTS) # check for futile position i.e the alternate position is in the way of a shot from best position if self.in_shot_triangle(best_point, alt_point): alt_point = self.remove_obstruction(best_point, alt_point) points = [best_point, alt_point] # moves the robots and assigns information for i in range(len(points)): if (self.moves[i] is None): self.moves[i] = skills.move.Move(points[i]) self.add_subbehavior( self.moves[i], self.names[i], required=False, priority=self.priorities[i]) else: self.moves[i].pos = points[i]
def other_robot_touching_ball(self): max_radius = constants.Robot.Radius + constants.Ball.Radius + 0.03 for bot in list(main.our_robots()) + list(main.their_robots()): if bot.visible and (not bot.is_ours() or not bot.shell_id() == self.kicker_shell_id): if bot.pos.near_point(main.ball().pos, max_radius): return True return False
def kicker_has_possession(self): if self.kicker_shell_id != None: for bot in main.our_robots(): if bot.shell_id() == self.kicker_shell_id: # we use two methods here because the ball-sensor output is often jittery return bot.has_ball() or evaluation.ball.robot_has_ball( bot) return False
def execute_running(self): # abort if we can't see the ball if not main.ball().valid: return ball_pos = main.ball().pos # the closest of their bots to the ball is their kicker their_kicker = min(main.their_robots(), key=lambda opp: opp.pos.dist_to(ball_pos)) # we build an array of (OpponentRobot, float distToClosestOfOurBots) tuples # we'll use these in a sec to assign our marking robots open_opps_and_dists = [] for opp in main.their_robots(): # ignore their kicker if opp == their_kicker: continue ball_dist = opp.pos.dist_to(ball_pos) # see if the opponent is close enough to the ball for us to care # if it is, we record the closest distance from one of our robots to it if ball_dist < 3.0: # which of our robots is closest to this opponent closest_self_dist = min([bot.pos.dist_to(opp.pos) for bot in main.our_robots()]) open_opps_and_dists.append( (opp, closest_self_dist) ) # Decide what each marking robot should do # @open_opps contains the robots we want to mark (if any) # any robot that isn't assigned a mark_robot will move towards the ball for i, mark_i in enumerate(self.marks): if mark_i.robot != None: if i < len(open_opps_and_dists): # mark the opponent mark_i.mark_robot = open_opps_and_dists[i][0] else: pass # NOTE: the old code ran these motion commands INSTEAD of running the mark command # we could do that, but it'd require removing the subbehavior and re-adding a move or something... # # move towards the ball and face it, but don't get within field center's radius # pos = mark_i.robot.pos # target = pos + (ball_pos - pos).normalized() * (ball_pos.dist_to(pos) - constants.Field.CenterRadius) # mark_i.robot.move(target) # mark_i.face(ball_pos) # tell the marking robots to avoid eachother more than normal for i, mark_i in enumerate(self.marks): for j, mark_j in enumerate(self.marks): if i == j: continue if mark_i.robot != None and mark_j.robot != None: mark_i.robot.set_avoid_teammate_radius(mark_j.robot.shell_id(), 0.5)
def execute_running(self): super().execute_running() # abort if we can't see the ball if not main.ball().valid: return ball_pos = main.ball().pos # the closest of their bots to the ball is their kicker their_kicker = min(main.their_robots(), key=lambda opp: opp.pos.dist_to(ball_pos)) # we build an array of (OpponentRobot, float distToClosestOfOurBots) tuples # we'll use these in a sec to assign our marking robots open_opps_and_dists = [] for opp in main.their_robots(): # ignore their kicker if opp == their_kicker: continue ball_dist = opp.pos.dist_to(ball_pos) # see if the opponent is close enough to the ball for us to care # if it is, we record the closest distance from one of our robots to it if ball_dist < 3.0: # which of our robots is closest to this opponent closest_self_dist = min( [bot.pos.dist_to(opp.pos) for bot in main.our_robots()]) open_opps_and_dists.append((opp, closest_self_dist)) # Decide what each marking robot should do # @open_opps contains the robots we want to mark (if any) # any robot that isn't assigned a mark_robot will move towards the ball for i, mark_i in enumerate(self.marks): if mark_i.robot != None: if i < len(open_opps_and_dists): # mark the opponent mark_i.mark_robot = open_opps_and_dists[i][0] else: pass # NOTE: the old code ran these motion commands INSTEAD of running the mark command # we could do that, but it'd require removing the subbehavior and re-adding a move or something... # # move towards the ball and face it, but don't get within field center's radius # pos = mark_i.robot.pos # target = pos + (ball_pos - pos).normalized() * (ball_pos.dist_to(pos) - constants.Field.CenterRadius) # mark_i.robot.move(target) # mark_i.face(ball_pos) # tell the marking robots to avoid eachother more than normal for i, mark_i in enumerate(self.marks): for j, mark_j in enumerate(self.marks): if i == j: continue if mark_i.robot != None and mark_j.robot != None: mark_i.robot.set_avoid_teammate_radius( mark_j.robot.shell_id(), 0.5)
def execute_kicker_forbidden(self): bot = None for b in main.our_robots(): if b.shell_id() == self.kicker_shell_id: bot = b break if self.kicker_shell_id and bot: main.system_state().draw_text( "Blocking double touch!", bot.pos, constants.Colors.Red, "Double Touches")
def execute_kicker_forbidden(self): bot = None for b in main.our_robots(): if b.shell_id() == self.kicker_shell_id: bot = b break if self.kicker_shell_id and bot: main.debug_drawer().draw_text("Blocking double touch!", bot.pos, constants.Colors.Red, "Double Touches")
def other_robot_touching_ball(self): for bot in filter(lambda bot: bot.visible, list(main.our_robots()) + list(main.their_robots())): if (bot.is_ours() and bot.has_ball() and bot.shell_id() != self.kicker_shell_id): return True if ((bot.shell_id() != self.kicker_shell_id or not bot.is_ours()) and self._bot_in_radius(bot)): return True return False
def score(cls): gs = main.game_state() if len(main.our_robots()) < 5: return float("inf") if (gs.is_ready_state() and gs.is_our_free_kick() and main.ball().pos.y > (constants.Field.Length - 1.2) and abs(main.ball().pos.x) > .6): return 0 else: return 10000
def within_range(self): shortest_opp_dist = 10 shortest_our_dist = 10 # TODO: Do some sort of prediction as the ball moves target_pos = main.ball().pos # Find closest opponent robot for bot in main.their_robots(): dist = self.estimate_path_length(bot.pos, target_pos, main.our_robots()) if (dist < shortest_opp_dist): shortest_opp_dist = dist # Find closest robot on our team for bot in main.our_robots(): dist = self.estimate_path_length(bot.pos, target_pos, main.their_robots()) if (dist < shortest_our_dist): shortest_our_dist = dist # Greater than 1 when we are further away return shortest_our_dist < shortest_opp_dist * 1.05
def on_enter_passing(self): self.remove_all_subbehaviors() #either pass to striker or distracter depending on shot chance pass_to_distract_chance = evaluation.passing.eval_pass( main.ball().pos, self.Distraction_recieve_pass_point, main.our_robots()) pass_to_striker_chance = evaluation.passing.eval_pass( main.ball().pos, self.striker_point, main.our_robots()) shot_of_striker_chance = evaluation.shooting.eval_shot( self.striker_point, main.our_robots()) if pass_to_distract_chance <= pass_to_striker_chance * shot_of_striker_chance: pass_striker_instead = True self.add_subbehavior( skills.move.Move(self.striker_point), 'make striker stay again', required=True) self.add_subbehavior( tactics.coordinated_pass.CoordinatedPass( self.Distraction_recieve_pass_point), 'distract pass', required=True)
def on_enter_kick(self): OurFreeKick.Running = False kicker = skills.line_kick.LineKick() kicker.use_chipper = True kicker.min_chip_range = OurFreeKick.MinChipRange kicker.max_chip_range = OurFreeKick.MaxChipRange kicker.target = self.gap shooting_line = robocup.Line(main.ball().pos, self.gap) # If we are at their goal, shoot full power if shooting_line.segment_intersection( constants.Field.TheirGoalSegment) is not None: kicker.kick_power = self.FullKickPower # If we are aiming in the forward direction and not at one of the "endzones", shoot full power elif (shooting_line.line_intersection(constants.Field.FieldBorders[0]) or shooting_line.line_intersection(constants.Field.FieldBorders[2]) and self.gap.y - main.ball().pos.y > 0): kicker.kick_power = self.FullKickPower # If we are probably aiming down the field, slowly kick so we dont carpet else: kicker.kick_power = self.BumpKickPower # Try passing if we are doing an indirect kick if self.indirect: pass # Check for valid target pass position if self.receive_value != 0 and len(main.our_robots()) >= 5: self.remove_all_subbehaviors() pass_behavior = tactics.coordinated_pass.CoordinatedPass( self.receive_pt, None, (kicker, lambda x: True), receiver_required=False, kicker_required=False, prekick_timeout=7, use_chipper=True) # We don't need to manage this anymore self.add_subbehavior(pass_behavior, 'kicker') else: kicker.target = (self.pos_up_field) self.add_subbehavior(kicker, 'kicker', required=False, priority=5) else: kicker.target = constants.Field.TheirGoalSegment self.add_subbehavior(kicker, 'kicker', required=False, priority=5)
def on_enter_clearing(self): # Line kick with chip # Choose most open area / Best pass, weight forward # Decrease weight on sides of field due to complexity of settling self.pass_target, self.pass_score = evaluation.passing_positioning.eval_best_receive_point( main.ball().pos, main.our_robots(), AdaptiveFormation.FIELD_POS_WEIGHTS, AdaptiveFormation.NELDER_MEAD_ARGS, AdaptiveFormation.PASSING_WEIGHTS) clear = skills.pivot_kick.PivotKick() clear.target = self.pass_target clear.aim_params['desperate_timeout'] = 3 clear.use_chipper = True self.add_subbehavior(clear, 'clear', required=False)
def our_robot_with_ball(): closest_bot, closest_dist = None, float("inf") for bot in main.our_robots(): if bot.visible: dist = (bot.pos - main.ball().pos).mag() if dist < closest_dist: closest_bot, closest_dist = bot, dist if closest_bot == None: return None else: if robot_has_ball(closest_bot): return closest_bot else: return None
def on_enter_start(self): # if we have too many robots isolate one of the robots so they don't help in the play goalie = main.root_play( ).goalie_id #.system_state().game_state.get_goalie_id() print(goalie) numRobots = len(main.our_robots()) - 4 if (goalie != None): numRobots = numRobots - 1 for i in range(numRobots): iso = skills.move.Move( robocup.Point(-constants.Field.Width / 2 + self.bot_buffer * i, 0)) self.add_subbehavior(iso, 'iso' + str(i), required=True, priority=1)
def on_enter_move(self): self.move_pos = self.calc_move_pos() self.pos_up_field = robocup.Point(main.ball().pos.x, constants.Field.Length * .75) if (main.ball().pos.y > constants.Field.Length / 2): sign = (main.ball().pos.x) / abs(main.ball().pos.x) * -1 x = sign * constants.Field.Width * 3 / 8 y = max(constants.Field.Length * .75, (main.ball().pos.y + constants.Field.Length) * 0.5) self.pos_up_field = robocup.Point(x, y) if self.indirect and (self.receive_value == 0 and len(main.our_robots()) >= 5): self.add_subbehavior(skills.move.Move(self.pos_up_field), 'receiver', required=False, priority=5)
def add_shot_obstacle(self, excluded_robots=[]): pt = self.aim_target_point if pt != None: # segment centered at the target point that's @width wide and perpendicular to the shot shot_perp = (main.ball().pos - pt).perp_ccw().normalized() width = 0.2 a = pt + shot_perp * width / 2.0 b = pt - shot_perp * width / 2.0 # build the obstacle polygon obs = robocup.Polygon() obs.add_vertex(main.ball().pos) obs.add_vertex(a) obs.add_vertex(b) # tell the bots to not go there for bot in main.our_robots(): if bot not in excluded_robots + [self.robot]: bot.add_local_obstacle(obs)
def execute_shooting(self): kicker = skills.line_kick.LineKick() #skills.pivot_kick.PivotKick() #aim for goal segmant win_eval = robocup.WindowEvaluator(main.context()) for g in main.our_robots(): win_eval.add_excluded_robot(g) windows, window = win_eval.eval_pt_to_opp_goal(main.ball().pos) if (window != None): kicker.target = window.segment.center() else: kicker.target = constants.Field.TheirGoalSegment kicker.aim_params['desperate_timeout'] = 8 if (not self.has_subbehavior_with_name('kicker') or self.subbehavior_with_name('kicker').is_done_running()): self.remove_all_subbehaviors() self.add_subbehavior(kicker, 'kicker', required=False, priority=5)
def recalculate_threat_shot(threat_index): if not isinstance(threat_index, int): raise TypeError("threat_index should be an int") # ignore all of our robots excluded_robots = list(main.our_robots()) # behaviors before this threat are counted as obstacles in their TARGET position (where we've # assigned them to go, not where they are right now) hypothetical_obstacles = [] for t in threats[0:threat_index]: hypothetical_obstacles.extend(map(lambda bhvr: bhvr.move_target, t.assigned_handlers)) threat = threats[threat_index] threat.shot_chance, threat.best_shot_window = evaluation.shot.eval_shot( pos=threat.pos, target=constants.Field.OurGoalSegment, windowing_excludes=excluded_robots, hypothetical_robot_locations=[], debug=False)
def recalculate_threat_shot(threat_index): if not isinstance(threat_index, int): raise TypeError("threat_index should be an int") # ignore all of our robots excluded_robots = list(main.our_robots()) # behaviors before this threat are counted as obstacles in their TARGET position (where we've # assigned them to go, not where they are right now) hypothetical_obstacles = [] for t in threats[0:threat_index]: hypothetical_obstacles.extend( map(lambda bhvr: bhvr.move_target, t.assigned_handlers)) threat = threats[threat_index] threat.shot_chance, threat.best_shot_window = evaluation.shot.eval_shot( pos=threat.pos, target=constants.Field.OurGoalSegment, windowing_excludes=excluded_robots, hypothetical_robot_locations=[], debug=False)
def execute_running(self): super().execute_running() # abort if we can't see the ball if not main.ball().valid: return ball_pos = main.ball().pos # the closest of their bots to the ball is their kicker their_kicker = min(main.their_robots(), key=lambda opp: opp.pos.dist_to(ball_pos)) # we build an array of (OpponentRobot, float distToClosestOfOurBots) tuples # we'll use these in a sec to assign our marking robots open_opps_and_dists = [] for opp in main.their_robots(): # ignore their kicker if opp == their_kicker: continue ball_dist = opp.pos.dist_to(ball_pos) # see if the opponent is close enough to the ball for us to care # if it is, we record the closest distance from one of our robots to it if ball_dist < 3.0: # which of our robots is closest to this opponent closest_self_dist = min( [bot.pos.dist_to(opp.pos) for bot in main.our_robots()]) open_opps_and_dists.append((opp, closest_self_dist)) # Decide what each marking robot should do # @open_opps contains the robots we want to mark (if any) # any robot that isn't assigned a mark_robot will move towards the ball for i, mark_i in enumerate(self.marks): if mark_i.robot != None: if i < len(open_opps_and_dists): # mark the opponent mark_i.mark_robot = open_opps_and_dists[i][0] else: pass
def recalculate_threat_shot(threat_index): if not isinstance(threat_index, int): raise TypeError("threat_index should be an int") # ignore all of our robots excluded_robots = list(main.our_robots()) # behaviors before this threat are counted as obstacles in their TARGET position (where we've # assigned them to go, not where they are right now) hypothetical_obstacles = [] for t in threats[0:threat_index]: hypothetical_obstacles.extend(map(lambda bhvr: bhvr.move_target, t.assigned_handlers)) threat = threats[threat_index] self.win_eval.excluded_robots.clear() for r in excluded_robots: self.win_eval.add_excluded_robot(r) _, threat.best_shot_window = self.win_eval.eval_pt_to_our_goal(threat.pos) if threat.best_shot_window is not None: threat.shot_chance = threat.best_shot_window.shot_success else: threat.shot_chance = 0.0
def on_enter_dribbling(self): self.dribbler = skills.dribble.Dribble() self.dribble_start_pt = main.ball().pos # Dribbles toward the best receive point self.dribbler.pos, _ = evaluation.passing_positioning.eval_best_receive_point( main.ball().pos, main.our_robots(), AdaptiveFormation.FIELD_POS_WEIGHTS, AdaptiveFormation.NELDER_MEAD_ARGS, AdaptiveFormation.DRIBBLING_WEIGHTS) self.add_subbehavior(self.dribbler, 'dribble', required=True) self.check_dribbling_timer = 0 if (not self.has_subbehavior_with_name('midfielders')): self.midfielders = tactics.advance_zone_midfielder.AdvanceZoneMidfielder( ) self.add_subbehavior( self.midfielders, 'midfielders', required=False, priority=10) self.midfielders.kick = False
def execute_running(self): super().execute_running() # abort if we can't see the ball if not main.ball().valid: return ball_pos = main.ball().pos # the closest of their bots to the ball is their kicker their_kicker = min(main.their_robots(), key=lambda opp: opp.pos.dist_to(ball_pos)) # we build an array of (OpponentRobot, float distToClosestOfOurBots) tuples # we'll use these in a sec to assign our marking robots open_opps_and_dists = [] for opp in main.their_robots(): # ignore their kicker if opp == their_kicker: continue ball_dist = opp.pos.dist_to(ball_pos) # see if the opponent is close enough to the ball for us to care # if it is, we record the closest distance from one of our robots to it if ball_dist < 3.0: # which of our robots is closest to this opponent closest_self_dist = min([bot.pos.dist_to(opp.pos) for bot in main.our_robots()]) open_opps_and_dists.append((opp, closest_self_dist)) # Decide what each marking robot should do # @open_opps contains the robots we want to mark (if any) # any robot that isn't assigned a mark_robot will move towards the ball for i, mark_i in enumerate(self.marks): if mark_i.robot != None: if i < len(open_opps_and_dists): # mark the opponent mark_i.mark_robot = open_opps_and_dists[i][0] else: pass
def __init__(self): super().__init__(continuous=True) self.debug = False self.add_transition(behavior.Behavior.State.start, behavior.Behavior.State.running, lambda: True, 'immediately') self.marks = [] if (main.game_state().is_their_direct()): self.intercept = (constants.Field.OurGoalSegment.center() - main.ball().pos) * 0.25 + main.ball().pos self.add_subbehavior(skills.move.Move(self.intercept), 'intercept direct', required=False, priority=5) for i in range(3): mark_i = skills.mark.Mark() mark_i.ratio = 0.7 self.add_subbehavior(mark_i, 'mark' + str(i), required=False, priority=3 - i) self.marks.append(mark_i) self.kick_eval = robocup.KickEvaluator(main.system_state()) self.kick_eval.debug = True for i, robot in enumerate(main.our_robots()): self.kick_eval.add_excluded_robot(robot) for i, robot in enumerate(main.their_robots()): self.kick_eval.add_excluded_robot(robot) their_kicker = min(main.their_robots(), key=lambda opp: opp.pos.dist_to(main.ball().pos)) self.kick_eval.add_excluded_robot(their_kicker)
def on_enter_dribbling(self): self.dribbler = skills.dribble.Dribble() self.dribble_start_pt = main.ball().pos # Dribbles toward the best receive point self.dribbler.pos, _ = evaluation.passing_positioning.eval_best_receive_point( main.ball().pos, main.our_robots(), AdaptiveFormation.FIELD_POS_WEIGHTS, AdaptiveFormation.NELDER_MEAD_ARGS, AdaptiveFormation.DRIBBLING_WEIGHTS) self.add_subbehavior(self.dribbler, 'dribble', required=True) self.check_dribbling_timer = 0 if (not self.has_subbehavior_with_name('midfielders')): self.midfielders = tactics.simple_zone_midfielder.SimpleZoneMidfielder( ) self.add_subbehavior(self.midfielders, 'midfielders', required=False, priority=10)
def __init__(self): super().__init__(start_state=DoubleTouchTracker.State.start) for state in DoubleTouchTracker.State: self.add_state(state) # FIXME: is it only restart plays? self.add_transition( DoubleTouchTracker.State.start, DoubleTouchTracker.State.restart_play_began, lambda: (main.root_play().play is not None and main.root_play().play. __class__.is_restart() and main.game_state().is_our_restart()), 'we start running an offensive restart play') self.add_transition( DoubleTouchTracker.State.restart_play_began, DoubleTouchTracker.State.kicking, lambda: ( (any(self._touching_ball(bot) for bot in main.our_robots())) or main.game_state( ).is_playing()) and not main.game_state().is_placement(), 'one of our bots has the ball or the ball was kicked') self.add_transition( DoubleTouchTracker.State.kicking, DoubleTouchTracker.State.kicker_forbidden, # The ball is no longer in restart, we have begun playing ( lambda: main.game_state().is_playing() or # We aren't in a restart anymore main.root_play().play is None or not main.root_play().play. __class__.is_restart()), 'ball has moved and is now in play') self.add_transition(DoubleTouchTracker.State.kicker_forbidden, DoubleTouchTracker.State.other_robot_touched, lambda: self.other_robot_touching_ball(), 'another robot has touched the ball')
def get_threat_list(self, unused_threat_handlers): # List of (position, score, Robot/None) threats = [] potential_threats = main.their_robots() # find the primary threat # if the ball is not moving OR it's moving towards our goal, it's the primary threat # if it's moving, but not towards our goal, the primary threat is the robot on their team most likely to catch it if (main.ball().vel.mag() > 0.4): if evaluation.ball.is_moving_towards_our_goal(): # Add tuple of pos and score threats.append((main.ball().pos, 1, None)) else: # Get all potential receivers potential_receivers = [] for opp in potential_threats: if self.estimate_potential_recievers_score(opp) == 1: potential_receivers.append((opp.pos, 1, opp)) if len(potential_receivers) > 0: # Add best receiver to threats # TODO Calc shot chance best_tuple = min(potential_receivers, key=lambda rcrv_tuple: rcrv_tuple[1]) threats.append((best_tuple[0], .81, best_tuple[2])) else: # Just deal with ball if no recievers threats.append((main.ball().pos, .9, None)) else: # Assume opp is dribbling ball if not constants.Field.OurGoalZoneShape.contains_point( main.ball().pos): # TODO: Calc shot chance threats.append((main.ball().pos, 1, None)) # if there are threats, check pass and shot chances # If the first item is not a ball, it is most likely a pass if len(threats) > 0 and threats[0][0] != main.ball().pos: for opp in potential_threats: # Exclude robots that have been assigned already excluded_bots = [] for r in map(lambda bhvr: bhvr.robot, unused_threat_handlers): excluded_bots.append(r) threats.append((opp.pos, self.estimate_risk_score( opp, excluded_bots), opp)) else: for opp in potential_threats: # Exclude all robots self.kick_eval.excluded_robots.clear() self.kick_eval.add_excluded_robot(opp) for r in main.our_robots(): self.kick_eval.add_excluded_robot(r) point, shotChance = self.kick_eval.eval_pt_to_our_goal(opp.pos) # Note: 0.5 is a bullshit value threats.append((opp.pos, 0.5 * shotChance, opp)) # Prevent threats from being below our goal line (causes incorrect pos) def _adjust_pt(threat): pt = threat[0] pt.y = max(pt.y, 0.1) return (pt,) + threat[1:] threats = list(map(_adjust_pt, threats)) return threats
def __init__(self): super().__init__(continuous=False) for s in AdaptiveFormation.State: self.add_state(s, behavior.Behavior.State.running) # Dribbling skill self.dribbler = None # Dribble start point self.dribble_start_pt = robocup.Point(0, 0) # Kicker for a shot self.kick = None # Controls robots while passes are being set up self.midfielders = None # State Decision Variables self.shot_chance = 0 self.pass_score = 0 # Prev State Decision Variables self.prev_shot_chance = 0 self.prev_pass_score = 0 # Used to keep dribble within rules self.check_dribbling_timer = 0 self.check_dribbling_timer_cutoff = 100 self.kick_eval = robocup.KickEvaluator(main.system_state()) for r in main.our_robots(): self.kick_eval.add_excluded_robot(r) # Add transitions self.add_transition(behavior.Behavior.State.start, AdaptiveFormation.State.collecting, lambda: True, 'immediately') self.add_transition(AdaptiveFormation.State.collecting, AdaptiveFormation.State.dribbling, lambda: self. subbehavior_with_name('defend').state == behavior. Behavior.State.completed, 'Ball Collected') self.add_transition( AdaptiveFormation.State.dribbling, AdaptiveFormation.State.passing, lambda: self.dribbler_has_ball() and self.should_pass_from_dribble( ) and not self.should_shoot_from_dribble(), 'Passing') self.add_transition( AdaptiveFormation.State.dribbling, AdaptiveFormation.State.shooting, lambda: self.dribbler_has_ball( ) and self.should_shoot_from_dribble(), 'Shooting') self.add_transition( AdaptiveFormation.State.dribbling, AdaptiveFormation.State.clearing, lambda: self.dribbler_has_ball( ) and self.should_clear_from_dribble( ) and not self.should_pass_from_dribble( ) and not self.should_shoot_from_dribble(), 'Clearing') self.add_transition( AdaptiveFormation.State.passing, AdaptiveFormation.State.dribbling, lambda: self.subbehavior_with_name( 'pass').state == behavior.Behavior.State.completed, 'Passed') # Reset to collecting when ball is lost at any stage self.add_transition(AdaptiveFormation.State.dribbling, AdaptiveFormation.State.collecting, lambda: not self.dribbler_has_ball(), 'Dribble: Ball Lost') self.add_transition( AdaptiveFormation.State.passing, AdaptiveFormation.State.collecting, lambda: self. subbehavior_with_name('pass').state == behavior.Behavior.State. cancelled or self.subbehavior_with_name('pass').state == behavior. Behavior.State.failed, 'Passing: Ball Lost') self.add_transition(AdaptiveFormation.State.shooting, AdaptiveFormation.State.collecting, lambda: self. subbehavior_with_name('kick').is_done_running(), 'Shooting: Ball Lost / Shot') self.add_transition(AdaptiveFormation.State.clearing, AdaptiveFormation.State.collecting, lambda: self. subbehavior_with_name('clear').is_done_running(), 'Clearing: Ball Lost')
def estimate_risk_score(pos, ignore_robots=[]): # Caches some kick eval functions max_time = 1 max_ball_vel = 8 # m/s per the rules est_turn_vel = 8 # rad/s per a random dice roll (Over estimates oppnents abilities) kick_eval = robocup.KickEvaluator(main.system_state()) for r in ignore_robots: kick_eval.add_excluded_robot(r) _, pass_score = kick_eval.eval_pt_to_robot(main.ball().pos, pos) shot_pt, shot_score = kick_eval.eval_pt_to_our_goal(pos) # Dist to ball ball_pos_vec = pos - main.ball().pos dist = ball_pos_vec.mag() max_dist = robocup.Point(constants.Field.Width, constants.Field.Length).mag() # Closest opp robot closest_opp_bot = evaluation.opponent.get_closest_opponent(main.ball().pos) delta_angle = ball_pos_vec.angle() - \ predict_kick_direction(closest_opp_bot) delta_angle = math.atan2(math.sin(delta_angle), math.cos(delta_angle)) # Underestimates max time to execute on ball # Assumes perfect opponent time = dist / max_ball_vel + math.fabs(delta_angle) / est_turn_vel # Limits to max time so we can invert it later on time = min(time, max_time) # Center, Dist, Angle pos_score = evaluation.field.field_pos_coeff_at_pos(pos, 0.05, 0.3, 0.05, False) space_coeff = evaluation.field.space_coeff_at_pos(pos, ignore_robots, main.our_robots()) # Delta angle between pass recieve and shot delta_angle = ball_pos_vec.angle() - (shot_pt - pos).angle() delta_angle = math.atan2(math.sin(delta_angle), math.cos(delta_angle)) angle_coeff = math.fabs(delta_angle) / math.pi # Shot only matters if its a good pass # Add pass back in for checking if pass is good (while shot is not) # # Add in time to weight closer points higher # # Pos is weighted higher to remove bad positions from calculations # # Space is weighted in so it is weighted towards lower density areas # # Delta angle for shot is weighted in so easier shots are weighted higher # # Distance to the ball squared # Pass, Time, Pos, Space, Angle weights = [0.1, 0.1, 2, 0.4, 0.3, 1] score = weights[0] * (shot_score * pass_score + pass_score) / 2 + \ weights[1] * (max_time - time) + \ weights[2] * pos_score + \ weights[3] * (1 - space_coeff) + \ weights[4] * angle_coeff + \ weights[5] * (1 - dist / max_dist)**2 return score / sum(weights)
def eval_pt_to_seg(self, origin, target): end = target.delta().magsq() # if target is a zero-length segment, there are no windows if end == 0: return [], None if self.debug: main.system_state().draw_line(target, constants.Colors.Blue, "Debug") windows = [Window(0, end)] # apply the obstacles bots = filter(lambda bot: bot not in self.excluded_robots and bot.visible, (list(main.our_robots()) + list(main.their_robots()))) bot_locations = list(map(lambda bot: bot.pos, bots)) bot_locations.extend(self.hypothetical_robot_locations) for pos in bot_locations: d = (pos - origin).mag() # whether or not we can chip over this bot chip_overable = (self.chip_enabled and (d < self.max_chip_range - constants.Robot.Radius) and (d > self.min_chip_range + constants.Robot.Radius)) if not chip_overable: self.obstacle_robot(windows, origin, target, pos) # set the segment and angles for each window p0 = target.get_pt(0) delta = target.delta() / end for w in windows: w.segment = robocup.Segment(p0 + delta * w.t0, p0 + delta * w.t1) w.a0 = (w.segment.get_pt(0) - origin).angle() * constants.RadiansToDegrees w.a1 = (w.segment.get_pt(1) - origin).angle() * constants.RadiansToDegrees best = max(windows, key=lambda w: w.segment.delta().magsq()) if len(windows) > 0 else None if self.debug and best is not None: main.system_state().draw_line(best.segment, constants.Colors.Green, "Debug") main.system_state().draw_line(robocup.Line(origin, best.segment.center()), constants.Colors.Green, "Debug") # # draw the windows if we're in debug mode # if self.debug: # for w in windows: # pts = [origin, w.segment.get_pt(0), w.segment.get_pt(1)] # color = (255, 0, 0) if w == best else (0, 255, 0) # main.system_state().draw_polygon(pts, 3, color, "Windows") return windows, best
def we_have_ball(self): return any( evaluation.ball.robot_has_ball(r) for r in main.our_robots())
def on_exit_restart_play_began(self): for bot in main.our_robots(): if bot.has_ball(): self.kicker_shell_id = bot.shell_id() return
def score(cls): if (not main.game_state().is_playing()): return float("inf") if len(main.our_robots()) < 5: return float("inf") return 10
def dribbler_has_ball(self): return any(evaluation.ball.robot_has_ball(r) for r in main.our_robots())