{- Index coordinates
+ + + + z z z x x x y y y
z z z x + - - - - - - - - -
z z z x x + x x x y y y z z z
z z z x x x + -> x x x y y y z z z
x x y y y + x x x y y y z z z
x y y y + - - - - - - - - -
y y y + y y y z z z x x x
+ + + + + + + + 6 7 8 0 1 2 3 4 5 0 0 0 0 0 0 0 0 0
6 7 8 0 + 2 2 2 2 + - - - - - - - - - - - - - - - - - -
6 7 8 0 1 + 1 1 1 1 1 + 0 1 2 3 4 5 6 7 8 2 2 2 2 2 2 2 2 2
6 7 8 0 1 2 + 0 0 0 0 0 0 + 0 1 2 3 4 5 6 7 8 1 1 1 1 1 1 1 1 1
1 2 3 4 5 + 2 2 2 2 2 + 0 1 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0
2 3 4 5 + 1 1 1 1 + - - - - - - - - - - - - - - - - - -
3 4 5 + 0 0 0 + 3 4 5 6 7 8 0 1 2 2 2 2 2 2 2 2 2 2
x y x y
Performance should be predictable: time over space -}
-- | Verse
Verse a = Verse
{ radius :: Int
, nodes :: IntMap a
}
v
where
v = Verse
{ radius = r
, nodes = IntMap.fromDistinctAscList $ zip [0..] (replicate (3 * r * r) void)
}
-- | Navigation
y * (radius v * 3) + x
swap . flip divMod (radius v * 3)
undefined
data Dir = I | L | M | N | H | U
N
opposite L = H
opposite M = U
opposite N = I
opposite H = L
opposite U = M
coordToIndex v $ f (mod (x + n) (r * 3) , y)
| I <- d = coordToIndex v $ f (x , y + n)
| U <- d = shift v n I . shift v n H $ i
| H <- d = shift v (negate n) L i
| N <- d = shift v (negate n) I i
| M <- d = shift v (negate n) U i
where
(x,y) = indexToCoord v i
r = radius v
f (x',y')
| y' >= r || y' < 0 = (mod (x' + t * 2 * r) (r * 3) , mod y' r)
| otherwise = (x' , y')
where
t = div y' r -- outbound multiplier
nodes v IntMap.! i
Map.fromList [(dir , node v (shift v 1 dir i)) | dir <- total]
-- | Manipulation
v { nodes = IntMap.adjust f i $ nodes v }
v { nodes = IntMap.insert i a $ nodes v }