{-# LANGUAGE UnicodeSyntax, Rank2Types, ExistentialQuantification #-}-- | This module defines the part of the SoccerFun API that is concerned with the player data types.moduleSoccerFun.PlayerwhereimportSoccerFun.RefereeActionimportSoccerFun.PreludeimportSoccerFun.BallimportSoccerFun.GeometryimportSoccerFun.TypesimportControl.Monad.StateimportSoccerFun.FieldimportData.List(find)dataPlayer=∀m.Player{playerID∷PlayerID,-- ^ must be uniquename∷String,-- ^ need not be uniqueheight∷Length,-- ^ should be in range [minHeight..maxHeight]pos∷Position,-- ^ should be on the ball fieldspeed∷Speed,-- ^ absolute direction and velocity with which player is movingnose∷Angle,-- ^ absolute direction in which player is lookingskills∷MajorSkills,-- ^ these improve performance of affected actionseffect∷MaybePlayerEffect,-- ^ The effect(s) of the previous actionstamina∷Stamina,-- ^ current stamina of a player: 1.0 is optimal, 0.0 is worsthealth∷Health,-- ^ current health of a player: 1.0 is optimal, 0.0 is worstbrain∷Brain(PlayerAIm)m-- ^ The precious asset: use and update the memory and make decisions}instanceEqPlayerwheref1==f2=playerIDf1==playerIDf2instanceShowPlayerwhereshow(Player{playerID=pid})=showpidtypePlayerAImemory=BrainInput→StatememoryPlayerActiondataBrainInput=BrainInput{referee∷[RefereeAction],-- ^ the referee actionsball∷BallState,-- ^ the state of the ballothers∷[Player],-- ^ all other ball playersme∷Player-- ^ the player himself}typePlayerWithAction=(PlayerAction,PlayerID)typePlayerWithEffect=(MaybePlayerEffect,PlayerID)typeMajorSkills=(Skill,Skill,Skill)dataSkill=Running-- ^ Faster running without ball in possession|Dribbling-- ^ Faster running with ball in possession|Rotating-- ^ Wider range of rotation|Gaining-- ^ Better ball gaining ability|Kicking-- ^ More accurate and wider ball kicking|Heading-- ^ More accurate and wider ball heading|Feinting-- ^ Wider range of feint manouvre|Jumping-- ^ Further jumping|Catching-- ^ Better catching|Tackling-- ^ More effective tackling|Schwalbing-- ^ Better acting of tackles|PlayingTheater-- ^ Better acting of playing theaterderiving(Eq,Show)dataFeintDirection=FeintLeft|FeintRightderiving(Eq,Show)-- | actions a player can intend to performdataPlayerAction=MoveSpeedAngle-- ^ wish to rotate over given angle, and then move with given speed|FeintFeintDirection-- ^ wish to make feint manouvre|KickBallSpeed3D-- ^ wish to kick ball with given speed|HeadBallSpeed3D-- ^ wish to head ball with given speed|GainBall-- ^ wish to gain possession of the ball from other player|CatchBall-- ^ wish to catch the ball with his hands|TacklePlayerIDVelocity-- ^ wish to tackle identified player, higher velocity is higher chance of succes AND injury (and foul?)|Schwalbe-- ^ wish to fall as if he was tackled|PlayTheater-- ^ wish to act as if he was hurtderiving(Eq,Show)dataPlayerEffect=MovedSpeedAngle-- ^ player has rotated with given angle, and then ran with given speed|FeintedFeintDirection-- ^ player had feinted|KickedBall(MaybeSpeed3D)-- ^ player kicked ball (Just v) with velocity, or didn't (Nothing)|HeadedBall(MaybeSpeed3D)-- ^ player headed ball (Just v) with velocity, or didn't (Nothing)|GainedBallSuccess-- ^ player attempt to gain ball from other player|CaughtBallSuccess-- ^ player caught the ball with his hands|TackledPlayerIDVelocitySuccess-- ^ player attempt to tackle an opponent|Schwalbed-- ^ player had performed a schwalbe|PlayedTheater-- ^ player had started to act hurt|OnTheGroundFramesToGo-- ^ tackled by someone else; FramesToGo is the amount of frames that you will be on the groundtypeStamina=FloattypeHealth=FloatdefaultPlayer∷PlayerID→PlayerdefaultPlayerplayerID=Player{playerID=playerID,name="default",height=1.6,pos=zero,speed=zero,nose=zero,skills=(Running,Kicking,Dribbling),effect=Nothing,stamina=maxStamina,health=maxHealth,brain=Brain{m=error"You need to provide defaultPlayer with a new brain.",ai=const$return$Movezerozero}}identifyPlayer∷PlayerID→Player→BoolidentifyPlayeridfb=id==(playerIDfb)playerIdentity∷Player→PlayerIDplayerIdentityfb=(playerIDfb)-- | getBall returns the ball (containing its position and speed-information)-- | that is either free or gained by a player.-- | For this reason, the list of players must contain all players, otherwise-- | this function may fail.getBall∷BallState→[Player]→BallgetBall(Freeball)_=ballgetBall(GainedByplayerID)allPlayers=casefind(identifyPlayerplayerID)allPlayersofNothing→error"getBall: no player found with requested identifier."Just(Player{pos=pos,speed=speed})→mkBallposspeed-- | Returns True if the ball is held by a Keeper in his own penaltyarea-- | Returns False when the ball is held by a Keeper in open field-- | Returns False when the ball is not held by a Keeper-- | Keepers should be numbered with 1.ballGainedByKeeper∷BallState→[Player]→ClubName→Home→Field→BoolballGainedByKeeper(Free_)____=FalseballGainedByKeeper(GainedByplayerID)allPlayersclubhomefield=casefilter(identifyPlayerplayerID)allPlayersof[keeper]→playerNoplayerID==1&&inPenaltyAreafield(if(clubNameplayerID==club)thenhomeelse(otherhome))(poskeeper)wrongNumber→error"ballGainedByKeeper: wrong number of keepers found."clonePlayer∷Brain(PlayerAIm)m→Player→PlayerclonePlayerbrain(PlayerplayerIDnameheightposspeednoseskillseffectstaminahealth_)=(PlayerplayerIDnameheightposspeednoseskillseffectstaminahealthbrain)classSameClubawheresameClub∷a→a→Bool-- ^ belong to same club-- TODO: move this to SoccerFun.GeometryclassGetPositionawheregetPosition∷a→PositioninRadiusOfPlayer∷Position→Player→Bool-- ^ True iff position touches/hits playerinRadiusOfPlayerpplayer=inRadiusOfPosition(zero{pxy=p})xWidthPlayeryWidthPlayer(heightplayer)(posplayer)skillsAsList∷Player→[Skill]-- ^ Skills of the player as a listskillsAsListfb=(\(a,b,c)→[a,b,c])(skillsfb)isFirstHalf∷Half→BoolisFirstHalfFirstHalf=TrueisFirstHalf_=FalseisSecondHalf∷Half→BoolisSecondHalfSecondHalf=TrueisSecondHalf_=False-- | chest size of playerxWidthPlayer=0.7/2.0-- | stomach size of playeryWidthPlayer=0.4/2.0getClubName∷Player→ClubNamegetClubNamefb=nameOf(playerIDfb)isKeeper∷Player→BoolisKeeperfb=playerNo(playerIDfb)==1isFielder∷Player→BoolisFielderfb=not(isKeeperfb)-- | minimum length of a person. Advantages: better gainball; better stamina at sprinting; better dribbling; less health damage when fall, better rotating.minLength=1.6∷Float-- | maximum length of a person. Advantages: wider gainball; better stamina at running; higher headball; improved catching; harder kicking.maxLength=2.1∷Float-- | minimum height of a person. Advantages: better gainball; better stamina at sprinting; better dribbling; less health damage when fall, better rotating.minHeight=1.6∷Float-- | maximum height of a person. Advantages: wider gainball; better stamina at running; higher headball; improved catching; harder kicking.maxHeight=2.1∷FloatmaxStamina=1.0∷FloatmaxHealth=1.0∷Float{-| Player attribute dependent abilities:
use these functions to make your player correctly dependent of abilities.
-}maxGainReach∷Player→MetremaxGainReachfb=(if(elemGaining(skillsAsListfb))then0.5else0.3)*(heightfb)-- | vertical jumpingmaxJumpReach∷Player→MetremaxJumpReachfb=(if(elemJumping(skillsAsListfb))then0.6else0.4)*(heightfb)maxGainVelocityDifference∷Player→Metre→VelocitymaxGainVelocityDifferencefbdPlayerBall=(if(elemGaining(skillsAsListfb))then15.0else10.0)-distanceDifficultywheredistanceDifficulty=maxzero(((0.8*(heightfb))**4.0)*(dPlayerBall/(heightfb)))maxCatchVelocityDifference∷Player→Metre→VelocitymaxCatchVelocityDifferencefbdPlayerBall=(if(elemGaining(skillsAsListfb))then20.0else17.0)-distanceDifficultywheredistanceDifficulty=maxzero(((0.8*(heightfb))**4.0)*(dPlayerBall/(heightfb)))maxKickReach∷Player→MetremaxKickReachfb=(if(elemKicking(skillsAsListfb))then0.6else0.4)*(heightfb)maxHeadReach∷Player→MetremaxHeadReachfb=(if(elemHeading(skillsAsListfb))then0.4else0.2)*(heightfb)-- | includes horizontal jumpingmaxCatchReach∷Player→MetremaxCatchReachfb=(if(elemCatching(skillsAsListfb))then1.8else1.5)*(heightfb)maxTackleReach∷Player→MetremaxTackleReachfb=(if(elemTackling(skillsAsListfb))then0.33else0.25)*(heightfb)maxVelocityBallKick∷Player→VelocitymaxVelocityBallKickfb=(if(elemKicking(skillsAsListfb))then27.0else25.0+(heightfb)/2.0)*(0.2*fatHealth+0.8)wherefatHealth=getHealthStaminaFactor(healthfb)(staminafb)maxVelocityBallHead∷Player→Velocity→VelocitymaxVelocityBallHeadfbballSpeed=0.7*ballSpeed+(if(elemHeading(skillsAsListfb))then7.0else5.0)*(0.1*fatHealth+0.9)wherefatHealth=getHealthStaminaFactor(healthfb)(staminafb)maxKickingDeviation∷Player→AnglemaxKickingDeviationskills=pi/2.0-- if (elem Kicking skills) (pi/18.0) (pi/2.0)maxHeadingDeviation∷Player→AnglemaxHeadingDeviationskills=pi/4.0-- if (elem Heading skills) (pi/16.0) (pi/5.0)-- | maximum angle with which player can rotatemaxRotateAngle∷Player→AnglemaxRotateAnglefb=pi/18.0*((5.0/(velocity$speedfb))*(heightfb/2.0))-- | maximum side step of player for feint manouvremaxFeintStep∷Player→MetremaxFeintStepfb=if(elemFeinting(skillsAsListfb))then0.75else0.5-- | combination of stamina and healthtypeHealthStaminaFactor=FloatgetHealthStaminaFactor∷Health→Stamina→HealthStaminaFactorgetHealthStaminaFactorhealthstamina|stamina<=health=stamina|otherwise=(stamina+health)/2teamHome∷ATeam→Half→HometeamHometeamhalf|team==Team1&&half==FirstHalf||team==Team2&&half==SecondHalf=West|otherwise=EastopponentHome∷ATeam→Half→HomeopponentHometeamhalf|team==Team2&&half==FirstHalf||team==Team1&&half==SecondHalf=West|otherwise=EastisMove∷PlayerAction→BoolisMove(Move__)=TrueisMove_=FalseisGainBall∷PlayerAction→BoolisGainBallGainBall=TrueisGainBall_=FalseisCatchBall∷PlayerAction→BoolisCatchBallCatchBall=TrueisCatchBall_=FalseisKickBall∷PlayerAction→BoolisKickBall(KickBall_)=TrueisKickBall_=FalseisHeadBall∷PlayerAction→BoolisHeadBall(HeadBall_)=TrueisHeadBall_=FalseisFeint∷PlayerAction→BoolisFeint(Feint_)=TrueisFeint_=FalseisPlayerTackle∷PlayerAction→BoolisPlayerTackle(Tackle__)=TrueisPlayerTackle_=FalseisSchwalbe∷PlayerAction→BoolisSchwalbeSchwalbe=TrueisSchwalbe_=FalseisPlayTheater∷PlayerAction→BoolisPlayTheaterPlayTheater=TrueisPlayTheater_=FalseisSkillOfAction∷Skill→PlayerAction→BoolisSkillOfActionRunning(Move__)=TrueisSkillOfActionRotating(Move__)=TrueisSkillOfActionGainingGainBall=TrueisSkillOfActionKicking(KickBall_)=TrueisSkillOfActionHeading(HeadBall_)=TrueisSkillOfActionFeinting(Feint_)=TrueisSkillOfActionTackling(Tackle__)=TrueisSkillOfActionSchwalbingSchwalbe=TrueisSkillOfActionCatchingCatchBall=TrueisSkillOfActionPlayingTheaterPlayTheater=TrueisSkillOfAction__=FalseisActionOnBall∷PlayerAction→BoolisActionOnBallGainBall=TrueisActionOnBallCatchBall=TrueisActionOnBall(KickBall_)=TrueisActionOnBall(HeadBall_)=TrueisActionOnBall_=FalseisMoved∷PlayerEffect→BoolisMoved(Moved__)=TrueisMoved_=FalseisGainedBall∷PlayerEffect→BoolisGainedBall(GainedBall_)=TrueisGainedBall_=FalseisKickedBall∷PlayerEffect→BoolisKickedBall(KickedBall_)=TrueisKickedBall_=FalseisHeadedBall∷PlayerEffect→BoolisHeadedBall(HeadedBall_)=TrueisHeadedBall_=FalseisFeinted∷PlayerEffect→BoolisFeinted(Feinted_)=TrueisFeinted_=FalseisTackled∷PlayerEffect→BoolisTackled(Tackled___)=TrueisTackled_=FalseisSchwalbed∷PlayerEffect→BoolisSchwalbedSchwalbed=TrueisSchwalbed_=FalseisCaughtBall∷PlayerEffect→BoolisCaughtBall(CaughtBall_)=TrueisCaughtBall_=FalseisPlayedTheater∷PlayerEffect→BoolisPlayedTheaterPlayedTheater=TrueisPlayedTheater_=FalseisOnTheGround∷PlayerEffect→BoolisOnTheGround(OnTheGround_)=TrueisOnTheGround_=FalsefailPlayerAction∷PlayerAction→PlayerEffectfailPlayerAction(Movesa)=MovedsafailPlayerActionGainBall=GainedBallFailfailPlayerActionCatchBall=CaughtBallFailfailPlayerAction(KickBallv)=KickedBallNothingfailPlayerAction(HeadBallv)=HeadedBallNothingfailPlayerAction(Feintd)=FeinteddfailPlayerAction(Tacklepv)=TackledpvFailfailPlayerActionSchwalbe=SchwalbedfailPlayerActionPlayTheater=PlayedTheater--failPlayerAction _ = error "failPlayerAction: unknown action failed"instanceGetPositionPlayerwheregetPositionfb=(posfb)instanceNameOfPlayerwherenameOffb=namefbinstanceNameOfPlayerIDwherenameOff=clubNamefinstanceSameClubPlayerIDwheresameClubid1id2=nameOfid1==nameOfid2instanceSameClubPlayerwheresameClubfb1fb2=sameClub(playerIDfb1)(playerIDfb2){- Player attribute dependent abilities:
-}{-isReprimanded ∷ PlayerEffect → Bool
isReprimanded (Reprimanded _) = True
isReprimanded _ = False
isScoredGoal ∷ PlayerEffect → Bool
isScoredGoal (ScoredGoal _) = True
isScoredGoal _ = False-}