Skip to content

Commit 9488d6d

Browse files
committed
Generator: maintain grounded / non-grounded matrix.
refs #4.
1 parent c23d6c5 commit 9488d6d

File tree

1 file changed

+63
-8
lines changed

1 file changed

+63
-8
lines changed

src/Generator.hs

Lines changed: 63 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ type P3d = (Int16, Int16, Int16)
3939

4040
data 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
5052
maxBID = 20
5153

5254
initState :: 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

6164
type 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+
92112
nearPlus :: P3 -> NearDiff -> P3
93113
nearPlus (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
100120
issueFill :: BID -> NearDiff -> Generator ()
101121
issueFill 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

Comments
 (0)