Repository: robojackets/robocup-software
Issue: Wrong usage of eval_best_receive_point in many places

## Description
We use `eval_best_receive_points` incorrectly in a lot of different places:

https://github.com/RoboJackets/robocup-software/blob/0c0f1448968d65b6429e48ec0e380d0d465aa064/soccer/gameplay/plays/Clear/adaptive_clear.py#L222-L237
https://github.com/RoboJackets/robocup-software/blob/757b8d3b90c290e2da23fd829c3efb279a7969a0/soccer/gameplay/plays/restarts/our_free_kick.py#L54-L57
https://github.com/RoboJackets/robocup-software/blob/757b8d3b90c290e2da23fd829c3efb279a7969a0/soccer/gameplay/plays/Legacy/adaptive_formation.py#L327-L331

However, the `eval_best_receive_point` has a signature of
https://github.com/RoboJackets/robocup-software/blob/0c0f1448968d65b6429e48ec0e380d0d465aa064/soccer/gameplay/evaluation/passing_positioning.py#L106-L115

There are parameters that are missing in these calls to `eval_best_receive_point`

- [ ] This bug has been reproduced by someone else


Changed files:
soccer/gameplay/plays/Clear/adaptive_clear.py, soccer/gameplay/plays/restarts/our_free_kick.py

diff --git a/soccer/gameplay/plays/Clear/adaptive_clear.py b/soccer/gameplay/plays/Clear/adaptive_clear.py
index f6d4ef0b3b..455525f769 100644
--- a/soccer/gameplay/plays/Clear/adaptive_clear.py
+++ b/soccer/gameplay/plays/Clear/adaptive_clear.py
@@ -1,18 +1,23 @@
-import main
+import enum
+from typing import Optional
+
 import robocup
+
 import behavior
 import constants
-import enum
-
-import standard_play
 import evaluation.ball
+import evaluation.opponent
 import evaluation.passing_positioning
+import main
+import skills.capture
+import skills.dribble
+import skills.move
+import skills.pivot_kick
+import standard_play
+import tactics.advance_zone_midfielder
 import tactics.coordinated_pass
 import tactics.defensive_forward
 import tactics.simple_zone_midfielder
-import tactics.advance_zone_midfielder
-import skills.move
-import skills.capture
 from situations import Situation
 
 
@@ -20,10 +25,9 @@ from situations import Situation
 # This is essentially a copy of adaptive formation, found in the legacy folder,
 # With the shooting option removed. It is intended to be used as a clearing play
 class AdaptiveClear(standard_play.StandardPlay):
-
     _situationList = [
         Situation.CLEAR,
-    ] # yapf: disable
+    ]  # yapf: disable
 
     # Min score to pass
     DRIBBLE_TO_PASS_CUTOFF = 0.1
@@ -54,8 +58,7 @@ class AdaptiveClear(standard_play.StandardPlay):
     CHIP_PASS_WEIGHTS = (2, 10, 0, 10)
 
     # Initial arguements for the nelder mead optimization in passing positioning
-    NELDER_MEAD_ARGS = (robocup.Point(0.5, 2), \\
-                        robocup.Point(0.01, 0.01), 1, 2, \\
+    NELDER_MEAD_ARGS = (robocup.Point(0.5, 2), robocup.Point(0.01, 0.01), 1, 2,
                         0.75, 0.5, 50, 1, 0.1)
 
     class State(enum.Enum):
@@ -68,26 +71,27 @@ class AdaptiveClear(standard_play.StandardPlay):
         # Clear when pass / dribble is worse and we are in our own zone
         clearing = 4
 
-    def __init__(self):
+    def __init__(self) -> None:
         super().__init__(continuous=False)
 
         for s in AdaptiveClear.State:
             self.add_state(s, behavior.Behavior.State.running)
 
         # Dribbling skill
-        self.dribbler = None
+        self.dribbler: Optional[skills.dribble.Dribble] = None
         # Dribble start point
         self.dribble_start_pt = robocup.Point(0, 0)
 
         # Controls robots while passes are being set up
-        self.midfielders = None
+        self.midfielders: Optional[
+            tactics.simple_zone_midfielder.SimpleZoneMidfielder] = None
 
         # State Decision Variables
-        self.pass_score = 0
+        self.pass_score: float = 0.0
         # Prev State Decision Variables
-        self.prev_pass_score = 0
+        self.prev_pass_score: float = 0.0
         # Used to keep dribble within rules
-        self.check_dribbling_timer = 0
+        self.check_dribbling_timer: int = 0
         self.check_dribbling_timer_cutoff = 100
 
         # Add transitions
@@ -133,40 +137,41 @@ class AdaptiveClear(standard_play.StandardPlay):
             'Clearing: Ball Lost')
 
     @classmethod
-    def score(cls):
+    def score(cls) -> float:
         score = super().score()
 
