@@ -39,7 +39,9 @@ type P3d = (Int16, Int16, Int16)
3939
4040data GeneratorState = GS {
4141 gsModel :: ModelFile ,
42- gsFilled :: BA. BitArray P3 ,
42+ gsHarmonics :: Harmonics ,
43+ gsFilled :: BA. BitArray P3 , -- voxels that are already filled by generator
44+ gsGrounded :: BA. BitArray P3 , -- grounded voxels
4345 gsStepNumber :: Step ,
4446 gsAliveBots :: [(Step , [AliveBot ])], -- which bots are alive. Record is to be added when set of bots is changed.
4547 gsBots :: Array BID BotState ,
@@ -50,13 +52,14 @@ maxBID :: BID
5052maxBID = 20
5153
5254initState :: ModelFile -> GeneratorState
53- initState model = GS model filled 0 [(0 ,[bid])] bots traces
55+ initState model = GS model Low filled grounded 0 [(0 ,[bid])] bots traces
5456 where
5557 bid = 0
5658 bots = array (0 , maxBID) [(bid, Bot bid (0 ,0 ,0 ) [] ) | bid <- [0 .. maxBID]]
5759 traces = array (0 , maxBID) [(bid, Seq. empty) | bid <- [0 .. maxBID]]
5860 r = mfResolution model
5961 filled = BA. array ((0 ,0 ,0 ), (r- 1 ,r- 1 ,r- 1 )) [((x,y,z), False ) | x <- [0 .. r- 1 ], y <- [0 .. r- 1 ], z <- [0 .. r- 1 ]]
62+ grounded = BA. array ((0 ,0 ,0 ), (r- 1 ,r- 1 ,r- 1 )) [((x,y,z), False ) | x <- [0 .. r- 1 ], y <- [0 .. r- 1 ], z <- [0 .. r- 1 ]]
6063
6164type Generator a = State GeneratorState a
6265
@@ -89,6 +92,23 @@ issue bid cmd = do
8992 let trace' = trace |> cmd
9093 modify $ \ st -> st {gsTraces = gsTraces st // [(bid, trace')]}
9194
95+ flipH :: Harmonics -> Harmonics
96+ flipH Low = High
97+ flipH High = Low
98+
99+ -- | Issue Flip command and remember resulting harmonics.
100+ issueFlip :: BID -> Generator ()
101+ issueFlip bid = do
102+ modify $ \ st -> st {gsHarmonics = flipH (gsHarmonics st)}
103+ issue bid Flip
104+
105+ -- | Set harmonics to target value
106+ setHarmonics :: BID -> Harmonics -> Generator ()
107+ setHarmonics bid target = do
108+ current <- gets gsHarmonics
109+ when (current /= target) $
110+ issueFlip bid
111+
92112nearPlus :: P3 -> NearDiff -> P3
93113nearPlus (x,y,z) (NearDiff dx dy dz) = (x+ fromIntegral dx, y+ fromIntegral dy, z+ fromIntegral dz)
94114
@@ -99,12 +119,47 @@ negateNear (NearDiff dx dy dz) = NearDiff (-dx) (-dy) (-dz)
99119-- This will mark the voxel as filled in generator's state
100120issueFill :: BID -> NearDiff -> Generator ()
101121issueFill bid nd = do
102- bot <- getBot bid
103- let c' = nearPlus (_pos bot) nd
104- filled <- isFilled c'
105- if filled
106- then fail $ " Voxel is already filled: " ++ show c'
107- else issue bid $ Fill nd
122+ bot <- getBot bid
123+ let c' = nearPlus (_pos bot) nd
124+ filled <- isFilled c'
125+ if filled
126+ then fail $ " Voxel is already filled: " ++ show c'
127+ else do
128+ issue bid $ Fill nd
129+ modify $ \ st -> st {gsFilled = gsFilled st BA. // [(c', True )]}
130+ updateGrounded c'
131+ where
132+ updateGrounded :: P3 -> Generator ()
133+ updateGrounded p@ (x,y,z) = do
134+ filled <- gets gsFilled
135+ grounded <- gets gsGrounded
136+ let result = check filled grounded p
137+ modify $ \ st -> st {gsGrounded = gsGrounded st BA. // [(p, result)]}
138+ where
139+ check _ _ (_,0 ,_) = True
140+ check filled grounded p@ (x,y,z) =
141+ if filled BA. ! p
142+ then
143+ let neighbours = [(x+ 1 , y, z), (x, y+ 1 , z), (x, y, z+ 1 ),
144+ (x- 1 , y, z), (x, y- 1 , z), (x, y, z- 1 )]
145+ in or [grounded BA. ! neighbour | neighbour <- neighbours]
146+ else False
147+
148+ -- | Is voxel grounded?
149+ -- This works by definition, i.e. always returns False for non-filled voxels.
150+ isGrounded :: P3 -> Generator Bool
151+ isGrounded p = do
152+ grounded <- gets gsGrounded
153+ return $ grounded BA. ! p
154+
155+ -- | Will voxel become grounded if we fill it?
156+ -- This checks if any neighbour voxel is grounded.
157+ willBeGrounded :: P3 -> Generator Bool
158+ willBeGrounded (x,y,z) = do
159+ grounded <- gets gsGrounded
160+ let neighbours = [(x+ 1 , y, z), (x, y+ 1 , z), (x, y, z+ 1 ),
161+ (x- 1 , y, z), (x, y- 1 , z), (x, y, z- 1 )]
162+ return $ or [fromMaybe False (grounded BA. !? neighbour) | neighbour <- neighbours]
108163
109164-- | Switch to the next step.
110165-- If we did not issue commands for some bots on current steps,
0 commit comments