Implement speed and ticks

Gormlaks now move 1/8th the speed of the character, which means we can
run away from them - yay!

Unfortunately this also introduces a bug where they'll eventually get
stuck and not do anything, so I'll be tackling that next.
This commit is contained in:
Griffin Smith 2019-10-13 12:37:08 -04:00
parent 8d36fb4af2
commit 8a4220df83
11 changed files with 277 additions and 84 deletions

View file

@ -10,10 +10,17 @@ import Control.Monad.Random
import Data.Aeson (object)
import qualified Data.Aeson as A
--------------------------------------------------------------------------------
import Xanthous.Data (Positioned(..), diffPositions, stepTowards, isUnit)
import Xanthous.Data
( Positioned(..), positioned, position
, diffPositions, stepTowards, isUnit
, Ticks, (|*|), invertedRate
)
import Xanthous.Data.EntityMap
import qualified Xanthous.Entities.Creature as Creature
import Xanthous.Entities.Creature (Creature)
import Xanthous.Entities.Creature
( Creature, hippocampus, creatureType
, destination, destinationProgress, destinationPosition
)
import Xanthous.Entities.Character (Character)
import qualified Xanthous.Entities.Character as Character
import qualified Xanthous.Entities.RawTypes as Raw
@ -28,30 +35,47 @@ import Xanthous.Monad (say)
stepGormlak
:: (MonadState GameState m, MonadRandom m)
=> Positioned Creature
=> Ticks
-> Positioned Creature
-> m (Positioned Creature)
stepGormlak pe@(Positioned pos creature) = do
newPos <- do
canSeeCharacter <- uses entities $ canSee (entityIs @Character) pos vision
if canSeeCharacter
then do
charPos <- use characterPosition
if isUnit (pos `diffPositions` charPos)
then attackCharacter $> pos
else pure $ pos `stepTowards` charPos
stepGormlak ticks pe@(Positioned pos creature) = do
dest <- maybe (selectDestination pos creature) pure
$ creature ^. hippocampus . destination
let progress' =
dest ^. destinationProgress
+ creature ^. creatureType . Raw.speed . invertedRate |*| ticks
if progress' < 1
then pure
$ pe
& positioned . hippocampus . destination
?~ (dest & destinationProgress .~ progress')
else do
lines <- uses entities $ linesOfSight pos (Creature.visionRadius creature)
line <- choose $ weightedBy length lines
pure $ fromMaybe pos $ fmap fst . headMay =<< tailMay =<< line
collisionAt newPos >>= \case
Nothing -> pure $ Positioned newPos creature
Just Stop -> pure pe
Just Combat -> do
ents <- use $ entities . atPosition newPos
when (any (entityIs @Character) ents) attackCharacter
pure pe
let newPos = dest ^. destinationPosition
remainingSpeed = progress' - 1
newDest <- selectDestination newPos creature
<&> destinationProgress +~ remainingSpeed
let pe' = pe & positioned . hippocampus . destination ?~ newDest
collisionAt newPos >>= \case
Nothing -> pure $ pe' & position .~ newPos
Just Stop -> pure pe'
Just Combat -> do
ents <- use $ entities . atPosition newPos
when (any (entityIs @Character) ents) attackCharacter
pure pe'
where
selectDestination pos' creature' = Creature.destinationFromPos <$> do
canSeeCharacter <- uses entities $ canSee (entityIs @Character) pos' vision
if canSeeCharacter
then do
charPos <- use characterPosition
if isUnit (pos' `diffPositions` charPos)
then attackCharacter $> pos'
else pure $ pos' `stepTowards` charPos
else do
lines <- uses entities $ linesOfSight pos' (Creature.visionRadius creature')
line <- choose $ weightedBy length lines
pure $ fromMaybe pos' $ fmap fst . headMay =<< tailMay =<< line
vision = Creature.visionRadius creature
attackCharacter = do
say ["combat", "creatureAttack"] $ object [ "creature" A..= creature ]
@ -60,7 +84,7 @@ stepGormlak pe@(Positioned pos creature) = do
newtype GormlakBrain = GormlakBrain Creature
instance Brain GormlakBrain where
step = fmap coerce . stepGormlak . coerce
step ticks = fmap coerce . stepGormlak ticks . coerce
--------------------------------------------------------------------------------