packages feed

haskell-snake-1.0.0: src/Game/HSnake/Player.hs

module Game.HSnake.Player where

import Control.Lens

import Game.HSnake.Basic
import Game.HSnake.Snake

import Data.List

data PlayerType = AI | Human
    deriving (Eq, Show)

data Player = Player {
    _playerType         :: PlayerType
   ,_snake              :: Snake
     {-|
          Temporary state variable to store next move's snake direction
          Without this when snake went North, and user quickly typed
          West, then South, snake would bump into itself
     -}
   ,_nextSnakeDirection :: Direction
   ,_colour             :: Colour
} deriving (Eq, Show)

makeLenses ''Player

initialPlayer :: Player
initialPlayer = Player
              Human
              initialSnake
              (initialSnake^.direction)
              Green

initialPlayerBottom :: Player
initialPlayerBottom = Player
              Human
              initialSnakeBottom
              (initialSnakeBottom^.direction)
              Green

initialComputer :: Player
initialComputer = Player
              AI
              initialSnakeBottom
              (initialSnakeBottom^.direction)
              Blue

isHuman :: Player -> Bool
isHuman (Player Human _ _ _) = True
isHuman _ = False

checkPlayerCollision :: Player -> Bool
checkPlayerCollision player = checkCollision $ player^.snake

movePlayer :: Player -> Player
movePlayer pl = snake .~ (moveSnake $ pl^.snake) $ pl

playerEatsApple :: Point -> Player -> Bool
playerEatsApple apple player = snakeEatsApple (player^.snake) apple

sumPlayersPosition :: [Player] -> [Point]
sumPlayersPosition ps = foldl (++) [] $ map (\pl -> pl^.snake^.position) ps

totalPlayersPosition :: [Player] -> [Point]
totalPlayersPosition = nub . sumPlayersPosition

checkPlayersCollision :: [Player] -> Bool
checkPlayersCollision ps = (length (filter checkPlayerCollision ps) > 0) ||
                          (length (totalPlayersPosition ps) < (length (sumPlayersPosition ps)))

increasePlayerSnakeLength :: Player -> Player
increasePlayerSnakeLength pl = snake .~ (increaseSnakeLength $ pl^.snake) $ pl

setNextPlayerDirection :: Player -> Direction -> Player
setNextPlayerDirection pl dir = nextSnakeDirection .~ dir $ pl

updatePlayerDirection :: Player -> Player
updatePlayerDirection pl = snake .~ changeSnakeDirection (pl^.snake) (pl^.nextSnakeDirection) $ pl