--- /dev/null
+implementation module RefereeFunctions\r
+\r
+import Referee\r
+\r
+ball_left_field_at :: !FootballField -> RefereeAI` (Maybe Position)\r
+ball_left_field_at field=:{fwidth,flength}\r
+ = \{RefereeInput | theBall}\r
+ -> case theBall of\r
+ Free ball = if (point_in_rectangle field_coordinates ball.ballPos.pxy)\r
+ Nothing\r
+ (Just (point_to_rectangle field_coordinates ball.ballPos.pxy))\r
+ gained = Nothing // footballers are incapable of leaving the football field\r
+where\r
+ field_coordinates = ({px = scale -0.5 flength, py = scale -0.5 fwidth}, {px = scale 0.5 flength, py = scale 0.5 fwidth})\r
+\r
+ball_in_goal :: !FootballField -> RefereeAI` (Maybe Home)\r
+ball_in_goal field=:{flength}\r
+ = \{RefereeInput | theBall}\r
+ -> case theBall of\r
+ Free ball = let ball_inside = isbetween ball.ballPos.pxy.py south north && ball.ballPos.pz <= goal_height\r
+ in if (ball.ballPos.pxy.px < scale -0.5 flength && ball_inside) (Just West)\r
+ (if (ball.ballPos.pxy.px > scale 0.5 flength && ball_inside) (Just East)\r
+ Nothing\r
+ )\r
+ gained = Nothing // footballers must kick the ball in the goal to score\r
+where\r
+ (north,south) = goal_poles field\r
+\r
+half_of_game :: !PlayingTime -> RefereeAI` Half\r
+half_of_game total_time\r
+ = \{RefereeInput | playingTime}\r
+ -> if (playingTime >= scale 0.5 total_time) FirstHalf SecondHalf\r
+\r
+players_in_offside_position :: !FootballField !Home -> RefereeAI` (AssocList FootballerID Position)\r
+players_in_offside_position field home\r
+ = \{RefereeInput | theBall,playingHalf,team1,team2}\r
+ -> let (players1,players2) = if (home == West && playingHalf == FirstHalf || home == East && playingHalf == SecondHalf)\r
+ (displacements team1, displacements team2)\r
+ (displacements team2, displacements team1)\r
+ ball = getFootball theBall (team1 ++ team2)\r
+ in offside_players field ball home players1 players2\r
+\r
+/** offside_players field ball home team opponents:\r
+ returns the players from @team that are in offside position.\r
+ @home is the current home of @team, and @opponents are the current opponents.\r
+ @ball is the current ball.\r
+*/\r
+offside_players :: !FootballField !Football !Home !Displacements !Displacements -> Displacements\r
+offside_players field ball home team opponents\r
+ = [(player,pos) \\ (player,pos) <- team // a player is in offside position if:\r
+ | team_ord pos.px middle_x // he is at the opponent's half of the field, and\r
+ && team_ord pos.px opponent_x // he is closer to the opponent's base line than the 2nd-last opponent, and\r
+ && team_ord pos.px ball_x // he is closer to the opponent's base line than the ball\r
+ ]\r
+where\r
+ middle_x = zero\r
+ ball_x = ball.ballPos.pxy.px\r
+ team_ord = if (home == West) (>) (<)\r
+ opponent_x = (snd ((sortBy opponent_ord opponents) !! 1)).px\r
+ opponent_ord = if (home == West) (\(_,p1) (_,p2) -> p1.px >= p2.px) (\(_,p1) (_,p2) -> p1.px <= p2.px)\r