Skip to content

Commit

Permalink
Version 1.9
Browse files Browse the repository at this point in the history
  • Loading branch information
Senders authored and Senders committed Apr 23, 2018
1 parent 8224bf8 commit a53cb3c
Show file tree
Hide file tree
Showing 32 changed files with 704 additions and 698 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
A chessengine build in Java that uses the UCI protocol to communicate with graphical interfaces.
Should be used with a 64 bit JRE for optimal performance.
The binaries are build using Java 9 and are not compatible with older Java versions.
Score is about 2950 elo.
Score is about 3000 elo.

## Features
- (magic) bitboards
Expand All @@ -25,7 +25,7 @@ Score is about 2950 elo.
## Future
- multi-threading
- singular extensions
- 3000 elo!
- improved king safety


_"Simplicity is the soul of efficiency"_ - Austin Freeman -
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<!-- artifactId>${engineName}</artifactId -->
<artifactId>chess22k</artifactId>

<version>1.8</version>
<version>1.9</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
12 changes: 12 additions & 0 deletions release-notes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
1.9 - 23-04-2018 - 3000 elo
- fixed some crashes
- improved sorting efficiency
- calculation instead of lookups for pawn move generation
- simplified SEE
- fixed movetime UCI command
- evaluation
- improved passed-pawn
- long ranged bishop
- bad bishop