-        #If we get a valid score from the super function, then we should calculate
-        #an offset and sum that with score and return that
-        if (score != float("inf")):
-            #currently the offset is just 0 because we haven't made one
+        # If we get a valid score from the super function, then we should calculate
+        # an offset and sum that with score and return that
+        if score != float("inf"):
+            # currently the offset is just 0 because we haven't made one
             scoreOffset = 0
             return score + scoreOffset
         else:
-            if (not main.game_state().is_playing()):
+            if not main.game_state().is_playing():
                 return float("inf")
             if len(main.our_robots()) < 5:
                 return float("inf")
             return 8
 
-    def should_pass_from_dribble(self):
+    def should_pass_from_dribble(self) -> bool:
 
         # If pass is above cutoff
-        if (self.pass_score > AdaptiveClear.DRIBBLE_TO_PASS_CUTOFF):
+        if self.pass_score > AdaptiveClear.DRIBBLE_TO_PASS_CUTOFF:
             print("Pass : " + str(self.pass_score))
             return True
 
         # Force pass if we are near our max dribble dist
         dribble_dist = (main.ball().pos - self.dribble_start_pt).mag()
-        if (dribble_dist > AdaptiveClear.MAX_DRIBBLE_DIST):
+        if dribble_dist > AdaptiveClear.MAX_DRIBBLE_DIST:
             return True
 
         # Under cutoff
         return False
 
-    def should_clear_from_dribble(self):
+    def should_clear_from_dribble(self) -> bool:
         # If outside clear zone
-        if (self.dribbler.pos.y > AdaptiveClear.CLEAR_FIELD_CUTOFF):
+        assert self.dribbler is not None
+        if self.dribbler.pos.y > AdaptiveClear.CLEAR_FIELD_CUTOFF:
             return False
 
         # If pass chances are getting better, hold off
@@ -178,25 +183,25 @@ class AdaptiveClear(standard_play.StandardPlay):
         closest_distance = (
             evaluation.opponent.get_closest_opponent(main.ball().pos, 1).pos -
             main.ball().pos).mag()
-        if (closest_distance > AdaptiveClear.CLEAR_DISTANCE_CUTOFF):
+        if closest_distance > AdaptiveClear.CLEAR_DISTANCE_CUTOFF:
             return False
 
         return True
 
-    def dribbler_has_ball(self):
+    def dribbler_has_ball(self) -> bool:
         return any(r.has_ball() for r in main.our_robots())
 
-    def on_enter_collecting(self):
+    def on_enter_collecting(self) -> None:
         self.remove_all_subbehaviors()
 
         # 2 man to man defenders and 1 zone defender
         defensive_forward = tactics.defensive_forward.DefensiveForward()
         self.add_subbehavior(defensive_forward, 'defend', required=True)
 
-    def on_exit_collecting(self):
+    def on_exit_collecting(self) -> None:
         self.remove_all_subbehaviors()
 
-    def on_enter_dribbling(self):
+    def on_enter_dribbling(self) -> None:
         self.dribbler = skills.dribble.Dribble()
         self.dribble_start_pt = main.ball().pos
 
@@ -219,7 +224,8 @@ class AdaptiveClear(standard_play.StandardPlay):
                                  required=False,
                                  priority=10)
 
-    def execute_dribbling(self):
+    def execute_dribbling(self) -> None:
+        assert self.dribbler is not None
         # Grab best pass
         self.pass_target, self.pass_score = evaluation.passing_positioning.eval_best_receive_point(
             main.ball().pos, main.our_robots(), AdaptiveClear.MIN_PASS_DIST,
@@ -228,7 +234,7 @@ class AdaptiveClear(standard_play.StandardPlay):
 
         # Recalculate dribbler pos
         self.check_dribbling_timer += 1
-        if (self.check_dribbling_timer > self.check_dribbling_timer_cutoff):
+        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(),
@@ -241,15 +247,15 @@ class AdaptiveClear(standard_play.StandardPlay):
         # Offensive positions move onto the ball in the direction of the goal
         # Defensive cover the center of the field
 
-    def on_exit_dribbling(self):
+    def on_exit_dribbling(self) -> None:
         self.remove_subbehavior('dribble')
 
-    def on_enter_clearing(self):
+    def on_enter_clearing(self) -> None:
         # 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(),
+            main.ball().pos, main.our_robots(), AdaptiveClear.MIN_PASS_DIST,
             AdaptiveClear.FIELD_POS_WEIGHTS, AdaptiveClear.NELDER_MEAD_ARGS,
             AdaptiveClear.PASSING_WEIGHTS)
 
@@ -259,13 +265,13 @@ class AdaptiveClear(standard_play.StandardPlay):
         clear.use_chipper = True
         self.add_subbehavior(clear, 'clear', required=False)
 
-    def on_exit_clearing(self):
+    def on_exit_clearing(self) -> None:
         self.remove_subbehavior('clear')
 
-    def on_enter_passing(self):
+    def on_enter_passing(self) -> None:
         # TODO: Use the moving receive when finished
         self.add_subbehavior(
             tactics.coordinated_pass.CoordinatedPass(self.pass_target), 'pass')
 
