{-# LANGUAGE PatternGuards, PatternSignatures #-} module Turns (dbPerformPlayerTurn) where import Control.Monad.Maybe import Control.Monad.Trans import DB import DBData import FactionData import Races import Plane import Control.Monad import Creature import Data.Ratio import Facing import Dice import TerrainData import Data.Maybe import Behavior import qualified Perception as P import Position dbPerformPlayerTurn :: Behavior -> CreatureRef -> DB () dbPerformPlayerTurn beh creature_ref = do dbBehave beh creature_ref dbFinishPendingAITurns dbFinishPendingAITurns :: DB () dbFinishPendingAITurns = do m_current_plane <- dbGetCurrentPlane case m_current_plane of Just p -> dbFinishPlanarAITurns p Nothing -> return () dbFinishPlanarAITurns :: PlaneRef -> DB () dbFinishPlanarAITurns plane_ref = do (all_creatures_on_plane :: [CreatureRef]) <- dbGetContents plane_ref any_players_left <- liftM (any (== Player)) $ mapM getCreatureFaction all_creatures_on_plane next_turn <- dbNextTurn $ map generalizeReference all_creatures_on_plane ++ [generalizeReference plane_ref] case next_turn of _ | not any_players_left -> do setPlayerState GameOver return () ref | ref =:= plane_ref -> do dbPerform1PlanarAITurn plane_ref dbFinishPlanarAITurns plane_ref ref | Just creature_ref <- coerceReferenceTyped _creature ref -> do faction <- getCreatureFaction creature_ref if (faction /= Player) then do dbPerform1CreatureAITurn creature_ref dbFinishPlanarAITurns plane_ref else setPlayerState (PlayerCreatureTurn creature_ref NormalMode) return () _ -> error "dbFinishPlanarAITurns: impossible case" dbPerform1PlanarAITurn :: PlaneRef -> DB () dbPerform1PlanarAITurn plane_ref = do creature_locations <- dbGetContents plane_ref player_locations <- filterRO (liftM (== Player) . getCreatureFaction . entity) creature_locations native_locations <- filterRO (liftM (/= Player) . getCreatureFaction . entity) creature_locations when (length native_locations < length player_locations * 2) $ do p <- roll $ map location player_locations spawn_position <- pickRandomClearSite 5 0 0 p (== RecreantFactory) plane_ref dbNewCreature Pirates recreant (Standing plane_ref spawn_position Here) return () dbAdvanceTime (1%100) plane_ref dbPerform1CreatureAITurn :: CreatureRef -> DB () dbPerform1CreatureAITurn creature_ref = atomic $ liftM (flip dbBehave creature_ref) $ P.runPerception creature_ref $ liftM (fromMaybe Vanish) $ runMaybeT $ do player <- MaybeT $ liftM listToMaybe $ filterM (liftM (== Player) . P.getCreatureFaction . entity) =<< P.visibleObjects my_position <- lift P.myPosition let face_to_player = faceAt my_position (location player) return $ case distanceBetweenChessboard my_position (location player) of 1 -> Attack $ face_to_player _ -> Step $ face_to_player