2018-03-03 16:03:17 +00:00
|
|
|
module Interior where
|
|
|
|
|
2018-10-14 21:18:41 +00:00
|
|
|
import qualified Affection as A
|
|
|
|
|
2018-03-03 16:03:17 +00:00
|
|
|
import Data.Matrix as M
|
|
|
|
import qualified Data.Map.Strict as Map
|
|
|
|
import Data.List as L
|
|
|
|
import Data.Maybe (isNothing, isJust)
|
|
|
|
|
2018-04-02 14:29:35 +00:00
|
|
|
import Linear.V2
|
|
|
|
|
2018-03-03 16:03:17 +00:00
|
|
|
import System.Random
|
|
|
|
|
|
|
|
-- internal imports
|
|
|
|
|
2018-04-02 14:29:35 +00:00
|
|
|
import Navigation
|
2018-04-14 11:34:28 +00:00
|
|
|
import Util
|
2018-04-02 14:29:35 +00:00
|
|
|
|
2018-06-04 03:29:20 +00:00
|
|
|
import Types
|
2018-03-03 16:03:17 +00:00
|
|
|
|
2018-03-03 16:42:24 +00:00
|
|
|
placeInteriorIO
|
|
|
|
:: Matrix TileState
|
|
|
|
-> Matrix (Maybe ImgId)
|
2018-04-02 14:29:35 +00:00
|
|
|
-> [ReachPoint]
|
2018-03-03 16:42:24 +00:00
|
|
|
-> [Graph]
|
2018-04-02 14:29:35 +00:00
|
|
|
-> IO (Matrix (Maybe ImgId), [ReachPoint])
|
|
|
|
placeInteriorIO imat imgmat irp graph =
|
2018-03-03 16:03:17 +00:00
|
|
|
do
|
|
|
|
rnd <- newStdGen
|
2018-04-02 14:29:35 +00:00
|
|
|
let (_, matps) =
|
2018-03-03 16:03:17 +00:00
|
|
|
foldl
|
2018-11-12 23:56:04 +00:00
|
|
|
(traverseGraph imat)
|
2018-04-02 14:29:35 +00:00
|
|
|
(rnd, (imgmat, irp))
|
2018-03-03 16:03:17 +00:00
|
|
|
graph
|
2018-04-02 14:29:35 +00:00
|
|
|
return matps
|
2018-11-12 23:56:04 +00:00
|
|
|
|
|
|
|
traverseGraph
|
|
|
|
:: Matrix TileState
|
|
|
|
-> (StdGen, (Matrix (Maybe ImgId), [ReachPoint]))
|
|
|
|
-> Graph
|
|
|
|
-> (StdGen, (Matrix (Maybe ImgId), [ReachPoint]))
|
|
|
|
traverseGraph imat acc (GHall sub) =
|
|
|
|
foldl (traverseGraph imat) acc sub
|
2018-11-13 03:16:02 +00:00
|
|
|
traverseGraph imat (rng, putt) (GRoom _ bnds) =
|
2018-11-12 23:56:04 +00:00
|
|
|
let applicable =
|
2019-01-18 18:02:45 +00:00
|
|
|
L.sortBy (\b a -> size (a, (ph, pw), rng) `compare` size (b, (ph, pw), rng)) (
|
2018-11-12 23:56:04 +00:00
|
|
|
L.filter
|
2019-01-18 18:02:45 +00:00
|
|
|
(\a -> roomType `elem` clusterRoom a && size (a, (ph, pw), rng) <= size bnds)
|
2018-11-12 23:56:04 +00:00
|
|
|
[minBound .. maxBound] :: [Cluster])
|
|
|
|
roomType = fst (L.minimumBy
|
|
|
|
(\b a -> (snd a :: Int) `compare` (snd b :: Int)) $ Map.toList $ foldl
|
|
|
|
(\acc a -> if a `Map.member` acc
|
|
|
|
then Map.insert a (acc Map.! a + 1) acc
|
|
|
|
else Map.insert a 1 acc
|
2018-03-03 16:03:17 +00:00
|
|
|
)
|
2018-11-12 23:56:04 +00:00
|
|
|
Map.empty
|
|
|
|
(M.submatrix
|
|
|
|
(fst $ matmin bnds) (fst $ matmax bnds)
|
|
|
|
(snd $ matmin bnds) (snd $ matmax bnds)
|
|
|
|
imat
|
|
|
|
)
|
|
|
|
)
|
2018-11-13 03:16:02 +00:00
|
|
|
(ph, g1) = randomR (1, fst (matmax bnds) - fst (matmin bnds) + 1) rng
|
|
|
|
(pw, g2) = randomR (1, snd (matmax bnds) - snd (matmin bnds) + 1) g1
|
2018-11-12 23:56:04 +00:00
|
|
|
in
|
|
|
|
foldl
|
2018-11-13 03:16:02 +00:00
|
|
|
(\(orng, (omat, orp)) -> placeCluster imat orng bnds (ph, pw) 1 omat orp)
|
|
|
|
(g2, putt)
|
2018-11-12 23:56:04 +00:00
|
|
|
applicable
|
|
|
|
|
|
|
|
placeCluster
|
|
|
|
:: Matrix TileState
|
|
|
|
-> StdGen
|
|
|
|
-> Boundaries Int
|
2018-11-13 03:16:02 +00:00
|
|
|
-> (Int, Int)
|
2018-11-12 23:56:04 +00:00
|
|
|
-> Int
|
|
|
|
-> Matrix (Maybe ImgId)
|
|
|
|
-> [ReachPoint]
|
|
|
|
-> Cluster
|
|
|
|
-> (StdGen, (Matrix (Maybe ImgId), [ReachPoint]))
|
2018-11-13 03:16:02 +00:00
|
|
|
placeCluster imat rng bnds dim try mat rp appl =
|
2018-11-12 23:56:04 +00:00
|
|
|
let (pr, g1) = randomR (fst (matmin bnds) - 1, fst (matmax bnds) - 1) rng
|
|
|
|
(pc, g2) = randomR (snd (matmin bnds) - 1, snd (matmax bnds) - 1) g1
|
2019-01-15 04:28:09 +00:00
|
|
|
(g2_1, g2_2) = split g2
|
2018-11-12 23:56:04 +00:00
|
|
|
freeRoom = foldl
|
|
|
|
(\acc a -> if isNothing a then acc + 1 else acc)
|
|
|
|
0
|
|
|
|
(M.toList $ M.submatrix
|
|
|
|
(fst $ matmin bnds) (fst $ matmax bnds)
|
|
|
|
(snd $ matmin bnds) (snd $ matmax bnds)
|
|
|
|
mat
|
|
|
|
) :: Int
|
2019-01-18 18:02:45 +00:00
|
|
|
(cmat, nrp) = clusterMatWithRPs appl dim g2_2
|
2018-11-12 23:56:04 +00:00
|
|
|
newmat = insertMat cmat mat (pr, pc)
|
|
|
|
exits = filter
|
|
|
|
(\p -> pointType p == RoomExit && inBounds (pointCoord p) bnds)
|
|
|
|
rp
|
|
|
|
oldreaches = foldl (\acc p ->
|
|
|
|
if pointType p /= RoomExit && inBounds (pointCoord p) bnds
|
|
|
|
then pointCoord p : acc
|
|
|
|
else acc
|
|
|
|
)
|
|
|
|
[]
|
|
|
|
rp
|
2019-01-18 18:02:45 +00:00
|
|
|
reaches = (map (+ V2 (pr - 1) (pc - 1)) (map pointCoord nrp))
|
2018-11-12 23:56:04 +00:00
|
|
|
newrp = rp ++ map (\(a, b, c) -> ReachPoint a b c)
|
2019-01-18 18:02:45 +00:00
|
|
|
(zip3
|
|
|
|
(map pointType nrp)
|
|
|
|
reaches
|
|
|
|
(map pointDir nrp)
|
|
|
|
)
|
2018-11-12 23:56:04 +00:00
|
|
|
in
|
2019-01-18 18:02:45 +00:00
|
|
|
if try >= 10 || fromIntegral freeRoom <= size (appl, dim, g2)
|
2018-11-12 23:56:04 +00:00
|
|
|
then (g2, (mat, rp))
|
|
|
|
else
|
|
|
|
if pr + nrows cmat - 1 > fst (matmax bnds) ||
|
|
|
|
pc + ncols cmat - 1 > snd (matmax bnds)
|
2019-01-18 18:02:45 +00:00
|
|
|
then placeCluster imat g2 bnds dim (try + 1) mat rp appl
|
2018-11-12 23:56:04 +00:00
|
|
|
else if
|
|
|
|
any (`notElem` clusterRoom appl)
|
|
|
|
(M.toList (M.submatrix
|
|
|
|
pr (pr + nrows cmat - 1)
|
|
|
|
pc (pc + ncols cmat - 1)
|
|
|
|
imat
|
|
|
|
)) ||
|
|
|
|
any isJust
|
|
|
|
(M.toList (M.submatrix
|
|
|
|
pr (pr + nrows cmat - 1)
|
|
|
|
pc (pc + ncols cmat - 1)
|
|
|
|
mat
|
|
|
|
))
|
2019-01-18 18:02:45 +00:00
|
|
|
then placeCluster imat g2_1 bnds dim (try + 1) mat rp appl
|
2018-11-12 23:56:04 +00:00
|
|
|
else if
|
|
|
|
any (`elem` (oldreaches))
|
|
|
|
(V2
|
|
|
|
<$> [pr .. pr + nrows cmat - 1]
|
|
|
|
<*> [pc .. pc + ncols cmat - 1])
|
2019-01-18 18:02:45 +00:00
|
|
|
then placeCluster imat g2 bnds dim (try + 1) mat rp appl
|
2018-10-14 21:18:41 +00:00
|
|
|
else if
|
2018-11-12 23:56:04 +00:00
|
|
|
isReachable newmat [(V2 10 10, Boundaries (0, 1) (0, 1))] (oldreaches ++ reaches) exits
|
2019-01-18 18:02:45 +00:00
|
|
|
then placeCluster imat g2_1 bnds dim (try + 1) newmat newrp appl
|
|
|
|
else placeCluster imat g2_1 bnds dim (try + 1) mat rp appl
|
2018-03-03 16:03:17 +00:00
|
|
|
|
|
|
|
insertMat
|
|
|
|
:: Matrix (Maybe a)
|
|
|
|
-> Matrix (Maybe a)
|
|
|
|
-> (Int, Int)
|
|
|
|
-> Matrix (Maybe a)
|
|
|
|
insertMat i into (roffs, coffs) =
|
|
|
|
if roffs + nrows i > nrows into || coffs + ncols i > ncols into
|
|
|
|
then error "insertMat: matrix to be inserted does not fit!"
|
|
|
|
else foldl
|
|
|
|
(\mat (ir, ic) ->
|
2018-03-03 16:42:24 +00:00
|
|
|
if isNothing (mat M.! (ir + roffs - 1, ic + coffs - 1))
|
|
|
|
then M.setElem (i M.! (ir, ic)) (ir + roffs - 1, ic + coffs - 1) mat
|
2018-03-03 16:03:17 +00:00
|
|
|
else mat
|
|
|
|
)
|
|
|
|
into
|
|
|
|
((,) <$> [1 .. nrows i] <*> [1 .. ncols i])
|