@@ -23,7 +23,7 @@ public static void main(String args[]) throws IOException {
23
23
largeBoard .play (2 , opponentMove );
24
24
algorithm .root = algorithm .root .getChild (opponentMove );
25
25
algorithm .root .parent = null ;
26
- algorithm .construct (largeBoard , 2 );
26
+ algorithm .construct (largeBoard , 1 );
27
27
System .err .println (largeBoard );
28
28
}
29
29
final int validActionCount = Integer .parseInt (in .readLine ());
@@ -36,12 +36,13 @@ public static void main(String args[]) throws IOException {
36
36
largeBoard .play (1 , bestMove );
37
37
algorithm .root = algorithm .root .getChild (bestMove );
38
38
algorithm .root .parent = null ;
39
- algorithm .construct (largeBoard , 1 );
39
+ algorithm .construct (largeBoard , 2 );
40
40
System .err .println (largeBoard );
41
41
}
42
42
}
43
43
}
44
44
45
+ //todo: write unit tests for each function
45
46
class MCTS {
46
47
public static final int TIME_OUT = 50 ;
47
48
public static final double CONSTANT = 10000d ;
@@ -51,7 +52,7 @@ public int suggestMove() {
51
52
return root .getChildren ()
52
53
.stream ()
53
54
.max (Comparator .comparingDouble (node -> node .wins / (double ) node .plays + node .plays / CONSTANT ))
54
- .map (c -> c .col )
55
+ .map (c -> c .move )
55
56
.orElseThrow (() -> new RuntimeException ("No moves to play!" ));
56
57
}
57
58
@@ -60,7 +61,8 @@ public void construct(final LargeBoard board, int player) {
60
61
while (System .currentTimeMillis () - startTime <= TIME_OUT ) {
61
62
TreeNode current = root ;
62
63
int position = current .selectChild (board );
63
- while (current .getChild (position ) != null ) {
64
+ //todo: Why do you check for canPlay?
65
+ while (board .canPlay (position ) && current .getChild (position ) != null ) {
64
66
current = current .getChild (position );
65
67
board .play (player , position );
66
68
position = current .selectChild (board );
@@ -80,15 +82,15 @@ public void construct(final LargeBoard board, int player) {
80
82
class TreeNode {
81
83
private static final Random random = new Random ();
82
84
public static final int SIMULATION_CONSTANT = 50 ;
83
- public final int col ;
85
+ public final int move ;
84
86
public int plays ;
85
87
public double wins ;
86
88
public TreeNode parent ;
87
89
private final int player ;
88
90
private Map <Integer , TreeNode > children = new HashMap <>();
89
91
90
- public TreeNode (final int col , final TreeNode parent , final int player ) {
91
- this .col = col ;
92
+ public TreeNode (final int move , final TreeNode parent , final int player ) {
93
+ this .move = move ;
92
94
this .parent = parent ;
93
95
this .player = player ;
94
96
}
@@ -98,21 +100,39 @@ public int selectChild(final LargeBoard board) {
98
100
.stream ()
99
101
.max (Comparator .comparingDouble (TreeNode ::getUtility ));
100
102
double maxUtility = child .map (TreeNode ::getUtility ).orElse (0d );
101
- int bestColumn = child .map (c -> c .col ).orElse (0 );
103
+ int bestColumn = child .map (c -> c .move ).orElse (0 );
102
104
final Set <Integer > expandedSet = children .keySet ();
103
105
final int currentBoardIndex = board .currentBoard ();
104
- int max = 81 ;
105
- int i = 0 ;
106
106
if (currentBoardIndex != -1 ) {
107
- i = (currentBoardIndex / 3 ) * 27 + (currentBoardIndex % 3 ) * 3 ;
108
- max = i + 21 ;
109
- }
110
- for (; i < max ; i ++) {
111
- if (board .canPlay (i ) && !expandedSet .contains (i )) {
112
- final double utility = Math .sqrt (Math .log (plays + 1 )) + (0.05 / Math .abs (9 / 2.0 - i ));
113
- if (utility > maxUtility ) {
114
- maxUtility = utility ;
115
- bestColumn = i ;
107
+ int start = (currentBoardIndex / 3 ) * 27 + (currentBoardIndex % 3 ) * 3 ;
108
+ for (int x = 0 ; x < 3 ; x ++, start ++) {
109
+ for (int y = 0 ; y < 3 ; y ++) {
110
+ int i = start + y * 9 ;
111
+ if (board .canPlay (i ) && !expandedSet .contains (i )) {
112
+ final double utility = Math .sqrt (Math .log (plays + 1 )) + (0.05 / Math .abs (40 - i ));
113
+ if (utility > maxUtility ) {
114
+ maxUtility = utility ;
115
+ bestColumn = i ;
116
+ }
117
+ }
118
+ }
119
+ }
120
+ } else {
121
+ for (int boardIndex = 0 ; boardIndex < 9 ; boardIndex ++) {
122
+ if ((board .largeOccupied & (1 << boardIndex )) == 0 ) {
123
+ int start = (boardIndex / 3 ) * 27 + (boardIndex % 3 ) * 3 ;
124
+ for (int x = 0 ; x < 3 ; x ++, start ++) {
125
+ for (int y = 0 ; y < 3 ; y ++) {
126
+ int i = start + y * 9 ;
127
+ if (board .canPlay (i ) && !expandedSet .contains (i )) {
128
+ final double utility = Math .sqrt (Math .log (plays + 1 )) + (0.05 / Math .abs (40 - i ));
129
+ if (utility > maxUtility ) {
130
+ maxUtility = utility ;
131
+ bestColumn = i ;
132
+ }
133
+ }
134
+ }
135
+ }
116
136
}
117
137
}
118
138
}
@@ -127,19 +147,34 @@ private double simulate(final LargeBoard board, int player) {
127
147
final int numberOfMovesPlayed = board .movesPlayed ;
128
148
final int originalPlayer = player ;
129
149
while (board .result () == -1 ) {
150
+ int movesToPlay = 0 ;
130
151
final int currentBoardIndex = board .currentBoard ();
131
- int max = 81 ;
132
- int position = 0 ;
152
+ final int possibilities [] = new int [currentBoardIndex != -1 ? 9 : 81 ];
133
153
if (currentBoardIndex != -1 ) {
134
- position = (currentBoardIndex / 3 ) * 27 + (currentBoardIndex % 3 ) * 3 ;
135
- max = position + 21 ;
136
- }
137
- final int possibilities [] = new int [max - position ];
138
- int movesToPlay = 0 ;
139
- for (; position < max ; position ++) {
140
- if (board .canPlay (position )) {
141
- possibilities [movesToPlay ] = position ;
142
- movesToPlay ++;
154
+ int start = (currentBoardIndex / 3 ) * 27 + (currentBoardIndex % 3 ) * 3 ;
155
+ for (int x = 0 ; x < 3 ; x ++, start ++) {
156
+ for (int y = 0 ; y < 3 ; y ++) {
157
+ int position = start + y * 9 ;
158
+ if (board .canPlay (position )) {
159
+ possibilities [movesToPlay ] = position ;
160
+ movesToPlay ++;
161
+ }
162
+ }
163
+ }
164
+ } else {
165
+ for (int boardIndex = 0 ; boardIndex < 9 ; boardIndex ++) {
166
+ if ((board .largeOccupied & (1 << boardIndex )) == 0 ) {
167
+ int start = (boardIndex / 3 ) * 27 + (boardIndex % 3 ) * 3 ;
168
+ for (int x = 0 ; x < 3 ; x ++, start ++) {
169
+ for (int y = 0 ; y < 3 ; y ++) {
170
+ int position = start + y * 9 ;
171
+ if (board .canPlay (position )) {
172
+ possibilities [movesToPlay ] = position ;
173
+ movesToPlay ++;
174
+ }
175
+ }
176
+ }
177
+ }
143
178
}
144
179
}
145
180
if (movesToPlay == 0 ) {
@@ -188,14 +223,14 @@ public TreeNode getChild(final int col) {
188
223
@ Override
189
224
public String toString () {
190
225
return "TreeNode{" +
191
- "\n col =" + col +
226
+ "\n move =" + move +
192
227
", \n plays=" + plays +
193
228
", \n wins=" + wins +
194
- ", \n parent=" + (parent == null ? -1 : parent .col ) +
229
+ ", \n parent=" + (parent == null ? -1 : parent .move ) +
195
230
", \n player=" + player +
196
231
", \n children=" + children .values ()
197
232
.stream ()
198
- .map (c -> "MOVE: " + c . col + " WINS: " + c .wins + " PLAYS: " + c .plays + "\n " )
233
+ .map (node -> "MOVE: " + node . move + " WINS: " + node .wins + " PLAYS: " + node .plays + "\n " )
199
234
.collect (Collectors .joining ("\n " )) +
200
235
'}' ;
201
236
}
@@ -318,9 +353,9 @@ public int currentBoard() {
318
353
@ Override
319
354
public String toString () {
320
355
return "LargeBoard{" +
321
- "\n largeBoard=" + largeBoard +
322
- ", \n largeCaptures=" + largeCaptures +
323
- ", \n largeOccupied=" + largeOccupied +
356
+ "\n largeBoard=" + Integer . toBinaryString ( largeBoard ) +
357
+ ", \n largeCaptures=" + Integer . toBinaryString ( largeCaptures ) +
358
+ ", \n largeOccupied=" + Integer . toBinaryString ( largeOccupied ) +
324
359
", \n movesPlayed=" + movesPlayed +
325
360
", \n moves=" + Arrays .toString (moves ) +
326
361
", \n boards=" + Arrays .deepToString (boards ) +
0 commit comments