initial framework added
[fp1415-soccerfun.git] / src / StdReferee / RefereeCoach_Keeper_Assignment.icl
1 implementation module RefereeCoach_Keeper_Assignment
2
3 import StdEnvExt
4 import Referee
5 import Team_Opponent_Keeper_Assignment
6 import Team_Student_Keeper_Assignment
7
8 RefereeCoach_Keeper :: !FootballField -> Referee
9 RefereeCoach_Keeper field = { name = "RefereeCoach Keeper"
10 , brain = { memory = initMem
11 , ai = randomlessRefereeAI (brain field)
12 }
13 , refActionPics = []
14 }
15
16 :: Memory = { first :: !Bool
17 , practiceFailed :: !Bool
18 , gameOver :: !Bool
19 , showHowExit :: !Maybe Exit
20 , timesGainedBy5 :: !Int
21 , practiceSucceed :: !Bool
22 }
23 :: Exit = { student :: !Team
24 , computer :: !Team
25 , ball :: !Position
26 , exit :: !Position
27 }
28
29 initMem :: Memory
30 initMem = { first = True
31 , practiceFailed = False
32 , gameOver = False
33 , showHowExit = Nothing
34 , timesGainedBy5 = 0
35 , practiceSucceed = False
36 }
37
38 brain :: !FootballField !(!RefereeInput,!Memory) -> (!RefereeOutput,!Memory)
39 brain field ({RefereeInput | playingTime=time,theBall=ballState,team1,team2},memory)
40 | memory.gameOver // game over because of succes or failure
41 = ([GameOver],memory)
42 | memory.practiceFailed && memory.practiceSucceed // assignment failed but you had already succeeded
43 = ([TellMessage "Failed, but you had already passed the test", DirectFreeKick studentHome ballKickoff],{memory & practiceFailed = False, showHowExit = Nothing})
44 | memory.practiceFailed // assignment failed
45 = ([TellMessage "Assignment failed, correct your team and try again"],{memory & gameOver = True})
46 | isEmpty (filter isKeeper studentTeam) // check if there is a keeper
47 = ([TellMessage ("No keeper in student team, please choose " <+++ base_TeamName_Student_Keeper)],{memory & gameOver = True})
48 # (refActions,memory) = if (time <= minutes 0.5 && not memory.practiceSucceed)
49 ([TellMessage "Well Done! (but let's see how much longer you can gain control...)"], {memory & practiceSucceed=True})
50 ([],memory)
51 # (refActions,memory) = if memory.first // when this is the first round, reposition the ball
52 (refActions ++ [DirectFreeKick studentHome ballKickoff],{memory & first = False})
53 (refActions,memory)
54 | isJust memory.showHowExit // The ball could pass, show how the ball could pass the keeper
55 # exitInfo = fromJust memory.showHowExit
56 # directionToExit = bearing zero exitInfo.ball exitInfo.exit // move the ball towards exit
57 # nextBallPos = move_point {dx = m (cosinus directionToExit), dy = m (sinus directionToExit)} exitInfo.ball
58 | studentHome == West && nextBallPos.px < scale -0.5 field.flength || studentHome == East && nextBallPos.px > scale 0.5 field.flength
59 = ([],{memory & practiceFailed = True})
60 | otherwise = ([DirectFreeKick West nextBallPos],{memory & showHowExit = Just {exitInfo & ball=nextBallPos}})
61 | not memory.first && topExit.py >= scale 0.5 goal_width - spaceAllowed
62 # sideStr = if (studentHome == West) "left" "right"
63 = ( [TellMessage ("Keeper left the " <+++ sideStr <+++ " side of the goal open. Exit ypos could be: " <+++ topExit.py)]
64 , {memory & showHowExit = Just {student=studentTeam,computer=compTeam,ball=theBall.ballPos.pxy,exit=topExit}}
65 )
66 | not memory.first && bottomExit.py <= scale -0.5 goal_width + spaceAllowed
67 # sideStr = if (studentHome == West) "right" "left"
68 = ( [TellMessage ("keeper left the " <+++ sideStr <+++ " side of the goal open. Exit ypos could be: " <+++ bottomExit.py)]
69 , {memory & showHowExit = Just {student=studentTeam,computer=compTeam,ball=theBall.ballPos.pxy,exit=bottomExit}}
70 )
71 | otherwise = (refActions,memory)
72 where
73 (compTeam,studentTeam,studentHome)
74 = if (stringStarts (nameOf team1) base_TeamName_Opponent_Keeper) (team1,team2,East) (team2,team1,West)
75 ballKickoff = if (studentHome == West)
76 {zero & px = scale -0.5 field.flength + penalty_area_depth}
77 {zero & px = scale 0.5 field.flength - penalty_area_depth}
78
79 /* The keeper has to cover the entire width of the goal minus spaceAllowed at both sides in order to be succesfull enough for this assignment.
80 */ spaceAllowed = scale (1.0/6.0) goal_width
81 theBall = getFootball ballState (team1 ++ team2)
82 keeper = hd (filter isKeeper studentTeam)
83 keeperPos = keeper.pos
84 ballDirection2keeper = bearing zero theBall keeper
85 (topReachKeeper,bottomReachKeeper)
86 = getMaximumCatchPositions ballDirection2keeper
87
88 /* Draws a line from football to keeper
89 determines the two directions the keeper can jump to cover max area behind him
90 gets the maximum distance the keeper can catch/jump
91 returns the two positions past which the ball can pass the keeper
92 */ getMaximumCatchPositions :: !Angle -> (!Position,!Position)
93 getMaximumCatchPositions ballDirection2keeper
94 # ballDirection2keeper = if (ballDirection2keeper < rad (1.5*pi)) (ballDirection2keeper + rad (1.5*pi)) (ballDirection2keeper - rad (0.5*pi))
95 # catchCorner1 = if (ballDirection2keeper < rad (1.5*pi)) (ballDirection2keeper + rad (1.5*pi)) (ballDirection2keeper - rad (0.5*pi))
96 # catchCorner2 = if (ballDirection2keeper > rad (0.5*pi)) (ballDirection2keeper - rad (1.5*pi)) (ballDirection2keeper + rad (0.5*pi))
97 # maxCatchDistance = maxCatchReach keeper
98 # maxPoint1 = {px=keeperPos.px + scale (sinus catchCorner1) maxCatchDistance, py=keeperPos.py + scale (~(cosinus catchCorner1)) maxCatchDistance }
99 # maxPoint2 = {px=keeperPos.px + scale (sinus catchCorner2) maxCatchDistance, py=keeperPos.py + scale (~(cosinus catchCorner2)) maxCatchDistance }
100 | maxPoint1.py < maxPoint2.py = (maxPoint2,maxPoint1)
101 | otherwise = (maxPoint1,maxPoint2)
102
103 // What if the keeper is passed could be the lowest position to let the ball exit the field
104 direction2topReach = bearing zero theBall topReachKeeper
105 topExit = getExitPos topReachKeeper theBall.ballPos.pxy direction2topReach
106 // What if the keeper is passed could be the lowest position to let the ball exit the field
107 direction2bottomReach = bearing zero theBall bottomReachKeeper
108 bottomExit = getExitPos bottomReachKeeper theBall.ballPos.pxy direction2bottomReach
109
110 getExitPos :: !Position !Position !Angle -> Position
111 getExitPos reachPos ballPos direction
112 = while aintOut (move_point {dx=m (cosinus dir),dy=m (sinus dir)}) target
113 where
114 (dir,target) = if (reachPos.px >= zero) (direction,reachPos) (oppositeDirection direction,ballPos)
115 aintOut = point_in_rectangle ({px = scale -0.5 field.flength, py = scale -0.5 field.fwidth}
116 ,{px = scale 0.5 field.flength, py = scale 0.5 field.fwidth}
117 )
118
119 oppositeDirection :: !Angle -> Angle
120 oppositeDirection d
121 | d > rad pi = d - rad pi
122 | otherwise = d + rad pi