summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregor Kleen <pngwjpgh@users.noreply.github.com>2016-11-12 22:25:47 +0100
committerGregor Kleen <pngwjpgh@users.noreply.github.com>2016-11-12 22:25:47 +0100
commitec57713b3d4acea066c30cf4285339303860df01 (patch)
treeb869a0fbe85e1f8498ac4484857f7b4b5f475188
parentcf4bda4d1c9a5e3e57c0b2682c7647d811a31740 (diff)
download2017-01-16_17:13:37-ec57713b3d4acea066c30cf4285339303860df01.tar
2017-01-16_17:13:37-ec57713b3d4acea066c30cf4285339303860df01.tar.gz
2017-01-16_17:13:37-ec57713b3d4acea066c30cf4285339303860df01.tar.bz2
2017-01-16_17:13:37-ec57713b3d4acea066c30cf4285339303860df01.tar.xz
2017-01-16_17:13:37-ec57713b3d4acea066c30cf4285339303860df01.zip
Timers for use with probabilistic focus and without
-rw-r--r--src/Main.hs134
-rw-r--r--src/Sequence/Contact/Archetypes.hs4
-rw-r--r--src/Sequence/Contact/Types.hs15
-rw-r--r--src/Sequence/Contact/Types/Internal.hs8
-rw-r--r--src/Sequence/Types.hs44
-rw-r--r--src/Sequence/Utils.hs25
6 files changed, 194 insertions, 36 deletions
diff --git a/src/Main.hs b/src/Main.hs
index 54ec08a..db49e14 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -36,6 +36,7 @@ import Data.Maybe
36import Data.Bool 36import Data.Bool
37import Data.Monoid (All(..)) 37import Data.Monoid (All(..))
38import Data.Ord 38import Data.Ord
39import Data.Ratio
39 40
40import Data.Foldable (toList) 41import Data.Foldable (toList)
41 42
@@ -84,7 +85,7 @@ main = do
84 , helpCommand "help" 85 , helpCommand "help"
85 , cmd "entities" listEntities "List all entities" 86 , cmd "entities" listEntities "List all entities"
86 , cmd "tip" focusTip "Focus the entity at the top of the queue" 87 , cmd "tip" focusTip "Focus the entity at the top of the queue"
87 , cmd "ptip" pFocusTip "Focus a random entity" 88 , cmd "pTip" pFocusTip "Focus a random entity"
88 , cmd "focus" setFocus "Focus a specific entity" 89 , cmd "focus" setFocus "Focus a specific entity"
89 , cmd "blur" blur "Focus no entity" 90 , cmd "blur" blur "Focus no entity"
90 , cmd "remove" remove "Remove the focused entity from the queue" 91 , cmd "remove" remove "Remove the focused entity from the queue"
@@ -98,6 +99,9 @@ main = do
98 , cmd "test" rollTest "Roll a test using the stats of the currently focused entity" 99 , cmd "test" rollTest "Roll a test using the stats of the currently focused entity"
99 , cmd "combat" entitySeqVal "Roll sequence value for the current focus and enter combat" 100 , cmd "combat" entitySeqVal "Roll sequence value for the current focus and enter combat"
100 , cmd "combat'" factionSeqVal "Roll sequence values for all members of a faction and have them enter combat" 101 , cmd "combat'" factionSeqVal "Roll sequence values for all members of a faction and have them enter combat"
102 , cmd "timer" entityTimer "Set a timer associated with the current entity"
103 , cmd "pTimer" pEntityTimer "Set a timer associated with the current entity. Scale remaining time dynamically with the number of combatants"
104 , cmd "untimer" clearEntityTimer "Remove the timer associated with the current entity"
101 , cmd "uncombat" clearEntitySeqVal "Drop the focused entity out of combat" 105 , cmd "uncombat" clearEntitySeqVal "Drop the focused entity out of combat"
102 , cmd "uncombat'" clearFactionSeqVal "Drop all members of a faction out of combat" 106 , cmd "uncombat'" clearFactionSeqVal "Drop all members of a faction out of combat"
103 , cmd "spend" spendSeq "Spend some of the current focusĀ“ AP" 107 , cmd "spend" spendSeq "Spend some of the current focusĀ“ AP"
@@ -117,13 +121,19 @@ main = do
117stateOutline :: Sh GameState String 121stateOutline :: Sh GameState String
118stateOutline = do 122stateOutline = do
119 st <- get 123 st <- get
120 case st of 124 time <- use gTimer
121 st | null (st ^. priorityQueue) -> return "" 125
122 | otherwise -> unlines <$> mapM table (st ^. gRounds') 126 unlines <$> sequence ( ( if not (null $ st ^. timers) || not (null $ st ^. gRounds')
127 then [ return $ "Round timer: " ++ show time ]
128 else []
129 )
130 ++ ( if not (null $ st ^. timers) then [ tTable ] else [] )
131 ++ ( if not (null $ st ^. gRounds') then map table (st ^. gRounds') else [] )
132 )
123 where 133 where
124 table :: Int -> Sh GameState String 134 table :: Int -> Sh GameState String
125 table round = do 135 table round = do
126 factions <- map (view faction') <$> use inhabitedFactions 136 factions <- map (view faction') <$> use combatFactions
127 st <- get 137 st <- get
128 let 138 let
129 roundStr 0 = "Current Round" 139 roundStr 0 = "Current Round"
@@ -147,6 +157,27 @@ stateOutline = do
147 colsAllG top . ([maybe "" show $ view seqVal seq] :) <$> mapM factionColumn [0..(length factions - 1)] 157 colsAllG top . ([maybe "" show $ view seqVal seq] :) <$> mapM factionColumn [0..(length factions - 1)]
148 -- layoutTableToString <$> rowGs <*> pure (Just (roundStr round : factions, repeat def)) <*> pure (repeat def) <*> pure unicodeBoldHeaderS 158 -- layoutTableToString <$> rowGs <*> pure (Just (roundStr round : factions, repeat def)) <*> pure (repeat def) <*> pure unicodeBoldHeaderS
149 tableString <$> pure (repeat def) <*> pure unicodeBoldHeaderS <*> pure (titlesH $ roundStr round : factions) <*> rowGs 159 tableString <$> pure (repeat def) <*> pure unicodeBoldHeaderS <*> pure (titlesH $ roundStr round : factions) <*> rowGs
160 tTable :: Sh GameState String
161 tTable = do
162 factions <- map (view faction') <$> use combatFactions'
163 st <- get
164 let
165 time = st ^. gTimer
166 protoRows = groupBy ((==) `on` fst) $ st ^. timers
167 faction id = fromJust $ view eFaction <$> Map.lookup id (st ^. gEntities)
168
169 rowGs :: Sh GameState [RowGroup]
170 rowGs = runListT $ do
171 rowGroup'@((t, _):_) <- ListT $ return protoRows
172 let
173 rowGroup = map snd rowGroup'
174 factionColumn i = runListT $ do
175 x <- ListT $ return rowGroup
176 guard $ factionIndex x == i
177 toDesc x
178 factionIndex id = fromJust $ elemIndex (view faction' $ faction id) factions
179 colsAllG top . ([show . round $ t ^. absTime - fromIntegral time] :) <$> mapM factionColumn [0..(length factions - 1)]
180 tableString <$> pure (repeat def) <*> pure unicodeBoldHeaderS <*> pure (titlesH $ ("Time left") : factions) <*> rowGs
150 181
151focusNotes :: GameState -> String 182focusNotes :: GameState -> String
152focusNotes st 183focusNotes st
@@ -191,24 +222,52 @@ stateMaintenance = do
191 gFocus' . eSeqVal .= Nothing 222 gFocus' . eSeqVal .= Nothing
192 -- gFocus .= Nothing 223 -- gFocus .= Nothing
193 void $ do 224 void $ do
225 newCount <- fromIntegral . length <$> use priorityQueue
226 lastCount <- fromIntegral <$> use gLastCount
227 time <- use gTimer
228 when (newCount /= lastCount) $ do
229 let
230 scale :: Entity -> Sh GameState Entity
231 scale entity = (execStateT ?? entity) $ do
232 eTimer . _Just %= scaleTimer time (newCount % (max 1 lastCount))
233 gEntities <~ (mapM scale =<< use gEntities)
234 gLastCount <~ length <$> use priorityQueue
235 void $ do
194 round <- use gRound 236 round <- use gRound
195 let 237 let
196 finished sVal = fromMaybe False (previews (seqVal . _Just) (<= 0) sVal) || view (seqRound . _Wrapped) sVal /= round 238 finished sVal = fromMaybe False (previews (seqVal . _Just) (<= 0) sVal) || view (seqRound . _Wrapped) sVal /= round
197 allFinished <- getAll . foldMapOf (gEntities . each . eStats . sSequence . _Just) (All . finished) <$> get 239 allFinished <- getAll . foldMapOf (gEntities . each . eSeqVal . _Just) (All . finished) <$> get
198 when allFinished $ do 240 when allFinished $ do
199 let 241 let
200 advanceRound' :: EntityIdentifier -> Entity -> Sh GameState Entity 242 advanceRound' :: EntityIdentifier -> Entity -> Sh GameState Entity
201 advanceRound' ident entity = fmap (fromMaybe entity . (\(m, s) -> s <$ m)) . (runStateT ?? entity) . runMaybeT $ do 243 advanceRound' ident entity = fmap (fromMaybe entity . (\(m, s) -> s <$ m)) . (runStateT ?? entity) . runMaybeT $ do
202 cRound <- MaybeT . preuse $ eStats . sSequence . _Just . seqRound . _Wrapped 244 cRound <- MaybeT . preuse $ eSeqVal . _Just . seqRound . _Wrapped
203 guard $ cRound < 0 245 guard $ cRound < 0
204 cVal <- MaybeT . preuse $ eStats . sSequence . _Just . seqVal . _Just 246 cVal <- MaybeT . preuse $ eSeqVal . _Just . seqVal . _Just
205 name <- lift . lift $ toName ident 247 name <- lift . lift $ toName ident
206 nVal' <- MaybeT . preuse $ eStats . sSeqVal 248 (newEntity, nVal) <- lift . lift $ rollSeqVal entity name
207 nVal <- MaybeT . focusState eStats $ evalFormula' [name] nVal' 249 put $ set eSeqVal nVal newEntity
208 eStats . sSequence . _Just . seqVal . _Just += nVal 250 when (cVal < 0) $ -- Carry over negative values from previous rounds
209 eStats . sSequence . _Just . seqRound . _Wrapped += 1 251 eSeqVal . _Just . seqVal . _Just += cVal
252 eSeqVal . _Just . seqRound . _Wrapped += 1
253 advanceTimer :: Entity -> Sh GameState Entity
254 advanceTimer entity = (execStateT ?? entity) $ do
255 rTime <- lift $ use gTimer
256 eTimer . _Just . absTime -= fromIntegral rTime
210 gRounds -= 1 257 gRounds -= 1
211 gEntities <~ (imapM advanceRound' =<< use gEntities) 258 gEntities <~ (mapM advanceTimer =<< imapM advanceRound' =<< use gEntities)
259 gTimer .= 0
260
261rollSeqVal :: Entity -> String -> Sh GameState (Entity, Maybe SeqVal)
262rollSeqVal entity name = do
263 let sVal = fromMaybe (val ignored ["Sequenzwert"] False) $ preview (eStats . sSeqVal) entity
264 (newEntity, sNum) <- evalFormula [name] entity sVal
265 round <- use gRound
266 let val = Just $ def
267 & set (seqRound . _Wrapped) round
268 & set seqVal (Just sNum)
269 & set seqEpsilon (entity ^. eStats . sSeqEpsilon)
270 return (newEntity, val)
212 271
213-- Query state 272-- Query state
214listFactions, listEntities :: Sh GameState () 273listFactions, listEntities :: Sh GameState ()
@@ -220,18 +279,39 @@ focusTip, blur, pFocusTip :: Sh GameState ()
220focusTip = gFocus <~ preuse tip 279focusTip = gFocus <~ preuse tip
221blur = gFocus .= Nothing 280blur = gFocus .= Nothing
222pFocusTip = do 281pFocusTip = do
282 nextTimer <- preuse $ timers . folding listToMaybe
283 time <- fromIntegral <$> use gTimer
223 round <- use gRound 284 round <- use gRound
224 let 285 let
225 eWeight :: Maybe SeqVal -> Int 286 eWeight :: Maybe SeqVal -> Int
226 eWeight sVal 287 eWeight sVal
227 | preview (_Just . seqRound . _Wrapped) sVal == Just round 288 | preview (_Just . seqRound . _Wrapped) sVal == Just round
228 , (preview (_Just . seqVal . _Just) -> Just n) <- sVal = n 289 , (preview (_Just . seqVal . _Just) -> Just n) <- sVal = max 0 n
229 | otherwise = 0 290 | otherwise = 0
230 entities <- map (over _2 . view $ eSeqVal . to eWeight) . Map.toList <$> use gEntities 291 entities <- map (over _2 . view $ eSeqVal . to eWeight) . Map.toList <$> use gEntities
231 case entities of 292 case nextTimer of
232 [] -> gFocus .= Nothing 293 nextTimer
233 _ -> gFocus <~ Just <$> liftIO (enact $ makeEventProb entities) 294 | Just timer <- nextTimer
234 295 , fst $ over _1 (\t -> t ^. absTime <= time) timer
296 -> gFocus .= Just (snd timer)
297 | null entities -> gFocus .= Nothing
298 | otherwise -> gFocus <~ Just <$> liftIO (enact $ makeEventProb entities)
299
300entityTimer, pEntityTimer :: Completable TimerLength -> Sh GameState ()
301entityTimer = entityTimer' Constant
302pEntityTimer = entityTimer' Scaled
303entityTimer' toTimer = withArg $ \(TimerLength origin n) -> do
304 time <- use gTimer
305 entities <- length <$> use priorityQueue
306 let
307 timer = case origin of
308 Absolute -> n
309 Now -> time + n
310 gFocus' . eTimer .= Just (scaleTimer time (max 1 $ fromIntegral entities) . toTimer $ fromIntegral timer)
311
312clearEntityTimer :: Sh GameState ()
313clearEntityTimer = gFocus' . eTimer .= Nothing
314
235-- Manual focus 315-- Manual focus
236setFocus :: Completable EntityIdentifier -> Sh GameState () 316setFocus :: Completable EntityIdentifier -> Sh GameState ()
237setFocus = withArg $ \ident -> gFocus ?= ident 317setFocus = withArg $ \ident -> gFocus ?= ident
@@ -346,21 +426,18 @@ clearFactionSeqVal = withArg $ \qFaction -> use gEntities >>= mapM_ (clearEntity
346entitySeqVal', clearEntitySeqVal' :: EntityIdentifier -> Sh GameState () 426entitySeqVal', clearEntitySeqVal' :: EntityIdentifier -> Sh GameState ()
347entitySeqVal' ident = void . runMaybeT $ do 427entitySeqVal' ident = void . runMaybeT $ do
348 entity <- MaybeT $ preuse (gEntities . ix ident) 428 entity <- MaybeT $ preuse (gEntities . ix ident)
349 let sVal = fromMaybe (val ignored ["Sequenzwert"] False) $ preview (eStats . sSeqVal) entity
350 name <- toName ident 429 name <- toName ident
351 round <- use gRound 430 (newEntity, val) <- lift $ rollSeqVal entity name
352 (newEntity, sNum) <- evalFormula [name] entity sVal
353 let val = Just $ def
354 & set (seqRound . _Wrapped) round
355 & set seqVal (Just sNum)
356 & set seqEpsilon (entity ^. eStats . sSeqEpsilon)
357 gEntities . at ident .= Just (newEntity & set eSeqVal val) 431 gEntities . at ident .= Just (newEntity & set eSeqVal val)
358 gLog <>= pure (ident, "Sequence: " ++ show sNum) 432 gLog <>= pure (ident, "Sequence: " ++ show (fromJust $ view seqVal =<< val))
359clearEntitySeqVal' ident = gEntities . ix ident . eSeqVal .= Nothing 433clearEntitySeqVal' ident = gEntities . ix ident . eSeqVal .= Nothing
360 434
361spendSeq :: Int -> String -> Sh GameState () 435spendSeq :: Int -> String -> Sh GameState ()
362spendSeq n logStr = withFocus $ \focusId -> do 436spendSeq n logStr = withFocus $ \focusId -> do
363 gEntities . ix focusId . eStats . sSequence . _Just . seqVal . _Just -= n 437 gFocus' . eSeqVal . _Just . seqVal . _Just -= n
438 hasSeq <- isJust <$> preuse (gFocus' . eSeqVal . _Just . seqVal . _Just)
439 when hasSeq $
440 gTimer += n
364 gLog <>= pure (focusId, logStr) 441 gLog <>= pure (focusId, logStr)
365 442
366delay :: Sh GameState () 443delay :: Sh GameState ()
@@ -478,4 +555,5 @@ printVal = withArg $ \formula -> withFocus $ \focusId -> do
478 (fromRational prob :: Double) 555 (fromRational prob :: Double)
479 barLength (replicate (round $ fromInteger barLength * normalize prob) '#') 556 barLength (replicate (round $ fromInteger barLength * normalize prob) '#')
480 lengths = map (length . show . fst) vals 557 lengths = map (length . show . fst) vals
481 normalize p = p / maximum (map snd vals) 558 -- normalize p = p / maximum (map snd vals)
559 normalize = id
diff --git a/src/Sequence/Contact/Archetypes.hs b/src/Sequence/Contact/Archetypes.hs
index 1973b97..f8d4c9d 100644
--- a/src/Sequence/Contact/Archetypes.hs
+++ b/src/Sequence/Contact/Archetypes.hs
@@ -119,6 +119,7 @@ prop = Prop
119 , _sFatigueShock = def 119 , _sFatigueShock = def
120 120
121 , _sSequence = Nothing 121 , _sSequence = Nothing
122 , _sTimer = Nothing
122 123
123 , _sExtraSkills = [] 124 , _sExtraSkills = []
124 , _sModifiers = [] 125 , _sModifiers = []
@@ -230,6 +231,7 @@ human = Humanoid
230 , _sFatigue = 0 231 , _sFatigue = 0
231 232
232 , _sSequence = Nothing 233 , _sSequence = Nothing
234 , _sTimer = Nothing
233 235
234 , _sPainShock = def 236 , _sPainShock = def
235 & set seReBar (vitBar 0.75) 237 & set seReBar (vitBar 0.75)
@@ -351,6 +353,7 @@ dog = Quadruped
351 , _sFatigue = 0 353 , _sFatigue = 0
352 354
353 , _sSequence = Nothing 355 , _sSequence = Nothing
356 , _sTimer = Nothing
354 357
355 , _sPainShock = def 358 , _sPainShock = def
356 , _sFatigueShock = def 359 , _sFatigueShock = def
@@ -440,6 +443,7 @@ dolphin = Dolphin
440 , _sFatigue = 0 443 , _sFatigue = 0
441 444
442 , _sSequence = Nothing 445 , _sSequence = Nothing
446 , _sTimer = Nothing
443 447
444 , _sPainShock = def 448 , _sPainShock = def
445 , _sFatigueShock = def 449 , _sFatigueShock = def
diff --git a/src/Sequence/Contact/Types.hs b/src/Sequence/Contact/Types.hs
index 5f8808d..c69a698 100644
--- a/src/Sequence/Contact/Types.hs
+++ b/src/Sequence/Contact/Types.hs
@@ -123,6 +123,20 @@ instance Default SeqVal where
123 } 123 }
124 124
125makeLenses ''ShockEffect 125makeLenses ''ShockEffect
126
127absTime :: Lens' Timer Rational
128absTime = lens get set
129 where
130 get (Constant n) = n
131 get (Scaled n) = n
132 set (Constant _) n = Constant n
133 set (Scaled _) n = Scaled n
134
135instance Eq Timer where
136 (==) = (==) `on` view absTime
137
138instance Ord Timer where
139 compare = comparing $ view absTime
126 140
127instance Default ShockEffect where 141instance Default ShockEffect where
128 def = ShockEffect { _seApplied = False 142 def = ShockEffect { _seApplied = False
@@ -148,6 +162,7 @@ instance Default Stats where
148 , _sFatigue = 0 162 , _sFatigue = 0
149 163
150 , _sSequence = Nothing 164 , _sSequence = Nothing
165 , _sTimer = Nothing
151 166
152 , _sPainShock = def 167 , _sPainShock = def
153 , _sFatigueShock = def 168 , _sFatigueShock = def
diff --git a/src/Sequence/Contact/Types/Internal.hs b/src/Sequence/Contact/Types/Internal.hs
index 7938a06..11116e9 100644
--- a/src/Sequence/Contact/Types/Internal.hs
+++ b/src/Sequence/Contact/Types/Internal.hs
@@ -83,6 +83,10 @@ data SeqVal = SeqVal
83 } 83 }
84 deriving (Show, Eq, Ord) 84 deriving (Show, Eq, Ord)
85 85
86data Timer = Scaled Rational
87 | Constant Rational
88 deriving (Show)
89
86data ShockEffect = ShockEffect 90data ShockEffect = ShockEffect
87 { _seApplied :: Bool 91 { _seApplied :: Bool
88 , _seVal 92 , _seVal
@@ -107,6 +111,7 @@ data Stats = Prop
107 , _sFatigueShock :: ShockEffect 111 , _sFatigueShock :: ShockEffect
108 112
109 , _sSequence :: Maybe SeqVal 113 , _sSequence :: Maybe SeqVal
114 , _sTimer :: Maybe Timer
110 115
111 , _sExtraSkills :: Map (CI String) (FormulaM Stats Test) 116 , _sExtraSkills :: Map (CI String) (FormulaM Stats Test)
112 , _sModifiers :: Set Modifier 117 , _sModifiers :: Set Modifier
@@ -171,6 +176,7 @@ data Stats = Prop
171 , _sFatigue :: Int 176 , _sFatigue :: Int
172 177
173 , _sSequence :: Maybe SeqVal 178 , _sSequence :: Maybe SeqVal
179 , _sTimer :: Maybe Timer
174 180
175 , _sPainShock :: ShockEffect 181 , _sPainShock :: ShockEffect
176 , _sFatigueShock :: ShockEffect 182 , _sFatigueShock :: ShockEffect
@@ -213,6 +219,7 @@ data Stats = Prop
213 , _sFatigue :: Int 219 , _sFatigue :: Int
214 220
215 , _sSequence :: Maybe SeqVal 221 , _sSequence :: Maybe SeqVal
222 , _sTimer :: Maybe Timer
216 223
217 , _sPainShock :: ShockEffect 224 , _sPainShock :: ShockEffect
218 , _sFatigueShock :: ShockEffect 225 , _sFatigueShock :: ShockEffect
@@ -255,6 +262,7 @@ data Stats = Prop
255 , _sFatigue :: Int 262 , _sFatigue :: Int
256 263
257 , _sSequence :: Maybe SeqVal 264 , _sSequence :: Maybe SeqVal
265 , _sTimer :: Maybe Timer
258 266
259 , _sPainShock :: ShockEffect 267 , _sPainShock :: ShockEffect
260 , _sFatigueShock :: ShockEffect 268 , _sFatigueShock :: ShockEffect
diff --git a/src/Sequence/Types.hs b/src/Sequence/Types.hs
index b5f6b4b..f2c08ac 100644
--- a/src/Sequence/Types.hs
+++ b/src/Sequence/Types.hs
@@ -1,12 +1,12 @@
1{-# LANGUAGE FlexibleInstances, FlexibleContexts, MultiParamTypeClasses, TypeSynonymInstances, ViewPatterns, OverloadedStrings, TemplateHaskell, GeneralizedNewtypeDeriving, TypeOperators, UndecidableInstances #-} 1{-# LANGUAGE FlexibleInstances, FlexibleContexts, MultiParamTypeClasses, TypeSynonymInstances, ViewPatterns, OverloadedStrings, TemplateHaskell, GeneralizedNewtypeDeriving, TypeOperators, UndecidableInstances, RankNTypes #-}
2 2
3module Sequence.Types 3module Sequence.Types
4 ( GameState, gEntities, gEntityNames, gFocus, gNextId', gLog 4 ( GameState, gEntities, gEntityNames, gFocus, gNextId', gLog, gTimer, gLastCount
5 , Faction, faction, faction' 5 , Faction, faction, faction'
6 , Entity(..), eFaction, eSeqVal, eStats, eNotes 6 , Entity(..), eFaction, eSeqVal, eStats, eNotes
7 , EntityName(..), entityName 7 , EntityName(..), entityName
8 , EntityIdentifier(..), entityId, entityId' 8 , EntityIdentifier(..), entityId, entityId'
9 , inhabitedFactions, priorityQueue, tip, insertEntity, gFocus', gRounds, gRounds', gRound 9 , inhabitedFactions, combatFactions, combatFactions', priorityQueue, timers, tip, insertEntity, gFocus', gRounds, gRounds', gRound, eTimer
10 ) where 10 ) where
11 11
12import Control.Lens 12import Control.Lens
@@ -81,6 +81,9 @@ instance Default Entity where
81eSeqVal :: Lens' Entity (Maybe SeqVal) 81eSeqVal :: Lens' Entity (Maybe SeqVal)
82eSeqVal = eStats . sSequence 82eSeqVal = eStats . sSequence
83 83
84eTimer :: Lens' Entity (Maybe Timer)
85eTimer = eStats . sTimer
86
84instance Stats :<: Entity where 87instance Stats :<: Entity where
85 ctx' = eStats 88 ctx' = eStats
86 89
@@ -102,24 +105,36 @@ entityId' = _Show . entityId
102 105
103data GameState = GameState 106data GameState = GameState
104 { _gEntities :: Map EntityIdentifier Entity 107 { _gEntities :: Map EntityIdentifier Entity
108 , _gLastCount :: Int
105 , _gEntityNames :: Bimap EntityIdentifier EntityName 109 , _gEntityNames :: Bimap EntityIdentifier EntityName
106 , _gFocus :: Maybe EntityIdentifier 110 , _gFocus :: Maybe EntityIdentifier
107 , _gNextId :: EntityIdentifier 111 , _gNextId :: EntityIdentifier
108 , _gLog :: Seq (EntityIdentifier, String) 112 , _gLog :: Seq (EntityIdentifier, String)
113 , _gTimer :: Int
109 } 114 }
110makeLenses ''GameState 115makeLenses ''GameState
111 116
112instance Default GameState where 117instance Default GameState where
113 def = GameState 118 def = GameState
114 { _gEntities = def 119 { _gEntities = def
120 , _gLastCount = 0
115 , _gEntityNames = Bimap.empty 121 , _gEntityNames = Bimap.empty
116 , _gFocus = Nothing 122 , _gFocus = Nothing
117 , _gNextId = toEnum 0 123 , _gNextId = toEnum 0
118 , _gLog = Seq.empty 124 , _gLog = Seq.empty
125 , _gTimer = 0
119 } 126 }
120 127
121inhabitedFactions :: Getter GameState [Faction] 128inhabitedFactions, combatFactions, combatFactions' :: Getter GameState [Faction]
122inhabitedFactions = to $ nub . sort . Map.elems . fmap (view eFaction) . view gEntities 129inhabitedFactions = factionList $ \_ _ -> True
130combatFactions = factionList $ \f st -> let
131 cFactions = map (view eFaction . fromJust . flip Map.lookup (st ^. gEntities) . snd) $ st ^. priorityQueue
132 in f `elem` cFactions
133combatFactions' = factionList $ \f st -> let
134 cFactions = map (view eFaction . fromJust . flip Map.lookup (st ^. gEntities) . snd) $ st ^. timers
135 in f `elem` cFactions
136factionList :: (Faction -> GameState -> Bool) -> Getter GameState [Faction]
137factionList pred = to $ \st -> filter (flip pred st) . nub . sort . Map.elems . fmap (view eFaction) . view gEntities $ st
123 138
124priorityQueue :: Getter GameState [(SeqVal, EntityIdentifier)] 139priorityQueue :: Getter GameState [(SeqVal, EntityIdentifier)]
125priorityQueue = to priorityQueue' 140priorityQueue = to priorityQueue'
@@ -128,8 +143,23 @@ priorityQueue = to priorityQueue'
128 filter (Nothing, _) = mempty 143 filter (Nothing, _) = mempty
129 filter (Just val, id) = pure (val, id) 144 filter (Just val, id) = pure (val, id)
130 145
146timers :: Getter GameState [(Timer, EntityIdentifier)]
147timers = to timers'
148 where
149 timers' state = sortBy (comparing fst) . concat . map filter . map (over _1 $ view eTimer) . map swap $ entities
150 where
151 entities = Map.toAscList $ view gEntities state
152 time = fromIntegral $ view gTimer state
153 filter (Nothing, _) = mempty
154 filter (Just v, id) = pure (v, id)
155
131tip :: Fold GameState EntityIdentifier 156tip :: Fold GameState EntityIdentifier
132tip = priorityQueue . folding (fmap snd . listToMaybe) 157tip = folding $ runReaderT tip'
158 where
159 tip' :: ReaderT GameState First EntityIdentifier
160 tip' = do
161 join . fmap (lift . First) . preview $ timers . folding (fmap snd . listToMaybe)
162 join . fmap (lift . First) . preview $ priorityQueue . folding (fmap snd . listToMaybe)
133 163
134gFocus' :: Traversal' GameState Entity 164gFocus' :: Traversal' GameState Entity
135gFocus' modifyFocus st = (flip runReader st) . (maybe (asks pure) return =<<) . runMaybeT $ do 165gFocus' modifyFocus st = (flip runReader st) . (maybe (asks pure) return =<<) . runMaybeT $ do
@@ -158,7 +188,7 @@ insertEntity entity = execState $ do
158 gNextId %= succ 188 gNextId %= succ
159 189
160gRounds :: Traversal' GameState Int 190gRounds :: Traversal' GameState Int
161gRounds = gEntities . each . eStats . sSequence . _Just . seqRound . _Wrapped 191gRounds = gEntities . each . eSeqVal . _Just . seqRound . _Wrapped
162 192
163gRounds' :: Getter GameState [Int] 193gRounds' :: Getter GameState [Int]
164gRounds' = to $ nub . sort . toListOf gRounds 194gRounds' = to $ nub . sort . toListOf gRounds
diff --git a/src/Sequence/Utils.hs b/src/Sequence/Utils.hs
index fbf3c7d..bb29b86 100644
--- a/src/Sequence/Utils.hs
+++ b/src/Sequence/Utils.hs
@@ -1,10 +1,12 @@
1{-# LANGUAGE ViewPatterns, FlexibleContexts, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances, OverloadedStrings, OverloadedLists, RankNTypes #-} 1{-# LANGUAGE ViewPatterns, FlexibleContexts, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances, OverloadedStrings, OverloadedLists, RankNTypes #-}
2 2
3module Sequence.Utils 3module Sequence.Utils
4 ( withArg, withFocus, withFocus' 4 ( TimerLength(..), TimerOrigin(..)
5 , withArg, withFocus, withFocus'
5 , focusState 6 , focusState
6 , toName, toDesc 7 , toName, toDesc
7 , outputLogged 8 , outputLogged
9 , scaleTimer
8 , Argument(..) 10 , Argument(..)
9 , Completion(..) 11 , Completion(..)
10 , module Sequence.Utils.Ask 12 , module Sequence.Utils.Ask
@@ -50,6 +52,10 @@ import Sequence.Formula
50 52
51import Text.Regex (mkRegex, subRegex) 53import Text.Regex (mkRegex, subRegex)
52 54
55data TimerLength = TimerLength TimerOrigin Int
56
57data TimerOrigin = Absolute | Now
58
53class Argument a st | a -> st where 59class Argument a st | a -> st where
54 arg :: String -> Sh st (Maybe a) 60 arg :: String -> Sh st (Maybe a)
55 61
@@ -93,6 +99,23 @@ outputLogged id str = gLog <>= pure (id, clean str) >> shellPutStrLn str
93 where 99 where
94 clean str = subRegex (mkRegex "(\x9B|\x1B\\[)[0-?]*[ -/]*[@-~]") str "" -- remove ANSI escapes 100 clean str = subRegex (mkRegex "(\x9B|\x1B\\[)[0-?]*[ -/]*[@-~]") str "" -- remove ANSI escapes
95 101
102scaleTimer :: Int -> Rational -> Timer -> Timer
103scaleTimer _ _ t@(Constant _) = t
104scaleTimer (fromIntegral -> now) factor (Scaled r) = Scaled $ ((max 0 $ r - now) * factor) + now
105
106instance Completion TimerLength GameState where
107 completableLabel _ = "<timer offset>"
108 complete _ st prefix = return []
109
110instance Argument TimerLength GameState where
111 arg str
112 | ('+':cs) <- str
113 , (Just n) <- readMaybe cs
114 , n >= 0 = return . Just $ TimerLength Now n
115 | (Just n) <- readMaybe str
116 , n >= 0 = return . Just $ TimerLength Absolute n
117 | otherwise = return Nothing
118
96instance Completion EntityIdentifier GameState where 119instance Completion EntityIdentifier GameState where
97 completableLabel _ = "<entity>" 120 completableLabel _ = "<entity>"
98 complete _ st prefix = return . filter ((isPrefixOf `on` CI.foldCase) prefix) . map ((evalState ?? st) . toName) . Map.keys $ st ^. gEntities 121 complete _ st prefix = return . filter ((isPrefixOf `on` CI.foldCase) prefix) . map ((evalState ?? st) . toName) . Map.keys $ st ^. gEntities