|
@ -7,6 +7,19 @@ import qualified Data.Set as Set |
|
|
|
|
|
|
|
|
import Datatypes |
|
|
import Datatypes |
|
|
|
|
|
|
|
|
|
|
|
unitMap :: (Cell -> Cell) -> Unit -> Unit |
|
|
|
|
|
unitMap f (Unit members pivot) = Unit (Set.map f members) (f pivot) |
|
|
|
|
|
|
|
|
|
|
|
centerUnit :: Unit -> Board -> Unit |
|
|
|
|
|
centerUnit u b = unitMap (\(x, y) -> (x + deltaX, y - unitTop)) u where |
|
|
|
|
|
members = unitMembers u |
|
|
|
|
|
yCoords = Set.map (\(x, y) -> y) members |
|
|
|
|
|
xCoords = Set.map (\(x, y) -> x) members |
|
|
|
|
|
unitTop = Set.findMin yCoords |
|
|
|
|
|
unitLeft = Set.findMin xCoords |
|
|
|
|
|
unitRight = Set.findMax xCoords |
|
|
|
|
|
deltaX = (unitLeft + (boardWidth b - unitRight - 1)) `div` 2 - unitLeft |
|
|
|
|
|
|
|
|
collides :: Unit -> Board -> Bool |
|
|
collides :: Unit -> Board -> Bool |
|
|
collides u b = not . Set.null $ Set.intersection (unitMembers u) (boardFilled b) |
|
|
collides u b = not . Set.null $ Set.intersection (unitMembers u) (boardFilled b) |
|
|
|
|
|
|
|
@ -15,8 +28,13 @@ isInvalidFor u b = any isOutside (Set.toList $ unitMembers u) where |
|
|
isOutside (x, y) = x < 0 || x >= boardWidth b || y < 0 || y >= boardHeight b |
|
|
isOutside (x, y) = x < 0 || x >= boardWidth b || y < 0 || y >= boardHeight b |
|
|
|
|
|
|
|
|
lockUnit :: Game -> Game |
|
|
lockUnit :: Game -> Game |
|
|
lockUnit (Game board (u:us) _) = Game newBoard us (Set.fromList []) where |
|
|
|
|
|
|
|
|
lockUnit (Game board (u:us) _ oldLines points) = Game newBoard us (Set.fromList []) newLines (newPoints + oldPoints) where |
|
|
newBoard = board { boardFilled = Set.union (unitMembers u) (boardFilled board) } |
|
|
newBoard = board { boardFilled = Set.union (unitMembers u) (boardFilled board) } |
|
|
|
|
|
newPoints = (Set.length (unitMembers u)) + (100 * (1 + newLines) * newLines `div` 2) + lineBonus |
|
|
|
|
|
lineBonus = if oldLines > 1 |
|
|
|
|
|
then floor ((oldLines - 1) * newPoints / 10) |
|
|
|
|
|
else 0 |
|
|
|
|
|
newLines = 0 |
|
|
|
|
|
|
|
|
checkSpawn :: Game -> Game |
|
|
checkSpawn :: Game -> Game |
|
|
checkSpawn game@(Game _ [] _) = game |
|
|
checkSpawn game@(Game _ [] _) = game |
|
@ -31,7 +49,7 @@ isCompleted _ = False |
|
|
step :: Game -> Command -> (Game, Notes) |
|
|
step :: Game -> Command -> (Game, Notes) |
|
|
step game@(Game _ [] _) command = (game, ErrorZero) |
|
|
step game@(Game _ [] _) command = (game, ErrorZero) |
|
|
step game@(Game board (unit:us) oldPositions) command = |
|
|
step game@(Game board (unit:us) oldPositions) command = |
|
|
if unit `collides` board || newUnit `isInvalidFor` board |
|
|
|
|
|
|
|
|
if newUnit `collides` board || newUnit `isInvalidFor` board |
|
|
then let final = checkSpawn (lockUnit game) in |
|
|
then let final = checkSpawn (lockUnit game) in |
|
|
(if isCompleted final then (final, Ended) else (final, OK)) |
|
|
(if isCompleted final then (final, Ended) else (final, OK)) |
|
|
else |
|
|
else |
|
|