9fa5a09dbb0c2cb3509f2fdece2697d363cab462
[fp1415-soccerfun.git] / src / Team_MartLubbers.icl
1 implementation module Team_MartLubbers
2
3 import Footballer
4 import FootballerFunctions
5
6 Names:: [String]
7 Names = [
8 "Odin",
9 "Frigg",
10 "Thor",
11 "Balder",
12 "Njord",
13 "Freyr",
14 "Freyja",
15 "Tyr",
16 "Bragi",
17 "Heimdall",
18 "Hoder",
19 "Vidar",
20 "Vale",
21 "Ullr",
22 "Forseti"]
23
24 Team_MartLubbers :: !Home !FootballField -> Team
25 Team_MartLubbers home field
26 | home==West = westTeam
27 | otherwise = eastTeam
28 where
29 eastTeam = mirror field westTeam
30 westTeam = [keeper : fielders]
31 clubname = base_TeamName_MartLubbers +++ if (home == West) "_W" "_E"
32 keeper = Aesir clubname home field {zero & px=scale -0.5 field.flength} 1 "Thor"
33 fielders = [Aesir clubname home field {px=scale (-0.5*dx) field.flength,py=scale (0.5*dy) field.fwidth} nr name
34 \\ (dx,dy) <- west_positions_fielders
35 & nr <- [2..]
36 & name <- Names
37 ]
38 west_positions_fielders = [(0.20, 0.40)
39 ,(0.20,-0.40)
40 ,(0.23, 0.00)
41 ,(0.50, 0.45)
42 ,(0.50,-0.45)
43 ,(0.60, 0.00)
44 ,(0.70, 0.35)
45 ,(0.70,-0.35)
46 ,(0.90, 0.05)
47 ,(0.90,-0.05)
48 ]
49
50 :: Role = Attack | Mid | Defense | Keeper
51
52 isAttack :: Role -> Bool
53 isAttack Attack = True
54 isAttack _ = False
55
56 isMid :: Role -> Bool
57 isMid Mid = True
58 isMid _ = False
59
60 isDefense :: Role -> Bool
61 isDefense Defense = True
62 isDefense _ = False
63
64 isKeep :: Role -> Bool
65 isKeep Keeper = True
66 isKeep _ = False
67
68 fromNumber :: Int -> Role
69 fromNumber 1 = Keeper
70 fromNumber i
71 | i < 4 = Attack
72 | i < 10 = Mid
73 | otherwise = Defense
74
75 :: Mem = {home :: !Home, origpos :: Position, seed :: !RandomSeed, role :: Role}
76
77 mirrorMem :: !Mem !FootballField -> Mem
78 mirrorMem mm field = {mm & home=other mm.home, origpos=mirror field mm.origpos}
79
80 Aesir :: !ClubName !Home !FootballField !Position !PlayersNumber !String -> Footballer
81 Aesir club home field position nr name
82 = { playerID = {clubName=club,playerNr=nr}
83 , name = name +++ "_" <+++ nr
84 , length = min_length
85 , pos = position
86 , nose = zero
87 , speed = zero
88 , skills = (Running, Kicking, Rotating)
89 , effect = Nothing
90 , stamina = max_stamina
91 , health = max_health
92 , brain = {memory=if (home == West) mm (mirrorMem mm field), ai = mind field}
93 }
94 where
95 mm = {home=West, origpos=position, seed=nullRandomSeed, role=fromNumber nr}
96
97 nextRandomNumber :: !Mem -> (Int, !Mem)
98 nextRandomNumber mm=:{seed} = let (i, newseed) = random seed in (i rem 100, {mm & seed=newseed})
99
100 mind :: !FootballField !(!BrainInput, !Mem) -> (!BrainOutput, !Mem)
101 mind field (x=:{referee,football,others,me}, mm=:{home,origpos,role})
102 // In case of the end of the half, mirror memory
103 | any (isEndHalf) referee = mind field ({x & referee=filter (\x.not (isEndHalf x)) referee}, mirrorMem mm field)
104 // In case of a pause or end, just halt
105 | any (isPauseGame) referee || any (isGameOver) referee = halt (x, mm)
106 // If I'm a keeper
107 | isKeep role
108 // Ball is in the other half of the field
109 | closerToGoal home ballPos zero = halt (x, mm)
110 // Ball gained by us
111 | we_have_ball
112 // Ball not in penalty area
113 | closerToGoal home ballPos {px=penalty_area_depth, py=zero} = halt (x, mm)
114 // Ball in penalty area
115 | otherwise
116 // Ball gained by them
117 | otherwise = halt (x, mm)
118 // If I'm a field player
119 | otherwise
120 // TODO:: The ball is free
121 | ballIsFree football
122 // I'm closest to the ball
123 | isClosest us me ballPos.pxy = afterfix (\(_,_).(GainBall, mm)) ballPos.pxy prec (x, mm)
124 // TODO: Some other player is the closest to the ball
125 | otherwise = halt (x, mm)
126 // TODO: We have the ball
127 | we_have_ball = halt (x, mm)
128 // TODO: I have the ball
129 | ballIsGainedBy me.playerID football
130 // TODO: Someone else has the ball
131 | otherwise = halt (x, mm)
132 // TODO: The ball is with the others
133 | otherwise = halt (x, mm)
134 where
135 we_have_ball = any (\x.ballIsGainedBy x.playerID football) us
136 ballPos = (getBall x).ballPos
137 them = me opponents others
138 us = me team others
139 prec = scale 0.5 (maxKickReach me)
140
141 closest :: [Footballer] Position -> Footballer
142 closest xs p = minListBy (\x y.(dist x.pos p) < (dist y.pos p)) xs
143
144 isClosest :: [Footballer] Footballer Position -> Bool
145 isClosest xs x p = closest [x:xs] p == x
146
147 closerToGoal :: !Home -> Metre Metre -> Bool
148 closerToGoal East = (<)
149 closerToGoal West = (>)
150
151 distToLine :: Position Position Position -> Metre
152 distToLine a b c = (abs (((b.px-a.px)*(a.py-c.py))-((a.px-c.px)*(b.py-a.py))))/d
153 where
154 (*) m1 m2 = (m (toReal m1)/(toReal m2))
155 (/) m1 m2 = (m (toReal m1)/(toReal m2))
156 d = sqrt(((b.px-a.px)*(b.px-a.px))+((b.py-a.py)*(b.py-a.py)))
157
158 afterfix :: (FootballerAI Mem) !Position !Metre !(!BrainInput, !Mem) -> (BrainOutput, !Mem)
159 afterfix after point diff (input=:{me,others}, mm)
160 # (i, mm) = nextRandomNumber mm
161 | d < diff = after (input, mm)
162 // There is a enemy standing in the way and I feel like it
163 | (dist closestOpp me.pos) < (maxTackleReach me) && i < 15 = (Tackle closestOpp.playerID (ms 6.0), mm)
164 // There is no enemy standing in the way
165 | otherwise = (move, mm)
166 where
167 closestOpp = closest (me opponents others) me.pos
168 d = dist me point
169 a = bearing zero me point
170 r = bearing me.nose me point
171 v = ms (max 6.0 (toReal d))
172 move = Move {direction=a, velocity=v} r
173
174 base_TeamName_MartLubbers :: String
175 base_TeamName_MartLubbers = "Æsir"