about summary refs log tree commit diff
path: root/src/Xanthous/AI
diff options
context:
space:
mode:
authorGriffin Smith <root@gws.fyi>2019-10-13T16·37-0400
committerGriffin Smith <root@gws.fyi>2019-10-13T16·37-0400
commit8a4220df830adb6f1616ca02dd06902474fd25df (patch)
treeb78e5eea207e77ca82759bf05a26a77ae3729c09 /src/Xanthous/AI
parent8d36fb4af2f938d96c8d6c22ccc575d0a98d0d38 (diff)
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.
Diffstat (limited to 'src/Xanthous/AI')
-rw-r--r--src/Xanthous/AI/Gormlak.hs72
1 files changed, 48 insertions, 24 deletions
diff --git a/src/Xanthous/AI/Gormlak.hs b/src/Xanthous/AI/Gormlak.hs
index db504c1e7d3a..e13eb8ffe71a 100644
--- a/src/Xanthous/AI/Gormlak.hs
+++ b/src/Xanthous/AI/Gormlak.hs
@@ -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
 
 --------------------------------------------------------------------------------