summaryrefslogtreecommitdiff
path: root/src/Main.hs
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 /src/Main.hs
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
Diffstat (limited to 'src/Main.hs')
-rw-r--r--src/Main.hs134
1 files changed, 106 insertions, 28 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