-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAlphaBeta.hs
41 lines (34 loc) · 1.43 KB
/
AlphaBeta.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
{-# LANGUAGE UndecidableInstances #-}
module AlphaBeta (solve) where
import AlphaBeta.ThunkTree (ThunkTree, evaluate, wrap)
import Data.Function.FastMemo (Memoizable)
import qualified Data.List as List
import Data.List.NonEmpty (NonEmpty)
import qualified Data.List.NonEmpty as NonEmpty
import Data.Ord (Down (Down))
import Game (Game, GameStatus (..))
import qualified MiniMax
import ZeroSumGame (IsZeroSumGame (..), ZeroSumGame (..))
import Prelude
newtype AlphaBeta game = AlphaBeta {getAlphaBeta :: game}
deriving via
ZeroSumGame (AlphaBeta game)
instance
(IsZeroSumGame game, Ord (Outcome game)) => Game (AlphaBeta game)
instance (IsZeroSumGame game, Ord (Outcome game)) => IsZeroSumGame (AlphaBeta game) where
type Position (AlphaBeta game) = Position game
type Move (AlphaBeta game) = Move game
type Outcome (AlphaBeta game) = ThunkTree (Outcome game)
status (AlphaBeta game) pos = case status game pos of
GameOver {outcome} -> GameOver (wrap outcome)
GameState {turn, moves} -> GameState {turn, moves = sortOn (Down . heuristic game pos) moves}
makeMove = makeMove . getAlphaBeta
heuristic = heuristic . getAlphaBeta
sortOn :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a
sortOn f = NonEmpty.fromList . List.sortOn f . NonEmpty.toList
solve ::
(IsZeroSumGame game, Memoizable (Position game), Ord (Outcome game)) =>
game ->
Position game ->
Outcome game
solve game = evaluate . MiniMax.solve (AlphaBeta game)