#1 Toggle selection
This commit is contained in:
parent
33c9a877d2
commit
5be2419163
2 changed files with 201 additions and 17 deletions
|
@ -1,10 +1,27 @@
|
|||
module PatienceBoard
|
||||
( Board
|
||||
( Game (..)
|
||||
, Board (..)
|
||||
, amountOfGameStacks
|
||||
, amountOfEndingStacks
|
||||
|
||||
,initBoard
|
||||
, handleInputs
|
||||
, initGame
|
||||
) where
|
||||
|
||||
import CardDeck
|
||||
import Selector
|
||||
|
||||
import InputHandler
|
||||
|
||||
----------------------------- Constants ------------------------------
|
||||
|
||||
-- Prepresentation of a Patience game
|
||||
data Game = Game {
|
||||
-- The playboard
|
||||
board :: Board,
|
||||
-- The selector
|
||||
selector :: Selector
|
||||
} deriving (Show)
|
||||
|
||||
-- Representation of a Patience board
|
||||
data Board = Board {
|
||||
|
@ -16,27 +33,104 @@ data Board = Board {
|
|||
pile :: Stack
|
||||
} deriving (Show)
|
||||
|
||||
-- Show the first of a stack of cards.
|
||||
showFirst :: Stack -> Stack
|
||||
showFirst (c:cs) = (showCard c):cs
|
||||
amountOfGameStacks :: Int
|
||||
amountOfGameStacks = 7
|
||||
|
||||
amountOfEndingStacks :: Int
|
||||
amountOfEndingStacks = 4
|
||||
|
||||
rotateStep :: Int
|
||||
rotateStep = 3
|
||||
|
||||
------------------------------- Init ---------------------------------
|
||||
|
||||
-- Split a full deck into 7 gameStacks and one pile of unused cards.
|
||||
splitDeck :: Stack -> [Stack]
|
||||
splitDeck = reverse . splitDeck' 7
|
||||
splitDeck = reverse . splitDeck' amountOfGameStacks
|
||||
where splitDeck' :: Int -> Stack -> [Stack]
|
||||
splitDeck' 0 cs = [cs]
|
||||
splitDeck' n cs = let (stack,rest) = splitAt n cs
|
||||
in (showFirst stack):(splitDeck' (n - 1) rest)
|
||||
in showFirst stack : splitDeck' (n - 1) rest
|
||||
|
||||
-- Return the initial board consisting of a stack of yet-to-be-turned
|
||||
-- cards and 7 stacks of increasingly large amount of cards (1, ..., 7)
|
||||
-- The initial board consisting of a stack of yet-to-be-turned cards
|
||||
-- and n stacks of increasingly large amount of cards (1, ..., n)
|
||||
initBoard :: Board
|
||||
initBoard = let pile:stacks = splitDeck generateShuffledDeck
|
||||
in Board {
|
||||
gameStacks = stacks,
|
||||
endingStacks = [[],[],[],[]],
|
||||
pile = pile
|
||||
}
|
||||
initBoard = Board {
|
||||
gameStacks = stacks,
|
||||
endingStacks = replicate amountOfEndingStacks [],
|
||||
pile = map showCard pile
|
||||
}
|
||||
where pile:stacks = splitDeck generateShuffledDeck
|
||||
|
||||
moveBetweenStacks :: Stack -> Int -> Stack -> Stack
|
||||
moveBetweenStacks from index to = undefined
|
||||
-- The initial state of the playboard, with a board and a cursor.
|
||||
initGame :: Game
|
||||
initGame = Game {
|
||||
board = initBoard,
|
||||
selector = initSelector
|
||||
}
|
||||
|
||||
--------------------------- Change cards -----------------------------
|
||||
|
||||
-- Show the first of a stack of cards.
|
||||
showFirst :: Stack -> Stack
|
||||
showFirst [] = []
|
||||
showFirst (c:cs) = showCard c : cs
|
||||
|
||||
-- Rotate the pile n times.
|
||||
rotatePile :: Board -> Board
|
||||
rotatePile b = b { pile = tail ++ head }
|
||||
where (head,tail) = splitAt rotateStep $ pile b
|
||||
|
||||
-- Check if a card can be placed ontop of a gameStack.
|
||||
canPlayOn :: Card -> Stack -> Bool
|
||||
canPlayOn (_,King,_) [] = True
|
||||
canPlayOn (t1,v1,_) ((t2,v2,_):cs) = differentColor && predValue
|
||||
where differentColor = t1 /= t2 && fromEnum t1 + fromEnum t2 `elem` [1,2,4,5]
|
||||
predValue = fromEnum v1 + 1 == fromEnum v2
|
||||
canPlayOn _ _ = False
|
||||
|
||||
-- Check if a card can be played ontop of an EndingStack.
|
||||
canFinishOn :: Card -> Stack -> Bool
|
||||
canFinishOn (_,Ace,_) [] = True
|
||||
canFinishOn (t1,v1,_) ((t2,v2,_):cs) = sameType && succValue
|
||||
where sameType = t1 == t2
|
||||
succValue = fromEnum v1 == fromEnum v2 + 1
|
||||
canFinishOn _ _ = False
|
||||
|
||||
-- Move a card to a GameStack. Move all the cards below the given card
|
||||
-- on the 'from' stack as well.
|
||||
moveToGS :: Stack -> Int -> Stack -> (Stack,Stack)
|
||||
moveToGS from index to
|
||||
| canPlayOn (from !! index) to = (showFirst removed, added)
|
||||
| otherwise = (from,to)
|
||||
where (diff,removed) = splitAt (index + 1) from
|
||||
added = diff ++ to
|
||||
|
||||
-- Move a card to an EndingStack. This can only be a single card at once.
|
||||
moveToES :: Stack -> Stack -> (Stack,Stack)
|
||||
moveToES from to
|
||||
| canFinishOn (head from) to = (showFirst removed, added)
|
||||
| otherwise = (from,to)
|
||||
where (diff,removed) = splitAt 1 from
|
||||
added = diff ++ to
|
||||
|
||||
------------------------------ Input ---------------------------------
|
||||
|
||||
-- Move the selector of the game. (Wrapper)
|
||||
moveSelector :: Direction -> Game -> Game
|
||||
moveSelector dir g@Game{ selector = s } = g{ selector = move dir s }
|
||||
|
||||
-- Toggle selector. (Wrapper)
|
||||
toggleSelector :: Game -> Game
|
||||
toggleSelector g@Game{ selector = s } = g{ selector = toggleSelection s }
|
||||
|
||||
-- Handle all the inputs necessary for patience.
|
||||
handleInputs :: Event -> Game -> Game
|
||||
handleInputs = composeInputHandler [
|
||||
handleUp (moveSelector U),
|
||||
handleDown (moveSelector D),
|
||||
handleLeft (moveSelector L),
|
||||
handleRight (moveSelector R),
|
||||
|
||||
handleSpace toggleSelector
|
||||
]
|
||||
|
|
Reference in a new issue