1
+ import commons .Color ;
1
2
import game .Board ;
2
3
import game .Move ;
3
4
4
- import java .util .Arrays ;
5
+ import java .util .Comparator ;
5
6
import java .util .List ;
7
+ import java .util .concurrent .CompletableFuture ;
8
+ import java .util .concurrent .ExecutionException ;
9
+ import java .util .concurrent .TimeUnit ;
10
+ import java .util .concurrent .TimeoutException ;
6
11
import java .util .stream .Collectors ;
7
12
8
13
public class Engine {
14
+ public static int nodesEvaluated ;
9
15
10
16
public int countAllMoves (final Board board , final int depth ) {
11
17
return countAllMoves (board , depth , 1000 );
12
18
}
13
19
14
20
public int countAllMoves (final Board board , final int depth , final int printAt ) {
15
21
final List <Move > legalMoves = board .getLegalMoves ();
16
- // if (board.fenRepresentation().equals("8/2p5/K2p4/1P4kr/1R6/6p1/4P3/8 w - -")) {
17
- // System.out.println("HERE");
18
- // System.out.println(board);
19
- // System.out.println(Arrays.deepToString(board.canCastle));
20
- // System.out.println(legalMoves.stream().map(Move::toString).collect(Collectors.joining("\n")));
21
- // final List<Move> legalMovezzz = board.getLegalMoves();
22
- // System.out.println(legalMovezzz);
23
- // }
24
22
if (legalMoves .isEmpty ()) {
25
23
return 0 ;
26
24
}
@@ -31,20 +29,160 @@ public int countAllMoves(final Board board, final int depth, final int printAt)
31
29
final Board copy = board .copy ();
32
30
copy .makeMove (move );
33
31
final int countAllMoves = countAllMoves (copy , depth - 1 , printAt );
34
- if (depth == printAt ) {// && board.fenRepresentation().equals("8/8/2pp4/1P4kr/K4pP1/8/4P3/1R6 b - -")) {
32
+ if (depth == printAt ) {
35
33
System .out .println (getString (move ) + ": " + countAllMoves + " " + move +
36
- // Arrays.deepToString(copy.canCastle) + " \n" + copy.getKing(Color.BLACK).getMoveList(copy) + " \n" +
37
34
" " + copy .fenRepresentation ());
38
35
}
39
36
return countAllMoves ;
40
37
}).sum ();
41
38
}
42
39
40
+ public Evaluation minMax (final Board board , final int depth , final int printAt ) {
41
+ final List <Move > legalMoves = board .getLegalMoves ();
42
+ nodesEvaluated ++;
43
+ if (legalMoves .isEmpty () || depth == 0 ) {
44
+ return new Evaluation (null , -board .evaluation (legalMoves .size ()));
45
+ }
46
+ Evaluation bestMove = null ;
47
+ for (Move move : legalMoves ) {
48
+ final Board copy = board .copy ();
49
+ copy .makeMove (move );
50
+ final Evaluation eval = minMax (copy , depth - 1 , printAt );
51
+ if (depth == printAt ) {
52
+ System .out .println (getString (move ) + ": " + eval .getScore () + " " + move +
53
+ " " + copy .fenRepresentation ());
54
+ }
55
+ if (bestMove == null || bestMove .getScore () > -eval .getScore ()) {
56
+ bestMove = new Evaluation (move , -eval .getScore ());
57
+ if (bestMove .getScore () < 0 && bestMove .getScore () + Integer .MAX_VALUE < 0.0001 ) {
58
+ return bestMove ;
59
+ }
60
+ }
61
+ }
62
+ return bestMove ;
63
+ }
64
+
65
+ public OutCome alphaBeta (final Board board , final int depth , double alpha , double beta , final int printAt ) {
66
+ final List <Move > legalMoves = board .getLegalMoves ();
67
+ nodesEvaluated ++;
68
+ if (legalMoves .isEmpty () || depth == 0 ) {
69
+ return new OutCome (board , null , -board .evaluation (legalMoves .size ()));
70
+ }
71
+ final List <OutCome > outComes = legalMoves .stream ().map (move -> {
72
+ final Board changedBoard = board .copy ();
73
+ changedBoard .makeMove (move );
74
+ return new OutCome (changedBoard , move , changedBoard .evaluation ());
75
+ }).sorted (Comparator .comparingDouble (outCome -> -outCome .getScore ())).collect (Collectors .toList ());
76
+ OutCome bestMove = null ;
77
+ for (final OutCome outCome : outComes ) {
78
+ final OutCome eval = alphaBeta (outCome .getBoard (), depth - 1 , alpha , beta , printAt );
79
+ if (depth == printAt ) {
80
+ System .out .println (getString (outCome .getMove ()) + ": " + eval .getScore () + " " + outCome +
81
+ " " + outCome .getBoard ().fenRepresentation ());
82
+ }
83
+ if (bestMove == null || bestMove .getScore () > -eval .getScore ()) {
84
+ bestMove = new OutCome (board , outCome .getMove (), -eval .getScore ());
85
+ if (bestMove .getScore () < 0 && bestMove .getScore () + Integer .MAX_VALUE < 0.0001 ) {
86
+ return bestMove ;
87
+ }
88
+ }
89
+ if (board .playerToMove .equals (Color .WHITE )) {
90
+ if (alpha < -bestMove .getScore ()) {
91
+ alpha = -bestMove .getScore ();
92
+ }
93
+ } else {
94
+ if (beta > bestMove .getScore ()) {
95
+ beta = bestMove .getScore ();
96
+ }
97
+ }
98
+ if (alpha > beta ) {
99
+ break ;
100
+ }
101
+ }
102
+ return bestMove ;
103
+ }
104
+
105
+ public OutCome iterativeDeepening (final Board board , final long time ) {
106
+ final long start = System .currentTimeMillis ();
107
+ int depth = 1 ;
108
+ OutCome evaluation = alphaBeta (board , depth , Integer .MIN_VALUE , Integer .MAX_VALUE , 1000 );
109
+ while (System .currentTimeMillis () - start < time * 1000 && Math .abs (evaluation .getScore ()) - Integer .MAX_VALUE < 0.0001 ) {
110
+ depth ++;
111
+ System .out .println ("DEPTH: " + depth + " EVAL: " + evaluation + " TIME: " + ((System .currentTimeMillis () - start ) / 1000 ));
112
+ try {
113
+ int finalDepth = depth ;
114
+ evaluation = CompletableFuture .supplyAsync (() -> alphaBeta (board , finalDepth , Integer .MIN_VALUE , Integer .MAX_VALUE , 1000 )).get (time * 1000 - (System .currentTimeMillis () - start ), TimeUnit .MILLISECONDS );
115
+ } catch (InterruptedException | ExecutionException | TimeoutException e ) {
116
+ System .out .println ("TIMEOUT: " + depth );
117
+ break ;
118
+ }
119
+ }
120
+ return evaluation ;
121
+ }
122
+
43
123
private String getString (Move move ) {
44
124
return move .piece .position .notation () + move .target .notation ();
45
125
}
46
126
}
47
127
128
+ class Evaluation {
129
+ private final Move move ;
130
+ private final double score ;
131
+
132
+ public Evaluation (Move move , double score ) {
133
+ this .move = move ;
134
+ this .score = score ;
135
+ }
136
+
137
+ public double getScore () {
138
+ return score ;
139
+ }
140
+
141
+ public Move getMove () {
142
+ return move ;
143
+ }
144
+
145
+ @ Override
146
+ public String toString () {
147
+ return "{" +
148
+ "move=" + move +
149
+ ", score=" + score +
150
+ '}' ;
151
+ }
152
+ }
153
+
154
+ class OutCome {
155
+ private final Board board ;
156
+ private final Move move ;
157
+ private final double score ;
158
+
159
+ public OutCome (Board board , Move move , double score ) {
160
+ this .move = move ;
161
+ this .score = score ;
162
+ this .board = board ;
163
+ }
164
+
165
+ public double getScore () {
166
+ return score ;
167
+ }
168
+
169
+ public Move getMove () {
170
+ return move ;
171
+ }
172
+
173
+ public Board getBoard () {
174
+ return board ;
175
+ }
176
+
177
+ @ Override
178
+ public String toString () {
179
+ return "{" +
180
+ "board=\n " + board +
181
+ ", move=" + move +
182
+ ", score=" + score +
183
+ '}' ;
184
+ }
185
+ }
48
186
/*
49
187
50
188
0 commit comments