1
Fork 0

#1 Redid all the logic

This commit is contained in:
Tibo De Peuter 2022-11-15 12:31:31 +01:00
parent 8d9186963f
commit df3b6ae092

View file

@ -40,6 +40,10 @@ data Board = Board {
pile :: Stack pile :: Stack
} deriving (Show) } deriving (Show)
-- The zones of the board. Represents either the pile, the endingStacks
-- or the gameStacks. It can also be out of the board.
data Zone = Pile | ES | GS | Out
amountOfGameStacks :: Int amountOfGameStacks :: Int
amountOfGameStacks = 7 amountOfGameStacks = 7
@ -113,6 +117,14 @@ isInGame (x, y) g = horizontalCheck && verticalCheck
upBound = y <= snd gameStacksCoord upBound = y <= snd gameStacksCoord
downBound = negate y < length (gameStacks (board g) !! x) downBound = negate y < length (gameStacks (board g) !! x)
-- Get the zone number from a coordinate.
getZoneFromCoord :: Game -> Coordinate -> Zone
getZoneFromCoord game (x, y)
| isInPile (x, y) = Pile
| isInEnding (x, y) = ES
| isInGame (x, y) game = GS
| otherwise = Out
-- Based on a coordinate, return a stack. -- Based on a coordinate, return a stack.
getStackFromCoord :: Game -> Coordinate -> Stack getStackFromCoord :: Game -> Coordinate -> Stack
getStackFromCoord game (x, y) getStackFromCoord game (x, y)
@ -146,7 +158,7 @@ rotatePile g@Game{ board = b } = g{ board = rotatedBoard }
canPlayOn :: Card -> Stack -> Bool canPlayOn :: Card -> Stack -> Bool
canPlayOn (_,King,_) [] = True canPlayOn (_,King,_) [] = True
canPlayOn (t1,v1,_) ((t2,v2,_):cs) = differentColor && predValue canPlayOn (t1,v1,_) ((t2,v2,_):cs) = differentColor && predValue
where differentColor = t1 /= t2 && fromEnum t1 + fromEnum t2 `elem` [1,2,4,5] where differentColor = t1 /= t2 && (fromEnum t1 + fromEnum t2) `elem` [1,2,4,5]
predValue = succ v1 == v2 predValue = succ v1 == v2
canPlayOn _ _ = False canPlayOn _ _ = False
@ -160,58 +172,144 @@ canFinishOn _ _ = False
-- Move a card to a GameStack. Move all the cards below the given card -- Move a card to a GameStack. Move all the cards below the given card
-- on the 'from' stack as well. -- on the 'from' stack as well.
moveToGS :: Stack -> Int -> Stack -> (Stack,Stack) moveBetweenGS :: Int -> Stack -> Stack -> (Stack,Stack)
moveToGS from index to moveBetweenGS index from to
| canPlayOn (from !! index) to = (showFirst removed, added) | canPlayOn (from !! index) to = (showFirst removed, added)
| otherwise = (from,to) | otherwise = (from,to)
where (diff,removed) = splitAt (index + 1) from where (diff,removed) = splitAt (index + 1) from
added = diff ++ to added = diff ++ to
-- Move a card to an EndingStack. This can only be a single card at once. -- Move a card to an EndingStack. This can only be a single card at once.
moveToES :: Stack -> Stack -> (Stack,Stack) moveToES :: Int -> Stack -> Stack -> (Stack,Stack)
moveToES from to moveToES _ from to
| canFinishOn (head from) to = (showFirst removed, added) | canFinishOn (head from) to = (showFirst removed, added)
| otherwise = (from,to) | otherwise = (from,to)
where (diff,removed) = splitAt 1 from where (diff,removed) = splitAt 1 from
added = diff ++ to added = diff ++ to
-- Move from an EndingStack to GameStack.
moveESToGS :: Int -> Stack -> Stack -> (Stack,Stack)
moveESToGS _ from to
| canPlayOn (head from) to = (cs, added)
| otherwise = (from, to)
where (c:cs) = from
added = c:to
-- Move from one gameStack to another.
moveGS2GS :: Coordinate -> Int -> Board -> Board
moveGS2GS fromCoord toStackNr board
| canPlayOn (from !! (index - 1)) to = newBoard
| otherwise = board
where (fromStackNr, negIndex) = fromCoord
fromAmount = length from
oldGS = gameStacks board
from = oldGS !! fromStackNr
to = oldGS !! toStackNr
index = fromAmount - negate negIndex
(diff, newFrom) = splitAt index from
newTo = diff ++ to
tempGS = switchStack oldGS fromStackNr (showFirst newFrom)
newGS = switchStack tempGS toStackNr newTo
newBoard = board{ gameStacks = newGS }
moveGS2ES :: Coordinate -> Int -> Board -> Board
moveGS2ES fromCoord toIndex board
| canFinishOn (head from) to = newBoard
| otherwise = board
where (fromIndex, _) = fromCoord
oldGS = gameStacks board
oldES = endingStacks board
from = oldGS !! fromIndex
to = oldES !! toIndex
(card:newGSStack) = from
newESStack = card:to
newGS = switchStack oldGS fromIndex (showFirst newGSStack)
newES = switchStack oldES toIndex newESStack
newBoard = board{ endingStacks = newES, gameStacks = newGS }
-- Move a card between pile and endingStacks.
moveP2ES :: Coordinate -> Int -> Board -> Board
moveP2ES _ toIndex board
| canFinishOn (head oldPile) to = newBoard
| otherwise = board
where oldPile = pile board
oldES = endingStacks board
to = oldES !! toIndex
(card:newPile) = oldPile
newESStack = card:to
newES = switchStack oldES toIndex newESStack
newBoard = board{ pile = newPile, endingStacks = newES }
-- Move a card between pile and gameStacks.
moveP2GS :: Coordinate -> Int -> Board -> Board
moveP2GS _ toStackNr board
| canPlayOn (head oldPile) to = newBoard
| otherwise = board
where oldPile = pile board
oldGS = gameStacks board
to = oldGS !! toStackNr
(card:newPile) = oldPile
newGSStack = card:to
newGS = switchStack oldGS toStackNr newGSStack
newBoard = board{ gameStacks = newGS, pile = newPile }
moveES2GS :: Coordinate -> Int -> Board -> Board
moveES2GS fromCoord toStackNr board
| canPlayOn (head from) to = newBoard
| otherwise = board
where (tempIndex, _) = fromCoord
fromIndex = tempIndex - (amountOfGameStacks - amountOfEndingStacks)
oldES = endingStacks board
oldGS = gameStacks board
from = oldES !! fromIndex
to = oldGS !! toStackNr
(card:newESStack) = from
newGSStack = card:to
newES = switchStack oldES fromIndex newESStack
newGS = switchStack oldGS toStackNr newGSStack
newBoard = board{ gameStacks = newGS, endingStacks = newES }
-- Switch a stack for another stack in a list of stacks. -- Switch a stack for another stack in a list of stacks.
switchStack :: [Stack] -> Int -> Stack -> [Stack] switchStack :: [Stack] -> Int -> Stack -> [Stack]
switchStack ss index new = front ++ new:back switchStack ss index new = front ++ new:back
where (front, back') = splitAt index ss where (front, back') = splitAt index ss
back = tail back' back = tail back'
-- Swap a stack in the Game for another stack. -- Get the stack that is located in the given zone at the given index.
updateStack :: Game -> Coordinate -> Stack -> Game getStackFromZone :: Game -> Zone -> Int -> Stack
updateStack game (x, y) new getStackFromZone game Pile index = pile (board game)
| isInEnding (x, y) = let originalBoard = board game getStackFromZone game ES index = endingStacks (board game) !! index
index = x - (amountOfGameStacks - amountOfEndingStacks) getStackFromZone game GS index = gameStacks (board game) !! index
newStack = switchStack (endingStacks originalBoard) index new
updatedBoard = originalBoard{ endingStacks = newStack } -- Move between to zones with two indexes
in game{ board = updatedBoard } getMoveFunction2 :: Zone -> Zone -> Coordinate -> Int -> Board -> Board
| isInPile (x, y) = let originalBoard = board game getMoveFunction2 Pile ES coord index = moveP2ES coord index
updatedBoard = originalBoard{ pile = new } getMoveFunction2 Pile GS coord index = moveP2GS coord index
in game{ board = updatedBoard } getMoveFunction2 GS GS coord index = moveGS2GS coord index
| otherwise = let originalBoard = board game getMoveFunction2 GS ES coord index = moveGS2ES coord index
stackNr = x getMoveFunction2 ES GS coord index = moveES2GS coord index
index = negate y getMoveFunction2 _ _ _ _ = id
newGameStacks = switchStack (gameStacks originalBoard) stackNr new
updatedBoard = originalBoard{ gameStacks = newGameStacks } transformIndex :: Zone -> Int -> Int
in game{ board = updatedBoard } transformIndex ES index = index - (amountOfGameStacks - amountOfEndingStacks)
transformIndex Pile _ = 0
transformIndex _ index = index
-- Move a card from Coordinate to Coordinate. -- Move a card from Coordinate to Coordinate.
moveCard :: Game -> Coordinate -> Coordinate -> Game moveCard :: Game -> Coordinate -> Coordinate -> Game
moveCard game (x, y) (a, b) moveCard game fromCoord toCoord = game{ board = newBoard }
| isInEnding (a, b) = let fromStack = getStackFromCoord game (x, y) where originalBoard = board game
toStack = getStackFromCoord game (a, b) (x, _) = fromCoord
(removed, added) = moveToES fromStack toStack (index, _) = toCoord
-- Swapping to old stack. properIndex = transformIndex toZone index
applyFirst = updateStack game (x, y) removed fromZone = getZoneFromCoord game fromCoord
-- Swapping the new stack. toZone = getZoneFromCoord game toCoord
result = updateStack applyFirst (a, b) added fromStack = getStackFromZone game fromZone x
in result toStack = getStackFromZone game toZone x
| otherwise = game moveFunction = getMoveFunction2 fromZone toZone fromCoord properIndex
newBoard = moveFunction originalBoard
------------------------------ Input --------------------------------- ------------------------------ Input ---------------------------------
-- Check if moving in a direction is legal. -- Check if moving in a direction is legal.