Make creature update an external function

This commit is contained in:
2022-07-20 01:22:17 +01:00
parent db44d5d6ce
commit 1f79fe157f
31 changed files with 562 additions and 462 deletions
+279
View File
@@ -0,0 +1,279 @@
module Dodge.Humanoid where
import Dodge.Data
import Dodge.Creature.Boid
import Dodge.Creature.YourControl
import Dodge.Creature.State
import Dodge.Creature.Impulse
import Dodge.Creature.ChainUpdates
import Dodge.Creature.Test
import Dodge.Creature.Volition
import LensHelp
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.Action
import Dodge.Creature.Perception
import Dodge.Creature.Strategy
import Dodge.Creature.SentinelAI
import qualified IntMapHelp as IM
import Geometry
import RandomHelp
import Data.Maybe
updateHumanoid :: Creature -> World -> World
updateHumanoid cr = case cr ^?! crType . humanoidAI of
ChaseAI -> defaultImpulsive
[ const doStrategyActions
, performActions
, const overrideMeleeCloseTarget
, const setViewPos
, setMvPos
, chaseCritMv
, chaseCritPerceptionUpdate [0]
, targetYouWhenCognizant
, const searchIfDamaged
, const (crMeleeCooldown %~ max 0 . subtract 1)
] cr
SpreadGunAI -> defaultImpulsive
[performActions
,watchUpdateStrat
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0)
[DoActionIf (const $ not . crIsAiming) drawWeapon
,DoActionThen
(DoActionWhile crHasTargetLOS $ ArbitraryAction chooseMovementSpreadGun)
(DoImpulses [ChangeStrategy WatchAndWait])
]
)
, (const crAwayFromPost, const goToPostStrat)
]
,perceptionUpdate [0]
,const doStrategyActions
,const reloadOverride
,targetYouWhenCognizant
,const $ overrideInternal
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
(\cr' -> cr' & crActionPlan . apStrategy .~ WatchAndWait)
] cr
PistolAI -> defaultImpulsive
[ performActions
, watchUpdateStrat
[ (crHasTargetLOS, \w cr' -> StrategyActions (ShootAt 0)
[DoActionIf (const $ not . crIsAiming) drawWeapon,chooseMovementPistol cr' w])
, (const crAwayFromPost, const goToPostStrat)
]
, perceptionUpdate [0]
, const doStrategyActions
, const reloadOverride
, targetYouWhenCognizant
, const $ overrideInternal
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
(crActionPlan . apStrategy .~ WatchAndWait)
] cr
LtAutoAI -> defaultImpulsive
[ performActions
, watchUpdateStrat
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0)
[DoActionIf (const $ not . crIsAiming) drawWeapon
,DoActionThen
(DoActionWhile crHasTargetLOS $ ArbitraryAction chooseMovementLtAuto)
(DoImpulses [ChangeStrategy WatchAndWait])
]
)
, (const crAwayFromPost, const goToPostStrat)
]
, perceptionUpdate [0]
, const doStrategyActions
, const reloadOverride
, targetYouWhenCognizant
, const $ overrideInternal
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
(crActionPlan . apStrategy .~ WatchAndWait)
] cr
LauncherAI -> defaultImpulsive
[ performActions
, watchUpdateStrat
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0) [retreatFireLauncher])
, (const crAwayFromPost, const goToPostStrat)
]
, perceptionUpdate [0]
, const doStrategyActions
, const reloadOverride
, targetYouWhenCognizant
, const $ overrideInternal
(\cr' -> crHasTarget cr' && crStratConMatches (GetTo (V2 0 0)) cr')
(crActionPlan . apStrategy .~ WatchAndWait)
] cr
SwarmAI -> defaultImpulsive
[ flockToPointUsing' (encircleDistP 100) (meleeHeadingMove 0.1 0.1 (pi/4) 3.9)
, const (crMeleeCooldown %~ max 0 . subtract 1)
, perceptionUpdate [0]
, const doStrategyActions
, targetYouWhenCognizant
] cr
AutoAI -> defaultImpulsive [sentinelAI] cr
FlockArmourChaseAI -> defaultImpulsive
[ watchUpdateStrat []
, const doStrategyActions
, performActions
, targetYouWhenCognizant
, setTargetMv (\_ -> _targetCr . _crIntention)
, flockACC
, perceptionUpdate [0]
, goToTarget
, const overrideMeleeCloseTarget
, const (crMeleeCooldown %~ max 0 . subtract 1)
] cr
MiniGunAI -> defaultImpulsive [sentinelFireType (const shootTillEmpty)] cr
LongAI -> defaultImpulsive [sentinelFireType $ const shootTillEmpty] cr
MultGunAI -> defaultImpulsive [sentinelExtraWatchUpdate
[ ( const $ not . crWeaponReady
, \_ _ -> StrategyActions Reload reloadActions
)
, (const $ not . crSafeDistFromTarg 150
, \_ cr' -> StrategyActions Flee
[const (not . crSafeDistFromTarg 150) `DoActionWhile` UseTarget (fleeFrom cr')
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait] ]
)
, (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0)
[ drawwp `DoActionThen` shootFirstMiss `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait] ]
)
]
] cr
YourAI -> stateUpdate yourControl cr
InanimateAI -> id
where
drawwp = DoActionIfElse NoAction (const crIsAiming) (DoActionThen drawWeapon (WaitThen 50 NoAction))
reloadActions =
[ holsterWeapon
, WaitThen 1 $ DoActionWhileInterrupt NoAction (const crIsReloading) (DoImpulses [ChangeStrategy WatchAndWait])
]
-- bit of a hack to get new random generators after each creature's update
defaultImpulsive :: [World -> Creature -> Creature]
-> Creature -> World -> World
defaultImpulsive = fmap (fmap updateRandGen) . stateUpdate . impulsiveAIBefore . chainCreatureUpdates
where
updateRandGen w = let (_,g) = randomR (0,1::Int) (_randGen w)
in w & randGen .~ g
chooseMovementSpreadGun :: Creature -> World -> Action
chooseMovementSpreadGun cr w
| dist cpos p < 30 && safeAngleVV (p -.- cpos) (unitVectorAtAngle (_crDir cr)) > pi
= DoImpulses [UseItem, MoveForward (-3)]
| d < 30 = DoImpulses [UseItem,TurnToward p 0.06]
| d < 60 = DoImpulses [UseItem,TurnToward p 0.06,MoveForward 3]
| d < 100 = DoImpulses [TurnToward p 0.06, MoveForward 3 ]
| d < 200 = DoImpulses [TurnToward p (0.06 + 0.002 *(d-100)), MoveForward 3 ]
| otherwise
= DoImpulses [TurnToward p 0.26, MoveForward 3]
where
d = dist cpos p
cpos = _crPos cr
tcr = _creatures w IM.! 0
p = _crPos tcr
chooseMovementPistol :: Creature -> World -> Action
chooseMovementPistol cr w = chooseMovementPistol' cr w
`DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
chooseMovementPistol' :: Creature -> World -> Action
chooseMovementPistol' cr w = takeOneWeighted [chargeProb,retreatProb,strafeProb,strafeProb]
[chargeActions
,retreatActionsPistol ycr cr
,strafeLeftActions
,strafeRightActions
] & evalState $ g
where
g = _randGen w
cpos = _crPos cr
ycr = _creatures w IM.! 0
ypos = _crPos ycr
chargeProb | dist cpos ypos > 300 = 5
| dist cpos ypos > 150 = 1
| otherwise = 0
strafeProb | dist cpos ypos > 150 = 1
| otherwise = 0
retreatProb | dist cpos ypos < 200 = 1 :: Float
| otherwise = 0
chargeActions =
[TurnToward ypos 0.1]
`DoImpulsesAlongside`
3
`DoReplicate`
ImpulsesList (replicate 9 [Move (V2 3 0)] ++ [[Move (V2 3 0),UseItem]])
strafeLeftActions =
DoImpulses [TurnToward yposr (2*pi)]
`DoActionThen`
3
`DoReplicate`
ImpulsesList (replicate 9 [Move (V2 0 3)] ++ [[Move (V2 0 3),UseItem]])
strafeRightActions =
DoImpulses [TurnToward yposl (2*pi)]
`DoActionThen`
3
`DoReplicate`
ImpulsesList (replicate 9 [Move (V2 0 (-3))] ++ [[Move (V2 0 (-3)),UseItem]])
yposl = ypos -.- 100 *.* vNormal (normalizeV $ ypos -.- cpos)
yposr = ypos +.+ 100 *.* vNormal (normalizeV $ ypos -.- cpos)
retreatActionsPistol :: Creature -> Creature -> Action
retreatActionsPistol tcr cr =
[TurnToward retreatOffset 0.2]
`DoImpulsesAlongside`
3
`DoReplicate`
ImpulsesList (replicate 9 [Move (V2 (-3) 0)] ++ [[UseItem]])
where
cpos = _crPos cr
tpos = _crPos tcr
retreatOffset =
let a | dist cpos tpos < 50 = 0
| isLeftOfA (_crDir cr) (argV $ tpos -.- cpos)
= -0.7
| otherwise = 0.7
in fromMaybe tpos $ intersectLineLine' cpos
(cpos +.+ rotateV a (tpos -.- cpos))
tpos
(tpos +.+ vNormal (cpos -.- tpos))
chooseMovementLtAuto :: Creature -> World -> Action
chooseMovementLtAuto cr w
| dist cpos p > 200 = DoImpulses [UseItem,TurnToward p 0.05 , MoveForward 3]
| dist cpos p < 80 = DoImpulses [UseItem,TurnToward p 0.05, MoveForward (-3) ]
| errorAngleVV 22 (p' -.- cpos) (unitVectorAtAngle (_crDir cr)) < 0.4
= DoImpulses [UseItem,TurnToward p' 0.01, Move (V2 0 3)]
| otherwise
= DoImpulses [UseItem,TurnToward p' 0.05, Move (V2 0 3)]
where
cpos = _crPos cr
tcr = _creatures w IM.! 0
p = _crPos tcr
v = vNormal $ p -.- cpos
p' = p +.+ 0.5 *.* (v -.- 20 *.* normalizeV v)
retreatFireLauncher :: Action
retreatFireLauncher = ImpulsesList ( [ UseItem ] : replicate 20 [ Turn 0.16 ])
`DoActionThen`
holsterWeapon
`DoActionThen`
ImpulsesList ( replicate 30 [ MoveForward 3 ])
`DoActionThen`
drawWeapon
`DoActionThen`
ImpulsesList ( [UseItem] : replicate 20 [ Turn $ negate 0.16 ] )
`DoActionThen`
holsterWeapon
`DoActionThen`
ImpulsesList ( replicate 15 [ MoveForward 3 ] )
`DoActionThen`
drawWeapon
`DoActionThen`
ImpulsesList (
replicate 100 [UseItem, ImpulseUseTarget $ \tcr -> TurnToward (_crPos tcr) (pi/16) ] )
`DoActionThen`
20
`WaitThen`
holsterWeapon
`DoActionThen`
ImpulsesList ( replicate 15 [ MoveForward 3 ] )
`DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]