--- /dev/null
+implementation module FootballerFunctions\r
+\r
+import Footballer\r
+\r
+returnAI` :: !FootballerAction -> FootballerAI`\r
+returnAI` action = const action\r
+\r
+move` :: !Speed !Angle -> FootballerAI`\r
+move` speed angle = returnAI` (Move speed angle)\r
+\r
+halt` :: FootballerAI`\r
+halt` = move` zero zero\r
+\r
+rotate` :: !Angle -> FootballerAI`\r
+rotate` angle = move` zero angle\r
+\r
+ahead` :: !Velocity -> FootballerAI`\r
+ahead` v = \input=:{me} -> move` {direction=me.nose,velocity=v} zero input\r
+\r
+fix` :: !Position !Metre -> FootballerAI`\r
+fix` point eps = \input=:{me} ->\r
+ let distance = dist me point\r
+ angle = bearing zero me point\r
+ rotate = bearing me.nose me point\r
+ v = ms (max 6.0 (toReal distance))\r
+ in if (distance <= eps)\r
+ (halt` input)\r
+ (move` {direction=angle,velocity=v} rotate input)\r
+\r
+kick` :: !Position -> FootballerAI`\r
+kick` point = \input=:{me} ->\r
+ let ball = getBall input\r
+ angle = bearing zero me point\r
+ v = ms (2.0 * (toReal (dist me point)))\r
+ in if (dist me ball <= maxKickReach me)\r
+ (KickBall {vxy = {direction=angle,velocity=v},vz=ms 1.0})\r
+ (halt` input)\r
+\r
+track_ball` :: !Metre -> FootballerAI`\r
+track_ball` eps = \input -> fix` (getBall input).ballPos.pxy eps input\r
+\r
+amnesia :: FootballerAI` -> FootballerAI m\r
+amnesia f = \(input,m) -> (f input,m)\r
+\r
+returnAI :: (FootballerAction -> FootballerAI m)\r
+returnAI = amnesia o returnAI`\r
+\r
+move :: (Speed Angle -> FootballerAI m)\r
+move = \speed angle -> amnesia (move` speed angle)\r
+\r
+halt :: (FootballerAI m)\r
+halt = amnesia halt`\r
+\r
+rotate :: (Angle -> FootballerAI m)\r
+rotate = amnesia o rotate`\r
+\r
+ahead :: (Velocity -> FootballerAI m)\r
+ahead = amnesia o ahead`\r
+\r
+fix :: (Position Metre -> FootballerAI m)\r
+fix = \point eps -> amnesia (fix` point eps)\r
+\r
+kick :: (Position -> FootballerAI m)\r
+kick = amnesia o kick`\r
+\r
+track_ball :: (Metre -> FootballerAI m)\r
+track_ball = \eps -> amnesia (track_ball` eps)\r
+\r
+centerOfGoal :: !Home !FootballField -> Position\r
+centerOfGoal home field = {zero & px = if (home==West) (~half_length) half_length}\r
+where\r
+ half_length = scale 0.5 field.flength\r
+\r
+(team) infix 9 :: !Footballer ![Footballer] -> [Footballer]\r
+(team) player players = filter (sameClub player) players\r
+\r
+(opponents) infix 9 :: !Footballer ![Footballer] -> [Footballer]\r
+(opponents) player players = filter (not o (sameClub player)) players\r
+\r
+getBall :: !BrainInput -> Football\r
+getBall {football,me,others}= getFootball football [me : others]\r
+\r
+:: HomeM m = { home :: !Home, mem :: !m }\r
+\r
+educate` :: (Home -> FootballerAI`) -> FootballerAI (HomeM m)\r
+educate` home_ai = \(input=:{referee},memory) ->\r
+ let new_home = if (any isEndHalf referee) other id memory.home\r
+ action = home_ai new_home input\r
+ in (action, {memory & home = new_home})\r
+\r
+educate :: (Home -> FootballerAI m) -> FootballerAI (HomeM m)\r
+educate home_ai = \(input=:{referee},memory) ->\r
+ let new_home = if (any isEndHalf referee) other id memory.home\r
+ (action,new_memory) = home_ai new_home (input,memory.mem)\r
+ in (action, {memory & home = new_home, mem = new_memory})\r