-
Notifications
You must be signed in to change notification settings - Fork 0
/
TeamRealist.java
executable file
·178 lines (151 loc) · 5.95 KB
/
TeamRealist.java
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
import java.util.*;
@Deprecated
public class TeamRealist extends Player {
// A Node represents a board position, a best move and payoffs; this is
// according to Realist assumptions.
private Node[] results; // Array of Nodes indexed by an integer representing
// a board position. Memory intensive!
public int[] bestMoveInts; // A best move node for each position, encoded
// with ``bit twiddling'' to save memory.
int maxNumMoves; // Called GameLimit in the project specs
private Random rand;
public TeamRealist(int maxNumMoves_) {
maxNumMoves = maxNumMoves_;
LinkedList<BoardPosition> allInitialBoardPositions = getAllInitialBoardPositions();
rand = new Random(0); // For choosing random moves...
// The following arrays have indices from BoardPosition.toInt():
results = new Node[1 << 23];
bestMoveInts = new int[1 << 23];
// Those indices will be less than 1<<23, or 2^23.
for (BoardPosition boardPosition : allInitialBoardPositions) {
computeBestMove(boardPosition);
}
results = null; // De-allocate results, so garbage collector will free
// up that memory.
}
public void prepareForSeries() {
}
public void prepareForMatch() {
}
public void receiveMatchOutcome(int matchOutcome) {
}
public MoveDescription chooseMove() {
BoardPosition boardPosition = toBoardPosition();
return (new Node(bestMoveInts[boardPosition.toInt()])).bestMove;
}
private Node computeBestMove(BoardPosition boardPosition) {
int currentPositionInt = boardPosition.toInt();
Node savedResult = results[currentPositionInt];
if (savedResult != null) {
return savedResult;
}
int currentPlayerColour = (boardPosition.numMovesPlayed % 2 == 0) ? WHITE : BLACK;
Node ret = null;
int[] payoffsWhiteWins = new int[] { 3, 0 };
int[] payoffsBlackWins = new int[] { 0, 3 };
int[] payoffsTie = new int[] { 2, 2 };
int[] payoffsDraw = new int[] { 1, 1 };
// if both kings have been captured, the game has ended
if (boardPosition.whiteKingPosition == 0 && boardPosition.blackKingPosition == 0) {
ret = new Node(null, payoffsTie);
} else if (boardPosition.whiteKingPosition == 0 && currentPlayerColour == BLACK) {
// if white king has been captured and it's black player's turn, the
// game has ended
// black won
ret = new Node(null, payoffsBlackWins);
} else if (boardPosition.blackKingPosition == 0 && currentPlayerColour == WHITE) {
// if black king has been captured and it's white player's turn, the
// game has ended
// white won
ret = new Node(null, payoffsWhiteWins);
} else if (currentPlayerColour == WHITE && boardPosition.whiteKingPosition == 0
&& boardPosition.whiteRookPosition == 0) {
// if it's white player's turn but he has no pieces left, the game
// has ended
// black won
ret = new Node(null, payoffsBlackWins);
} else if (currentPlayerColour == BLACK && boardPosition.blackKingPosition == 0
&& boardPosition.blackRookPosition == 0) {
// if it's black player's turn but he has no pieces left, the game
// has ended
// white won
ret = new Node(null, payoffsWhiteWins);
} else if (boardPosition.numMovesPlayed == maxNumMoves) {
// if we have reached the maximum number of moves, the game is over
if (boardPosition.whiteKingPosition != 0 && boardPosition.blackKingPosition != 0) {
// draw
ret = new Node(null, payoffsDraw);
} else if (boardPosition.blackKingPosition == 0) {
// white won
ret = new Node(null, payoffsWhiteWins);
} else {
// !whiteKingRemains
// black won
ret = new Node(null, payoffsBlackWins);
}
} else {
// Game has not ended
// Explore all possible moves
ArrayList<MoveDescription> allPossibleMoves = boardPosition.getAllPossibleMoves();
ArrayList<Node> allBestNodes = new ArrayList<Node>();
int bestScore = 0;
for (MoveDescription moveDescription : allPossibleMoves) {
BoardPosition newBoardPosition = boardPosition.doMove(moveDescription);
Node node = computeBestMove(newBoardPosition);
if (allBestNodes.size() == 0) {
bestScore = node.getScore(currentPlayerColour);
allBestNodes.add(new Node(moveDescription, node.getScore(WHITE), node.getScore(BLACK)));
} else if (node.getScore(currentPlayerColour) == bestScore) {
allBestNodes.add(new Node(moveDescription, node.getScore(WHITE), node.getScore(BLACK)));
} else if (node.getScore(currentPlayerColour) > bestScore) {
bestScore = node.getScore(currentPlayerColour);
allBestNodes = new ArrayList<Node>();
allBestNodes.add(new Node(moveDescription, node.getScore(WHITE), node.getScore(BLACK)));
}
}
ret = allBestNodes.get(rand.nextInt(allBestNodes.size()));
}
// Add result to array!
results[currentPositionInt] = ret;
//if (ret.bestMove != null) {
bestMoveInts[currentPositionInt] = ret.toInt();
//}
return ret;
}
public static class Node {
public MoveDescription bestMove;
public int scoreWhite, scoreBlack;
public Node(MoveDescription bestMove_, int scoreWhite_, int scoreBlack_) {
bestMove = bestMove_;
scoreWhite = scoreWhite_;
scoreBlack = scoreBlack_;
}
public Node(MoveDescription bestMove_, int[] score_) {
this(bestMove_, score_[WHITE], score_[BLACK]);
}
public int getScore(int colour) {
return (colour == WHITE) ? scoreWhite : scoreBlack;
}
public int toInt() {//encode a node as a 14 bit integer.
//bits 0-3 for scoreBlack, 4-7 for scoreWhite, 8-12 for bestMove, 13 indicates that bestMove is null.
if (bestMove != null) {
return (bestMove.toInt() << 8)// 5-bit integer
+ (scoreWhite << 4)// 4-bit integer
+ (scoreBlack);// 4-bit integer
} else {
return (1<<13) // 5-bit integer
+ (scoreWhite << 4)// 4-bit integer
+ (scoreBlack);// 4-bit integer
}
}
public Node(int nodeInt) {// decode an integer into a node.
if ((nodeInt>>13)==1) {
bestMove = null;
} else {
bestMove = new MoveDescription(nodeInt >> 8);
}
scoreWhite = (nodeInt - ((nodeInt >> 8) << 8)) >> 4;
scoreBlack = nodeInt - ((nodeInt >> 4) << 4);
}
}
}