Refactor bullet particles

This commit is contained in:
2021-05-19 13:46:19 +02:00
parent 44f239c673
commit 4463dc7716
29 changed files with 637 additions and 535 deletions
+5 -3
View File
@@ -199,11 +199,11 @@ moveBy
-> World
moveBy n v = over (creatures . ix n . crPos) (+.+ v)
reloadWeapon
startReloadingWeapon
:: Int -- ^ Creature id
-> World
-> Maybe World
reloadWeapon cid w =
startReloadingWeapon cid w =
let cr = _creatures w IM.! cid
it = _crInv cr IM.! _crInvSel cr
itRef = creatures . ix cid . crInv . ix (_crInvSel cr)
@@ -216,7 +216,8 @@ reloadWeapon cid w =
{- | Start reloading if clip is empty. -}
crAutoReload :: Creature -> Creature
crAutoReload cr = case cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo of
Just 0 -> cr & crInv . ix (_crInvSel cr) . wpReloadState %~ (`fromMaybe` reloadT)
Just 0 | _posture (_crStance cr) /= Aiming
-> cr & crInv . ix (_crInvSel cr) . wpReloadState %~ (`fromMaybe` reloadT)
& crInv . ix (_crInvSel cr) . wpLoadedAmmo %~ (`fromMaybe` maxA)
_ -> cr
where
@@ -368,3 +369,4 @@ creatureTurnToward p turnSpeed cr
where
vToTarg = p -.- _crPos cr
dirToTarget = argV vToTarg
+6 -280
View File
@@ -1,162 +1,19 @@
module Dodge.Creature.ActionRat
( shootTargetWithStrat
, aimThenShootStrat
, suppressShootTarget
, suppress
, shootAdvance
, shootFirstMiss
, doStrategyActions
, doStrategyActionsR
, reloadOverride
, reloadOverrideR
, reloadOverrideNoHolster
, shootAdvanceStrat
, shootMoveStrat
, watchUpdateStrat
, watchUpdateStratR
, goToPostStrat
, overrideInternal
, overrideInternalR
, fleeTime
( goToPostStrat
)
where
import Dodge.Data
import Dodge.Base
--import Dodge.Base
--import Dodge.Base.Collide
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.Stance.Data
--import Dodge.Creature.Stance.Data
import Dodge.Creature.Test
import Dodge.Creature.Volition
--import Geometry
import Data.List
--import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad.Reader
shootTargetWithStrat
:: (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> (World -> Creature -> Creature -> [Action] -> [Action])
-- ^ Function for determining shooting strategy given target
-> World
-> Creature
-> Creature
shootTargetWithStrat targFunc strat w cr = case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crAction %~ strat w cr crTarg
{- | Action update for a simple shooting creature -}
suppressShootTarget
:: (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> World
-> Creature
-> Creature
suppressShootTarget targFunc w cr = case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crAction %~ suppress w cr crTarg
suppress :: World -> Creature -> Creature -> [Action] -> [Action]
suppress w cr tcr as
| canSee (_crID cr) (_crID tcr) w && cr ^. crStance . posture /= Aiming
&& cr ^? crInv . ix (_crInvSel cr) . wpReloadState == Just 0 =
[ DrawWeapon
, WaitThen 50 ShootTillEmpty
, AimAtCloseSlow
{ _targetID = _crID tcr
, _targetSeenAt = _crPos cr
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/4
}
]
| otherwise = as
-- This should be decomposed properly
shootFirstMiss :: Int -> World -> Creature -> Strategy
shootFirstMiss tcid _ _ = StrategyActions (ShootAt tcid) acs
where
acs =
[ DoActionIfElse NoAction crIsAiming (DoActionThen DrawWeapon (WaitThen 50 NoAction))
`DoActionThen`
LeadTarget (30,50)
`DoActionThen`
advanceShoot
`DoActionThen`
LeadTarget (0,0)
`DoActionThen`
lostest `DoActionWhile`
advanceShoot `DoActionThen`
75 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
]
lostest (w,cr') = canSee (_crID cr') tcid w
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
fleeTime :: Int -> World -> Creature -> Strategy
fleeTime t _ _ = StrategyActions Flee
[ t `DoReplicate`
UseTargetCID FleeFrom
`DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
]
aimThenShootStrat :: Int -> World -> Creature -> Strategy
aimThenShootStrat tcid _ _ = StrategyActions (ShootAt tcid)
[ DoActionIfElse NoAction crIsAiming (DoActionThen DrawWeapon (WaitThen 50 NoAction))
`DoActionThen`
50
`WaitThen`
DoImpulses [UseItem, ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = tcid
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
shootMoveStrat :: Point2 -> Int -> World -> Creature -> Strategy
shootMoveStrat moveV tcid _ _ = StrategyActions (ShootAt tcid)
[ DoActionIfElse NoAction crIsAiming (DoActionThen DrawWeapon (WaitThen 50 NoAction))
`DoActionThen`
lostest `DoActionWhile`
75 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = tcid
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
where
lostest (w,cr') = canSee (_crID cr') tcid w
advanceShoot = ImpulsesList [[UseItem, Move moveV]]
shootAdvanceStrat :: Int -> World -> Creature -> Strategy
shootAdvanceStrat tcid _ _ = StrategyActions (ShootAt tcid)
[ DoActionIfElse NoAction crIsAiming (DoActionThen DrawWeapon (WaitThen 50 NoAction))
`DoActionThen`
lostest `DoActionWhile`
advanceShoot `DoActionThen`
75 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = tcid
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
where
lostest (w,cr') = canSee (_crID cr') tcid w
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
--import Control.Lens
goToPostStrat :: World -> Creature -> Strategy
goToPostStrat w cr = case find sentinelGoal $ _crGoal $ _crActionPlan cr of
@@ -171,137 +28,6 @@ goToPostStrat w cr = case find sentinelGoal $ _crGoal $ _crActionPlan cr of
sentinelGoal (SentinelAt _ _) = True
sentinelGoal _ = False
holsterIfAiming
| crIsAiming (w,cr) = HolsterWeapon
| crIsAiming (w,cr) = holsterWeapon
| otherwise = NoAction
overrideInternal
:: ((World , Creature) -> Bool)
-> (World -> Creature -> Creature)
-> World
-> Creature
-> Creature
overrideInternal test update w cr
| test (w,cr) = update w cr
| otherwise = cr
overrideInternalR
:: ((World , Creature) -> Bool)
-> (World -> Creature -> Creature)
-> Creature
-> Reader World Creature
overrideInternalR test update cr = reader $ \w ->
if test (w,cr)
then update w cr
else cr
shootAdvance :: World -> Creature -> Creature -> [Action] -> [Action]
shootAdvance w cr tcr as
| lostest (w,cr) && cr ^. crStance . posture /= Aiming
&& cr ^? crInv . ix (_crInvSel cr) . wpReloadState == Just 0 =
[ DrawWeapon
, DoImpulses [ChangeStrategy $ ShootAt $ _crID tcr]
, 50 `WaitThen`
lostest `DoActionWhile`
advanceShoot `DoActionThen`
50 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = _crID tcr
, _targetSeenAt = _crPos cr
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
| cr ^. crStance . posture == Aiming && cr ^? crInv . ix (_crInvSel cr) . wpReloadState /= Just 0
= [ HolsterWeapon ]
| otherwise = as
where
lostest (w',cr') = canSee (_crID cr') (_crID tcr) w'
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
doStrategyActions
:: World
-> Creature
-> Creature
doStrategyActions _ cr = case cr ^? crActionPlan . crStrategy of
Just (StrategyActions strat acs) -> cr & crActionPlan . crAction .~ acs
& crActionPlan . crStrategy .~ strat
_ -> cr
doStrategyActionsR
:: Creature
-> Reader World Creature
doStrategyActionsR cr = return $ case cr ^? crActionPlan . crStrategy of
Just (StrategyActions strat acs) -> cr & crActionPlan . crAction .~ acs
& crActionPlan . crStrategy .~ strat
_ -> cr
reloadOverride
:: World
-> Creature
-> Creature
reloadOverride _ cr
| cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0
&& cr ^. crStance . posture == Aiming
= cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions
| otherwise = cr
where
reloadActions =
[ HolsterWeapon
, WaitThen 1 $ DoActionWhileInterrupt NoAction crIsReloading (DoImpulses [ChangeStrategy WatchAndWait])
]
reloadOverrideR
:: Creature
-> Reader World Creature
reloadOverrideR cr
| cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0
&& cr ^. crStance . posture == Aiming
= return $ cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions
| otherwise = return $ cr
where
reloadActions =
[ HolsterWeapon
, WaitThen 1 $ DoActionWhileInterrupt NoAction crIsReloading (DoImpulses [ChangeStrategy WatchAndWait])
]
reloadOverrideNoHolster
:: World
-> Creature
-> Creature
reloadOverrideNoHolster _ cr
| cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0
&& cr ^. crStance . posture == Aiming
= cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions
| otherwise = cr
where
reloadActions =
[ DoActionWhileInterrupt NoAction crIsReloading (DoImpulses [ChangeStrategy WatchAndWait])
]
watchUpdateStrat
:: [ ((World, Creature) -> Bool, World -> Creature -> Strategy) ]
-> World
-> Creature
-> Creature
watchUpdateStrat fs w cr = case cr ^? crActionPlan . crStrategy of
Just WatchAndWait -> cr
& crActionPlan . crStrategy .~ listGuard (fs, \_ _ -> WatchAndWait) (w, cr) w cr
_ -> cr
watchUpdateStratR
:: [ ((World, Creature) -> Bool, World -> Creature -> Strategy) ]
-> Creature
-> Reader World Creature
watchUpdateStratR fs cr = reader $ \w -> case cr ^? crActionPlan . crStrategy of
Just WatchAndWait -> cr
& crActionPlan . crStrategy .~ listGuard (fs, \_ _ -> WatchAndWait) (w, cr) w cr
_ -> cr
listGuard :: ([(a -> Bool, b)] , b) -> a -> b
listGuard ( (test,y):ps, z ) x
| test x = y
| otherwise = listGuard (ps, z) x
listGuard (_,z) _ = z
+3 -20
View File
@@ -4,12 +4,9 @@ module Dodge.Creature.AutoCrit
import Dodge.Data
import Dodge.Default
import Dodge.Creature.Picture
import Dodge.Creature.Test
import Dodge.Creature.ActionRat
import Dodge.Creature.SentinelAI
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.SetTarget
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
--import Dodge.Creature.State.Data
import Dodge.Item.Weapon
@@ -17,28 +14,14 @@ import Dodge.Item.Consumable
--import Geometry
import Picture
--import Dodge.RandomHelp
--
--import Data.Maybe
import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad
--import System.Random
autoCrit :: Creature
autoCrit = defaultCreature
{ _crPict = basicCrPict red
, _crUpdate = stateUpdate $ impulsiveAIR $
performActionsR
>=> watchUpdateStratR
[ (crHasTargetLOS, shootAdvanceStrat 0)
, (crAwayFromPost, goToPostStrat)
]
>=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR
>=> reloadOverrideR
>=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait)
, _crUpdate = stateUpdate $ impulsiveAIR $ sentinelAI
, _crActionPlan = ActionPlan
{ _crImpulse = []
, _crAction = []
+50
View File
@@ -0,0 +1,50 @@
module Dodge.Creature.ChaseCrit
(smallChaseCrit
,chaseCrit
) where
import Dodge.Data
import Dodge.Default
import Dodge.Creature.Picture
--import Dodge.Creature.Test
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.ChooseTarget
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
import Dodge.Creature.State.Data
import Dodge.Item.Consumable
import Dodge.Picture.Layer
--import Geometry
import Picture
--import Dodge.RandomHelp
--import Data.Maybe
import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad
--import System.Random
smallChaseCrit :: Creature
smallChaseCrit = chaseCrit
{ _crHP = 1
, _crRad = 4
, _crPict = basicCrPict green
, _crInv = IM.fromList [(0,medkit 200)]
, _crCorpse = onLayer CorpseLayer $ color (greyN 0.5) $ circleSolid 4
}
chaseCrit :: Creature
chaseCrit = defaultCreature
{ _crUpdate = stateUpdate $ impulsiveAIR $
doStrategyActionsR >=>
performActionsR >=>
overrideMeleeCloseTargetR >=>
chaseTargetR targetYouLOS >=>
basicPerceptionUpdateR [0] >=>
targetYouWhenCognizantR >=>
return . (crMeleeCooldown . _Just %~ (max 0 . subtract 1))
, _crHP = 300
, _crPict = basicCrPict green
, _crInv = IM.fromList [(0,medkit 200)]
, _crMeleeCooldown = Just 0
, _crFaction = ColorFaction green
}
+24 -25
View File
@@ -103,6 +103,30 @@ flockPointTarget f targFunc w cr = case targFunc cr w of
crs = IM.restrictKeys (_creatures w) is
p = f crTarg crs cr
flockPointTargetR
:: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
flockPointTargetR f targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ chaseTarg' p cr crTarg
where
is = _swarm $ _crGroup cr
crs = IM.restrictKeys (_creatures w) is
p = f crTarg crs cr
--swarmUseCenter
-- :: (Creature -> Point2 -> Creature -> Point2)
-- :: (Creature -> IM.IntMap Creature -> Creature -> Point2)
-- -> (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-- -> World
-- -> Creature
-- -> Creature
--swarmUseCenter
chaseTarget
:: (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> World
@@ -112,13 +136,6 @@ chaseTarget targFunc w cr = case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ chaseTarg cr crTarg
chaseTargetR
:: (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
chaseTargetR targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ chaseTarg cr crTarg
overrideMeleeCloseTarget :: World -> Creature -> Creature
overrideMeleeCloseTarget _ cr = case _crTarget cr of
@@ -132,24 +149,6 @@ overrideMeleeCloseTarget _ cr = case _crTarget cr of
where
cpos = _crPos cr
overrideMeleeCloseTargetR
:: Creature
-> Reader World Creature
overrideMeleeCloseTargetR cr = return $ maybe cr (tryMeleeAttack cr) (_crTarget cr)
tryMeleeAttack :: Creature -> Creature -> Creature
tryMeleeAttack cr tcr
| _crMeleeCooldown cr == Just 0
&& dist (_crPos tcr) cpos < _crRad cr + _crRad tcr + 5
&& abs (_crDir cr - argV (_crPos tcr -.- cpos)) < pi/4
= cr & crActionPlan . crStrategy .~ StrategyActions MeleeStrike meleeActions
| otherwise = cr
where
cpos = _crPos cr
meleeActions =
[DoImpulses [Melee (_crID tcr)]
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
]
chaseTarg' :: Point2 -> Creature -> Creature -> [Impulse]
chaseTarg' p cr crT
+17 -17
View File
@@ -6,9 +6,10 @@ import Dodge.Data
import Dodge.Default
import Dodge.Creature.Picture
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.ActionRat
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.SetTarget
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
@@ -20,24 +21,23 @@ import Picture
import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad.Reader
launcherCrit :: Creature
launcherCrit = defaultCreature
{ _crPict = basicCrPict red
, _crUpdate = stateUpdate $ impulsiveAI $ composeInternalAIs
[ performActions
, watchUpdateStrat
-- [ (crHasTargetLOS, shootMoveStrat (0,3) 0)
, _crUpdate = stateUpdate $ impulsiveAIR $
performActionsR
>=> watchUpdateStratR
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0) [retreatFire])
, (crAwayFromPost, goToPostStrat)
]
, basicPerceptionUpdate [0]
, doStrategyActions
, reloadOverride
, targetYouWhenCognizant
, overrideInternal (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait
]
>=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR
>=> reloadOverrideR
>=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait)
, _crActionPlan = ActionPlan
{ _crImpulse = []
, _crAction = []
@@ -54,26 +54,26 @@ launcherCrit = defaultCreature
retreatFire :: Action
retreatFire = ImpulsesList ( [ UseItem ] : replicate 20 [ Turn 0.16 ])
`DoActionThen`
HolsterWeapon
holsterWeapon
`DoActionThen`
ImpulsesList ( replicate 30 [ MoveForward 3 ])
`DoActionThen`
DrawWeapon
drawWeapon
`DoActionThen`
ImpulsesList ( [UseItem] : replicate 20 [ Turn $ negate 0.16 ] )
`DoActionThen`
HolsterWeapon
holsterWeapon
`DoActionThen`
ImpulsesList ( replicate 15 [ MoveForward 3 ] )
`DoActionThen`
DrawWeapon
drawWeapon
`DoActionThen`
ImpulsesList (
replicate 100 [UseItem, ImpulseUseTarget $ \tcr -> TurnToward (_crPos tcr) (pi/16) ] )
`DoActionThen`
20
`WaitThen`
HolsterWeapon
holsterWeapon
`DoActionThen`
ImpulsesList ( replicate 15 [ MoveForward 3 ] )
`DoActionThen`
+13 -13
View File
@@ -5,9 +5,10 @@ import Dodge.Data
import Dodge.Default
import Dodge.Creature.Picture
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.ActionRat
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.SetTarget
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
@@ -21,17 +22,17 @@ import Picture
--import Data.Maybe
import qualified Data.IntMap.Strict as IM
import Control.Lens
--import Control.Monad.State
import Control.Monad.Reader
--import System.Random
ltAutoCrit :: Creature
ltAutoCrit = defaultCreature
{ _crPict = basicCrPict red
, _crUpdate = stateUpdate $ impulsiveAI $ composeInternalAIs
[ performActions
, watchUpdateStrat
, _crUpdate = stateUpdate $ impulsiveAIR $
performActionsR
>=> watchUpdateStratR
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0)
[DoActionIf (not . crIsAiming) DrawWeapon
[DoActionIf (not . crIsAiming) drawWeapon
,DoActionThen
(DoActionWhile crHasTargetLOS $ ArbitraryAction chooseMovement)
(DoImpulses [ChangeStrategy WatchAndWait])
@@ -39,13 +40,12 @@ ltAutoCrit = defaultCreature
)
, (crAwayFromPost, goToPostStrat)
]
, basicPerceptionUpdate [0]
, doStrategyActions
, reloadOverride
, targetYouWhenCognizant
, overrideInternal (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait
]
>=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR
>=> reloadOverrideR
>=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait)
, _crActionPlan = ActionPlan
{ _crImpulse = []
, _crAction = []
+3 -2
View File
@@ -5,9 +5,10 @@ import Dodge.Data
import Dodge.Default
import Dodge.Creature.Picture
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.ActionRat
import Dodge.Creature.ReaderUpdate
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.SetTarget
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
@@ -31,7 +32,7 @@ pistolCrit = defaultCreature
performActionsR
>=> watchUpdateStratR
[ (crHasTargetLOS, \w cr -> StrategyActions (ShootAt 0)
[DoActionIf (not . crIsAiming) DrawWeapon,chooseMovement cr w])
[DoActionIf (not . crIsAiming) drawWeapon,chooseMovement cr w])
, (crAwayFromPost, goToPostStrat)
]
>=> basicPerceptionUpdateR [0]
+1 -8
View File
@@ -125,9 +125,6 @@ performAction
-> Action
-> ( [Impulse] , Maybe Action )
performAction cr w ac = case ac of
ShootTillEmpty -> case cr ^? crInv . ix (_crInvSel cr) . wpReloadState of
Just x | x == 0 -> ( [UseItem] , Just ShootTillEmpty )
_ -> ( [] , Just (WaitThen 20 HolsterWeapon) )
AimAtCloseSlow tcid p speed slowSpeed a
| canSee (_crID cr) tcid w && safeAngleVV (unitVectorAtAngle cdir) (tpos -.- cpos) < a
-> ([TurnToward tpos slowSpeed] , Just $ AimAtCloseSlow tcid tpos speed slowSpeed a)
@@ -143,8 +140,6 @@ performAction cr w ac = case ac of
ImpulsesList (xs:xss) -> (xs, Just $ ImpulsesList xss)
ImpulsesList _ -> ([], Nothing)
DoImpulses imps -> (imps, Nothing)
DrawWeapon -> ([ChangePosture Aiming, MakeSound pickUpSound] , Nothing)
HolsterWeapon -> ([ChangePosture AtEase, MakeSound putDownSound] , Nothing)
DoActionThen fsta afta -> case performAction cr w fsta of
(imps , Just nxta) -> (imps, Just (DoActionThen nxta afta))
(imps , Nothing ) -> (imps, Just afta)
@@ -175,12 +170,10 @@ performAction cr w ac = case ac of
LeadTarget p -> case cr ^? crTarget . _Just of
Just tcr -> ([TurnTo (_crPos tcr +.+ rotateV (_crDir tcr) p)], Nothing)
_ -> ([], Nothing)
FleeFrom cid -> case w ^? creatures . ix cid of
Just tcr -> ([MoveForward 3, TurnToward ((2 *.* _crPos cr) -.- _crPos tcr) (pi/4)], Nothing)
_ -> ([], Nothing)
UseTargetCID f -> case cr ^? crTarget . _Just of
Just tcr -> performAction cr w (f $ _crID tcr)
_ -> ([],Nothing)
UseTarget f -> performAction cr w $ f $ cr ^? crTarget . _Just
UseAheadPos f -> performAction cr w (f (_crPos cr +.+ 20 *.* unitVectorAtAngle (_crDir cr)))
ArbitraryAction f -> performAction cr w (f cr w)
DoImpulsesAlongside sideImp mainAc -> case performAction cr w mainAc of
+138
View File
@@ -0,0 +1,138 @@
{- | Function updating a creature in a Reader World environment -}
module Dodge.Creature.ReaderUpdate
where
import Dodge.Data
import Dodge.Creature.Stance.Data
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.AlertLevel.Data
import Geometry
import qualified Data.IntMap.Strict as IM
import Control.Monad.Reader
import Control.Lens
overrideMeleeCloseTargetR
:: Creature
-> Reader World Creature
overrideMeleeCloseTargetR cr = return $ maybe cr (tryMeleeAttack cr) (_crTarget cr)
tryMeleeAttack :: Creature -> Creature -> Creature
tryMeleeAttack cr tcr
| _crMeleeCooldown cr == Just 0
&& dist (_crPos tcr) cpos < _crRad cr + _crRad tcr + 5
&& abs (_crDir cr - argV (_crPos tcr -.- cpos)) < pi/4
= cr & crActionPlan . crStrategy .~ StrategyActions MeleeStrike meleeActions
| otherwise = cr
where
cpos = _crPos cr
meleeActions =
[DoImpulses [Melee (_crID tcr)]
`DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
]
chaseTargetR
:: (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> Creature
-> Reader World Creature
chaseTargetR targFunc cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crImpulse .~ chaseTarg cr crTarg
chaseTarg :: Creature -> Creature -> [Impulse]
chaseTarg cr crT
| dist tpos cpos < combinedRad + 5
&& abs (_crDir cr - argV (tpos -.- cpos)) < pi/4
= [ TurnToward tpos 0.05 ]
| abs (_crDir cr - argV (tpos -.- cpos)) < pi/4
= [MoveForward 2.5 , TurnToward tpos 0.2, RandomTurn 0.2 ]
| otherwise = [MoveForward 2.5 , TurnToward tpos 0.05, RandomTurn 0.2 ]
where
cpos = _crPos cr
tpos = _crPos crT
combinedRad = _crRad cr + _crRad crT
doStrategyActionsR
:: Creature
-> Reader World Creature
doStrategyActionsR cr = return $ case cr ^? crActionPlan . crStrategy of
Just (StrategyActions strat acs) -> cr & crActionPlan . crAction .~ acs
& crActionPlan . crStrategy .~ strat
_ -> cr
reloadOverrideR
:: Creature
-> Reader World Creature
reloadOverrideR cr
| cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo == Just 0
&& cr ^. crStance . posture == Aiming
= return $ cr & crActionPlan . crStrategy .~ StrategyActions Reload reloadActions
| otherwise = return $ cr
where
reloadActions =
[ holsterWeapon
, WaitThen 1 $ DoActionWhileInterrupt NoAction crIsReloading (DoImpulses [ChangeStrategy WatchAndWait])
]
overrideInternalR
:: ((World , Creature) -> Bool)
-> (World -> Creature -> Creature)
-> Creature
-> Reader World Creature
overrideInternalR test update cr = reader $ \w ->
if test (w,cr)
then update w cr
else cr
overrideInternalRR
:: ((World , Creature) -> Bool)
-> (Creature -> Reader World Creature)
-> Creature
-> Reader World Creature
overrideInternalRR test update cr = reader $ \w ->
if test (w,cr)
then runReader (update cr) w
else cr
watchUpdateStratR
:: [ ((World, Creature) -> Bool, World -> Creature -> Strategy) ]
-> Creature
-> Reader World Creature
watchUpdateStratR fs cr = reader $ \w -> case cr ^? crActionPlan . crStrategy of
Just WatchAndWait -> cr
& crActionPlan . crStrategy .~ listGuard (fs, \_ _ -> WatchAndWait) (w, cr) w cr
_ -> cr
watchUpdateStratRRR
:: [ (Creature -> Reader World Bool, Creature -> Reader World Strategy) ]
-> Creature
-> Reader World Creature
watchUpdateStratRRR fs cr = do
return undefined fs cr
-- reader $ \w -> case cr ^? crActionPlan . crStrategy of
-- Just WatchAndWait -> cr
-- & crActionPlan . crStrategy .~ listGuard (fs, \_ _ -> WatchAndWait) (w, cr) w cr
-- _ -> cr
listGuard :: ([(a -> Bool, b)] , b) -> a -> b
listGuard ( (test,y):ps, z ) x
| test x = y
| otherwise = listGuard (ps, z) x
listGuard (_,z) _ = z
targetYouWhenCognizantR :: Creature -> Reader World Creature
targetYouWhenCognizantR cr = reader $ \w -> case cr ^? crAwarenessLevel . ix 0 of
-- Just (Cognizant _) -> cr & crTarget ?~ _creatures w IM.! 0
Just (Cognizant _) -> cr {_crTarget = Just $! _creatures w IM.! 0}
_ -> cr & crTarget .~ Nothing
shootTargetWithStratR
:: (Creature -> World -> Maybe Creature) -- ^ Function for determining target
-> (World -> Creature -> Creature -> [Action] -> [Action])
-- ^ Function for determining shooting strategy given target
-> Creature
-> Reader World Creature
shootTargetWithStratR targFunc strat cr = reader $ \w -> case targFunc cr w of
Nothing -> cr
Just crTarg -> cr & crActionPlan . crAction %~ strat w cr crTarg
+136
View File
@@ -0,0 +1,136 @@
module Dodge.Creature.SentinelAI
where
import Dodge.Data
import Dodge.Base.Collide
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.ActionRat
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
--import Dodge.Creature.State
--import Dodge.Creature.State.Data
--import Geometry
--import Picture
--import Dodge.RandomHelp
import Data.Maybe
--import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad
import Control.Monad.Reader
--import System.Random
sentinelAI :: Creature -> Reader World Creature
sentinelAI = sentinelExtraWatchUpdate
[ (crHasTargetLOS
, \ _ cr ->
let lostest (w,cr') = canSee (_crID cr') tcid w
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
tcid = _crID $ fromJust $ _crTarget cr
in StrategyActions (ShootAt tcid)
[ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
`DoActionThen`
lostest `DoActionWhile`
advanceShoot `DoActionThen`
75 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = tcid
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
)
]
>=> reloadOverrideR
where
sentinelFireType
:: (Int -> Action)
-> Creature
-> Reader World Creature
sentinelFireType f = performActionsR
>=> watchUpdateStratR
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0)
[ drawwp `DoActionThen` f 0 `DoActionThen` DoImpulses [ChangeStrategy WatchAndWait]
, aiming]
)
, (crAwayFromPost, goToPostStrat)
]
>=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR
>=> reloadOverrideR
>=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait)
where
drawwp = DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
aiming = AimAtCloseSlow
{ _targetID = 0
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
sentinelExtraWatchUpdate
:: [((World, Creature) -> Bool , World -> Creature -> Strategy)]
-> Creature
-> Reader World Creature
sentinelExtraWatchUpdate xs = performActionsR
>=> watchUpdateStratR
( xs ++ [(crAwayFromPost, goToPostStrat)] )
>=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR
-- >=> reloadOverrideR
>=> targetYouWhenCognizantR
>=> (overrideInternalR (onBoth (&&) crHasTarget (crStratConMatches (GetTo (0,0))))
$ \ _ -> crActionPlan . crStrategy .~ WatchAndWait)
shootAtAdvance :: Int -> [Action]
shootAtAdvance tcid =
[ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
`DoActionThen`
lostest `DoActionWhile`
advanceShoot `DoActionThen`
75 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = tcid
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
where
lostest (w,cr') = canSee (_crID cr') tcid w
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
shootAtWhileContinueTime :: Int -> World -> Creature -> Strategy
shootAtWhileContinueTime tcid _ _ = StrategyActions (ShootAt tcid)
[ DoActionIfElse NoAction crIsAiming (DoActionThen drawWeapon (WaitThen 50 NoAction))
`DoActionThen`
lostest `DoActionWhile`
advanceShoot `DoActionThen`
75 `DoReplicate`
advanceShoot `DoActionThen`
DoImpulses [ChangeStrategy WatchAndWait]
, AimAtCloseSlow
{ _targetID = tcid
, _targetSeenAt = (0,0) -- hack
, _aimSpeed = 0.2
, _slowAimSpeed = 0.01
, _slowAimAngle = pi/8
}
]
where
lostest (w,cr') = canSee (_crID cr') tcid w
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
-6
View File
@@ -7,7 +7,6 @@ import Dodge.Data
import Dodge.Creature.AlertLevel.Data
import Control.Lens
import Control.Monad.Reader
import qualified Data.IntMap.Strict as IM
{- | Assumes that you are id 0: if creature is cognizant of you, sets you as target -}
targetYouWhenCognizant
@@ -18,8 +17,3 @@ targetYouWhenCognizant w cr = case cr ^? crAwarenessLevel . ix 0 of
Just (Cognizant _) -> cr & crTarget ?~ _creatures w IM.! 0
_ -> cr & crTarget .~ Nothing
targetYouWhenCognizantR :: Creature -> Reader World Creature
targetYouWhenCognizantR cr = reader $ \w -> case cr ^? crAwarenessLevel . ix 0 of
-- Just (Cognizant _) -> cr & crTarget ?~ _creatures w IM.! 0
Just (Cognizant _) -> cr {_crTarget = Just $! _creatures w IM.! 0}
_ -> cr & crTarget .~ Nothing
+3 -2
View File
@@ -5,9 +5,10 @@ import Dodge.Data
import Dodge.Default
import Dodge.Creature.Picture
import Dodge.Creature.Test
import Dodge.Creature.Volition
import Dodge.Creature.ActionRat
import Dodge.Creature.ReaderUpdate
--import Dodge.Creature.ChooseTarget
import Dodge.Creature.SetTarget
import Dodge.Creature.Rationality
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
@@ -31,7 +32,7 @@ spreadGunCrit = defaultCreature
performActionsR
>=> watchUpdateStratR
[ (crHasTargetLOS, \_ _ -> StrategyActions (ShootAt 0)
[DoActionIf (not . crIsAiming) DrawWeapon
[DoActionIf (not . crIsAiming) drawWeapon
,DoActionThen
(DoActionWhile crHasTargetLOS $ ArbitraryAction chooseMovement)
(DoImpulses [ChangeStrategy WatchAndWait])
+12 -5
View File
@@ -2,6 +2,7 @@ module Dodge.Creature.State where
import Dodge.Data
import Dodge.Creature.State.Data
import Dodge.Creature.Stance.Data
--import Dodge.Creature.Test
import Dodge.Base
import Dodge.SoundLogic
import Dodge.RandomHelp
@@ -40,7 +41,7 @@ stateUpdate u w (f,g) cr =
((f',g') , maybeCr) ->
( (invSideEff cr . movementSideEff cr . deathEff . f'
, g')
, fmap (updateReloadCounter . doDamage . crAutoReload) $ crOrCorpse =<< maybeCr
, fmap (stepReloading . stepItemUseCooldown . doDamage . crAutoReload) $ crOrCorpse =<< maybeCr
)
where
crOrCorpse cr'
@@ -153,10 +154,16 @@ isFrictionless cr = case cr ^? crStance . carriage of
Just Floating -> True
_ -> False
updateReloadCounter :: Creature -> Creature
updateReloadCounter cr = over (crInv . ix iSel . itUseTime) decreaseToZero
. over (crInv . ix iSel . wpReloadState) decreaseToZero
$ cr
stepItemUseCooldown :: Creature -> Creature
stepItemUseCooldown cr = over (crInv . ix iSel . itUseTime) decreaseToZero cr
where
iSel = _crInvSel cr
stepReloading :: Creature -> Creature
stepReloading cr
-- | crIsAiming' cr = cr
-- | otherwise
= over (crInv . ix iSel . wpReloadState) decreaseToZero cr
where
iSel = _crInvSel cr
+9 -5
View File
@@ -11,6 +11,7 @@ import Dodge.Creature.ImpulseRat
import Dodge.Creature.ChooseTarget
--import Dodge.Creature.SetTarget
import Dodge.Creature.Rationality
import Dodge.Creature.ReaderUpdate
import Dodge.Creature.AlertLevel
import Dodge.Creature.State
import Dodge.Creature.State.Data
@@ -22,18 +23,21 @@ import Picture
--import Data.Maybe
--import qualified Data.IntMap.Strict as IM
import Control.Lens
import Control.Monad.Reader
--import Control.Monad.State
--import System.Random
swarmCrit :: Creature
swarmCrit = defaultCreature
{ _crUpdate = stateUpdate $ impulsiveAI $ composeInternalAIs
[ flockPointTarget encircle targetYouLOS
, \ _ -> crMeleeCooldown . _Just %~ (max 0 . subtract 1)
, basicPerceptionUpdate [0]
{ _crUpdate = stateUpdate $ impulsiveAIR $
flockPointTargetR encircle targetYouLOS
>=> return . (crMeleeCooldown . _Just %~ (max 0 . subtract 1))
>=> basicPerceptionUpdateR [0]
>=> doStrategyActionsR
>=> targetYouWhenCognizantR
-- , doStrategyActions
-- , targetYouWhenCognizant
]
, _crHP = 1
, _crRad = 2
, _crMass = 2
+9
View File
@@ -49,6 +49,9 @@ crCanSeeCIDR cid cr = reader $ \w -> hasLOS (_crPos cr) (_crPos $ _creatures w I
crIsAiming :: (World,Creature) -> Bool
crIsAiming (_,cr) = _posture (_crStance cr) == Aiming
crIsAiming' :: Creature -> Bool
crIsAiming' cr = _posture (_crStance cr) == Aiming
crIsAimingR :: Creature -> Reader World Bool
crIsAimingR cr = return $ _posture (_crStance cr) == Aiming
@@ -99,3 +102,9 @@ crAwayFromPostR cr = return $ case find sentinelGoal $ _crGoal $ _crActionPlan c
where
sentinelGoal (SentinelAt _ _) = True
sentinelGoal _ = False
crHasAmmo :: (World,Creature) -> Bool
crHasAmmo (_,cr) = maybe False (> 0) $ cr ^? crInv . ix (_crInvSel cr) . wpLoadedAmmo
crCanShoot :: (World,Creature) -> Bool
crCanShoot p = crIsAiming p && crHasAmmo p
+39
View File
@@ -0,0 +1,39 @@
{- | Not a good name, perhaps: internal creature actions. -}
module Dodge.Creature.Volition
where
import Dodge.Data
import Dodge.Base.Collide
import Dodge.Creature.Test
import Dodge.Creature.Stance.Data
import Dodge.SoundLogic.Synonyms
import Geometry
holsterWeapon, drawWeapon :: Action
holsterWeapon = DoImpulses [ChangePosture AtEase, MakeSound putDownSound]
drawWeapon = DoImpulses [ChangePosture Aiming, MakeSound pickUpSound]
fleeFrom :: Creature -> Maybe Creature -> Action
fleeFrom cr mtcr = case mtcr of
Just tcr -> DoImpulses [MoveForward 3, TurnToward ((2 *.* _crPos cr) -.- _crPos tcr) (pi/4)]
Nothing -> NoAction
shootTillEmpty :: Action
--shootTillEmpty = (crCanShoot `DoActionWhile` DoImpulses [UseItem])
shootTillEmpty = (crCanShoot `DoActionWhile` DoImpulses [UseItem])
`DoActionThen` 20 `WaitThen` holsterWeapon
advanceShoot' :: Int -> Action
advanceShoot' tcid = lostest `DoActionWhile`
advanceShoot `DoActionThen`
75 `DoReplicate`
advanceShoot
where
lostest (w,cr) = canSee (_crID cr) tcid w
advanceShoot = ImpulsesList [[UseItem, MoveForward 3]]
shootFirstMiss' :: Action
shootFirstMiss' =
LeadTarget (30,50) `DoActionThen`
DoImpulses [UseItem] `DoActionThen`
(crCanShoot `DoActionWhile` DoActions [LeadTarget (0,0),DoImpulses [UseItem]])
`DoActionThen` 20 `WaitThen` holsterWeapon