-    def on_exit_passing(self):
+    def on_exit_passing(self) -> None:
         self.remove_subbehavior('pass')
diff --git a/soccer/gameplay/plays/restarts/our_free_kick.py b/soccer/gameplay/plays/restarts/our_free_kick.py
index 6e458c0ad7..333c0f8d29 100644
--- a/soccer/gameplay/plays/restarts/our_free_kick.py
+++ b/soccer/gameplay/plays/restarts/our_free_kick.py
@@ -2,16 +2,18 @@ import standard_play
 import behavior
 import skills.move
 import skills.pivot_kick
+import skills.line_kick
 import constants
 import robocup
 import math
 import main
 import tactics.coordinated_pass
 import evaluation.passing_positioning
+import evaluation.shooting
 import enum
 
-class OurFreeKick(standard_play.StandardPlay):
 
+class OurFreeKick(standard_play.StandardPlay):
     Running = False
     BumpKickPower = 0.01
     FullKickPower = 1
@@ -52,7 +54,7 @@ class OurFreeKick(standard_play.StandardPlay):
                             'kick')
 
         self.receive_pt, self.receive_value = evaluation.passing_positioning.eval_best_receive_point(
-            main.ball().pos,
+            main.ball().pos, [],
             OurFreeKick.MIN_PASS_DIST,
             field_weights=(2.0, 10.0, 0.1))
         self.gap = evaluation.shooting.find_gap(
@@ -65,16 +67,20 @@ class OurFreeKick(standard_play.StandardPlay):
             coordinated_pass.CoordinatedPass.State.timeout, 'kicker completes')
 
     @classmethod
-    def score(cls):
+    def score(cls) -> float:
         gs = main.game_state()
         return 3 if OurFreeKick.Running or (
             gs.is_ready_state() and gs.is_our_free_kick()) else float("inf")
 
     def receiver_near_pos(self):
-        return len(main.our_robots()) <= 4 or (self.has_subbehavior_with_name('receiver') and (self.subbehavior_with_name('receiver').robot is not None)) and \\
-            ((self.subbehavior_with_name('receiver').robot.pos - self.pos_up_field).mag() < 0.5)
-
-    def on_enter_move(self):
+        receiver_subbhvr = self.has_subbehavior_with_name('receiver')
+        assert receiver_subbhvr is None or isinstance(receiver_subbhvr,
+                                                      skills.move.Move)
+        return len(main.our_robots()) <= 4 or (
+            receiver_subbhvr and receiver_subbhvr.robot is not None) and \\
+               (receiver_subbhvr.robot.pos - self.pos_up_field).mag() < 0.5
+
+    def on_enter_move(self) -> None:
         self.move_pos = self.calc_move_pos()
 
         self.pos_up_field = robocup.Point(main.ball().pos.x,
@@ -94,25 +100,26 @@ class OurFreeKick(standard_play.StandardPlay):
                 required=False,
                 priority=5)
 
-    def execute_move(self):
+    def execute_move(self) -> None:
         self.move_pos = self.calc_move_pos()
 
     # def on_exit_move(self):
     # self.remove_all_subbehaviors()
 
-    def on_enter_kick(self):
+    def on_enter_kick(self) -> None:
         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.min_chip_range = OurFreeKick.MinChipRange  # type: ignore
+        kicker.max_chip_range = OurFreeKick.MaxChipRange  # type: ignore
 
         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:
+        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])
@@ -141,14 +148,18 @@ class OurFreeKick(standard_play.StandardPlay):
                 self.add_subbehavior(pass_behavior, 'kicker')
             else:
                 kicker.target = (self.pos_up_field)
-                self.add_subbehavior(kicker, 'kicker', required=False, priority=5)
+                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 execute_kick(self):
+    def execute_kick(self) -> None:
         if self.indirect \\
-           and self.subbehavior_with_name('kicker').state == tactics.coordinated_pass.CoordinatedPass.State.timeout:
+            and self.subbehavior_with_name(
+            'kicker').state == tactics.coordinated_pass.CoordinatedPass.State.timeout:
             self.indirect = False
             self.remove_subbehavior('kicker')
             kicker = skills.line_kick.LineKick()
@@ -160,14 +171,14 @@ class OurFreeKick(standard_play.StandardPlay):
             OurFreeKick.Running = passState == tactics.coordinated_pass.CoordinatedPass.State.receiving or \\
                                   passState == tactics.coordinated_pass.CoordinatedPass.State.kicking
 
-    def on_exit_kick(self):
+    def on_exit_kick(self) -> None:
         OurFreeKick.Running = False
 
     @classmethod
-    def is_restart(cls):
+    def is_restart(cls) -> bool:
         return True
 
-    def calc_move_pos(self):
+    def calc_move_pos(self) -> robocup.Point:
         point = self.gap
         if (self.indirect and self.receive_value != 0):
             point = self.receive_pt