-
Notifications
You must be signed in to change notification settings - Fork 1
/
Board.hs
99 lines (81 loc) · 3.5 KB
/
Board.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
-- Board.hs
-- Mancala's board.
module Board(initBoard,
getPlayerHoles,
getOtherPlayerHoles,
getOtherPlayer,
removeMancalaHole,
board2holes,
holes2board,
updateHole,
sow,
move,
capture,
getLastHole) where
import Types
import Data.List(splitAt)
-- Inits Board with X holes (including mancala hole) with Y seeds
initBoard :: Int -> Seed -> Board
initBoard nHoles seeds = (holes, holes)
where holes = replicate nHoles seeds ++ [0]
-- Returns player's holes
getPlayerHoles :: Player -> Board -> [Seed]
getPlayerHoles A board = fst board
getPlayerHoles B board = snd board
getOtherPlayerHoles :: Player -> Board -> [Seed]
getOtherPlayerHoles player b = getPlayerHoles (getOtherPlayer player) b
getOtherPlayer :: Player -> Player
getOtherPlayer player = if player == A
then B
else A
-- Return just normal holes
removeMancalaHole :: [Seed] -> [Seed]
removeMancalaHole seeds = reverse (tail (reverse seeds))
board2holes :: Player -> Board -> [Seed]
board2holes player b = if player == A
then fst b ++ snd b
else snd b ++ fst b
holes2board :: Player -> [Seed] -> Board
holes2board p holes = if p == A
then splitAt (length holes `div` 2) holes
else (snd (holes2board A holes), fst (holes2board A holes))
-- Updates seeds quantity on a hole
updateHole :: Position -> Seed -> [Seed] -> [Seed]
updateHole pos seed holes = take pos holes ++ (seed : drop (pos + 1) holes)
-- Sows X seeds on holes
sow :: Int -> Position -> [Seed] -> [Seed]
sow n pos holes =
if n <= length toBeSown
then take pos holes ++ sown ++ drop (pos + n) holes
else sow (n - length toBeSown) 0
(take pos holes ++ sown ++ drop (pos + length toBeSown) holes)
where sown = map (+1) toBeSown
toBeSown = take n (drop pos (removeMancalaHole holes))
-- Makes the move
move :: Hole -> Board -> Board
move (player, pos) b = holes2board player sownBoard
where sownBoard = sow seeds (pos + 1) holesSeedsRemoved
holesSeedsRemoved = updateHole pos 0 allHoles
allHoles = board2holes player b
seeds = (getPlayerHoles player b) !! pos
-- Captures other player's seeds
capture :: Hole -> Board -> Board
capture (player, pos) b = holes2board (getOtherPlayer player) holesCapturedSeeds
where holesCapturedSeeds = updateHole mancalaPos newMancalaSeeds holesRemovedSeeds
newMancalaSeeds = (holesRemovedSeeds !! mancalaPos) + opositeSeeds
mancalaPos = length holesRemovedSeeds - 1
holesRemovedSeeds = updateHole opositePos 0 (board2holes (getOtherPlayer player) b)
opositeSeeds = otherPlayerHoles !! opositePos
opositePos = length otherPlayerHoles - pos - 2
otherPlayerHoles = (getOtherPlayerHoles player b)
getLastHole :: Hole -> Board -> Hole
getLastHole (player, pos) b = (getPlayer, newPosition `mod` (boardSize `div` 2))
where seeds = (getPlayerHoles player b) !! pos
getPlayer = getPlayerByPosition (player, newPosition) b
newPosition = ((pos + seeds) `mod` (boardSize - 1))
boardSize = length (fst b ++ snd b)
getPlayerByPosition :: Hole -> Board -> Player
getPlayerByPosition (player, pos) (s1, s2) = if pos >= halfBoardSize
then getOtherPlayer player
else player
where halfBoardSize = (length (s1 ++ s2)) `div` 2