parent
7dc72ee211
commit
425bb6eee2
3 changed files with 44 additions and 44 deletions
|
@ -5,7 +5,7 @@ module Patience
|
|||
import PatienceBoard
|
||||
import PatienceRenderer
|
||||
|
||||
import Graphics.Gloss (green, play)
|
||||
import Graphics.Gloss (dim, green, play)
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Single module to play patience. --
|
||||
|
@ -21,6 +21,19 @@ type FPS = Int
|
|||
|
||||
-- Play a game of patience.
|
||||
playPatience :: FPS -> IO()
|
||||
playPatience fps = do play window green fps initGame render handleInputs step
|
||||
playPatience fps = do play window bgcolor fps initGame render handleInputs step
|
||||
where window = getWindow
|
||||
step _ g = g
|
||||
bgcolor = dim green
|
||||
|
||||
---------------------------- Documentation ---------------------------
|
||||
-- The structure of this project is based on the Model-View- --
|
||||
-- Controller as known in Java. This clearly seperates different --
|
||||
-- functionality from each other. I also tried to put as much --
|
||||
-- functionality of the same thing into a single module. I always --
|
||||
-- asked myself: "Could I use this piece of code in a different --
|
||||
-- project?" If the answer was yes, there is now a module for it. --
|
||||
-- -*- --
|
||||
-- This block merely serves as a message to the person reviewing --
|
||||
-- this code. --
|
||||
----------------------------------------------------------------------
|
||||
|
|
|
@ -28,7 +28,7 @@ data Game = Game {
|
|||
board :: Board,
|
||||
-- The selector
|
||||
selector :: Selector
|
||||
} deriving (Show)
|
||||
} deriving (Show, Eq)
|
||||
|
||||
-- Representation of a Patience board
|
||||
data Board = Board {
|
||||
|
@ -38,7 +38,7 @@ data Board = Board {
|
|||
endingStacks :: [Stack],
|
||||
-- Stack of cards that are not yet on the board
|
||||
pile :: Stack
|
||||
} deriving (Show)
|
||||
} deriving (Show, Eq)
|
||||
|
||||
-- The zones of the board. Represents either the pile, the endingStacks
|
||||
-- or the gameStacks. It can also be out of the board.
|
||||
|
@ -117,7 +117,7 @@ isInGame (x, y) g = horizontalCheck && verticalCheck
|
|||
upBound = y <= snd gameStacksCoord
|
||||
xStack = gameStacks (board g) !! x
|
||||
downBound = zero || negate y < length xStack
|
||||
zero = y == 0 && length xStack == 0
|
||||
zero = y == 0 && null xStack
|
||||
|
||||
-- Get the zone number from a coordinate.
|
||||
getZoneFromCoord :: Game -> Coordinate -> Zone
|
||||
|
@ -127,22 +127,6 @@ getZoneFromCoord game (x, y)
|
|||
| isInGame (x, y) game = GS
|
||||
| otherwise = Out
|
||||
|
||||
-- Based on a coordinate, return a stack.
|
||||
getStackFromCoord :: Game -> Coordinate -> Stack
|
||||
getStackFromCoord game (x, y)
|
||||
| isInPile (x, y) = pile $ board game
|
||||
| isInEnding (x, y) = endingStacks (board game) !! (x - (amountOfGameStacks - amountOfEndingStacks))
|
||||
| isInGame (x, y) game = gameStacks (board game) !! x
|
||||
| otherwise = pile $ board game
|
||||
|
||||
-- Based on a coordinate, return a card.
|
||||
getCardFromCoord :: Game -> Coordinate -> Card
|
||||
getCardFromCoord game (x, y)
|
||||
| isInPile (x, y) = head $ pile (board game)
|
||||
| isInEnding (x, y) = head $ endingStacks (board game) !! (x - (amountOfGameStacks - amountOfEndingStacks))
|
||||
| isInGame (x, y) game = (gameStacks (board game) !! x ) !! negate y
|
||||
| otherwise = (NoneType, NoneValue, Hidden)
|
||||
|
||||
--------------------------- Change cards -----------------------------
|
||||
|
||||
-- Show the first of a stack of cards.
|
||||
|
@ -161,9 +145,9 @@ canPlayOn :: Stack -> Int -> Stack -> Bool
|
|||
canPlayOn [] _ _ = False
|
||||
canPlayOn cs index [] = v1 == King && vis == Visible
|
||||
where (_,v1,vis) = cs !! index
|
||||
canPlayOn cs index ((t2,v2,_):_) = differentColor && predValue && visibility
|
||||
canPlayOn cs index ((t2,v2,vis2):_) = differentColor && predValue && visibility
|
||||
where (t1,v1,vis) = cs !! index
|
||||
differentColor = t1 /= t2 && (fromEnum t1 + fromEnum t2) `elem` [1,2,4,5]
|
||||
differentColor = not $ (t1,v1,vis) `matchColor` (t2,v2,vis2)
|
||||
predValue = succ v1 == v2
|
||||
visibility = vis == Visible
|
||||
|
||||
|
@ -194,7 +178,7 @@ moveGS2GS fromCoord toStackNr board
|
|||
tempGS = switchStack oldGS fromStackNr (showFirst newFrom)
|
||||
newGS = switchStack tempGS toStackNr newTo
|
||||
newBoard = board{ gameStacks = newGS }
|
||||
|
||||
-- Move from a gameStack to an endingStack.
|
||||
moveGS2ES :: Coordinate -> Int -> Board -> Board
|
||||
moveGS2ES fromCoord toIndex board
|
||||
| canFinishOn from 0 to = newBoard
|
||||
|
@ -236,6 +220,7 @@ moveP2GS _ toStackNr board
|
|||
newGS = switchStack oldGS toStackNr newGSStack
|
||||
newBoard = board{ gameStacks = newGS, pile = newPile }
|
||||
|
||||
-- Move a card from an endingStack to a gameStack.
|
||||
moveES2GS :: Coordinate -> Int -> Board -> Board
|
||||
moveES2GS fromCoord toStackNr board
|
||||
| canPlayOn from 0 to = newBoard
|
||||
|
@ -264,6 +249,7 @@ getStackFromZone :: Game -> Zone -> Int -> Stack
|
|||
getStackFromZone game Pile index = pile (board game)
|
||||
getStackFromZone game ES index = endingStacks (board game) !! index
|
||||
getStackFromZone game GS index = gameStacks (board game) !! index
|
||||
getStackFromZone _ Out _ = []
|
||||
|
||||
-- Move between to zones with two indexes
|
||||
getMoveFunction2 :: Zone -> Zone -> Coordinate -> Int -> Board -> Board
|
||||
|
@ -274,6 +260,7 @@ getMoveFunction2 GS ES coord index = moveGS2ES coord index
|
|||
getMoveFunction2 ES GS coord index = moveES2GS coord index
|
||||
getMoveFunction2 _ _ _ _ = id
|
||||
|
||||
-- Tranform the index based on the zone.
|
||||
transformIndex :: Zone -> Int -> Int
|
||||
transformIndex ES index = index - (amountOfGameStacks - amountOfEndingStacks)
|
||||
transformIndex Pile _ = 0
|
||||
|
@ -316,11 +303,13 @@ toggleSelector g@Game{ selector = s@Selector{ selected = Just coord } } = moved
|
|||
-- Handle all the inputs necessary for patience.
|
||||
handleInputs :: Event -> Game -> Game
|
||||
handleInputs = composeInputHandler [
|
||||
-- Selector movement
|
||||
handleUp (moveSelector U),
|
||||
handleDown (moveSelector D),
|
||||
handleLeft (moveSelector L),
|
||||
handleRight (moveSelector R),
|
||||
|
||||
-- Selection handling
|
||||
handleSpace toggleSelector,
|
||||
-- Pile rotation
|
||||
handleEnter rotatePile
|
||||
]
|
||||
|
|
|
@ -3,6 +3,7 @@ module PatienceRenderer
|
|||
, getWindow
|
||||
) where
|
||||
|
||||
import CardDeck
|
||||
import PatienceBoard
|
||||
import Selector
|
||||
|
||||
|
@ -32,16 +33,6 @@ stackDistance = 10
|
|||
zoneDistance :: Float
|
||||
zoneDistance = 25
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- Render the GameStacks zone.
|
||||
renderGS :: Board -> Picture
|
||||
renderGS = renderStacks stackDistance (negate cardDistance) . gameStacks
|
||||
|
||||
-- Render the EndingStacks zone.
|
||||
renderES :: Board -> Picture
|
||||
renderES = renderStacks stackDistance 0 . endingStacks
|
||||
|
||||
-- X axis render difference for EndingStacks
|
||||
esXDiff :: Float
|
||||
esXDiff = fromIntegral esX * cardDistance
|
||||
|
@ -53,10 +44,6 @@ esYDiff :: Float
|
|||
esYDiff = fromIntegral esY * (zoneDistance + cardHeight)
|
||||
where (_, esY) = endingStacksCoord
|
||||
|
||||
-- Render the Pile zone.
|
||||
renderPile :: Board -> Picture
|
||||
renderPile = renderStack 0 . pile
|
||||
|
||||
-- X axis render difference for Pile
|
||||
pileXDiff :: Float
|
||||
pileXDiff = 0
|
||||
|
@ -65,6 +52,20 @@ pileXDiff = 0
|
|||
pileYDiff :: Float
|
||||
pileYDiff = esYDiff
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
-- Render the GameStacks zone.
|
||||
renderGS :: Board -> Picture
|
||||
renderGS = renderStacks stackDistance (negate cardDistance) . gameStacks
|
||||
|
||||
-- Render the EndingStacks zone.
|
||||
renderES :: Board -> Picture
|
||||
renderES = renderStacks stackDistance 0 . endingStacks
|
||||
|
||||
-- Render the Pile zone.
|
||||
renderPile :: Board -> Picture
|
||||
renderPile = renderStack 0 . pile
|
||||
|
||||
-- Get the diff based on a coordinate because different 'zones' have
|
||||
-- different offsets.
|
||||
getDiff :: Coordinate -> (Float, Float)
|
||||
|
@ -100,17 +101,14 @@ renderPSelector ps = compose [
|
|||
(xd1, yd1) = getDiff (position ps)
|
||||
(xd2, yd2) = getDiff $ getSelected ps
|
||||
|
||||
getSelected :: Selector -> Coordinate
|
||||
getSelected s@Selector{ selected = Just c } = c
|
||||
getSelected s@Selector{ selected = Nothing } = (0,0)
|
||||
|
||||
-- Render the patience game.
|
||||
render :: Game -> Picture
|
||||
render game = translate centerX centerY $ compose [
|
||||
renderBoard $ board game,
|
||||
renderPSelector $ selector game
|
||||
]
|
||||
where centerX = negate $ (cardWidth + stackDistance) * (fromIntegral amountOfGameStacks - 1) / 2
|
||||
centerY = 0 -- TODO Different center
|
||||
centerY = 0
|
||||
|
||||
-- The default window to play patience.
|
||||
getWindow :: Display
|
||||
|
|
Reference in a new issue