packages feed

midimory-0.0.2: src/Game.hs

module Game where

import qualified Configuration as Config

import qualified Sound.ALSA.Sequencer.Event as Event

import qualified System.Random as Rnd

import qualified Control.Monad.Trans.State as MS
import qualified Control.Monad.Trans.Class as MT
import Control.Monad (forM)
import Control.Applicative ((<$>))

import qualified Data.Sequence as Seq
import qualified Data.Array as Array
import Data.Sequence (Seq, ViewL((:<)), (><), )
import Data.Array (Array)



data Player = PlayerA | PlayerB

switchPlayer :: Player -> Player
switchPlayer PlayerA = PlayerB
switchPlayer PlayerB = PlayerA

formatPlayer :: Player -> String
formatPlayer PlayerA = "Player A"
formatPlayer PlayerB = "Player B"


data Choice = First | Second

makeMessage :: Player -> Choice -> String
makeMessage player choice =
   formatPlayer player ++ ": Hit " ++
   (case choice of First -> "first"; Second -> "second") ++
   " button!"

completeMessage :: (Ord a, Num a) => a -> Player -> (a, a) -> String
completeMessage maxScore pl (a,b) =
   let winners =
         if a+b < maxScore
           then []
           else
              case compare a b of
                 GT -> [PlayerA]
                 LT -> [PlayerB]
                 EQ -> [PlayerA, PlayerB]
   in case winners of
         [] -> makeMessage pl First
         [winner] -> "Game Over! The winner is " ++ formatPlayer winner
         _ -> "Game Over! Stalemate!"



pick :: Int -> Seq a -> (a, Seq a)
pick n as =
   let (prefix, suffix) = Seq.splitAt n as
   in  case Seq.viewl suffix of
          Seq.EmptyL -> error "pick: index too large"
          a :< rest -> (a, prefix >< rest)

shuffle :: (Rnd.RandomGen g) => [a] -> MS.State g [a]
shuffle xs =
   flip MS.evalStateT (Seq.fromList xs) $
   forM (takeWhile (>=0) $ tail $ iterate (subtract 1) (length xs)) $ \maxN -> do
      n <- MT.lift $ MS.state $ Rnd.randomR (0, maxN)
      MS.state $ pick n

shufflePitches ::
   (Rnd.RandomGen g) => Config.T -> MS.State g (Array (Int, Int) Event.Pitch)
shufflePitches cfg =
   Array.listArray ((0, 0), (Config.rows cfg - 1, Config.columns cfg - 1))
   <$>
   shuffle ((\ps -> ps++ps) $ Config.pitches cfg)