Skip to content

Commit cf89fb4

Browse files
committed
null and quite searches added
1 parent 944a6e4 commit cf89fb4

File tree

1 file changed

+195
-64
lines changed
  • src/main/java/main/java/hackerearth/taunt

1 file changed

+195
-64
lines changed

src/main/java/main/java/hackerearth/taunt/Taunt.java

Lines changed: 195 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public static void main(String[] args) throws IOException {
3333
}
3434

3535
class MinMax {
36+
public static final int PIECE_VALUE = 1000;
3637
public static int MAX_DEPTH = 60;
3738
public final int TIME_OUT;
3839
private final int movesPlayed;
@@ -85,16 +86,12 @@ public void printStats() {
8586
}
8687

8788
private Move findBestMove(final int player, final Board board) {
88-
int toTake = startConfigs[0].strength - 2, toGive = startConfigs[0].strength + 2;
89-
int result = player == 1 ? MIN_VALUE : MAX_VALUE;
89+
int toTake = startConfigs[0].strength - 2 * PIECE_VALUE, toGive = startConfigs[0].strength + 2 * PIECE_VALUE;
90+
int result = player == 1 ? toTake : toGive;
9091
Move bestMove = startConfigs[0].move;
9192
try {
9293
for (final Configuration possibleConfig : startConfigs) {
93-
final int moveValue = evaluate(board.play(possibleConfig.move),
94-
flip(player),
95-
0,
96-
toTake,
97-
toGive);
94+
final int moveValue = evaluate(board.play(possibleConfig.move), flip(player), 0, toTake, toGive);
9895
possibleConfig.strength = moveValue;
9996
if (player == 1) {
10097
if (toTake < moveValue) {
@@ -106,13 +103,9 @@ private Move findBestMove(final int player, final Board board) {
106103
if (player == 1 && result < moveValue) {
107104
result = moveValue;
108105
bestMove = possibleConfig.move;
109-
// System.out.println("RESULT: " + result + " " + possibleConfig.move + " PLAYER: " + player + " " +
110-
// "depth: " + depth);
111106
} else if (player == 2 && result > moveValue) {
112107
result = moveValue;
113108
bestMove = possibleConfig.move;
114-
// System.out.println("RESULT: " + result + " " + possibleConfig.move + " PLAYER: " + player + " " +
115-
// "depth: " + depth);
116109
}
117110
if (toTake >= toGive) {
118111
if (possibleConfig.killer) {
@@ -191,7 +184,121 @@ private int evaluate(final Board board,
191184
if (terminated != null) {
192185
result = terminated;
193186
} else if (level >= depth) {
194-
result = board.evaluatePosition(board.pieceCount[1], board.pieceCount[2]);
187+
result = quietSearch(board, player, level, a, b);
188+
} else {
189+
boolean furtherProcessingRequired = true;
190+
if (!board.isEndGame() && depth > 4) {
191+
final int previousPlayer = MinMax.flip(player);
192+
final int minimumTheyWillTake = previousPlayer == 1 ? toTake : toGive - 1;
193+
final int nullSearchResult = nullSearch(board,
194+
previousPlayer,
195+
level + 3,
196+
minimumTheyWillTake,
197+
minimumTheyWillTake + 1);
198+
if (Math.abs(nullSearchResult) == MinMax.MAX_VALUE) {
199+
furtherProcessingRequired = true;
200+
} else if (previousPlayer == 2 && nullSearchResult > minimumTheyWillTake) {
201+
result = toGive;
202+
furtherProcessingRequired = false;
203+
} else if (previousPlayer == 1 && nullSearchResult <= minimumTheyWillTake) {
204+
result = toTake;
205+
furtherProcessingRequired = false;
206+
}
207+
}
208+
if (furtherProcessingRequired) {
209+
final Configuration[] configurations = new Configuration[board.options[player]];
210+
for (int i = 0; i < configurations.length; i++) {
211+
configurations[i] = new Configuration(board.moves[player][i],
212+
board,
213+
level);
214+
}
215+
Arrays.sort(configurations, getConfigurationComparator(player));
216+
for (final Configuration possibleConfig : configurations) {
217+
computations++;
218+
final int moveValue = evaluate(board.play(possibleConfig.move),
219+
flip(player),
220+
level + 1,
221+
toTake,
222+
toGive);
223+
possibleConfig.strength = moveValue;
224+
if (player == 1) {
225+
if (toTake < moveValue) {
226+
toTake = moveValue;
227+
}
228+
} else if (toGive > moveValue) {
229+
toGive = moveValue;
230+
}
231+
if (player == 1 && result < moveValue) {
232+
result = moveValue;
233+
} else if (player == 2 && result > moveValue) {
234+
result = moveValue;
235+
}
236+
if (toTake >= toGive) {
237+
result = moveValue;
238+
if (possibleConfig.killer) {
239+
if (possibleConfig.move.equals(killerMoves[level][0])) {
240+
efficiency[level][0]++;
241+
} else {
242+
efficiency[level][1]++;
243+
if (efficiency[level][0] < efficiency[level][1]) {
244+
final Move temp = killerMoves[level][0];
245+
killerMoves[level][0] = killerMoves[level][1];
246+
killerMoves[level][1] = temp;
247+
}
248+
}
249+
} else {
250+
if (killerMoves[level][0] == null) {
251+
killerMoves[level][0] = possibleConfig.move;
252+
efficiency[level][0] = 1;
253+
} else if (killerMoves[level][1] == null || efficiency[level][1] < 1) {
254+
killerMoves[level][1] = possibleConfig.move;
255+
efficiency[level][1] = 1;
256+
}
257+
}
258+
break;
259+
} else if (possibleConfig.killer) {
260+
if (possibleConfig.move.equals(killerMoves[level][0])) {
261+
efficiency[level][0]--;
262+
} else if (possibleConfig.move.equals(killerMoves[level][1])) {
263+
efficiency[level][1]--;
264+
}
265+
if (efficiency[level][0] < efficiency[level][1] && killerMoves[level][1] != null) {
266+
final Move temp = killerMoves[level][0];
267+
killerMoves[level][0] = killerMoves[level][1];
268+
killerMoves[level][1] = temp;
269+
final int t = efficiency[level][0];
270+
efficiency[level][0] = efficiency[level][1];
271+
efficiency[level][1] = t;
272+
}
273+
if (efficiency[level][0] < 0) {
274+
killerMoves[level][0] = null;
275+
}
276+
if (efficiency[level][1] < 0) {
277+
killerMoves[level][1] = null;
278+
}
279+
}
280+
}
281+
}
282+
}
283+
return result;
284+
}
285+
286+
private int nullSearch(final Board board,
287+
final int player,
288+
final int level,
289+
final int a,
290+
final int b) throws TimeoutException {
291+
int toTake = a, toGive = b;
292+
int result = player == 1 ? a : b;
293+
if (!test && System.currentTimeMillis() - startTime >= TIME_OUT) {
294+
timeOut = true;
295+
throw new TimeoutException();
296+
}
297+
final Integer terminated = board.isTerminated(movesPlayed + level, board.pieceCount[1], board.pieceCount[2]);
298+
if (terminated != null) {
299+
result = terminated;
300+
} else if (level >= depth) {
301+
result = quietSearch(board, player, level + 1, a, b);
195302
} else {
196303
final Configuration[] configurations = new Configuration[board.options[player]];
197304
for (int i = 0; i < configurations.length; i++) {
@@ -202,11 +309,11 @@ private int evaluate(final Board board,
202309
Arrays.sort(configurations, getConfigurationComparator(player));
203310
for (final Configuration possibleConfig : configurations) {
204311
computations++;
205-
final int moveValue = evaluate(board.play(possibleConfig.move),
206-
flip(player),
207-
level + 1,
208-
toTake,
209-
toGive);
312+
final int moveValue = nullSearch(board.play(possibleConfig.move),
313+
flip(player),
314+
level + 1,
315+
toTake,
316+
toGive);
210317
possibleConfig.strength = moveValue;
211318
if (player == 1) {
212319
if (toTake < moveValue) {
@@ -222,52 +329,72 @@ private int evaluate(final Board board,
222329
}
223330
if (toTake >= toGive) {
224331
result = moveValue;
225-
if (possibleConfig.killer) {
226-
if (possibleConfig.move.equals(killerMoves[level][0])) {
227-
efficiency[level][0]++;
228-
} else {
229-
efficiency[level][1]++;
230-
if (efficiency[level][0] < efficiency[level][1]) {
231-
final Move temp = killerMoves[level][0];
232-
killerMoves[level][0] = killerMoves[level][1];
233-
killerMoves[level][1] = temp;
234-
}
235-
}
236-
} else {
237-
if (killerMoves[level][0] == null) {
238-
killerMoves[level][0] = possibleConfig.move;
239-
efficiency[level][0] = 1;
240-
} else if (killerMoves[level][1] == null || efficiency[level][1] < 1) {
241-
killerMoves[level][1] = possibleConfig.move;
242-
efficiency[level][1] = 1;
243-
}
244-
}
245332
break;
246-
} else if (possibleConfig.killer) {
247-
if (possibleConfig.move.equals(killerMoves[level][0])) {
248-
efficiency[level][0]--;
249-
} else if (possibleConfig.move.equals(killerMoves[level][1])) {
250-
efficiency[level][1]--;
251-
}
252-
if (efficiency[level][0] < efficiency[level][1] && killerMoves[level][1] != null) {
253-
final Move temp = killerMoves[level][0];
254-
killerMoves[level][0] = killerMoves[level][1];
255-
killerMoves[level][1] = temp;
256-
final int t = efficiency[level][0];
257-
efficiency[level][0] = efficiency[level][1];
258-
efficiency[level][1] = t;
333+
}
334+
}
335+
}
336+
return result;
337+
}
338+
339+
private int quietSearch(final Board board,
340+
final int player,
341+
final int level,
342+
final int a,
343+
final int b) throws TimeoutException {
344+
int toTake = a, toGive = b;
345+
int result = player == 1 ? a : b;
346+
if (!test && System.currentTimeMillis() - startTime >= TIME_OUT) {
347+
timeOut = true;
348+
throw new TimeoutException();
349+
}
350+
final Integer terminated = board.isTerminated(movesPlayed + level, board.pieceCount[1], board.pieceCount[2]);
351+
if (terminated != null) {
352+
result = terminated;
353+
} else if (level >= depth + 5) {
354+
result = board.evaluatePosition(board.pieceCount[1], board.pieceCount[2]);
355+
} else {
356+
final List<Move> captureMoves = Arrays.stream(board.moves[player])
357+
.filter(Objects::nonNull)
358+
.filter(Move::isACapture)
359+
.collect(Collectors.toList());
360+
if (captureMoves.isEmpty()) {
361+
result = board.evaluatePosition(board.pieceCount[1], board.pieceCount[2]);
362+
} else {
363+
//System.out.println("Quiet search level: " + (level - depth) + " move: " + captureMoves.size());
364+
final Configuration[] configurations = new Configuration[captureMoves.size()];
365+
for (int i = 0; i < captureMoves.size(); i++) {
366+
configurations[i] = new Configuration(captureMoves.get(i),
367+
board,
368+
level);
369+
}
370+
Arrays.sort(configurations, getConfigurationComparator(player));
371+
for (final Configuration possibleConfig : configurations) {
372+
computations++;
373+
final int moveValue = quietSearch(board.play(possibleConfig.move),
374+
flip(player),
375+
level + 1,
376+
toTake,
377+
toGive);
378+
possibleConfig.strength = moveValue;
379+
if (player == 1) {
380+
if (toTake < moveValue) {
381+
toTake = moveValue;
382+
}
383+
} else if (toGive > moveValue) {
384+
toGive = moveValue;
259385
}
260-
if (efficiency[level][0] < 0) {
261-
killerMoves[level][0] = null;
386+
if (player == 1 && result < moveValue) {
387+
result = moveValue;
388+
} else if (player == 2 && result > moveValue) {
389+
result = moveValue;
262390
}
263-
if (efficiency[level][1] < 0) {
264-
killerMoves[level][1] = null;
391+
if (toTake >= toGive) {
392+
result = moveValue;
393+
break;
265394
}
266395
}
267396
}
268397
}
269-
//System.out.println("LEVEL: " + level + " " + Arrays.toString(killerMoves[level]));
270-
//board.undo(move);
271398
return result;
272399
}
273400

@@ -448,7 +575,7 @@ public String toString() {
448575

449576
public boolean isACapture() {
450577
//TODO: Add quiet search
451-
return capturedPieces.isEmpty();
578+
return !capturedPieces.isEmpty();
452579
}
453580

454581
public String describe() {
@@ -768,20 +895,20 @@ public int heuristicValue(final int movesPlayed,
768895
final int firstPlayerPieceCount,
769896
final int secondPlayerPieceCount) {
770897
final Integer terminated = isTerminated(movesPlayed, firstPlayerPieceCount, secondPlayerPieceCount);
771-
return terminated != null ? terminated : evaluatePosition(firstPlayerPieceCount, secondPlayerPieceCount);
898+
return terminated != null ? terminated : firstPlayerPieceCount - secondPlayerPieceCount;
772899
}
773900

774901
public int evaluatePosition(final int firstPlayerPieceCount, final int secondPlayerPieceCount) {
775-
return firstPlayerPieceCount - secondPlayerPieceCount;
902+
return (firstPlayerPieceCount - secondPlayerPieceCount) * MinMax.PIECE_VALUE;
776903
}
777904

778905
public Integer isTerminated(final int moveNumber,
779-
final int firstPLayerPieceCount,
780-
final int secondPLayerPieceCount) {
781-
final boolean hasEnded = moveNumber >= 100 || firstPLayerPieceCount == 0 || secondPLayerPieceCount == 0;
906+
final int firstPlayerPieceCount,
907+
final int secondPlayerPieceCount) {
908+
final boolean hasEnded = moveNumber >= 100 || firstPlayerPieceCount == 0 || secondPlayerPieceCount == 0;
782909
if (hasEnded) {
783-
assert firstPLayerPieceCount + secondPLayerPieceCount > 0;
784-
return firstPLayerPieceCount > secondPLayerPieceCount ? MinMax.MAX_VALUE : MinMax.MIN_VALUE;
910+
assert firstPlayerPieceCount + secondPlayerPieceCount > 0;
911+
return firstPlayerPieceCount > secondPlayerPieceCount ? MinMax.MAX_VALUE : MinMax.MIN_VALUE;
785912
} else {
786913
return null;
787914
}
@@ -813,6 +940,10 @@ private String toReadableString() {
813940
return stringBuilder.toString();
814941
}
815942

943+
public boolean isEndGame() {
944+
return pieceCount[1] + pieceCount[2] < 9;
945+
}
946+
816947
public static class Cell {
817948
final int x, y;
818949

0 commit comments

Comments
 (0)