implementation module Team_MartLubbers import Footballer import FootballerFunctions Names:: [String] Names = [ "Odin", "Frigg", "Thor", "Balder", "Njord", "Freyr", "Freyja", "Tyr", "Bragi", "Heimdall", "Hoder", "Vidar", "Vale", "Ullr", "Forseti"] Team_MartLubbers :: !Home !FootballField -> Team Team_MartLubbers home field | home==West = westTeam | otherwise = eastTeam where eastTeam = mirror field westTeam westTeam = [keeper : fielders] clubname = base_TeamName_MartLubbers +++ if (home == West) "_W" "_E" keeper = Aesir clubname home field {zero & px=scale -0.5 field.flength} 1 "Thor" fielders = [Aesir clubname home field {px=scale (-0.5*dx) field.flength,py=scale (0.5*dy) field.fwidth} nr name \\ (dx,dy) <- west_positions_fielders & nr <- [2..] & name <- Names ] west_positions_fielders = [(0.20, 0.40) ,(0.20,-0.40) ,(0.23, 0.00) ,(0.50, 0.45) ,(0.50,-0.45) ,(0.60, 0.00) ,(0.70, 0.35) ,(0.70,-0.35) ,(0.90, 0.05) ,(0.90,-0.05) ] :: Mem = {home :: !Home, origpos :: Position, seed :: !RandomSeed} mirrorMem :: !Mem !FootballField -> Mem mirrorMem mm field = {mm & home=other mm.home, origpos=mirror field mm.origpos} Aesir :: !ClubName !Home !FootballField !Position !PlayersNumber !String -> Footballer Aesir club home field position nr name = { playerID = {clubName=club,playerNr=nr} , name = name +++ "_" <+++ nr , length = min_length , pos = position , nose = zero , speed = zero , skills = (Running, Kicking, Tackling) , effect = Nothing , stamina = max_stamina , health = max_health , brain = {memory=if (home == West) mm (mirrorMem mm field), ai = mind field} } where mm = {home=West, origpos=position, seed=nullRandomSeed} nextRandomNumber :: !Mem -> (Int, !Mem) nextRandomNumber mm=:{seed} = let (i, newseed) = random seed in (i rem 100, {mm & seed=newseed}) mind :: !FootballField !(!BrainInput, !Mem) -> (!BrainOutput, !Mem) mind field (x=:{referee,football,others,me}, mm=:{home,origpos}) # (i, mm) = nextRandomNumber mm // In case of the end of the half, mirror memory | any (isEndHalf) referee = mind field ({x & referee=filter (\x.not (isEndHalf x)) referee}, mirrorMem mm field) // In case of a pause or end, just halt | any (isPauseGame) referee || any (isGameOver) referee = halt (x, mm) // Keeper | me.playerID.playerNr == 1 | i_have_ball = kick closest_free_teammate (x, mm) | ball_in_reach maxCatchReach && not_previously_kicked = (CatchBall, mm) | ball_in_reach maxKickReach && not_previously_kicked = kick closest_free_teammate (x, mm) | ball_their_half = halt (x, mm) | ball_within_16 | we_have_ball = stayInGoal (x, mm) | ballIsFree football | isClosest others me ballPos.pxy = halt (x, mm) | otherwise = stayInGoal (x, mm) | otherwise | length (filter player_within_16 them) == 1 | (dist me.pos ballPos.pxy) < (maxCatchReach me) = (CatchBall, mm) | otherwise = fix ballPos.pxy (maxCatchReach me) (x, mm) | otherwise = stayInGoal (x, mm) | otherwise | we_have_ball = halt (x, mm) | otherwise = stayInGoal (x, mm) // Defense | me.playerID.playerNr > 7 | ball_their_half | i_have_ball = kick closest_free_teammate (x, mm) | otherwise = fix {origpos & px=origpos.px + (scale 0.5 ballPos.pxy.px)} prec (x, mm) | otherwise // TODO I have the ball | i_have_ball = moveForward i (x, mm) // TODO we have the ball | we_have_ball = fix {px=ballPos.pxy.px, py=origpos.py} prec (x, mm) // they have the ball | otherwise = obtainBall i (x, mm) // Attacker | otherwise | i_have_ball = moveForward i (x, mm) | ballIsFree football | ball_in_reach maxGainReach && not_previously_kicked = (GainBall, mm) | isClosest us me ballPos.pxy = fix ballPos.pxy prec (x, mm) | otherwise = fix {px=ballPos.pxy.px + (m 10.0), py=origpos.py} prec (x, mm) | we_have_ball = fix {px=ballPos.pxy.px + (m 10.0), py=origpos.py} prec (x, mm) | otherwise = obtainBall i (x, mm) where obtainBall :: Int -> FootballerAI m obtainBall i | ball_in_reach maxTackleReach && length has_ball > 0 | i < 15 = \(_,mm).(Tackle (hd has_ball).playerID (ms 10.0), mm) | otherwise = \(_,mm).(GainBall, mm) | ball_in_reach maxGainReach = \(_,mm).(GainBall, mm) | isClosest us me ballPos.pxy = fix ballPos.pxy prec | otherwise = fix (attract (scale 3.0 prec) closest_free_player ballPos.pxy) prec moveForward :: Int -> FootballerAI m moveForward i = kick closest_free_teammate stayInGoal = fix (attract goal_area_depth our_goal ballPos.pxy) prec closest_free_player = (closest them me.pos).pos closest_free_teammate | length players_closer_to_goal > 0 = (closest players_closer_to_goal me.pos).pos | otherwise = their_goal players_closer_to_goal = filter (\x.not (closerToHome home x.pos.px me.pos.px)) us player_within_16 p = inPenaltyArea field home p.pos ball_within_16 = inPenaltyArea field home ballPos.pxy not_previously_kicked = if (isNothing me.effect) True (not (isKickedBall (fromJust me.effect))) has_ball = filter (\x.ballIsGainedBy x.playerID football) others we_have_ball = any (\x.sameClub me x) has_ball they_have_ball = any (\x.not (sameClub me x)) has_ball i_have_ball = ballIsGainedBy me.playerID football ball_their_half = closerToHome home zero ballPos.pxy.px ball_in_reach distfunc = (dist me.pos ballPos) < (distfunc me) our_goal = (centerOfGoal home field) their_goal = (centerOfGoal (other home) field) ballPos = (getBall x).ballPos them = me opponents others us = me team others prec = maxGainReach me closest :: [Footballer] Position -> Footballer closest xs p = minListBy (\x y.(dist x.pos p) < (dist y.pos p)) xs isClosest :: [Footballer] Footballer Position -> Bool isClosest xs x p = closest [x:xs] p == x closerToHome :: !Home -> a a -> Bool | Ord a closerToHome East = (>) closerToHome West = (<) distToLine :: Position Position Position -> Metre distToLine a b c = (abs (((b.px-a.px)*(a.py-c.py))-((a.px-c.px)*(b.py-a.py))))/d where (*) m1 m2 = (m (toReal m1)/(toReal m2)) (/) m1 m2 = (m (toReal m1)/(toReal m2)) d = sqrt(((b.px-a.px)*(b.px-a.px))+((b.py-a.py)*(b.py-a.py))) base_TeamName_MartLubbers :: String base_TeamName_MartLubbers = "Ęsir"