Skip to content

Commit 437f704

Browse files
authored
Move more code to Robots.hs, do not export private fields (#1669)
A continuation of #1667. * Do not export `_viewCenter` or `_focusedRobotID` * Move record initialization code to `Robot.hs` as `setRobotInfo`. * `modifyViewCenter`, `unfocus`, `recalcViewCenter` now operate directly on `Robots` instead of `GameState`.
1 parent 536f1dc commit 437f704

File tree

5 files changed

+67
-55
lines changed

5 files changed

+67
-55
lines changed

src/Swarm/Game/State.hs

+9-48
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,8 @@ module Swarm.Game.State (
4747
currentScenarioPath,
4848
needsRedraw,
4949
replWorking,
50-
applyViewCenterRule,
51-
recalcViewCenter,
52-
modifyViewCenter,
50+
recalcViewCenterAndRedraw,
5351
viewingRegion,
54-
unfocus,
5552
focusedRobot,
5653
RobotRange (..),
5754
focusedRange,
@@ -84,8 +81,8 @@ import Data.Bifunctor (first)
8481
import Data.Digest.Pure.SHA (sha1, showDigest)
8582
import Data.Foldable (toList)
8683
import Data.Foldable.Extra (allM)
84+
import Data.Function (on)
8785
import Data.Int (Int32)
88-
import Data.IntMap (IntMap)
8986
import Data.IntMap qualified as IM
9087
import Data.IntSet qualified as IS
9188
import Data.List (partition, sortOn)
@@ -323,51 +320,19 @@ messageIsFromNearby l e = case e ^. leSource of
323320
InfinitelyFar -> False
324321
Measurable x -> x <= hearingDistance
325322

326-
-- | Given a current mapping from robot names to robots, apply a
327-
-- 'ViewCenterRule' to derive the location it refers to. The result
328-
-- is 'Maybe' because the rule may refer to a robot which does not
329-
-- exist.
330-
applyViewCenterRule :: ViewCenterRule -> IntMap Robot -> Maybe (Cosmic Location)
331-
applyViewCenterRule (VCLocation l) _ = Just l
332-
applyViewCenterRule (VCRobot name) m = m ^? at name . _Just . robotLocation
333-
334323
-- | Recalculate the view center (and cache the result in the
335324
-- 'viewCenter' field) based on the current 'viewCenterRule'. If
336325
-- the 'viewCenterRule' specifies a robot which does not exist,
337326
-- simply leave the current 'viewCenter' as it is. Set 'needsRedraw'
338327
-- if the view center changes.
339-
recalcViewCenter :: GameState -> GameState
340-
recalcViewCenter g =
328+
recalcViewCenterAndRedraw :: GameState -> GameState
329+
recalcViewCenterAndRedraw g =
341330
g
342-
{ _robotInfo =
343-
(g ^. robotInfo)
344-
{ _viewCenter = newViewCenter
345-
}
346-
}
347-
& (if newViewCenter /= oldViewCenter then needsRedraw .~ True else id)
331+
& robotInfo .~ newRobotInfo
332+
& (if ((/=) `on` (^. viewCenter)) oldRobotInfo newRobotInfo then needsRedraw .~ True else id)
348333
where
349-
oldViewCenter = g ^. robotInfo . viewCenter
350-
newViewCenter =
351-
fromMaybe oldViewCenter $
352-
applyViewCenterRule (g ^. robotInfo . viewCenterRule) (g ^. robotInfo . robotMap)
353-
354-
-- | Modify the 'viewCenter' by applying an arbitrary function to the
355-
-- current value. Note that this also modifies the 'viewCenterRule'
356-
-- to match. After calling this function the 'viewCenterRule' will
357-
-- specify a particular location, not a robot.
358-
modifyViewCenter :: (Cosmic Location -> Cosmic Location) -> GameState -> GameState
359-
modifyViewCenter update g =
360-
g
361-
& case g ^. robotInfo . viewCenterRule of
362-
VCLocation l -> robotInfo . viewCenterRule .~ VCLocation (update l)
363-
VCRobot _ -> robotInfo . viewCenterRule .~ VCLocation (update (g ^. robotInfo . viewCenter))
364-
365-
-- | "Unfocus" by modifying the view center rule to look at the
366-
-- current location instead of a specific robot, and also set the
367-
-- focused robot ID to an invalid value. In classic mode this
368-
-- causes the map view to become nothing but static.
369-
unfocus :: GameState -> GameState
370-
unfocus = (\g -> g {_robotInfo = (g ^. robotInfo) {_focusedRobotID = -1000}}) . modifyViewCenter id
334+
oldRobotInfo = g ^. robotInfo
335+
newRobotInfo = recalcViewCenter oldRobotInfo
371336

372337
-- | Given a width and height, compute the region, centered on the
373338
-- 'viewCenter', that should currently be in view.
@@ -663,10 +628,7 @@ pureScenarioToGameState scenario theSeed now toRun gsc =
663628
gs = initGameState gsc
664629
preliminaryGameState =
665630
gs
666-
& robotInfo .~ (gs ^. robotInfo) {_focusedRobotID = baseID}
667-
& robotInfo %~ setRobotList robotList'
668-
& robotInfo . viewCenterRule .~ VCRobot baseID
669-
& robotInfo . robotNaming . gensym .~ initGensym
631+
& robotInfo %~ setRobotInfo baseID robotList'
670632
& creativeMode .~ scenario ^. scenarioCreative
671633
& winCondition .~ theWinCondition
672634
& winSolution .~ scenario ^. scenarioSolution
@@ -756,7 +718,6 @@ pureScenarioToGameState scenario theSeed now toRun gsc =
756718
(\x -> WinConditions Ongoing (ObjectiveCompletion (CompletionBuckets (NE.toList x) mempty mempty) mempty))
757719
(NE.nonEmpty (scenario ^. scenarioObjectives))
758720

759-
initGensym = length robotList - 1
760721
addRecipesWith f = IM.unionWith (<>) (f $ scenario ^. scenarioRecipes)
761722

762723
-- | Create an initial game state corresponding to the given scenario.

src/Swarm/Game/State/Robot.hs

+55-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ module Swarm.Game.State.Robot (
1717

1818
-- * Initialization
1919
initRobots,
20+
setRobotInfo,
2021

2122
-- * Accessors
22-
_viewCenter,
23-
_focusedRobotID,
2423
robotMap,
2524
robotsByLocation,
2625
robotsWatching,
@@ -41,7 +40,11 @@ module Swarm.Game.State.Robot (
4140
addRobot,
4241
addRobotToLocation,
4342
addTRobot,
44-
setRobotList,
43+
44+
-- ** View
45+
modifyViewCenter,
46+
unfocus,
47+
recalcViewCenter,
4548
) where
4649

4750
import Control.Arrow (Arrow ((&&&)))
@@ -59,7 +62,7 @@ import Data.IntSet.Lens (setOf)
5962
import Data.List.NonEmpty qualified as NE
6063
import Data.Map (Map)
6164
import Data.Map qualified as M
62-
import Data.Maybe (mapMaybe)
65+
import Data.Maybe (fromMaybe, mapMaybe)
6366
import Data.Set qualified as S
6467
import Data.Tuple (swap)
6568
import GHC.Generics (Generic)
@@ -378,17 +381,65 @@ removeRobotFromLocationMap (Cosmic oldSubworld oldPlanar) rid =
378381
tidyDelete robID =
379382
surfaceEmpty M.null . M.update (deleteOne robID) oldPlanar
380383

384+
setRobotInfo :: RID -> [Robot] -> Robots -> Robots
385+
setRobotInfo baseID robotList rState =
386+
(setRobotList robotList rState) {_focusedRobotID = baseID}
387+
& viewCenterRule .~ VCRobot baseID
388+
381389
setRobotList :: [Robot] -> Robots -> Robots
382390
setRobotList robotList rState =
383391
rState
384392
& robotMap .~ IM.fromList (map (view robotID &&& id) robotList)
385393
& robotsByLocation .~ M.map (groupRobotsByPlanarLocation . NE.toList) (groupRobotsBySubworld robotList)
386394
& internalActiveRobots .~ setOf (traverse . robotID) robotList
395+
& robotNaming . gensym .~ initGensym
387396
where
397+
initGensym = length robotList - 1
398+
388399
groupRobotsBySubworld =
389400
binTuples . map (view (robotLocation . subworld) &&& id)
390401

391402
groupRobotsByPlanarLocation rs =
392403
M.fromListWith
393404
IS.union
394405
(map (view (robotLocation . planar) &&& (IS.singleton . view robotID)) rs)
406+
407+
-- | Modify the 'viewCenter' by applying an arbitrary function to the
408+
-- current value. Note that this also modifies the 'viewCenterRule'
409+
-- to match. After calling this function the 'viewCenterRule' will
410+
-- specify a particular location, not a robot.
411+
modifyViewCenter :: (Cosmic Location -> Cosmic Location) -> Robots -> Robots
412+
modifyViewCenter update rInfo =
413+
rInfo
414+
& case rInfo ^. viewCenterRule of
415+
VCLocation l -> viewCenterRule .~ VCLocation (update l)
416+
VCRobot _ -> viewCenterRule .~ VCLocation (update (rInfo ^. viewCenter))
417+
418+
-- | "Unfocus" by modifying the view center rule to look at the
419+
-- current location instead of a specific robot, and also set the
420+
-- focused robot ID to an invalid value. In classic mode this
421+
-- causes the map view to become nothing but static.
422+
unfocus :: Robots -> Robots
423+
unfocus = (\ri -> ri {_focusedRobotID = -1000}) . modifyViewCenter id
424+
425+
-- | Recalculate the view center (and cache the result in the
426+
-- 'viewCenter' field) based on the current 'viewCenterRule'. If
427+
-- the 'viewCenterRule' specifies a robot which does not exist,
428+
-- simply leave the current 'viewCenter' as it is.
429+
recalcViewCenter :: Robots -> Robots
430+
recalcViewCenter rInfo =
431+
rInfo
432+
{ _viewCenter = newViewCenter
433+
}
434+
where
435+
newViewCenter =
436+
fromMaybe (rInfo ^. viewCenter) $
437+
applyViewCenterRule (rInfo ^. viewCenterRule) (rInfo ^. robotMap)
438+
439+
-- | Given a current mapping from robot names to robots, apply a
440+
-- 'ViewCenterRule' to derive the location it refers to. The result
441+
-- is 'Maybe' because the rule may refer to a robot which does not
442+
-- exist.
443+
applyViewCenterRule :: ViewCenterRule -> IntMap Robot -> Maybe (Cosmic Location)
444+
applyViewCenterRule (VCLocation l) _ = Just l
445+
applyViewCenterRule (VCRobot name) m = m ^? at name . _Just . robotLocation

src/Swarm/Game/Step.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ gameTick = do
110110
Nothing -> pure ()
111111

112112
-- Possibly update the view center.
113-
modify recalcViewCenter
113+
modify recalcViewCenterAndRedraw
114114

115115
when ticked $ do
116116
-- On new tick see if the winning condition for the current objective is met.

src/Swarm/Game/Step/Const.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ execConst runChildProg c vs s k = do
769769
-- point is that there's no way to tell the difference
770770
-- between this situation and the situation where the
771771
-- robot exists but is too far away.
772-
False -> modify unfocus
772+
False -> robotInfo %= unfocus
773773

774774
-- If it does exist, set it as the view center.
775775
Just _ -> robotInfo . viewCenterRule .= VCRobot rid

src/Swarm/TUI/Controller.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1371,7 +1371,7 @@ scrollView update = do
13711371
-- always work, but there seems to be some sort of race condition
13721372
-- where 'needsRedraw' gets reset before the UI drawing code runs.
13731373
invalidateCacheEntry WorldCache
1374-
gameState %= modifyViewCenter (fmap update)
1374+
gameState . robotInfo %= modifyViewCenter (fmap update)
13751375

13761376
-- | Convert a directional key into a direction.
13771377
keyToDir :: V.Key -> Heading

0 commit comments

Comments
 (0)