Files
loop/src/Dodge/Humanoid.hs
T

291 lines
11 KiB
Haskell

module Dodge.Humanoid where
import Data.Maybe
import Dodge.Creature.Action
import Dodge.Creature
import Dodge.Data.CreatureEffect
import Dodge.Data.World
import Geometry
import LensHelp
import RandomHelp
updateHumanoid :: Creature -> World -> World
updateHumanoid cr = case cr ^?! crType of
ChaseCrit {} ->
humanoidAIList
[ const doStrategyActions
, performActions
, const overrideMeleeCloseTarget
, setViewPos
, setMvPos
, chaseCritMv
, chaseCritPerceptionUpdate [0]
, targetYouWhenCognizant
, const searchIfDamaged
, const (crType . meleeCooldown %~ max 0 . subtract 1)
, const (crVocalization . vcCoolDown %~ max 0 . subtract 1)
]
cr
_ -> id
-- SpreadGunAI ->
-- defaultImpulsive
-- [ performActions
-- , watchUpdateStrat
-- [
-- ( crHasTargetLOS
-- , \_ _ ->
-- StrategyActions
-- (ShootAt 0)
-- [ DoActionIf (WdCrNegate $ WdCrBlfromCrBl CrIsAiming) drawWeapon
-- , DoActionThen
-- (DoActionWhile WdCrLOSTarget $ ArbitraryAction ChooseMovementSpreadGun)
-- (DoImpulses [ChangeStrategy WatchAndWait])
-- ]
-- )
-- , (const crAwayFromPost, const goToPostStrat)
-- ]
-- , perceptionUpdate [0]
-- , const doStrategyActions
-- , 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 (WdCrNegate $ WdCrBlfromCrBl CrIsAiming) drawWeapon, chooseMovementPistol cr' w]
-- )
-- , (const crAwayFromPost, const goToPostStrat)
-- ]
-- , perceptionUpdate [0]
-- , const doStrategyActions
-- , 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 (WdCrNegate $ WdCrBlfromCrBl CrIsAiming) drawWeapon
-- , DoActionThen
-- (DoActionWhile WdCrLOSTarget $ ArbitraryAction ChooseMovementLtAuto)
-- (DoImpulses [ChangeStrategy WatchAndWait])
-- ]
-- )
-- , (const crAwayFromPost, const goToPostStrat)
-- ]
-- , perceptionUpdate [0]
-- , const doStrategyActions
-- , 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
-- , 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
-- , \_ _ ->
-- StrategyActions
-- Flee
-- [ WdCrNegate (WdCrSafeDistFromTarget 150) `DoActionWhile` UseSelf CrFleeFromTarget -- (fleeFrom cr')
-- `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
-- ]
-- )
-- ,
-- ( crHasTargetLOS
-- , \_ _ ->
-- StrategyActions
-- (ShootAt 0)
-- [drawwp `DoActionThen` shootFirstMiss `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]]
-- )
-- ]
-- ]
-- cr
-- InanimateAI -> id
-- where
-- drawwp = DoActionIfElse NoAction (WdCrBlfromCrBl CrIsAiming) (DoActionThen drawWeapon (WaitThen 50 NoAction))
-- reloadActions =
-- [ holsterWeapon
-- --, WaitThen 1 $ DoActionWhileInterrupt NoAction (WdCrBlfromCrBl CrIsReloading) (DoImpulses [ChangeStrategy WatchAndWait])
-- , WaitThen 1 $ (DoImpulses [ChangeStrategy WatchAndWait])
-- ]
humanoidAIList ::
[World -> Creature -> Creature] ->
Creature ->
World ->
World
humanoidAIList
= crUpdate . impulsiveAIBefore . chainCreatureUpdates
-- 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) . crUpdate . impulsiveAIBefore . chainCreatureUpdates
where
updateRandGen w =
let (_, g) = randomR (0, 1 :: Int) (_randGen w)
in w & randGen .~ g
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 = w ^?! cWorld . lWorld . creatures . ix 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))
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 (TurnTowardCr (pi / 16))
]
)
`DoActionThen` 20
`WaitThen` holsterWeapon
`DoActionThen` ImpulsesList (replicate 15 [MoveForward 3])
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]