Allure-0.4.1: src/GeometryRnd.hs
module GeometryRnd where
import Data.List as L
import Data.Set as S
import Geometry
import Random
findLocInArea :: Area -> (Loc -> Bool) -> Rnd Loc
findLocInArea a@((y0, x0), (y1, x1)) p = do
rx <- randomR (x0, x1)
ry <- randomR (y0, y1)
let loc = (ry, rx)
if p loc then return loc else findLocInArea a p
locInArea :: Area -> Rnd Loc
locInArea a = findLocInArea a (const True)
connectGrid' :: (Y,X) -> Set (Y,X) -> Set (Y,X) -> [((Y,X), (Y,X))] ->
Rnd [((Y,X), (Y,X))]
connectGrid' (ny, nx) unconnected candidates acc
| S.null candidates = return (L.map normalize acc)
| otherwise = do
c <- oneOf (S.toList candidates)
-- potential new candidates:
let ns = S.fromList $ neighbors ((0,0),(ny-1,nx-1)) c
nu = S.delete c unconnected -- new unconnected
-- (new candidates, potential connections):
(nc, ds) = S.partition (`S.member` nu) ns
new <- if S.null ds
then return id
else do
d <- oneOf (S.toList ds)
return ((c,d) :)
connectGrid' (ny,nx) nu (S.delete c (candidates `S.union` nc)) (new acc)
connectGrid :: (Y,X) -> Rnd [((Y,X), (Y,X))]
connectGrid (ny, nx) = do
let unconnected = S.fromList [ (y, x) | x <- [0..nx-1], y <- [0..ny-1] ]
-- candidates are neighbors that are still unconnected; we start with
-- a random choice
rx <- randomR (0, nx-1)
ry <- randomR (0, ny-1)
let candidates = S.fromList [ (ry, rx) ]
connectGrid' (ny, nx) unconnected candidates []
randomConnection :: (Y,X) -> Rnd ((Y,X), (Y,X))
randomConnection (ny, nx) = do
rb <- randomR (False, True)
if rb
then do
rx <- randomR (0, nx-2)
ry <- randomR (0, ny-1)
return (normalize ((ry, rx), (ry, rx+1)))
else do
ry <- randomR (0, ny-2)
rx <- randomR (0, nx-1)
return (normalize ((ry, rx), (ry+1, rx)))