-
Notifications
You must be signed in to change notification settings - Fork 0
/
TeamOptimist.java
executable file
·156 lines (131 loc) · 5.62 KB
/
TeamOptimist.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
import java.util.*;
@Deprecated
public class TeamOptimist 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!
private int[] bestMoveInts; //A best move for each position, encoded with ``bit twiddling'' to save memory.
int maxNumMoves; //Called GameLimit in the project specs
private Random rand;
public TeamOptimist(int maxNumMoves_) {
maxNumMoves = maxNumMoves_;
LinkedList<BoardPosition> allInitialBoardPositions = getAllInitialBoardPositions();
rand = new Random(0); //For choosing random moves...
//BoardPosition.toInt() will be used for indices in the following arrays:
results = new Node[1<<23];
bestMoveInts = new int[1<<23];
//Those indices will be less than 1<<23; that is 1 shifted left by 23 bits, which gives 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 MoveDescription(bestMoveInts[boardPosition.toInt()]);
}
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;
double[] payoffsWhiteWins;
double[] payoffsBlackWins;
double[] payoffsTie;
double[] payoffsDraw;
if (boardPosition.myColour == WHITE) {
payoffsWhiteWins = new double[] {3.0, 3.0};
payoffsBlackWins = new double[] {0.0, 0.0};
payoffsTie = new double[] {2.0, 2.0};
payoffsDraw = new double[] {1.0, 1.0};
} else {
payoffsWhiteWins = new double[] {0.0, 0.0};
payoffsBlackWins = new double[] {3.0, 3.0};
payoffsTie = new double[] {2.0, 2.0};
payoffsDraw = new double[] {1.0, 1.0};
}
// 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> ();
double bestScore=0.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) { //Dangerous to compare doubles!!!
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.bestMove.toInt();
}
return ret;
}
private class Node {
public MoveDescription bestMove;
public double scoreWhite, scoreBlack;
public Node(MoveDescription bestMove_, double scoreWhite_, double scoreBlack_) {
bestMove = bestMove_;
scoreWhite = scoreWhite_;
scoreBlack = scoreBlack_;
}
public Node(MoveDescription bestMove_, double [] score_) {
this(bestMove_, score_[WHITE], score_[BLACK]);
}
public double getScore(int colour) {
return (colour == WHITE) ? scoreWhite : scoreBlack;
}
}
}