|
|
@ -13,10 +13,10 @@ import Datatypes.Unit (Unit(..)) |
|
|
|
import qualified Datatypes.Unit as Unit |
|
|
|
|
|
|
|
data Notes = OK |
|
|
|
| Ended |
|
|
|
| Collision |
|
|
|
| CollisionWithRowElision |
|
|
|
| ErrorZero |
|
|
|
| GameOver |
|
|
|
| Lock { rowsCleaned :: Int } |
|
|
|
| ErrorSamePosition |
|
|
|
| ErrorGameEnded |
|
|
|
deriving (Show,Eq) |
|
|
|
|
|
|
|
cmdToString :: [Command] -> String |
|
|
@ -28,7 +28,6 @@ cmdToString (RotateClockwise:cs) = 'd' : cmdToString cs |
|
|
|
cmdToString (RotateCounterclockwise:cs) = 'k' : cmdToString cs |
|
|
|
cmdToString [] = [] |
|
|
|
|
|
|
|
|
|
|
|
data Command = MoveW |
|
|
|
| MoveE |
|
|
|
| MoveSW |
|
|
@ -36,6 +35,14 @@ data Command = MoveW |
|
|
|
| RotateClockwise |
|
|
|
| RotateCounterclockwise |
|
|
|
deriving (Show,Eq) |
|
|
|
|
|
|
|
moveScore :: Int -> Int -> Int -> Int |
|
|
|
moveScore size lines linesOld = points + lineBonus where |
|
|
|
points = size + 100 * ((1 + lines) * lines) `div` 2 |
|
|
|
lineBonus = if linesOld > 1 |
|
|
|
then floor (fromIntegral ((linesOld - 1) * points) / 100) |
|
|
|
else 0 |
|
|
|
|
|
|
|
checkSpawn :: Game -> Game |
|
|
|
checkSpawn game@(Game _ [] _ _ _) = game |
|
|
|
checkSpawn game@(Game board (u:us) oldPos _ _) = if u `Unit.collidesWith` board |
|
|
@ -43,13 +50,18 @@ checkSpawn game@(Game board (u:us) oldPos _ _) = if u `Unit.collidesWith` board |
|
|
|
else game |
|
|
|
|
|
|
|
lockUnit :: Game -> Game |
|
|
|
lockUnit (Game board (u:us) _ oldLines oldPoints) = Game newBoard us (Set.fromList []) newLines (newPoints + lineBonus + oldPoints) where |
|
|
|
tempBoard = board { Board.filled = Set.union (Unit.members u) (Board.filled board) } |
|
|
|
(newBoard, newLines) = Board.clearLines tempBoard |
|
|
|
newPoints = (Set.size (Unit.members u)) + (100 * (1 + newLines) * newLines `div` 2) |
|
|
|
lineBonus = if oldLines > 1 |
|
|
|
then floor (fromIntegral ((oldLines - 1) * newPoints) / 10) |
|
|
|
else 0 |
|
|
|
lockUnit game = game { |
|
|
|
board = newBoard, |
|
|
|
units = us, |
|
|
|
visitedUnits = Set.empty, |
|
|
|
oldLines = clearedLines, |
|
|
|
score = Game.score game + newScore |
|
|
|
} where |
|
|
|
(u:us) = Game.units game |
|
|
|
mergedBoard = u `Unit.mergeWith` (Game.board game) |
|
|
|
(newBoard, clearedLines) = Board.clearLines mergedBoard |
|
|
|
size = Set.size $ Unit.members u |
|
|
|
newScore = moveScore size clearedLines (Game.oldLines game) |
|
|
|
|
|
|
|
testStep = let unit = Unit (0, 0) (Set.fromList [(2,9)]) |
|
|
|
board = Board 5 10 (Set.fromList [(0,8),(1,8),(0,9),(1,9),(4,8),(3,9),(4,9)]) |
|
|
@ -68,14 +80,14 @@ testStep3 = let unit = Unit (0, 0) (Set.fromList [(2,9)]) |
|
|
|
in step (Game board [unit] (Set.fromList []) 0 0) MoveSW |
|
|
|
|
|
|
|
step :: Game -> Command -> (Game, Notes) |
|
|
|
step game@(Game _ [] _ _ _) command = (game, ErrorZero) |
|
|
|
step game@(Game _ [] _ _ _) command = (game, ErrorGameEnded) |
|
|
|
step game@(Game board (unit:us) oldPositions o l) command = |
|
|
|
if newUnit `Unit.collidesWith` board || newUnit `Unit.isOutsideOf` board |
|
|
|
then let final = checkSpawn (lockUnit game) in |
|
|
|
(if Game.completed final then (final, Ended) else (final, OK)) |
|
|
|
(if Game.completed final then (final, GameOver) else (final, Lock 0)) |
|
|
|
else |
|
|
|
if Set.member (hash newUnit) oldPositions |
|
|
|
then (Game board (newUnit:us) oldPositions o l, ErrorZero) |
|
|
|
then (Game board (newUnit:us) oldPositions o l, ErrorSamePosition) |
|
|
|
else (Game board (newUnit:us) newOldPositions o l, OK) |
|
|
|
where |
|
|
|
newUnit = applyCommand unit command |
|
|
|