--- /dev/null
+implementation module RefereeCoach_Rounds_Assignment\r
+\r
+import Referee\r
+\r
+RefereeCoach_Rounds :: !FootballField -> Referee\r
+RefereeCoach_Rounds field = { name = "RefereeCoach_Rounds"\r
+ , brain = { memory = mkMemory\r
+ , ai = randomlessRefereeAI (brain field)\r
+ }\r
+ , refActionPics = []\r
+ }\r
+\r
+:: Memory = { players :: ![(FootballerID, [Checkpoint])] // players and their checkpoints\r
+ , stage :: !Stage // current stage of training\r
+ }\r
+:: Stage = Begin | Rounds | End Success\r
+:: Checkpoint = { base :: !Position\r
+ , distance :: !Metre\r
+ , check :: !Bool\r
+ }\r
+\r
+mkMemory :: Memory\r
+mkMemory = { players = []\r
+ , stage = Begin\r
+ }\r
+\r
+fail :: Memory -> Memory\r
+fail memory = {memory & stage = End Fail}\r
+\r
+ok :: Memory -> Memory\r
+ok memory = {memory & stage = End Success}\r
+\r
+rounds :: Memory -> Memory\r
+rounds memory = {memory & stage = Rounds}\r
+\r
+instance toPosition3D Checkpoint\r
+where toPosition3D {base} = toPosition3D base\r
+\r
+cornerCheckpoints :: !FootballField !Metre -> [Checkpoint]\r
+cornerCheckpoints field d = [ { base = {px = x, py = y}, distance = d, check = False } \r
+ \\ x <- [scale -0.5 field.flength, scale 0.5 field.flength]\r
+ , y <- [scale 0.5 field.fwidth, scale -0.5 field.fwidth ]\r
+ ]\r
+\r
+checkPoint :: !Position !Checkpoint -> Checkpoint\r
+checkPoint pos checkpoint = {checkpoint & check = checkpoint.check || dist pos checkpoint <= checkpoint.distance}\r
+\r
+checkpointsCleared :: ![Checkpoint] -> Bool\r
+checkpointsCleared checks = and [check \\ {check} <- checks]\r
+\r
+distanceFromEdges :== m 5.0\r
+\r
+isIllegal :: !FootballField !Position !Metre -> Bool\r
+isIllegal field pos distance = point_in_rectangle ({px = scale -0.5 field.flength + distance, py = scale -0.5 field.fwidth + distance}\r
+ ,{px = scale 0.5 field.flength - distance, py = scale 0.5 field.fwidth - distance}\r
+ ) pos\r
+\r
+brain :: !FootballField !(!RefereeInput,!Memory) -> (!RefereeOutput,!Memory)\r
+\r
+// Assignment has started. Locate all players and their checkpoints.\r
+brain field ({RefereeInput | team1,team2},memory=:{stage = Begin})\r
+| isEmpty players = verdict [TellMessage "No players selected."] (fail memory)\r
+| otherwise = ([], rounds {memory & players = players})\r
+where\r
+ players = [(player.playerID,cornerCheckpoints field distanceFromEdges) \\ player <- team1 ++ team2]\r
+\r
+// Assignment is in the running stage. Monitor players and provide feedback.\r
+brain field ({RefereeInput | playingTime=time,unittime=dt,team1,team2},memory=:{players,stage = Rounds})\r
+| time <= minutes dt = verdict msg` (next next_memory)\r
+ with\r
+ (msg`,next) = if (all (checkpointsCleared o snd) checked) \r
+ ([], ok)\r
+ ([TellMessage "Not all checkpoints have been cleared."],fail)\r
+| isEmpty illegal_positions = ([], next_memory)\r
+| otherwise = ([TellMessage (length illegal_positions +++> " players have moved too far from edge.")], fail next_memory)\r
+where\r
+ next_memory = { memory & players = checked }\r
+ checked = [ (playerID, map (checkPoint pos) checkpoints) \\ (playerID,checkpoints) <- players\r
+ & pos <- positions\r
+ ]\r
+ positions = [ (find_player playerID all_players).pos \\ (playerID,_) <- players\r
+ ]\r
+ illegal_positions = [ (playerID,pos) \\ (playerID,_) <- players\r
+ & pos <- positions\r
+ | isIllegal field pos distanceFromEdges\r
+ ]\r
+ all_players = team1 ++ team2\r
+\r
+// Assignment has ended. Stop training session and give final verdict.\r
+brain _ (_,memory) = verdict [] memory\r
+\r
+verdict :: ![RefereeAction] !Memory -> (![RefereeAction],!Memory)\r
+verdict actions memory=:{stage=End how}\r
+ = (actions ++ [TellMessage msg,GameOver], memory)\r
+where\r
+ msg = if (how == Success) "Well done! Move on to next exercise."\r
+ "Improve your assignment and try again."\r
+verdict actions memory = (actions ++ [GameOver], fail memory)\r
+\r
+find_player :: FootballerID [Footballer] -> Footballer\r
+find_player playerID players = case filter (identify_player playerID) players of\r
+ [player : _] = player\r
+ no_one = abort ("player " <+++ playerID <+++ " lost in oblivion...")\r