Ai.java (2866B) download
1package nl.isygameclient.models;
2
3import java.security.SecureRandom;
4import java.util.*;
5import nl.isygameclient.util.Vector2D;
6
7public class Ai extends Player {
8
9 public static final int DEPTH = 5;
10 public static final Random AI_RANDOM = new Random();
11
12 private final int[][] heuristics;
13
14 public Ai(String name, String playingAs, int[][] heuristics) {
15 super(name, playingAs);
16 this.heuristics = heuristics;
17 }
18
19 public static <T> T randomMove(Collection<T> possibleMoves) {
20 int size = possibleMoves.size();
21 int item = AI_RANDOM.nextInt(size); // In real life, the Random object should be rather more shared than this
22 int i = 0;
23 for (T obj : possibleMoves)
24 if (i == item)
25 return obj;
26 else
27 i++;
28 return null;
29 }
30
31 private double miniMaxAlphaBeta(double alpha, double beta, Integer depth, boolean isMaximizing) {
32 var playerManager = game.getPlayerManager();
33 var currentPlayer = playerManager.getCurrentPlayer();
34 var possibleMoves = game.getValidMoves(currentPlayer);
35
36 if (depth == 0 || game.isGameOver()) {
37 return heuristicScore(currentPlayer);
38 }
39
40 double bestValue;
41 if (isMaximizing) {
42 bestValue = Double.MIN_VALUE;
43 for (Vector2D<Integer, Integer> move : possibleMoves) {
44 game.move(currentPlayer, move);
45 double value = miniMaxAlphaBeta(alpha, beta, depth - 1, false);
46 game.undo();
47
48 bestValue = Math.max(bestValue, value);
49 alpha = Math.max(alpha, bestValue);
50 if (beta <= alpha) {
51 break;
52 }
53 }
54
55 } else {
56 bestValue = Double.MAX_VALUE;
57 for (Vector2D<Integer, Integer> move : possibleMoves) {
58 game.move(currentPlayer, move);
59 double value = miniMaxAlphaBeta(alpha, beta, depth - 1, true);
60 game.undo();
61
62 bestValue = Math.min(bestValue, value);
63 beta = Math.min(beta, bestValue);
64 if (beta <= alpha) {
65 break;
66 }
67 }
68 }
69 return bestValue;
70 }
71
72 @Override
73 public Vector2D<Integer, Integer> onPlayerTurn() {
74 var manager = game.getPlayerManager();
75 var currentPlayer = manager.getCurrentPlayer();
76 var possibleMoves = game.getValidMoves(currentPlayer);
77
78 double bestValue = Integer.MIN_VALUE;
79 var bestMove = randomMove(possibleMoves);
80
81 for (Vector2D<Integer, Integer> move : possibleMoves) {
82 game.move(currentPlayer, move);
83 double moveValue = miniMaxAlphaBeta(Double.MIN_VALUE, Double.MAX_VALUE, DEPTH, false);
84 if (moveValue > bestValue) {
85 bestValue = moveValue;
86 bestMove = move;
87 }
88 game.undo();
89 }
90 return bestMove;
91 }
92
93 public int heuristicScore(Player player) {
94 var board = game.getBoard();
95 int score = 0;
96 for (int y = 0; y < board.getHeight(); y++) {
97 for (int x = 0; x < board.getWidth(); x++) {
98 if (Objects.equals(player, board.get(new Vector2D<>(x, y)))) {
99 score += heuristics[y][x];
100 }
101 }
102 }
103 return score;
104 }
105
106 public void setGame(Game game) {
107 this.game = game;
108 }
109}