Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bin/zobristTable.dat
Binary file not shown.
35 changes: 32 additions & 3 deletions src/main/java/Main.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import State.State;
import Tree.Heuristics;
import Tree.MonteCarloTree;
import ygraph.ai.smartfox.games.BaseGameGUI;
import ygraph.ai.smartfox.games.GameClient;
Expand All @@ -11,6 +12,7 @@
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Map;
import java.util.Scanner;

import State.*;

Expand All @@ -27,7 +29,7 @@ public class Main extends GamePlayer {
private int colour;

private MonteCarloTree monteCarloTree;
private final double cValue = 2.0;
private final double cValue = 1.4;
private int depth = 0;
private static int[] moveDictionary;

Expand All @@ -38,8 +40,10 @@ public class Main extends GamePlayer {
*/
public static void main(String[] args) {
GamePlayer player;
String name = "new";
System.out.println(name);
if (args.length == 2)
player = new Main(args[0] + "-" + ((int) (Math.random() * 1000)), args[1]);
player = new Main(name, args[1]);
else
player = new HumanPlayer();

Expand Down Expand Up @@ -132,13 +136,38 @@ public boolean handleGameMessage(String messageType, Map<String, Object> msgDeta

private void makeMove() {
makeMonteCarloMove();
// theClown();
depth++;
}

private void theClown() {
ArrayList<Action> actions = ActionGenerator.generateActions(state, colour);
Action definitelyTheBestAction = null;
double bestH = Math.pow(-1, colour) * Integer.MAX_VALUE;
for (Action a : actions) {
double h = Heuristics.bigPoppa(new State(state, a), colour);
if (colour == 1 && h > bestH) {
definitelyTheBestAction = a;
bestH = h;
} else if (colour == 2 && h < bestH) {
definitelyTheBestAction = a;
bestH = h;
}
}
if (definitelyTheBestAction == null) {
System.out.println("OPPONENT WINS!!");
new Scanner(System.in).nextLine();
}
state = new State(state, definitelyTheBestAction);
getGameClient().sendMoveMessage(definitelyTheBestAction.toServerResponse());
getGameGUI().updateGameState(definitelyTheBestAction.toServerResponse());
}

private void makeMonteCarloMove() {
System.out.println("colour = " + colour);
long start = System.currentTimeMillis();
if (action != null)
monteCarloTree.updateRoot(state, action, colour, depth);
monteCarloTree = new MonteCarloTree(state, cValue, colour, depth, moveDictionary);
Action definitelyTheBestAction = monteCarloTree.search();
if (definitelyTheBestAction == null) {
System.out.println("OPPONENT WINS!!");
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/State/ZobristHash.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package State;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Random;

public class ZobristHash {
private static boolean initialized = false;
private static long[] zobristTable;
private static long blackToMove;

public static long zobristHash(BitBoard bitBoard, int colorToMove) {
if (!initialized) init();

long hash = 0;

if (colorToMove == State.BLACK_QUEEN)
hash = blackToMove;

int index = 0; // Start at 0 for black
long currentBoard = bitBoard.getBlackQueensBottom();
while (currentBoard > 0) {
if ((currentBoard & 1L) == 1)
hash ^= zobristTable[index];
currentBoard >>= 1;
index += 3;
}
index = 150; // Make sure that the index is correct going into the next loop because the last loop likely didn't execute a full 50 times
currentBoard = bitBoard.getBlackQueensTop();
while (currentBoard > 0) {
if ((currentBoard & 1L) == 1)
hash ^= zobristTable[index];
currentBoard >>= 1;
index += 3;
}

index = 1; // Start at 1 for white
currentBoard = bitBoard.getWhiteQueensBottom();
while (currentBoard > 0) {
if ((currentBoard & 1L) == 1)
hash ^= zobristTable[index];
currentBoard >>= 1;
index += 3;
}
index = 151; // Make sure that the index is correct going into the next loop because the last loop likely didn't execute a full 50 times
currentBoard = bitBoard.getWhiteQueensTop();
while (currentBoard > 0) {
if ((currentBoard & 1L) == 1)
hash ^= zobristTable[index];
currentBoard >>= 1;
index += 3;
}

index = 2; // Start at 2 for arrows
currentBoard = bitBoard.getArrowBottom();
while (currentBoard > 0) {
if ((currentBoard & 1L) == 1)
hash ^= zobristTable[index];
currentBoard >>= 1;
index += 3;
}
index = 152; // Make sure that the index is correct going into the next loop because the last loop likely didn't execute a full 50 times
currentBoard = bitBoard.getArrowTop();
while (currentBoard > 0) {
if ((currentBoard & 1L) == 1)
hash ^= zobristTable[index];
currentBoard >>= 1;
index += 3;
}

return hash;
}

public static void init() {
Path path = Paths.get("bin/zobristTable.dat");
try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(Files.newInputStream(path)))) {
zobristTable = (long[]) in.readObject();
blackToMove = in.readLong();
} catch (Exception e) {
// Generate table if it doesn't exist or there are any errors reading it

// Addressed boardIndex * 3 + (pieceNumber - 1) // 0 = black, 1 = white, 2 = arrow
// This does waste 25% of the space, but is more efficient for lookup
zobristTable = new long[300];

// Fill table with random longs
HashSet<Long> randomLongs = new HashSet<>();
Random r = new Random();
for (int i = 0; i < zobristTable.length; i++) {
// Fill table with random longs making sure there are no duplicates (even though it's an extremely small chance)
long randLong = r.nextLong();
while (randomLongs.contains(randLong))
randLong = r.nextLong();
randomLongs.add(randLong);
zobristTable[i] = randLong;
}

// Also generate another bitstring for if black is the player that makes the next move
blackToMove = r.nextLong();
while (randomLongs.contains(blackToMove))
blackToMove = r.nextLong();

// Save to file
try (ObjectOutputStream out = new ObjectOutputStream(Files.newOutputStream(path))) {
out.writeObject(zobristTable);
out.writeLong(blackToMove);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}

// Only set initialized to true if we make it here without an exception
initialized = true;
}
}
Loading