initial framework added
[fp1415-soccerfun.git] / src / StdReferee / RefereeCoach_Slalom_Assignment.icl
1 implementation module RefereeCoach_Slalom_Assignment
2
3 import Referee
4
5 RefereeCoach_Slalom :: !FootballField -> Referee
6 RefereeCoach_Slalom field = { name = "RefereeCoach_Slalom"
7 , brain = { memory = mkMemory
8 , ai = randomlessRefereeAI (brain field)
9 }
10 , refActionPics = []
11 }
12
13 :: Stage = Begin | Slalom | Kick | End Success
14 instance == Stage where == Begin Begin = True
15 == Slalom Slalom = True
16 == Kick Kick = True
17 == (End s1) (End s2) = s1 == s2
18 == _ _ = False
19
20 :: Memory = { positions :: ![Position] // all positions of student player, in reverse order
21 , stage :: !Stage // the current stage of the training
22 , home :: Home // home of student player, determined at Begin
23 }
24
25 mkMemory :: Memory
26 mkMemory = { positions = []
27 , stage = Begin
28 , home = undef
29 }
30
31 slalom :: Memory -> Memory
32 slalom memory = {memory & stage = Slalom}
33
34 after_kick :: Memory -> Memory
35 after_kick memory = {memory & stage = Kick}
36
37 fail :: Memory -> Memory
38 fail memory = {memory & stage = End Fail}
39
40 ok :: Memory -> Memory
41 ok memory = {memory & stage = End Success}
42
43 position :: Position Memory -> Memory
44 position p memory = {memory & positions = [p:memory.positions]}
45
46 knownHome :: Home Memory -> Memory
47 knownHome home memory = {memory & home = home}
48
49 brain :: !FootballField !(!RefereeInput,!Memory) -> (!RefereeOutput,!Memory)
50 // Assignment has started. Check teams and determine home of student player.
51 brain field ({RefereeInput | team1,team2},memory=:{stage = Begin})
52 | not ok_teams = ([TellMessage "Wrong teams selected."],fail memory)
53 | otherwise = ([DirectFreeKick home ball],position student.pos (slalom (knownHome home memory)))
54 where
55 (ok_teams,home) = case (team1,team2) of
56 ([p],[_,_:_]) = (True, West)
57 ([_,_:_],[p]) = (True, East)
58 otherwise = (False,undef)
59 student = if (home == West) (hd team1) (hd team2)
60 west_ball_pos = {zero & px = scale -0.5 field.flength + penalty_area_depth}
61 ball = if (home == West) (mirror field west_ball_pos) west_ball_pos
62 // Assignment has ended. Stop training session.
63 brain _ (_,memory=:{stage = End how})
64 = ([TellMessage msg, GameOver],memory)
65 where
66 msg = if (how == Success) "Well done! Move on to next exercise."
67 "Improve your assignment and try again."
68 // Assignment is in slalom or kicking stage.
69 brain field ({RefereeInput | playingTime=time, theBall=ballState, team1, team2}, memory=:{home,positions,stage})
70 | time <= zero = ([TellMessage "Out of time."],fail memory) // time's up
71 | ballIsFree ballState && ballIsOut field ball // ball is out
72 # ball_pos = ball.ballPos.pxy
73 # (north,south) = goal_poles field
74 | not (isbetween ball_pos.py south north) // student did not kick ball in goal
75 = ([TellMessage "You should play the ball in the goal."],fail memory)
76 | home == West && ball_pos.px < scale -0.5 field.flength + m 1.0 ||
77 home == East && ball_pos.px > scale 0.5 field.flength - m 1.0 // student kicked ball in wrong goal
78 = ([TellMessage "You should play the ball in the other goal."],fail memory)
79 | otherwise = ([ContinueGame],ok memory) // student ended exercise correctly
80 | isMoved action
81 | compare_pos student.pos last_pos // student is moving in wrong direction
82 = ([TellMessage "You're moving in the wrong direction."],fail memory)
83 | any (\other -> dist other student < m 0.5) others // student moves too close to opponents
84 = ([TellMessage "Don't move so close to opponents."],fail memory)
85 | not up_and_down = ([TellMessage "You're not doing a slalom."],fail memory) // student is not doing slalom
86 | otherwise = ([ContinueGame],memory)
87 | isKickedBall action
88 | stage == Kick = ([TellMessage "Don't kick the ball twice."],fail memory) // kick the ball only once
89 | otherwise = ([ContinueGame],after_kick memory)
90 | otherwise = ([TellMessage ("Illegal action. Perform only Move and KickBall. You did: " <+++ typeOfAction action)],fail memory)
91 where
92 ball = getFootball ballState (team1 ++ team2)
93 (student,others) = if (home == West) (hd team1,team2) (hd team2,team1)
94 action = fromJust student.effect
95 last_pos = hd positions
96 new_positions = [student.pos : positions]
97 compare_px = if (home == West) < >
98 compare_pos pos1 pos2 = compare_px pos1.px pos2.px
99 close_px pos1 pos2 = abs (pos1.px - pos2.px) <= m 1.0
100 line_up_others = sortBy compare_pos (map (\{Footballer | pos} -> pos) others)
101 close_encounters = takeWhile (not o isEmpty) [filter (close_px other_pos) new_positions \\ other_pos <- line_up_others]
102 up_and_down = isAlternating
103 [ map (\studentpos -> studentpos.py < other_pos.py) close_encounter
104 \\ close_encounter <- close_encounters
105 & other_pos <- line_up_others
106 ]
107
108 ballIsOut :: !FootballField !Football -> Bool
109 ballIsOut field ball = not (point_in_rectangle ({px = scale -0.5 field.flength, py = scale -0.5 field.fwidth}
110 ,{px = scale 0.5 field.flength, py = scale 0.5 field.fwidth}
111 ) ball.ballPos.pxy)
112
113 typeOfAction :: !FootballerEffect -> String
114 typeOfAction (Moved _ _) = "Move"
115 typeOfAction (GainedBall _) = "GainBall"
116 typeOfAction (KickedBall _) = "KickBall"
117 typeOfAction (HeadedBall _) = "HeadBall"
118 typeOfAction (Feinted _) = "Feint"
119 typeOfAction (Tackled _ _ _) = "Tackle"
120 typeOfAction (CaughtBall _) = "Catch"
121
122 isAlternating :: [[a]] -> Bool | Eq, ~ a
123 isAlternating sequences = isEmpty sequences || all isSingleton singletons && map hd singletons == take n (iterate ~ (hd (hd singletons)))
124 where
125 singletons = map removeDup sequences
126 n = length sequences