-
Notifications
You must be signed in to change notification settings - Fork 1
/
MiniMax.elm
104 lines (80 loc) · 2.46 KB
/
MiniMax.elm
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
module MiniMax
exposing
( Value
, Problem
, Depth
, PlayerType(..)
, miniMax
, findMax
)
import Random exposing (minInt, maxInt)
type alias Value =
Int
type alias Problem state move =
{ heuristic : state -> Value
, moves : PlayerType -> state -> Maybe ( PlayerType, List move )
, apply : move -> state -> state
}
type alias Depth =
Int
type PlayerType
= Maximizing
| Minimizing
findMax : Problem state move -> Depth -> state -> ( Maybe move, Value )
findMax problem depth state =
miniMax problem depth Maximizing state
miniMax : Problem state move -> Depth -> PlayerType -> state -> ( Maybe move, Value )
miniMax problem depth playerType state =
let
bestMove playerType =
List.map
(\mv ->
let
state' =
problem.apply mv state
( _, bestVal ) =
miniMax problem (depth - 1) (otherType playerType) state'
in
( Just mv, bestVal )
)
>> searchBest playerType
in
if depth == 0 then
( Nothing, problem.heuristic state )
else
case problem.moves playerType state of
Just ( playerType', moves ) ->
bestMove playerType' moves
Nothing ->
( Nothing, problem.heuristic state )
searchBest : PlayerType -> List ( Maybe move, Value ) -> ( Maybe move, Value )
searchBest playerType =
let
cmp =
case playerType of
Maximizing ->
(>)
Minimizing ->
(<)
compare =
(\( mv, val ) ( bestMv, bestVal ) ->
if val `cmp` bestVal then
( mv, val )
else
( bestMv, bestVal )
)
start =
case playerType of
Maximizing ->
( Nothing, minInt )
Minimizing ->
( Nothing, maxInt )
in
List.foldl compare start
otherType : PlayerType -> PlayerType
otherType playerType =
case playerType of
Minimizing ->
Maximizing
Maximizing ->
Minimizing