module TipTileMaps (transTileIntoPosition , transTileIntoTexCoord , transPositionIntoTile , transpositionTipTile , getTilePos , isNeighborEmptyTile , shuffleTiles , cursorTileBasePosX , cursorTileBasePosY , dTiletileID) where import Graphics.Rendering.OpenGL import Graphics.UI.GLUT import States import VectorMaps import PositionMaps import Random import System.Random ------タイルからポジションのベクトルを得る transTileIntoPosition :: Table -> MState -> (Vector2 GLint) -> (Vector2 GLfloat) transTileIntoPosition tb mst (Vector2 x y) = let w = (tableWidth tb) / (fdivTileNum mst) tx = tableX tb ty = tableY tb in (Vector2 ((realToFrac x) * w - 1 + tx) ((realToFrac y) * w - 1 + ty) ) ------ポジションからタイルのベクトルを得る transPositionIntoTile :: Table -> MState -> (Vector2 GLfloat) -> (Vector2 GLint) transPositionIntoTile tb mst (Vector2 x y) = let w = (tableWidth tb) / (fdivTileNum mst) tx = tableX tb ty = tableY tb in (Vector2 (floor (( x + 1 - tx) / w ) ) (floor (( y + 1 - ty) / w)) ) ------タイルからテクスチャ座標のベクトルを得る transTileIntoTexCoord :: (Vector2 GLint) -> MState -> (Vector2 GLfloat) transTileIntoTexCoord (Vector2 x y) mst = (Vector2 ((realToFrac x ) * (rdivTileNum mst)) (((realToFrac ((divTileNum mst - 1) - y)) * (rdivTileNum mst))) ) -----タイル交換   transpositionTipTile :: GLint -> GLint -> [TipTile] -> [TipTile] transpositionTipTile i j tiles = case (dTiletileID tiles i) of Nothing -> tiles Just t -> transpositionTipTile' i j tiles tiles -----タイル交換  (再帰) transpositionTipTile' :: GLint -> GLint -> [TipTile] -> [TipTile] -> [TipTile] transpositionTipTile' i j tiles [] = [] transpositionTipTile' i j tiles ( t : rts ) | (tileID t) == i = (changeTilePosToTile t ((\(Just x) -> x) (dTiletileID tiles j))) : (transpositionTipTile' i j tiles rts) | (tileID t) == j = (changeTilePosToTile t ((\(Just x) -> x) (dTiletileID tiles i))) : (transpositionTipTile' i j tiles rts) | otherwise = (t : (transpositionTipTile' i j tiles rts)) -----タイルを指定したタイルの位置へ移す changeTilePosToTile :: TipTile -> TipTile -> TipTile changeTilePosToTile t1 t2 = tipTilePositionChange t1 (tilePosition t2) ----- filterTileID ::GLint -> TipTile -> Bool filterTileID n tile = (tileID tile) == n ----- filterTilePos :: Position -> TipTile -> Bool filterTilePos pos tile = (tilePosition tile) == (postionToVectorInt pos) -----tileIDからタイルの特定 dTiletileID :: [TipTile] -> GLint -> (Maybe TipTile) dTiletileID tiles n = let stiles = (filter (filterTileID n) tiles) in if (length stiles) == 0 then Nothing else Just ( stiles !! 0) -----タイル座標からタイルを得る dTileTilePos :: [TipTile] -> (Vector2 GLint) -> (Maybe TipTile) dTileTilePos tiles (Vector2 x y) | (length stiles) == 0 = Nothing | otherwise = Just ( stiles !! 0 ) where stiles = (filter (filterTilePos (Position x y)) tiles) -----tileIDのタイルの位置の取得 getTilePosFormTileID :: [TipTile] -> GLint-> Maybe (Vector2 GLint) getTilePosFormTileID tiles n = fmap tilePosition ( dTiletileID tiles n) -----EmptyTileに隣接するタイルか否か (タイルIDを受け取る) isNeighborEmptyTile :: GLint -> MState -> Bool isNeighborEmptyTile tID mst =let postID = (getTilePosFormTileID (tipTiles mst) tID ) posemp = (getTilePosFormTileID (tipTiles mst) (-1) ) in case postID of Nothing -> False Just xP -> case posemp of Nothing -> False Just eP -> (vectorNorml1 (vectorSubtract xP eP )) == 1 -----Positionの位置のタイルを得る getTilePos :: DState -> MState -> Position -> (Maybe TipTile) getTilePos dst mst pos = dTileTilePos (tipTiles mst) (getTileCoordPos pos mst dst) -----Positionのタイルの座標を得る getTileCoordPos :: Position -> MState -> DState -> (Vector2 GLint) getTileCoordPos pos mst dst = transPositionIntoTile (mainTable dst) mst (getWCoordPos dst pos ) cursorTileBasePosX :: DState -> MState -> PMState -> GLint cursorTileBasePosX dst mst pmst = case (fmap (`rem` (divTileNum mst)) (cursorTileBasePos dst mst pmst)) of Nothing -> (-1) Just x -> x + 1 cursorTileBasePosY :: DState -> MState -> PMState -> GLint cursorTileBasePosY dst mst pmst = case (fmap (`quot` (divTileNum mst)) (cursorTileBasePos dst mst pmst)) of Nothing -> (-1) Just x -> x + 1 -----カーソルののっているタイルのID cursorTileBasePos :: DState -> MState -> PMState -> (Maybe GLint) cursorTileBasePos dst mst pmst = fmap tileID (cursorTile dst mst pmst) -----カーソルののっているタイル cursorTile :: DState -> MState -> PMState -> (Maybe TipTile) cursorTile dst mst pmst = (cPosition pmst) >>= (getTilePos dst mst ) ----- -------Tileたちをシャッフルする shuffleTiles :: MState -> MState shuffleTiles mst = let rgen = randGen mst stileGen = shuffleTiles' ((tipTiles mst) , (randGen mst)) (divTileNum mst) 42 in mStateTransRandGen (mStateTransTipTiles mst (fixRDTile (divTileNum mst) (fst stileGen))) (snd stileGen) -------Tileたちをシャッフルする shuffleTiles' :: ([TipTile] , StdGen) -> GLint -> GLint -> ([TipTile] , StdGen) shuffleTiles' (tiles , gen) dNum 0 = ((transpositionTipTile 0 1 tiles) , gen) shuffleTiles' (tiles , gen) dNum n = let stileGen = (shuffleTiles' (tiles , gen) dNum (n - 1)) rnd = randomTileTransposition (0, dNum^2 - 1 ) (snd stileGen) rnd2 = randomTileTransposition ( randomBoundV (dNum^2 - 1) (fst rnd )) (snd rnd) in (transpositionTipTile (fst rnd) (fst rnd2) (fst stileGen) , (snd rnd2)) -------固定隅TileのIDチェック checkRDTile :: GLint -> [TipTile] -> GLint checkRDTile n tiles = tileID ((\(Just x) -> x) (dTileTilePos tiles (Vector2 (n-1) 0) )) -------固定隅Tileの修正(n^2のタイルにおいて) fixRDTile :: GLint -> [TipTile] -> [TipTile] fixRDTile n tiles = if (checkRDTile n tiles) == (n - 1) then transpositionTipTile 0 1 tiles else transpositionTipTile (checkRDTile n tiles) (n - 1) tiles ------- randomBoundV :: GLint -> GLint -> (GLint,GLint) randomBoundV maxV x = if (x <= maxV `quot` 2) then (x + 1 , maxV) else (0 , x - 1)