Skip to content

Commit

Permalink
Wow that is a bit faster
Browse files Browse the repository at this point in the history
  • Loading branch information
psychout98 committed Dec 19, 2023
1 parent d28bf64 commit 5275831
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,32 @@ public void compute() {
Collection<AnalysisBoard> futures = new ArrayList<>();
for (byte i=0;i<8;i++) {
for (byte j=0;j<8;j++) {
if (boardData.getBoardKey()[i][j] != 'x') {
String pieceKey = String.format("%c%x%x", boardData.getBoardKey()[i][j], i, j);
char key = boardData.keyAtSpace(i, j);
if (key != 'x' &&
(boardData.isWhiteToMove() ?
Character.isUpperCase(key) :
Character.isLowerCase(key))) {
String pieceKey = String.format("%c%x%x", key, i, j);
List<MoveNode> moveNodes = Moves.moves.get(pieceKey);
for (MoveNode moveNode : moveNodes) {
while (moveNode != null) {
// possibleMoves++;
try {
ComputerMove computerMove = new ComputerMove(moveNode.getMoveArray(), boardData, depth, maxDepth);
if (computerMove.isKingKiller()) {
if (computerMove.getEndKey() == 'k' || computerMove.getEndKey() == 'K') {
valid = false;
break;
} else if (computerMove.getEndKey() != 'x') {
moveNode = null;
} else {
moveNode = moveNode.getNext();
}
futures.add(computerMove.getAnalysisBoard());
moveNode = moveNode.getNext();
} catch (InvalidMoveException e) {
if (e.getMoveException() == MoveException.OBSTRUCTED_PATH) {
moveNode = null;
} else {
moveNode = moveNode.getNext();
moveNode = moveNode != null ? moveNode.getNext() : null;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
@AllArgsConstructor
public class BoardData {

private final char[][] boardKey;
private String boardKey;
private final boolean whiteToMove;
private final String castles;
private final byte[] enPassantTarget;
Expand All @@ -23,7 +23,7 @@ public class BoardData {
public BoardData(String fen) {
materialAdvantage = 0;
String[] fields = fen.split(" ");
boardKey = new char[8][8];
boardKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
loadBoardKey(fields[0]);
if (Objects.equals(fields[1], "w")) {
whiteToMove = true;
Expand All @@ -40,20 +40,21 @@ public BoardData(String fen) {
enPassantTarget = Objects.equals(fields[3], "-") ? null : Board.spaceToSpace(fields[3]);
}

public char keyAtSpace(byte row, byte col) {
return boardKey.charAt((8 * row) + col);
}

public void loadBoardKey(String boardField) {
String[] splitBoard = boardField.split("/");
if (splitBoard.length == 8) {
for (byte i = 0; i < 8; i++) {
byte j = 0;
for (char c : splitBoard[i].toCharArray()) {
if (FEN.validChars.contains(String.valueOf(c))) {
boardKey[i][j] = c;
boardKey = boardKey.substring(0, (8 * i) + j) + c + boardKey.substring((8 * i) + j + 1);
materialAdvantage += calculatePoints(c);
j++;
} else if (c > 47 && c < 58) {
for (byte k = j; k < (j + c - 48); k++) {
boardKey[i][k] = 'x';
}
j += (byte) (c - 48);
} else {
throw new InvalidFENException("Invalid character \"" + c + "\" in FEN");
Expand All @@ -69,7 +70,7 @@ public static int calculatePoints(char key) {
return Objects.requireNonNullElse(pointValues.get(key), 0);
}

public static BoardData updatedBoard(BoardData previousBoardData, char[][] boardKey, char key, char endKey, byte startCol, byte endCol, byte[] enPassantTarget, int newAdvantage) {
public static BoardData updatedBoard(BoardData previousBoardData, String boardKey, char key, char endKey, byte startCol, byte endCol, byte[] enPassantTarget, int newAdvantage) {
return new BoardData(boardKey, !previousBoardData.whiteToMove, updateCastle(previousBoardData.castles, key, endKey, startCol, endCol), enPassantTarget, newAdvantage);
}

Expand Down Expand Up @@ -117,11 +118,7 @@ public static String updateCastle(String oldCastle, char key, char endKey, byte
castle.append(entry.getKey());
}
}
if (castle.isEmpty()) {
return "-";
} else {
return castle.toString();
}
return castle.toString();
}

}
171 changes: 51 additions & 120 deletions src/main/java/com/example/chessserver3/model/computer/ComputerMove.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import com.example.chessserver3.exception.InvalidMoveException;
import com.example.chessserver3.exception.MoveException;
import com.example.chessserver3.model.board.Board;
import com.example.chessserver3.model.board.Castle;
import lombok.*;
import java.util.Objects;
Expand All @@ -14,203 +13,135 @@ public class ComputerMove {

private final String moveCode;
private final char key;
private String boardKey;
private final boolean white;
private final byte startRow;
private final byte endRow;
private final byte startCol;
private final byte endCol;
private final char endKey;
private boolean castleMove;
private boolean enPassant;
private boolean pushTwo;
private boolean kingKiller;
private final AnalysisBoard analysisBoard;

public ComputerMove(final byte[] moveArray, final BoardData previousBoardData, byte depth, byte maxDepth) {
boardKey = previousBoardData.getBoardKey();
startRow = moveArray[0];
startCol = moveArray[1];
endRow = moveArray[2];
endCol = moveArray[3];
key = previousBoardData.getBoardKey()[startRow][startCol];
key = keyAtSpace(startRow, startCol);
white = Character.isUpperCase(key);
if (white != previousBoardData.isWhiteToMove()) {
throw new InvalidMoveException(MoveException.NOT_YOUR_TURN);
}
enPassant = false;
castleMove = false;
pushTwo = false;
kingKiller = false;
moveCode = String.format("%s%s%s%s", startRow, startCol, endRow, endCol);
boolean pawnMove = key == 'p' || key == 'P';
char[][] boardKey = Board.copyBoardKey(previousBoardData.getBoardKey());
endKey = boardKey[endRow][endCol];
endKey = keyAtSpace(endRow, endCol);
int newAdvantage = previousBoardData.getMaterialAdvantage() - Objects.requireNonNullElse(pointValues.get(endKey), 0);
if (isObstructed(boardKey)) {
if (endKey != 'x' && Character.isLowerCase(key) == Character.isLowerCase(endKey)) {
throw new InvalidMoveException(MoveException.OBSTRUCTED_PATH);
}
if (pawnMove) {
runPawnMove(boardKey, previousBoardData.getEnPassantTarget());
runPawnMove(previousBoardData.getEnPassantTarget());
} else if ((key == 'k' || key == 'K') && castle.get(moveCode) != null && previousBoardData.getCastles().contains(Castle.castleKeys.get(moveCode))) {
runCastle(boardKey);
runCastle();
} else if ((key == 'k' || key == 'K') && Math.abs(endCol - startCol) == 2) {
throw new InvalidMoveException(MoveException.INVALID_CASTLE);
} else {
runBasicMove(boardKey);
runBasicMove();
}
if (white ? endKey == 'k' : endKey == 'K') {
kingKiller = true;
}
analysisBoard = new AnalysisBoard(BoardData.updatedBoard(previousBoardData, boardKey, key, endKey, startCol, endCol, pushTwo ? enPassantTarget() : null, newAdvantage), (byte) (depth + 1), maxDepth, moveCode);
analysisBoard = new AnalysisBoard(
BoardData.updatedBoard(
previousBoardData,
boardKey,
key,
endKey,
startCol,
endCol,
pushTwo ? enPassantTarget() : null, newAdvantage
),
(byte) (depth + 1),
maxDepth,
moveCode);
}

private byte[] enPassantTarget() {
return new byte[]{(byte) (white ? startRow - 1 : startRow + 1), startCol};
private void updateBoardKey(byte row, byte col, char key) {
boardKey = boardKey.substring(0, (8 * row) + col) + key + boardKey.substring((8 * row) + col + 1);
}

private boolean isObstructed(char[][] boardKey) {
boolean obstructed = false;
boolean open = endKey == 'x' || (Character.isLowerCase(key) != Character.isLowerCase(endKey));
if (kingsAndKnights.contains(String.valueOf(key))) {
obstructed = !open;
}
if (queensAndBishops.contains(String.valueOf(key))) {
obstructed = !open || diagonalObstruction(boardKey);
}
if (queensAndRooksAndPawns.contains(String.valueOf(key))) {
obstructed = !open || obstructed || straightObstruction(boardKey);
}
return obstructed;
private char keyAtSpace(byte row, byte col) {
return boardKey.charAt((8 * row) + col);
}

private boolean diagonalObstruction(char[][] boardKey) {
int vertical = endRow - startRow;
int horizontal = endCol - startCol;
if (Math.abs(vertical) != Math.abs(horizontal)) {
return false;
} else if (vertical > 0 && horizontal > 0) {
for (int i=1; i<vertical; i++) {
if (boardKey[startRow + i][startCol + i] != 'x') {
return true;
}
}
} else if (vertical > 0 && horizontal < 0) {
for (int i=1; i<vertical; i++) {
if (boardKey[startRow + i][startCol - i] != 'x') {
return true;
}
}
} else if (vertical < 0 && horizontal > 0) {
for (int i=-1; i>vertical; i--) {
if (boardKey[startRow + i][startCol - i] != 'x') {
return true;
}
}
} else if (vertical < 0 && horizontal < 0) {
for (int i=-1; i>vertical; i--) {
if (boardKey[startRow + i][startCol + i] != 'x') {
return true;
}
}
}
return false;
}

private boolean straightObstruction(char[][] boardKey) {
int vertical = endRow - startRow;
int horizontal = endCol - startCol;
if (vertical != 0 && horizontal != 0) {
return false;
} else if (vertical == 0 && horizontal < 0) {
for (int i=endCol + 1; i<startCol; i++) {
if (boardKey[startRow][i] != 'x') {
return true;
}
}
} else if (vertical == 0 && horizontal > 0){
for (int i=startCol + 1; i<endCol; i++) {
if (boardKey[startRow][i] != 'x') {
return true;
}
}
} else if (vertical < 0) {
for (int i=endRow + 1; i<startRow; i++) {
if (boardKey[i][startCol] != 'x') {
return true;
}
}
} else {
for (int i=startRow + 1; i<endRow; i++) {
if (boardKey[i][startCol] != 'x') {
return true;
}
}
}
return false;
private byte[] enPassantTarget() {
return new byte[]{(byte) (white ? startRow - 1 : startRow + 1), startCol};
}

private void runBasicMove(char[][] boardKey) {
boardKey[startRow][startCol] = 'x';
boardKey[endRow][endCol] = key;
private void runBasicMove() {
updateBoardKey(startRow, startCol, 'x');
updateBoardKey(endRow, endCol, key);
}

private void runPawnMove(char[][] boardKey, byte[] enPassantTarget) {
private void runPawnMove(byte[] enPassantTarget) {
if (Math.abs(endRow - startRow) == 2) {
pushTwo = true;
if (endKey == 'x' && (white ? startRow == 6 : startRow == 1)) {
runBasicMove(boardKey);
runBasicMove();
} else {
throw new InvalidMoveException(MoveException.INVALID_PUSH_TWO);
}
} else if (startCol != endCol) {
if (isEnPassant(enPassantTarget)) {
runEnPassant(boardKey);
runEnPassant();
} else {
if (endKey == 'x' || Character.isLowerCase(key) == Character.isLowerCase(endKey)) {
throw new InvalidMoveException(MoveException.INVALID_PAWN_ATTACK);
}
if (endRow == (white ? 0 : 7)) {
runQueenPromotion(boardKey);
runQueenPromotion();
} else {
runBasicMove(boardKey);
runBasicMove();
}
}
} else {
if (endKey != 'x') {
throw new InvalidMoveException(MoveException.INVALID_PUSH_ONE);
}
if (endRow == (white ? 0 : 7)) {
runQueenPromotion(boardKey);
runQueenPromotion();
} else {
runBasicMove(boardKey);
runBasicMove();
}
}
}

private void runEnPassant(char[][] boardKey) {
int targetRow = white ? endRow + 1 : endRow - 1;
private void runEnPassant() {
byte targetRow = (byte) (white ? endRow + 1 : endRow - 1);
enPassant = true;
boardKey[startRow][startCol] = 'x';
boardKey[endRow][endCol] = key;
boardKey[targetRow][endCol] = 'x';
updateBoardKey(startRow, startCol, 'x');
updateBoardKey(endRow, endCol, key);
updateBoardKey(targetRow, endCol, 'x');
}

private void runQueenPromotion(char[][] boardKey) {
boardKey[startRow][startCol] = 'x';
boardKey[endRow][endCol] = white ? 'Q' : 'q';
private void runQueenPromotion() {
updateBoardKey(startRow, startCol, 'x');
updateBoardKey(endRow, endCol, white ? 'Q' : 'q');
}

private void runCastle(char[][] boardKey) {
private void runCastle() {
for (byte[] space : Castle.castleRoutes.get(moveCode)) {
if (boardKey[space[0]][space[1]] != 'x') {
if (keyAtSpace(space[0], space[1]) != 'x') {
throw new InvalidMoveException(MoveException.INVALID_CASTLE);
}
}
castleMove = true;
byte[] rookMove = Castle.castleRookMove.get(moveCode);
boardKey[startRow][startCol] = 'x';
boardKey[endRow][endCol] = key;
boardKey[rookMove[0]][rookMove[1]] = 'x';
boardKey[rookMove[2]][rookMove[3]] = white ? 'R' : 'r';
updateBoardKey(startRow, startCol, 'x');
updateBoardKey(endRow, endCol, key);
updateBoardKey(rookMove[0], rookMove[1], 'x');
updateBoardKey(rookMove[2], rookMove[3], white ? 'R' : 'r');
}

public boolean isEnPassant(byte[] enPassantTarget) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void autoMove(final Board board, final byte level) {
commonPool.invoke(analysisBoard);
// long endTime = System.nanoTime();
// System.out.println(analysisBoard.getPossibleMoves() + " moves checked");
// System.out.println((double) 1000000000 * analysisBoard.getEvaluatedMoves() / (endTime - startTime) + " moves per second");
// System.out.println(1000000000 * analysisBoard.getEvaluatedMoves() / (endTime - startTime) + " moves per second");
board.move(analysisBoard.getBestMoveCode());
boardRepository.update(board);
template.convertAndSend("/board/" + board.getId(), "computer");
Expand Down

0 comments on commit 5275831

Please sign in to comment.