module VM where import Data.Set (Set) import qualified Data.Set as Set import Test.QuickCheck type Cell = (Int, Int) data Board = Board { boardWidth :: Int, boardHeight :: Int, filled :: Set Cell } data Unit = Unit { unitMembers :: Set Cell, unitPivot :: Cell } deriving Show data Command = MoveW | MoveE | MoveSW | MoveSE | RotateClockwise | RotateCounterclockwise data Game = Game Board Unit -- data Game = Game { board :: Board, unit :: Unit } -- isValidPosition :: Unit -> Board data Notes = OK | Collision | CollisionWithRowElision -- step :: Game -> Command -> (Game, Notes) -- step game inst applyWholeUnit :: Unit -> (Cell -> Cell) -> Unit applyWholeUnit (Unit members pivot) f = Unit (Set.map f members) (f pivot) applyCommand :: Unit -> Command -> Unit applyCommand unit MoveW = applyWholeUnit unit move where move (x, y) = (x - 1, y) applyCommand unit MoveE = applyWholeUnit unit move where move (x, y) = (x + 1, y) applyCommand unit MoveSW = applyWholeUnit unit move where move (x, y) = (x - ((y + 1) `mod` 2), y + 1) applyCommand unit MoveSE = applyWholeUnit unit move where move (x, y) = (x + (y `mod` 2), y + 1) applyCommand (Unit members pivot) RotateClockwise = Unit (Set.map transform members) pivot where transform cell = rotateCell pivot cell applyCommand (Unit members pivot) RotateCounterclockwise = Unit (Set.map transform members) pivot where transform cell = counterRotateCell pivot cell rotateCell :: Cell -> Cell -> Cell rotateCell (px, py) (x, y) = (px - ddiag + (doriz + px `mod` 2) `div` 2, py + doriz) where (ddiag, doriz) = relativePosition (px, py) (x, y) counterRotateCell :: Cell -> Cell -> Cell counterRotateCell pivot = rp . rp . rp . rp . rp where rp = rotateCell pivot relativePosition :: Cell -> Cell -> (Int, Int) relativePosition (px, py) (x, y) = (diagDir, horizDir) where diagDir = y - py horizDir = x - px + (if py `mod` 2 == 0 then diagDir + diagDir `mod` 2 else diagDir - diagDir `mod` 2) `div` 2 test :: (Cell -> Cell) -> [Bool] test f = [f (0,3) == (2,5), f (1,3) == (3, 6), f (2,3) == (3,7), f (3, 3) == (4,8), f (2, 4) == (2,7)] test2 :: (Cell -> Cell) -> [Bool] test2 f = [f (2,5) == (3,6), f (3,6) == (2, 7), f (2,7) == (1,7), f (1, 7) == (1,6), f (1, 6) == (1,5), f (1, 5) == (2, 5)] deepCheck p = quickCheckWith (stdArgs { maxSuccess = 10000 }) p testTutto = do deepCheck (\pivot cell -> let r2 = rotateCell pivot in (r2 . r2 . r2 . r2 . r2 . r2) cell == cell) deepCheck (\pivot cell -> cell == counterRotateCell pivot (rotateCell pivot cell))