Level0-1.0: src/World.hs
module World where
import Types
import Game
import System.Random (randomRIO)
-- get random (Int, Int), making sure it isn't a point in the map.
randomXY :: World -> IO Point
randomXY world = do
x <- randomRIO (1, 31)
y <- randomRIO (1, 31)
if P x y `elem` stage world
then randomXY world
else return (P x y)
-- if the item is eaten, return (True, the item's coordinates)
-- else, return (False, the item's coordinates)
updateItem :: Item -> Snake -> Bool
updateItem Nothing _ = False
updateItem (Just p) snake' = p `elem` points snake'
-- if the old and new direction is D, then don't do anything
-- if the direction is anything else, and we aren't adding to the snake, then move the snake and check for collisions
-- otherwise try and move it and insert x new blocks in the snake.
updateSnake :: Stage -> Direction -> Snake -> Int -> Bool -> Snake
-- if the snake is paused, don't update it
updateSnake _ _ s _ True = s
-- if the snake is dead, don't update it
updateSnake _ _ d@(Snake False _ _ ) _ _ = d
-- check for collisions in the new snake
updateSnake stage' d (Snake True _ ps) 0 _ = collision stage' $ Snake True d $ moveD d (head ps) : init ps
updateSnake stage' d (Snake True _ ps) x _ = collision stage' $ Snake True d $ moveD d (head ps) : replicate x (head ps) ++ init ps
-- check for collisions, if there is one, empty the snake
collision :: Stage -> Snake -> Snake
collision stage' s@(Snake _ _ ps) =
if head ps `elem` tail ps ++ stage'
then s { alive = False }
else s
moveD :: Direction -> Point -> Point
moveD dir' (P x y) = wrap $ case dir' of
N -> moveP (P 0 (-1))
S -> moveP (P 0 1)
E -> moveP (P 1 0)
W -> moveP (P (-1) 0)
where
-- raw coordinate without trying to loop around the edge of the screen
wrap (P x0 y0) = P (mod x0 blocksWH) (mod y0 blocksWH)
moveP (P x0 y0) = P (x0 + x) (y0 + y)
-- make sure the snake isn't trying to turn into itself
dir :: Direction -> Direction -> Direction
dir oldDir newDir = case oldDir of
N -> case newDir of
S -> N
_ -> newDir
S -> case newDir of
N -> S
_ -> newDir
E -> case newDir of
W -> E
_ -> newDir
W -> case newDir of
E -> W
_ -> newDir