module MainState (newMState ) where import Graphics.Rendering.OpenGL import Graphics.UI.GLUT import States import VectorMaps import Control.Applicative import qualified Data.Map as Map import EventFlags (eventMState) import EventCheck (eventResetCheck) import ResionMap import SetValue (resetMState) import System.Random import BoardOperater import AIReversi (aiDecision ) -----新しいMStateの作成 newMState :: MState -> DState -> KState -> MState newMState mst dst kst = let mst' = eventMState dst kst mst gMode = gameMode mst in case gMode of GameTitle -> mst' GamePlay2P -> (eventAllAct (maingameProg mst' kst) kst) GamePlay1P -> (eventAllAct (maingameProgCPU mst' kst) kst) ------リセットイベント eventReset :: MState -> KState -> MState eventReset mst kst =if eventResetCheck mst kst then resetMState mst else mst -------イベント実行 eventAct :: KState -> MState -> EventKey -> MState eventAct kst mst ekey = case ekey of EReset -> eventReset mst kst _ -> mst -------すべてのイベント実行 eventAllAct :: MState -> KState -> MState eventAllAct mst kst = let ekeys = Map.keys (events mst) in foldl (eventAct kst) mst ekeys -----ゲーム進行 maingameProg :: MState -> KState -> MState maingameProg mst kst = let gpProg = gamePlayProg mst in case gpProg of SelectCell -> putStoneM mst kst PuttedCell -> nextTurn mst -----ゲーム進行 (CPU戦) maingameProgCPU :: MState -> KState -> MState maingameProgCPU mst kst = let gpProg = gamePlayProg mst gturn = gameTurn mst in case gpProg of SelectCell -> case gturn of Turn1P -> putStoneM mst kst Turn2P -> putStoneCPU mst PuttedCell -> nextTurn mst -----ターンの管理 nextTurn :: MState -> MState nextTurn mst = let gturn = gameTurn mst gbcs = gBoardCells mst gs = (getTurnStone mst gturn) mst' = mStateChangeGamePlayProg mst SelectCell in if existPuttableCell mst (opStone gs) gbcs then mStateChangeGTurn mst' (opTurn gturn) else mst' -----クリックした位置のセルに石を置く putStoneM :: MState -> KState -> MState putStoneM mst kst = putStoneP mst (gameTurn mst) kst -----クリックした位置のセルに石を置く (ターン指定) putStoneP :: MState -> GameTurn -> KState -> MState putStoneP mst gturn kst = case (getClickCellPos mst kst) of Nothing -> mst Just x -> putStoneT mst gturn x -----CPUターンの石を置く putStoneCPU :: MState -> MState putStoneCPU mst = let aD = aiDecision mst v = fst aD mst' = mStateChangeRandGen mst (snd aD) in putStoneT mst' Turn2P v -----位置を指定して石を置く putStoneT :: MState -> GameTurn -> (Vector2 GLint) -> MState putStoneT mst gturn cPos = let gbcs = gBoardCells mst gs = getTurnStone mst gturn in if dPuttableCell gs gbcs cPos then mStateChangeGamePlayProg (mStateChangeGBoardCells mst (putStone gs gbcs cPos) ) PuttedCell else mst -----クリックした位置のセルの位置を得る getClickCellPos :: MState -> KState -> (Maybe (Vector2 GLint)) getClickCellPos mst kst = if dClickPosInBoard mst kst then transPosIntoCellPos mst (fmap (getCellPos mst) (clickPos kst) ) else Nothing ----ボードの相対座標からそのセルの位置を得る transPosIntoCellPos :: MState -> Maybe (Vector2 GLfloat) -> Maybe (Vector2 GLint) transPosIntoCellPos mst mv = let tb = displayGameBoard mst w = boardWidth tb / (fromIntegral (divBoardNumX mst)) h = boardHeight tb / (fromIntegral (divBoardNumY mst)) in case mv of Nothing -> Nothing Just (Vector2 x y) -> Just (fmap floor (Vector2 (x / w) (y / h))) ----クリックした位置のテーブルの相対座標 getCellPos :: MState -> (Vector2 GLfloat) -> (Vector2 GLfloat) getCellPos mst v = let tb = displayGameBoard mst posX = boardPosX tb posY = boardPosY tb in (-) <$> v <*> (Vector2 posX posY) ----クリックした位置のテーブル内であるか dClickPosInBoard :: MState -> KState -> Bool dClickPosInBoard mst kst = let tb = displayGameBoard mst posX = boardPosX tb posY = boardPosY tb w = boardWidth tb h = boardHeight tb in case (clickPos kst) of Nothing -> False Just x -> (containIntervalCC2 (Vector2 posX posY) (Vector2 (posX + w) (posY + h)) x) == True