initial framework added
[fp1415-soccerfun.git] / src / StdReferee / RefereeFunctions.icl
diff --git a/src/StdReferee/RefereeFunctions.icl b/src/StdReferee/RefereeFunctions.icl
new file mode 100644 (file)
index 0000000..be34336
--- /dev/null
@@ -0,0 +1,60 @@
+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