packages feed

Rasenschach-0.1: Lineup.hs

module Lineup where

import Debug.Trace

import Data.List
import Data.Maybe
import Data.Ord

import FRP.Yampa
import FRP.Yampa.Geometry

import Object
import ObjectBehaviour
import Message
import AL
import Global
import BasicTypes
import Helper
import States
import Physics


lineupKickoff :: Param -> ALOut -> Time -> Team -> Int -> Int -> (ALOut, ALObj)
lineupKickoff param alout time possession scoreHome scoreAway =
   let (homeOos, homeObjs, maybeHomeKickers) = lineupKickoffTeam param alout Home (possession == Home)
       (awayOos, awayObjs, maybeAwayKickers) = lineupKickoffTeam param alout Away (possession == Away)
       (kicksOff, kickedTo) = if maybeHomeKickers == Nothing then
                                   fromJust maybeAwayKickers
                              else fromJust maybeHomeKickers
       bid = ballId alout
       gid = gameId alout
       (ballOos, ballObjs) = lineupKickoffBall param bid kicksOff time
       (gameOos, gameObjs) = lineupKickoffGame param gid time possession scoreHome scoreAway
   in
#if DEBUG_MODE
       trace ("Lineup durchgeführt" ++
              show ((ballOos  `appendAL` gameOos  `appendAL` homeOos  `appendAL` awayOos)) ++
              show "Home=" ++ show (map fst $ assocsAL homeObjs) ++
              show "Away=" ++ show (map fst $ assocsAL awayObjs)) $
#endif
       (ballOos  `appendAL` gameOos  `appendAL` homeOos  `appendAL` awayOos,
        ballObjs `appendAL` gameObjs `appendAL` homeObjs `appendAL` awayObjs)


-- *************************************************************************
--
-- Player lineups
--
-- *************************************************************************

