packages feed

starrover2-0.0.9: src/SpaceState/Combat.hs

module SpaceState.Combat(startCombat)
where

import System.Random
import Data.List
import Data.Maybe
import Control.Monad
import Control.Monad.State as State
import Prelude hiding (catch)

import Graphics.Rendering.OpenGL as OpenGL
import Graphics.UI.SDL as SDL
import qualified Data.Edison.Assoc.StandardMap as M

import Combat
import Space
import Cargo
import TextScreen
import Politics
import SDLUtils
import Universe

import SpaceState.Common
import SpaceState.Game
import SpaceState.Init
import SpaceState.Difficulty

startCombat :: Maybe (String, Enemy, String) -- ^ If Nothing, use random enemy
                                             -- and standard message. Otherwise
                                             -- use given (msg, enemy, enemy allegiance).
            -> StateT SpaceState IO (Bool, Bool) -- ^ (gameOver?, combatWon?)
startCombat n = do
  state <- State.get
  (s, en, enalleg) <- case n of
                        Nothing -> do
                          en' <- liftIO $ randomEnemy $ difficultyAIshift $ difficulty state
                          enalleg' <- liftIO $ randomAllegiance
                          s' <- return $
                           concat ["You spot another ship traveling nearby.\n",
                                   "It seems to be a " ++ (describeEnemy en') ++ ".\n",
                                   "The ship is part of the country of " ++ enalleg' ++ ".\n",
                                   "Press ENTER to start a battle against the foreign ship\n",
                                   "or ESCAPE to escape"]
                          return (s', en', enalleg')
                        Just m -> return m
  c <- pressOneOfScreen 
             (liftIO $ makeTextScreen (100, 400) 
                         [(gamefont state, Color4 1.0 1.0 1.0 1.0, s)]
                          (return ()))
             [SDLK_RETURN, SDLK_ESCAPE]
  if c == SDLK_RETURN
    then do
      enemyrot <- liftIO $ fromIntegral `fmap` randomRIO (-180, 180 :: Int)
      enpos <- liftIO $ randPos ((0, 0), (50, 100))
      plpos <- liftIO $ randPos ((100, 0), (150, 100))
      let plrot = angleFromTo plpos enpos - 90
      (newhealth, newpoints, mnewcargo) <- liftIO $ evalStateT combatLoop 
                                           (newCombat plalleg enalleg intermediate (plhealth state) plpos enpos plrot enemyrot en)
      if newhealth == 0
        then do
          releaseKeys
          gameover <- lostLife "You fought bravely, but your ship was blown to pieces." recoveryText
          return (gameover, False)
        else do
          modify $ modPlHealth $ const newhealth
          case mnewcargo of
            Nothing -> do
              liftIO $ makeTextScreen (100, 400) [(gamefont state, Color4 1.0 1.0 1.0 1.0, "The enemy is out of your sight.\n\n"),
                                       (gamefont state, Color4 1.0 1.0 1.0 1.0, "Press ENTER to continue")] (return ())
              liftIO $ getSpecificSDLChar SDLK_RETURN
              releaseKeys
              return (False, False)
            Just newcargo -> do
              when (not (M.null newcargo)) $ do
                modify $ modPoints (+(newpoints * (diffcoeff $ difficulty state)))
                (_, cargo', _, hold') <- liftIO $ execStateT 
                               (takeScreen ("Captured cargo") 
                                   (gamefont state) (monofont state)) 
                               (newcargo, plcargo state, plcash state, plholdspace state)
                modify $ modPlCargo (const cargo')
                modify $ modPlHoldspace (const hold')
              killed enalleg
              releaseKeys
              return (False, True)
    else do
      releaseKeys
      return (False, False)

internationalAction :: String -> Int -> StateT SpaceState IO ()
internationalAction s f = modify $ modAllegAttitudes $ consequences f s allegiances relations

killed :: String -> StateT SpaceState IO ()
killed enalleg = internationalAction enalleg (-1)