-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchomp.hs
104 lines (88 loc) · 2.48 KB
/
chomp.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
99
100
101
102
103
104
-- Copyright © 2013 Bart Massey
-- [This program is licensed under the "MIT License"]
-- Please see the file COPYING in the source
-- distribution of this software for license terms.
-- Chomp player in Haskell
import Data.Array
import Data.List (foldl1')
import Text.Printf
data Move = Move { coords :: (Int, Int) }
newtype Board = Board { squares :: Array (Int, Int) Bool }
rows :: Int
rows = 3
cols :: Int
cols = 4
newBoard :: Board
newBoard = Board $
listArray ((0, 0), (rows - 1, cols - 1)) $
repeat True
instance Show Board where
show b =
unlines $ [ concat $ [ boardChar b (i, j) | j <- [0 .. cols - 1] ] |
i <- [0 .. rows - 1] ]
where
boardChar b c
| not (squares b ! c) = "."
| c == (0, 0) = "*"
| otherwise = "o"
instance Show Move where
show move =
show (adjust $ coords move)
where
adjust (r, c) = (r + 1, c + 1)
getMove :: IO Move
getMove =
fmap (Move . adjust . read) getLine
where
adjust (r, c) = (r - 1, c - 1)
makeMove :: Board -> Move -> Board
makeMove b (Move (r0, c0)) =
Board $
squares b // [ ((r, c), False) |
r <- [r0 .. rows - 1],
c <- [c0 .. cols - 1] ]
negamax :: Board -> Either Move Move
negamax b =
tryMoves $ map fst $ filter snd $ assocs $ squares b
where
tryMoves [] =
Right undefined
tryMoves ms =
foldl1' firstRight $ map (Left . Move) ms
where
firstRight (Right m) _ =
Right m
firstRight _ (Left cmove) =
case negamax $ makeMove b cmove of
Left _ -> Right cmove
Right _ -> Left cmove
firstRight _ (Right _) =
error "internal error: Right cmove"
type Action = Board -> IO Board
humanTurn :: Action
humanTurn b =
fmap (makeMove b) getMove
computerTurn :: Action
computerTurn b = do
case negamax b of
Right m -> do
_ <- printf "%s :-)\n" $ show m
return $ makeMove b m
Left m
| coords m == (0, 0) -> do
_ <- printf "%s :-(\n" $ show m
return $ makeMove b m
| otherwise -> do
_ <- printf "%s :-P\n" $ show m
return $ makeMove b m
playGame :: Board -> (Action, String) -> (Action, String) -> IO ()
playGame b p1@(a1, s1) p2 = do
case (squares b) ! (0, 0) of
True -> do
putStr $ show b
b' <- a1 b
putStrLn ""
playGame b' p2 p1
False -> putStrLn s1
main :: IO ()
main = playGame newBoard (humanTurn, "I lose.") (computerTurn, "You lose.")