import qualified SOEGraphics as G import Monad data Orien = NW | NE | SW | SE deriving Show type Trom = (Int, Int, Orien) pow2 :: Int -> Int pow2 0 = 1 pow2 n = 2 * pow2 (n-1) translate :: (Int,Int) -> [Trom] -> [Trom] translate (dx,dy) = map (\(x,y,o) -> (x+dx,y+dy,o)) yflip :: Int -> [Trom] -> [Trom] yflip n = map (\(x,y,o) -> (n-x-1, y, yf o)) where yf NW = NE yf NE = NW yf SW = SE yf SE = SW xflip :: Int -> [Trom] -> [Trom] xflip n = map (\(x,y,o) -> (x, n-y-1, xf o)) where xf NW = SW xf NE = SE xf SW = NW xf SE = NE -- Invariant: Tiling has the "hole" in the lower-right corner. tile :: Int -> [Trom] tile 0 = [] tile n = (half-1, half-1, NW) : ul ++ ur ++ ll ++ lr where pred = n-1 half = pow2 (n-1) ul = tile pred lr = translate (half,half) ul ur = translate (half,0) (yflip half ul) ll = translate (0,half) (xflip half ul) -- infinite stream of colors, excluding black. colors = tail (map fst G.colorList) ++ colors -- pixels per block pps = 30 :: Int -- top-level renderer render :: String -> Int -> [Trom] -> IO () render title n ts = G.runGraphics $ do w <- G.openWindow title (dim,dim) zipWithM_ (renderTrom w) colors ts where dim = pow2 n * pps -- rendering tiling renderTiling n = render ("tile "++show n) n (tile n) -- rendering individual trominoes as polygons renderTrom w c t = G.drawInWindow w (G.withColor c (G.polygon (tromPoly t))) tromPoly (x,y,o) = map (\(a,b,_) -> (pps*x+a, pps*y+b)) (tromShape o) tromShape NW = basePoly tromShape NE = translate (-pps,0) (yflip (pps*2+gap+1) basePoly) tromShape SW = translate (0,-pps) (xflip (pps*2+gap+1) basePoly) tromShape SE = translate (-pps,0) (yflip (pps*2+gap+1) (tromShape SW)) basePoly = [(gap,gap,NW),(2*pps,gap,NW),(2*pps,pps,NW), (pps,pps,NW),(pps,2*pps,NW),(gap,2*pps,NW)] gap :: Int gap = 2