3
3
import game .Move ;
4
4
5
5
import java .util .Comparator ;
6
+ import java .util .HashMap ;
6
7
import java .util .List ;
8
+ import java .util .Map ;
7
9
import java .util .concurrent .CompletableFuture ;
8
10
import java .util .concurrent .ExecutionException ;
9
11
import java .util .concurrent .TimeUnit ;
12
14
13
15
public class Engine {
14
16
public static int nodesEvaluated ;
17
+ public Map <Long , Result > transpositionTable = new HashMap <>();
15
18
16
19
public int countAllMoves (final Board board , final int depth ) {
17
20
return countAllMoves (board , depth , 1000 );
@@ -66,43 +69,61 @@ public OutCome alphaBeta(final Board board, final int depth, double alpha, doubl
66
69
final List <Move > legalMoves = board .getLegalMoves ();
67
70
nodesEvaluated ++;
68
71
if (legalMoves .isEmpty () || depth == 0 ) {
69
- return new OutCome (board , null , -board .evaluation (legalMoves .size ()));
72
+ final double score ;
73
+ if (transpositionTable .containsKey (board .zobristHash )) {
74
+ score = transpositionTable .get (board .zobristHash ).eval ;
75
+ } else {
76
+ score = board .evaluation (legalMoves .size ());
77
+ transpositionTable .put (board .zobristHash , new Result (score , 0 ));
78
+ }
79
+ return new OutCome (board , null , -score );
70
80
}
71
81
final List <OutCome > outComes = legalMoves .stream ().map (move -> {
72
82
final Board changedBoard = board .copy ();
73
83
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 ;
84
+ final double score ;
85
+ if (transpositionTable .containsKey (changedBoard .zobristHash )) {
86
+ score = transpositionTable .get (changedBoard .zobristHash ).eval ;
87
+ } else {
88
+ score = changedBoard .evaluation (changedBoard .getLegalMoves ().size ());
89
+ transpositionTable .put (changedBoard .zobristHash , new Result (score , 0 ));
90
+ }
91
+ return new OutCome (changedBoard , move , score );
92
+ }).sorted (Comparator .comparingDouble (OutCome ::getScore )).collect (Collectors .toList ());
93
+ OutCome bestOutCome = null ;
77
94
for (final OutCome outCome : outComes ) {
78
95
final OutCome eval = alphaBeta (outCome .getBoard (), depth - 1 , alpha , beta , printAt );
79
96
if (depth == printAt ) {
80
97
System .out .println (getString (outCome .getMove ()) + ": " + eval .getScore () + " " + outCome +
81
98
" " + outCome .getBoard ().fenRepresentation ());
82
99
}
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 ;
100
+ if (bestOutCome == null || bestOutCome .getScore () > -eval .getScore ()) {
101
+ bestOutCome = new OutCome (board , outCome .getMove (), -eval .getScore ());
102
+ if (bestOutCome .getScore () < 0 && bestOutCome .getScore () + Integer .MAX_VALUE < 0.0001 ) {
103
+ return bestOutCome ;
87
104
}
88
105
}
89
106
if (board .playerToMove .equals (Color .WHITE )) {
90
- if (alpha < -bestMove .getScore ()) {
91
- alpha = -bestMove .getScore ();
107
+ if (alpha < -bestOutCome .getScore ()) {
108
+ alpha = -bestOutCome .getScore ();
92
109
}
93
110
} else {
94
- if (beta > bestMove .getScore ()) {
95
- beta = bestMove .getScore ();
111
+ if (beta > bestOutCome .getScore ()) {
112
+ beta = bestOutCome .getScore ();
96
113
}
97
114
}
98
- if (alpha > beta ) {
115
+ if (alpha >= beta ) {
99
116
break ;
100
117
}
101
118
}
102
- return bestMove ;
119
+ if (!transpositionTable .containsKey (board .zobristHash ) || transpositionTable .get (board .zobristHash ).depth < depth ) {
120
+ transpositionTable .put (board .zobristHash , new Result (-bestOutCome .getScore (), depth ));
121
+ }
122
+ return bestOutCome ;
103
123
}
104
124
105
125
public OutCome iterativeDeepening (final Board board , final long time ) {
126
+ transpositionTable = new HashMap <>();
106
127
final long start = System .currentTimeMillis ();
107
128
int depth = 1 ;
108
129
OutCome evaluation = alphaBeta (board , depth , Integer .MIN_VALUE , Integer .MAX_VALUE , 1000 );
@@ -183,26 +204,14 @@ public String toString() {
183
204
'}' ;
184
205
}
185
206
}
186
- /*
187
-
188
-
189
207
190
208
191
- b4g4
192
- b4h4
209
+ class Result {
210
+ final double eval ;
211
+ final int depth ;
193
212
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
- b4g4
205
- b4h4
206
- b4g4
207
- b4h4
208
- */
213
+ public Result (double eval , int depth ) {
214
+ this .eval = eval ;
215
+ this .depth = depth ;
216
+ }
217
+ }
0 commit comments