-- returns the lineup for given team on kickoff, depending on whether team
-- kicks off or nor, and also the player who has the ball on kickoff (if any)
lineupKickoffTeam :: Param -> ALOut -> Team -> Bool -> (ALOut, ALObj, Maybe (ObjId, ObjId))
lineupKickoffTeam param oos team kicksoff =
   let players = (filterAL ((== team) . fst3 . oosTeamInfo) .
                  mapAL (ooObsObjState . snd) .
                  filterAL isPlayerOO) oos
       sorted = fromAssocs $
                sortBy (\(_, oos) (_, oos') ->
                    comparing dist oos oos') $
                assocsAL players
       (kicksOffPlId, kicksOffPl) = sorted `at` 0
       (kickedToPlId, kickedToPl)  = sorted `at` 1
       kickOffSpot = Point2 (pPitchWidth param / 2) (pPitchLength param / 2)
       dist oos = distance (basePos oos) kickOffSpot
       basePls = if kicksoff then deleteAL kicksOffPlId $
                                  deleteAL kickedToPlId players
                             else players
       (baseOuts, baseObjs) = mkBase param team basePls
       (kicksOut, kicksObjs) = if kicksoff then mkObjs param team
                                                       (kicksOffPlId, kicksOffPl)
                                                       (kickedToPlId, kickedToPl)
                                           else (emptyAL, emptyAL)
   in (baseOuts `appendAL` kicksOut,
       baseObjs `appendAL` kicksObjs,
       if kicksoff then Just (kicksOffPlId, kickedToPlId)
                   else Nothing
      )

isPlayerOO (ObjOutput {ooObsObjState = OOSPlayer {}}) = True
isPlayerOO _ = False

mkBase param team oos =
   (mapAL (mkStandardPlayerObjOutput . snd) oos,
    mapAL (uncurry (mkStandardPlayerObject param team)) oos)

mkObjs param team (fromId, fromPl) (toId, toPl) =
   let toOut = mkKickedToPlayerObjOutput param team toPl
       toObj = mkKickedToPlayerObject param toId team toPl

       fromOut = mkKicksOffPlayerObjOutput param team fromPl
       fromObj = mkKicksOffPlayerObject param fromId team fromPl

   in (fromAssocs [(toId, toOut), (fromId, fromOut)],
       fromAssocs [(toId, toObj), (fromId, fromObj)])

basePos = piBasePosDefense. oosPlayerInfo

kicksOffPosition param team
--   | team == Home = Point2 42 52    -- basierend auf 80, 96 muss man noch verformeln
--   | team == Away = Point2 38 44
   | team == Home = Point2 (pPitchWidth param / 2 + 2) (pPitchLength param / 2 + 1)
   | team == Away = Point2 (pPitchWidth param / 2 - 2) (pPitchLength param / 2 - 1)


kickedToPosition param team
--   | team == Home = Point2 35 50
--   | team == Away = Point2 45 46
   | team == Home = Point2 (pPitchWidth param / 2 - 5) (pPitchLength param / 2)
   | team == Away = Point2 (pPitchWidth param / 2 + 5) (pPitchLength param / 2)


----------------------------------------------------------------------------------
--
-- create ObjOutput for player
--
----------------------------------------------------------------------------------

mkpoo :: Position2 -> ObsObjState -> ObjOutput
mkpoo pos oos = ObjOutput
   oos {oosPos = pos .+! 0}
   NoEvent NoEvent []

mkStandardPlayerObjOutput :: ObsObjState -> ObjOutput
mkStandardPlayerObjOutput oos = mkpoo (basePos oos) oos

mkKickedToPlayerObjOutput param = mkpoo . kickedToPosition param
mkKicksOffPlayerObjOutput param = mkpoo . kicksOffPosition param


----------------------------------------------------------------------------------
--
-- create Object for player
--
----------------------------------------------------------------------------------

mkpo :: Param -> ObjId -> ObsObjState -> Position2 -> BasicState -> Angle -> Object
mkpo param  oid oos pos pbsInit angle0 =
   maker param
         oid
         0
         pos
         (vector3 0 0 0)
         angle0
         (oosSelected oos)
         False --(oosDesignated oos)
         (oosTeamInfo oos)
         (oosPlayerInfo oos)
         pbsInit
         NoFoot
         (if (== Goalie) . piPlayerRole . oosPlayerInfo $ oos then TSGoalieWaitingForKickOff
          else if ai then TSWaitingForKickOff else TSNonAIKickingOff)
   where ai = not $ oosSelected oos
         playerRole (_,pr,_,_) = pr
         maker = if ai then playerAI else player


mkStandardPlayerObject :: Param -> Team -> ObjId -> ObsObjState -> Object
mkStandardPlayerObject param team oid oos =
   mkpo param oid oos (basePos oos) PBSNoBall (if team == Home then 3*pi/2 else pi/2)
mkKickedToPlayerObject param oid team oos =
   mkpo param oid oos (kickedToPosition param team) PBSNoBall (if team == Home then 0 else pi)
mkKicksOffPlayerObject param oid team oos =
   mkpo param oid oos (kicksOffPosition param team) PBSInPossession (if team == Home then pi else 0)


-- *************************************************************************
--
-- Ball lineup
--
-- *************************************************************************

lineupKickoffBall :: Param -> ObjId -> ObjId -> Time -> (ALOut, ALObj)
lineupKickoffBall param ballId playerId t0 =
  let (_, bobjs, boos) = mkBallInPossession param
                                            ballId
                                            playerId
                                            t0
                                            False
                                            playerId
                                            (pitchCenter param .+! 0)
                                            (vector3 0 0 0)
                                            []
  in (fromAssocs [(ballId, boos)],
      fromAssocs [(ballId, bobjs)])


-- *************************************************************************
--
-- Game lineup
--
-- *************************************************************************

lineupKickoffGame :: Param -> ObjId -> Time -> Team -> Int -> Int -> (ALOut, ALObj)
lineupKickoffGame param oid time possession scoreHome scoreAway =
   let goos = ObjOutput
                  (OOSGame time
                      (scoreHome, scoreAway)
                      (GSKickOff, GPTeamPosition possession (pitchCenter param) time True)
                      possession
                      (Point3 (-10) (-10) 0))
                  NoEvent
                  NoEvent
                  []
       gobj = game param oid possession scoreHome scoreAway time
  in (fromAssocs [(oid, goos)],
      fromAssocs [(oid, gobj)])