1.8 - 04-03-2018 - 2950 elo
- generation of pseudo-legal moves (no elo gain but cleaner code)
- refactored move generation class
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/nl/s22k/chess/Bitboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public class Bitboard {
public static final long G1_H1 = G1 | H1;
public static final long B3_C2 = B3 | C2;
public static final long G3_F2 = G3 | F2;
public static final long D4_E5 = D4 | E5;
public static final long E4_D5 = E4 | D5;
public static final long B6_C7 = B6 | C7;
public static final long G6_F7 = G6 | F7;
public static final long A8_B8 = A8 | B8;
Expand Down Expand Up @@ -136,7 +138,10 @@ public class Bitboard {
public static final long RANK_78 = RANK_7 | RANK_8;
public static final long RANK_234 = RANK_2 | RANK_3 | RANK_4;
public static final long RANK_567 = RANK_5 | RANK_6 | RANK_7;
public static final long RANK_23456 = RANK_2 | RANK_3 | RANK_4 | RANK_5 | RANK_6;
public static final long RANK_34567 = RANK_3 | RANK_4 | RANK_5 | RANK_6 | RANK_7;
public static final long RANK_PROMOTION[] = { RANK_7, RANK_2 };
public static final long RANK_NON_PROMOTION[] = { ~RANK_PROMOTION[0], ~RANK_PROMOTION[1] };

// files
public static final long FILE_A = A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8;
Expand Down Expand Up @@ -164,7 +169,6 @@ public class Bitboard {

public static final long WHITE_SPACE_ZONE = (RANK_2 | RANK_3 | RANK_4) & (FILE_C | FILE_D | FILE_E | FILE_F);
public static final long BLACK_SPACE_ZONE = (RANK_7 | RANK_6 | RANK_5) & (FILE_C | FILE_D | FILE_E | FILE_F);
public static final long[] PAWN_2_MOVE_RANK = { RANK_2, RANK_7 };

public static long getWhitePawnAttacks(final long pawns) {
return pawns << 9 & Bitboard.NOT_FILE_H | pawns << 7 & Bitboard.NOT_FILE_A;
Expand All @@ -183,9 +187,9 @@ public static long getPawnNeighbours(final long pawns) {
*/
public static int manhattanCenterDistance(int sq) {
int file = sq & 7;
int rank = sq >> 3;
file ^= (file - 4) >> 8;
rank ^= (rank - 4) >> 8;
int rank = sq >>> 3;
file ^= (file - 4) >>> 8;
rank ^= (rank - 4) >>> 8;
return (file + rank) & 7;
}

Expand Down
18 changes: 5 additions & 13 deletions src/main/java/nl/s22k/chess/CheckUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ public static long getCheckingPieces(final ChessBoard cb) {
return (cb.pieces[cb.colorToMoveInverse][NIGHT] & StaticMoves.KNIGHT_MOVES[kingIndex]
| (cb.pieces[cb.colorToMoveInverse][ROOK]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getRookMoves(kingIndex, cb.allPieces)
| (cb.pieces[cb.colorToMoveInverse][BISHOP]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getBishopMoves(kingIndex, cb.allPieces)
| cb.pieces[cb.colorToMoveInverse][PAWN] & StaticMoves.PAWN_ALL_ATTACKS[cb.colorToMove][kingIndex]
| cb.pieces[cb.colorToMoveInverse][PAWN] & StaticMoves.PAWN_ATTACKS[cb.colorToMove][kingIndex]
);
}

public static long getCheckingPieces(final ChessBoard cb, final int sourcePieceIndex) {
switch(sourcePieceIndex) {
case PAWN:
return cb.pieces[cb.colorToMoveInverse][PAWN] & StaticMoves.PAWN_ALL_ATTACKS[cb.colorToMove][cb.kingIndex[cb.colorToMove]];
return cb.pieces[cb.colorToMoveInverse][PAWN] & StaticMoves.PAWN_ATTACKS[cb.colorToMove][cb.kingIndex[cb.colorToMove]];
case NIGHT:
return cb.pieces[cb.colorToMoveInverse][NIGHT] & StaticMoves.KNIGHT_MOVES[cb.kingIndex[cb.colorToMove]];
case BISHOP:
Expand All @@ -50,23 +50,15 @@ public static boolean isInCheck(final int kingIndex, final int colorToMove, fina
return (enemyPieces[NIGHT] & StaticMoves.KNIGHT_MOVES[kingIndex]
| (enemyPieces[ROOK] | enemyPieces[QUEEN]) & MagicUtil.getRookMoves(kingIndex, allPieces)
| (enemyPieces[BISHOP] | enemyPieces[QUEEN]) & MagicUtil.getBishopMoves(kingIndex, allPieces)
| enemyPieces[PAWN] & StaticMoves.PAWN_ALL_ATTACKS[colorToMove][kingIndex]
)!= 0;
}

public static boolean isInSlidingCheck(final int kingIndex, final long horVerPieces, final long diagPieces, final long allPieces) {

// put 'super-piece' in kings position
return (horVerPieces & MagicUtil.getRookMoves(kingIndex, allPieces)
| diagPieces & MagicUtil.getBishopMoves(kingIndex, allPieces)
| enemyPieces[PAWN] & StaticMoves.PAWN_ATTACKS[colorToMove][kingIndex]
)!= 0;
}

public static boolean isInCheckIncludingKing(final int kingIndex, final int colorToMove, final long[] enemyPieces, final long allPieces, final int enemyMajorPieces) {

//TODO
if(enemyMajorPieces==0) {
return (enemyPieces[PAWN] & StaticMoves.PAWN_ALL_ATTACKS[colorToMove][kingIndex]
return (enemyPieces[PAWN] & StaticMoves.PAWN_ATTACKS[colorToMove][kingIndex]
| enemyPieces[KING] & StaticMoves.KING_MOVES[kingIndex]
)!= 0;
}
Expand All @@ -75,7 +67,7 @@ public static boolean isInCheckIncludingKing(final int kingIndex, final int colo
return (enemyPieces[NIGHT] & StaticMoves.KNIGHT_MOVES[kingIndex]
| (enemyPieces[ROOK] | enemyPieces[QUEEN]) & MagicUtil.getRookMoves(kingIndex, allPieces)
| (enemyPieces[BISHOP] | enemyPieces[QUEEN]) & MagicUtil.getBishopMoves(kingIndex, allPieces)
| enemyPieces[PAWN] & StaticMoves.PAWN_ALL_ATTACKS[colorToMove][kingIndex]
| enemyPieces[PAWN] & StaticMoves.PAWN_ATTACKS[colorToMove][kingIndex]
| enemyPieces[KING] & StaticMoves.KING_MOVES[kingIndex]
)!= 0;
}
Expand Down
41 changes: 2 additions & 39 deletions src/main/java/nl/s22k/chess/ChessBoard.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public final class ChessBoard {

public final int[] mobilityScore = new int[2];
public long passedPawns;
public final long[] outposts = new long[2];

public static ChessBoard getInstance() {
return instance;
Expand Down Expand Up @@ -441,34 +442,6 @@ public void setPinnedAndDiscoPieces() {
}
}

public long getPinnedPieces(final int color, final long allPieces) {

final int colorInverse = 1 - color;
long pinnedPieces = 0;

// bishop and queen
long piece = (pieces[colorInverse][BISHOP] | pieces[colorInverse][QUEEN]) & allPieces & MagicUtil.bishopMovesEmptyBoard[kingIndex[color]];
while (piece != 0) {
final long checkedPiece = ChessConstants.BISHOP_IN_BETWEEN[kingIndex[color]][Long.numberOfTrailingZeros(piece)] & allPieces;
if (Long.bitCount(checkedPiece) == 1) {
pinnedPieces |= checkedPiece;
}
piece &= piece - 1;
}

// rook and queen
piece = (pieces[colorInverse][ROOK] | pieces[colorInverse][QUEEN]) & allPieces & MagicUtil.rookMovesEmptyBoard[kingIndex[color]];
while (piece != 0) {
final long checkedPiece = ChessConstants.ROOK_IN_BETWEEN[kingIndex[color]][Long.numberOfTrailingZeros(piece)] & allPieces;
if (Long.bitCount(checkedPiece) == 1) {
pinnedPieces |= checkedPiece;
}
piece &= piece - 1;
}

return pinnedPieces;
}

public void undoMove(int move) {

final int fromIndex = MoveUtil.getFromIndex(move);
Expand Down Expand Up @@ -537,7 +510,7 @@ public void undoMove(int move) {

public void updateKingValues(final int kingColor, final int index) {
kingIndex[kingColor] = index;
kingArea[kingColor] = ChessConstants.KING_SAFETY_MASK[kingColor][index];
kingArea[kingColor] = ChessConstants.KING_AREA[kingColor][index];
}

public boolean isLegal(final int move) {
Expand All @@ -558,12 +531,6 @@ public boolean isLegal(final int move) {
return true;
}

public boolean isLegalMove(final int fromIndex, final int toIndex) {
// called when king is in check and by killer-move-validity-check
return !CheckUtil.isInSlidingCheck(kingIndex[colorToMove], pieces[colorToMoveInverse][ROOK] | pieces[colorToMoveInverse][QUEEN],
pieces[colorToMoveInverse][BISHOP] | pieces[colorToMoveInverse][QUEEN], allPieces ^ Util.POWER_LOOKUP[fromIndex] ^ Util.POWER_LOOKUP[toIndex]);
}

private boolean isLegalEvasiveMove(final int fromIndex, final int toIndex) {
// called when king is in check and by killer-move-validity-check
return !CheckUtil.isInCheck(kingIndex[colorToMove], colorToMove, pieces[colorToMoveInverse],
Expand Down Expand Up @@ -621,10 +588,8 @@ public boolean isValidQuietMove(int move) {
return false;
}
break;

case NIGHT:
break;

case BISHOP:
if ((MagicUtil.getBishopMoves(fromIndex, allPieces) & Util.POWER_LOOKUP[toIndex]) == 0) {
return false;
Expand All @@ -635,13 +600,11 @@ public boolean isValidQuietMove(int move) {
return false;
}
break;

case QUEEN:
if (((MagicUtil.getBishopMoves(fromIndex, allPieces) | MagicUtil.getRookMoves(fromIndex, allPieces)) & Util.POWER_LOOKUP[toIndex]) == 0) {
return false;
}
break;

case KING:
if (MoveUtil.getMoveType(move) == MoveUtil.TYPE_CASTLING) {
long castlingIndexes = CastlingUtil.getCastlingIndexes(this);
Expand Down
63 changes: 40 additions & 23 deletions src/main/java/nl/s22k/chess/ChessConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class ChessConstants {
public static final int[] COLOR_FACTOR_8 = { 8, -8 };
public static final int[] COLOR_FACTOR_16 = { 16, -16 };

public static final long[][] KING_SAFETY_MASK = new long[2][64];
public static final long[][] KING_AREA = new long[2][64];
public static final long[][] KING_PAWN_SHIELD_KINGSIDE_MASK = new long[2][8];
public static final long[][] KING_PAWN_SHIELD_QUEENSIDE_MASK = new long[2][8];

Expand Down Expand Up @@ -176,7 +176,7 @@ public class ChessConstants {
// fill passed-pawn-masks
for (int i = 0; i < 64; i++) {
PASSED_PAWN_MASKS[WHITE][i] = ((Bitboard.FILES[i & 7] | Bitboard.FILES_ADJACENT[i & 7]) & ~Bitboard.RANKS[i / 8]) >>> i << i;
PASSED_PAWN_MASKS[BLACK][i] = ((Bitboard.FILES[i & 7] | Bitboard.FILES_ADJACENT[i & 7]) & ~Bitboard.RANKS[i / 8]) << (63 - i) >> (63 - i);
PASSED_PAWN_MASKS[BLACK][i] = ((Bitboard.FILES[i & 7] | Bitboard.FILES_ADJACENT[i & 7]) & ~Bitboard.RANKS[i / 8]) << (63 - i) >>> (63 - i);
}
}

Expand All @@ -190,32 +190,49 @@ public class ChessConstants {
//
for (int i = 0; i < 64; i++) {
// NEXT
KING_SAFETY_MASK[WHITE][i] |= (StaticMoves.KING_MOVES[i] & Bitboard.RANKS[i / 8]) | Util.POWER_LOOKUP[i];
KING_SAFETY_MASK[BLACK][i] |= (StaticMoves.KING_MOVES[i] & Bitboard.RANKS[i / 8]) | Util.POWER_LOOKUP[i];

if (i > 7) {
KING_SAFETY_MASK[WHITE][i] |= StaticMoves.KING_MOVES[i] & Bitboard.RANKS[i / 8 - 1];
KING_SAFETY_MASK[BLACK][i] |= StaticMoves.KING_MOVES[i] & Bitboard.RANKS[i / 8 - 1];
if (i > 15) {
KING_SAFETY_MASK[BLACK][i] |= StaticMoves.KING_MOVES[i] >>> 8 & Bitboard.RANKS[i / 8 - 2];
}
KING_AREA[WHITE][i] |= StaticMoves.KING_MOVES[i] | Util.POWER_LOOKUP[i];
KING_AREA[BLACK][i] |= StaticMoves.KING_MOVES[i] | Util.POWER_LOOKUP[i];

if (i > 15) {
KING_AREA[BLACK][i] |= StaticMoves.KING_MOVES[i] >>> 8;
}
if (i < 56) {
KING_SAFETY_MASK[BLACK][i] |= StaticMoves.KING_MOVES[i] & Bitboard.RANKS[i / 8 + 1];
KING_SAFETY_MASK[WHITE][i] |= StaticMoves.KING_MOVES[i] & Bitboard.RANKS[i / 8 + 1];
if (i < 48) {
KING_SAFETY_MASK[WHITE][i] |= StaticMoves.KING_MOVES[i] << 8 & Bitboard.RANKS[i / 8 + 2];
}

if (i < 48) {
KING_AREA[WHITE][i] |= StaticMoves.KING_MOVES[i] << 8;
}
}

// always 3 wide, even at file 1 and 8
for (int i = 0; i < 64; i++) {
for (int color = 0; color < 2; color++) {
if (i % 8 == 0) {
KING_SAFETY_MASK[color][i] |= KING_SAFETY_MASK[color][i + 1];
KING_AREA[color][i] |= KING_AREA[color][i + 1];
} else if (i % 8 == 7) {
KING_SAFETY_MASK[color][i] |= KING_SAFETY_MASK[color][i - 1];
KING_AREA[color][i] |= KING_AREA[color][i - 1];
}
}
}

// always 4 long
for (int i = 0; i < 64; i++) {
if (i < 8) {
KING_AREA[WHITE][i] = KING_AREA[WHITE][i + 8];
} else if (i > 47) {
if (i > 55) {
KING_AREA[WHITE][i] = KING_AREA[WHITE][i - 16];
} else {
KING_AREA[WHITE][i] = KING_AREA[WHITE][i - 8];
}
}
}
for (int i = 0; i < 64; i++) {
if (i > 55) {
KING_AREA[BLACK][i] = KING_AREA[BLACK][i - 8];
} else if (i < 16) {
if (i < 8) {
KING_AREA[BLACK][i] = KING_AREA[BLACK][i + 16];
} else {
KING_AREA[BLACK][i] = KING_AREA[BLACK][i + 8];
}
}
}
Expand All @@ -225,14 +242,14 @@ public class ChessConstants {
// king-pawn-shield masks
for (int i = 1; i < 64; i += 8) {
// king-side
KING_PAWN_SHIELD_KINGSIDE_MASK[WHITE][i / 8] |= KING_SAFETY_MASK[WHITE][i];
KING_PAWN_SHIELD_KINGSIDE_MASK[BLACK][i / 8] |= KING_SAFETY_MASK[BLACK][i];
KING_PAWN_SHIELD_KINGSIDE_MASK[WHITE][i / 8] |= KING_AREA[WHITE][i];
KING_PAWN_SHIELD_KINGSIDE_MASK[BLACK][i / 8] |= KING_AREA[BLACK][i];
}

for (int i = 6; i < 64; i += 8) {
// queen-side
KING_PAWN_SHIELD_QUEENSIDE_MASK[WHITE][i / 8] |= KING_SAFETY_MASK[WHITE][i];
KING_PAWN_SHIELD_QUEENSIDE_MASK[BLACK][i / 8] |= KING_SAFETY_MASK[BLACK][i];
KING_PAWN_SHIELD_QUEENSIDE_MASK[WHITE][i / 8] |= KING_AREA[WHITE][i];
KING_PAWN_SHIELD_QUEENSIDE_MASK[BLACK][i / 8] |= KING_AREA[BLACK][i];
}
}

Expand Down
Loading

0 comments on commit a53cb3c

Please sign in to comment.