module Grids
(Grid,
gridAt,
generateGrid,
arbitraryReplaceGrid)
where
import RNG
import RandomUtils
import ListUtils
import Data.Map as Map
import Data.Ratio
import Data.List
data Grid a = CompletelyRandomGrid Integer ((Integer,Integer) -> Integer) [(Integer,a)]
| InterpolatedGrid Integer ((Integer,Integer) -> Integer) (Map (a,a) [(Integer,a)]) (Grid a)
| ArbitraryReplacementGrid Integer ((Integer,Integer) -> Integer) [(Rational,a)] [(Integer,a)] (Grid a)
| SpecificPlacementGrid (Map (Integer,Integer) a) (Grid a)
| CachedGrid ((Integer,Integer) -> a) (Grid a)
data Grid_Persistant a = CompletelyRandomGrid_Persistant Integer [(Integer,a)]
| InterpolatedGrid_Persistant Integer [((a,a),[(Integer,a)])] (Grid_Persistant a)
| ArbitraryReplacementGrid_Persistant Integer [(Rational,a)] [(Integer,a)] (Grid_Persistant a)
| SpecificPlacementGrid_Persistant [((Integer,Integer),a)] (Grid_Persistant a)
deriving (Read,Show)
toPersistant :: (Grid a) -> (Grid_Persistant a)
toPersistant (CompletelyRandomGrid x _ prob_list) =
CompletelyRandomGrid_Persistant x prob_list
toPersistant (InterpolatedGrid x _ prob_map grid) =
InterpolatedGrid_Persistant x (toList prob_map) (toPersistant grid)
toPersistant (ArbitraryReplacementGrid x _ sources replacements grid) =
ArbitraryReplacementGrid_Persistant x sources replacements $ toPersistant grid
toPersistant (SpecificPlacementGrid placement_map grid) =
SpecificPlacementGrid_Persistant (toList placement_map) (toPersistant grid)
toPersistant (CachedGrid _ grid) = toPersistant grid
fromPersistant :: (Ord a) => (Grid_Persistant a) -> (Grid a)
fromPersistant (CompletelyRandomGrid_Persistant x prob_list) =
cachedGridOf $ CompletelyRandomGrid x (randomIntegerGrid x) prob_list
fromPersistant (InterpolatedGrid_Persistant x prob_map grid) =
cachedGridOf $ InterpolatedGrid x (randomIntegerGrid x) (fromList prob_map) (fromPersistant grid)
fromPersistant (ArbitraryReplacementGrid_Persistant x sources replacements grid) =
cachedGridOf $ ArbitraryReplacementGrid x (randomIntegerGrid x) sources replacements (fromPersistant grid)
fromPersistant (SpecificPlacementGrid_Persistant placement_map grid) =
cachedGridOf $ SpecificPlacementGrid (fromList placement_map) (fromPersistant grid)
fromPersistant_tupled :: (Ord a) => (Grid_Persistant a,String) -> (Grid a,String)
fromPersistant_tupled (x,y) = (fromPersistant x,y)
instance (Show a) => Show (Grid a) where
show grid = show $ toPersistant grid
instance (Ord a, Read a) => Read (Grid a) where
readsPrec n = \x -> Prelude.map fromPersistant_tupled (readsPrec n x)
gridAt :: Ord a => Grid a -> (Integer,Integer) -> a
gridAt (CompletelyRandomGrid _ seedfn weights) at = weightedPick (seedfn at) weights
gridAt (InterpolatedGrid _ seedfn interpolation_map grid) at@(x,y) =
let here = gridAt grid (x `div` 2,y `div` 2)
there = gridAt grid (x `div` 2 + 1,y `div` 2 + 1)
there_x = gridAt grid (x `div` 2 + 1,y `div` 2)
there_y = gridAt grid (x `div` 2,y `div` 2 + 1)
interpolate a1 a2 = weightedPick (seedfn at) (interpolation_map ! (a1,a2))
in case (even x,even y) of
(True,True) -> here
(True,False) -> (interpolate here there_y)
(False,True) -> (interpolate here there_x)
(False,False) -> (interpolate here there)
gridAt (ArbitraryReplacementGrid _ seedfn sources replacements grid) at =
case fmap fst $ find ((== here) . snd) sources of
Just frequency | ((seedfn at) `mod` (denominator frequency) < (numerator frequency)) ->
weightedPick (seedfn at) replacements
_ -> here
where here = gridAt grid at
gridAt (SpecificPlacementGrid rep_map grid) at =
findWithDefault (gridAt grid at) at rep_map
gridAt (CachedGrid map_fn _) at = map_fn at
cachedGridOf :: Ord a => Grid a -> Grid a
cachedGridOf already_cached_grid@(CachedGrid _ _) = already_cached_grid
cachedGridOf any_other_grid = CachedGrid (cachedAccessor2D (gridAt any_other_grid)) any_other_grid
-- |
-- Generates a random grid. The first Integer, smoothness,
-- indicates the recursion depth for the generator. The
-- Integer list is the random integer stream used to generate
-- the map.
generateGrid :: (Ord a) => [(Integer,a)] -> Map (a,a) [(Integer,a)] -> Integer -> [Integer] -> Grid a
generateGrid weights _ 0 seeds = let seed = head seeds
in CompletelyRandomGrid seed (randomIntegerGrid seed) weights
generateGrid weights interps n seeds = let seed = head seeds
in cachedGridOf $ InterpolatedGrid seed (randomIntegerGrid seed) interps $
generateGrid weights interps (n-1) (tail seeds)
-- |
-- Arbitrarily (randomly) replaces some elements of a grid with another.
--
arbitraryReplaceGrid :: (Ord a) => [(Rational,a)] -> [(Integer,a)] -> Integer -> Grid a -> Grid a
arbitraryReplaceGrid sources replacements seed grid = cachedGridOf $
ArbitraryReplacementGrid seed (randomIntegerGrid seed) sources replacements grid