-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAI.hs
72 lines (58 loc) · 2.65 KB
/
AI.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
module AI where
import Datatypes
import Board
import Rules
import Heuristics
-- TODO: replace by official function
myMinimumBy :: (a -> Int) -> [a] -> a
myMinimumBy fn [a] = a
myMinimumBy fn (a:b) = if (fn a) < (fn minRest) then a else minRest
where
minRest = myMinimumBy fn b
getMove :: GameState -> Int -> Move
getMove state seed = getBestMoveMinMax state
getRandomMove :: GameState -> Int -> Move
getRandomMove state seed = possibleMoves!!index
where
possibleMoves = statePossibleMoves state
index = seed `mod` (length possibleMoves)
getBestMoveNoRecursion :: GameState -> Move
getBestMoveNoRecursion state = bestMove
where
(board, color) = state
possibleMoves = statePossibleMoves state
bestMove = myMinimumBy (moveValue board color) possibleMoves
getBestMoveMinMax :: GameState -> Move
getBestMoveMinMax state = negamax 2 state
-- Code inspired from the excellent http://giocc.com/concise-implementation-of-minimax-through-higher-order-functions.html
-- and from https://webcache.googleusercontent.com/search?q=cache:ixWFqj2T1CQJ:https://chessprogramming.wikispaces.com/Negamax+&cd=1&hl=en&ct=clnk&gl=fr
foldMoves :: Int -> GameState -> (Move, Int) -> Move -> (Move, Int)
foldMoves depth state (currentBestMove, currentBestScore) move
| nextScore > currentBestScore = (move, nextScore)
| otherwise = (currentBestMove, currentBestScore)
where
nextScore = -negamaxScore depth (makeMove state move)
negamax :: Int -> GameState -> Move
negamax depth state = bestMove
where
nextMoves = statePossibleMoves state
(bestMove, bestScore) = foldl (foldMoves depth state) (head nextMoves, minBound :: Int) nextMoves
negamaxScore :: Int -> GameState -> Int
negamaxScore 0 (board, color) = boardHeuristic board color
negamaxScore depth state = maximum $ map (\move -> -(negamaxScore (depth -1) (makeMove state move))) nextMoves
where
nextMoves = statePossibleMoves state
-- alphaBetaScore :: Int -> Int -> Int -> GameState -> Int
-- alphaBetaScore _ _ 0 (board, color) = boardHeuristic board color
-- alphaBetaScore alphaInit betaInit depth state =
-- foldl (\(alpha, beta) move ->
-- let deeperScore = -(alphaBetaScore alpha beta (depth -1) (makeMove state move)) in
-- (minimum [alpha, deeperScore], maximum [beta, deeperScore])
-- ) (alphaInit, betaInit) nextMoves
-- where
-- nextMoves = statePossibleMoves state
-- quiesce :: Int -> Int -> GameState -> Int
-- quiesce alpha beta (board, color) =
-- let heuristic = boardHeuristic board color in
-- let captures = statePossibleCaptures state in
-- captures