Skip to content

Commit

Permalink
Version 1.7
Browse files Browse the repository at this point in the history
  • Loading branch information
Senders authored and Senders committed Dec 28, 2017
1 parent ceb31c5 commit f6147f5
Show file tree
Hide file tree
Showing 44 changed files with 2,691 additions and 1,480 deletions.
8 changes: 6 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 2800 elo.
Score is about 2900 elo.

## Features
- (magic) bitboards
Expand All @@ -17,11 +17,15 @@ Score is about 2800 elo.
- futility pruning
- static exchange evaluation for move ordering and pruning
- aspiration window
- evaluation scores tuned using the Texel's tuning method
- evaluation parameters tuned using the Texel's tuning method
- tapered eval
- no openingbook or endgame tablebases
- no pondering

## Future
- evaluate space
- multi-threading


_"Simplicity is the soul of efficiency"_ - Austin Freeman -

27 changes: 25 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<!-- so we can simply build other (experimental) artifacts -->
<!-- artifactId>${engineName}</artifactId -->
<artifactId>chess22k</artifactId>
<version>1.6</version>

<version>1.7</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down Expand Up @@ -46,6 +46,11 @@
<target>1.9</target>
</configuration>
</plugin>
<plugin>
<groupId>org.openclover</groupId>
<artifactId>clover-maven-plugin</artifactId>
<version>4.2.1</version>
</plugin>
</plugins>
</build>

Expand All @@ -55,6 +60,24 @@
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>org.openclover</groupId>
<artifactId>clover-maven-plugin</artifactId>
<version>4.2.1</version>
</dependency>
</dependencies>

<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.4</version>
<configuration>
<skipEmptyReport>false</skipEmptyReport>
</configuration>
</plugin>
</plugins>
</reporting>

</project>
18 changes: 18 additions & 0 deletions release-notes.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
1.7 - 28-12-2017 - 2900 elo
- fixed a futility pruning bug
- no quiescence search when in check
- use move history score for LMR and futility pruning
- implemented a pawn endgame extension
- implemented currmove UCI command
- improved time management
- improved evaluation
- hanging pieces
- discovered checks
- knight forks
- rook prison
- skewed pieces
- certain endgames
- fixed some crashes
- split-up methods into smaller ones for better inlining (suggested by JITWatch)


1.6 - 03-11-2017 - 2800 elo
- more accurate SEE (pinned pieces)
- improved king safety
Expand Down
28 changes: 23 additions & 5 deletions src/main/java/nl/s22k/chess/Bitboard.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ public class Bitboard {
public static final long RANK_78 = RANK_7 | RANK_8;
public static final long RANK_2345 = RANK_2 | RANK_3 | RANK_4 | RANK_5;
public static final long RANK_4567 = RANK_4 | RANK_5 | RANK_6 | RANK_7;
public static final long RANK_PROMOTION[] = new long[] { RANK_7, RANK_2 };
public static final long RANK_PROMOTION[] = { RANK_7, RANK_2 };

// files
public static final long FILE_A = A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8;
Expand All @@ -151,17 +151,20 @@ public class Bitboard {
public static final long NOT_FILE_A = ~FILE_A;
public static final long NOT_FILE_H = ~FILE_H;

public static final long RANKS[] = new long[] { RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8 };
public static final long FILES[] = new long[] { FILE_H, FILE_G, FILE_F, FILE_E, FILE_D, FILE_C, FILE_B, FILE_A };
public static final long FILES_ADJACENT[] = new long[] { FILE_G, FILE_H | FILE_F, FILE_G | FILE_E, FILE_F | FILE_D, FILE_E | FILE_C, FILE_D | FILE_B,
FILE_C | FILE_A, FILE_B };
public static final long RANKS[] = { RANK_1, RANK_2, RANK_3, RANK_4, RANK_5, RANK_6, RANK_7, RANK_8 };
public static final long FILES[] = { FILE_H, FILE_G, FILE_F, FILE_E, FILE_D, FILE_C, FILE_B, FILE_A };
public static final long FILES_ADJACENT[] = { FILE_G, FILE_H | FILE_F, FILE_G | FILE_E, FILE_F | FILE_D, FILE_E | FILE_C, FILE_D | FILE_B, FILE_C | FILE_A,
FILE_B };

public static final long KING_SIDE = FILE_F | FILE_G | FILE_H;
public static final long QUEEN_SIDE = FILE_A | FILE_B | FILE_C;

public static final long WHITE_SIDE = RANK_1 | RANK_2 | RANK_3 | RANK_4;
public static final long BLACK_SIDE = RANK_5 | RANK_6 | RANK_7 | RANK_8;

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 long getWhitePawnAttacks(final long pawns) {
return pawns << 9 & Bitboard.NOT_FILE_H | pawns << 7 & Bitboard.NOT_FILE_A;
}
Expand All @@ -170,4 +173,19 @@ public static long getBlackPawnAttacks(final long pawns) {
return pawns >>> 9 & Bitboard.NOT_FILE_A | pawns >>> 7 & Bitboard.NOT_FILE_H;
}

public static long getPawnNeighbours(final long pawns) {
return pawns << 1 & Bitboard.NOT_FILE_H | pawns >>> 1 & Bitboard.NOT_FILE_A;
}

/**
* @author Gerd Isenberg
*/
public static int manhattanCenterDistance(int sq) {
int file = sq & 7;
int rank = sq >> 3;
file ^= (file - 4) >> 8;
rank ^= (rank - 4) >> 8;
return (file + rank) & 7;
}

}
3 changes: 1 addition & 2 deletions src/main/java/nl/s22k/chess/CastlingUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,7 @@ public static boolean isValidCastlingMove(final ChessBoard cb, final int fromInd
long kingIndexes = ChessConstants.IN_BETWEEN[fromIndex][toIndex] | Util.POWER_LOOKUP[toIndex];
while (kingIndexes != 0) {
// king does not move through a checked position?
if (CheckUtil.isInCheckIncludingKing(Long.numberOfTrailingZeros(kingIndexes), cb.colorToMove, cb.friendlyPieces[cb.colorToMove],
cb.pieces[cb.colorToMoveInverse], cb.allPieces)) {
if (CheckUtil.isInCheckIncludingKing(Long.numberOfTrailingZeros(kingIndexes), cb.colorToMove, cb.pieces[cb.colorToMoveInverse], cb.allPieces)) {
return false;
}
kingIndexes &= kingIndexes - 1;
Expand Down
71 changes: 25 additions & 46 deletions src/main/java/nl/s22k/chess/CheckUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,68 +19,47 @@ public static long getCheckingPieces(final ChessBoard cb) {

// put 'super-piece' in kings position
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.friendlyPieces[cb.colorToMove])
| (cb.pieces[cb.colorToMoveInverse][BISHOP]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getBishopMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
| (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]
);
}

public static long getCheckingPiecesWithoutKnight(final ChessBoard cb) {
final int kingIndex = cb.kingIndex[cb.colorToMove];

// put 'super-piece' in kings position
return ((cb.pieces[cb.colorToMoveInverse][ROOK]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getRookMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
| (cb.pieces[cb.colorToMoveInverse][BISHOP]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getBishopMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
| cb.pieces[cb.colorToMoveInverse][PAWN] & StaticMoves.PAWN_ALL_ATTACKS[cb.colorToMove][kingIndex]
);
}

public static long getCheckingPiecesWithoutPawn(final ChessBoard cb) {
final int kingIndex = cb.kingIndex[cb.colorToMove];

// put 'super-piece' in kings position
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.friendlyPieces[cb.colorToMove])
| (cb.pieces[cb.colorToMoveInverse][BISHOP]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getBishopMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
);
}

public static long getCheckingPiecesWithoutKnightAndPawn(final ChessBoard cb) {
final int kingIndex = cb.kingIndex[cb.colorToMove];

// put 'super-piece' in kings position
return ((cb.pieces[cb.colorToMoveInverse][ROOK]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getRookMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
| (cb.pieces[cb.colorToMoveInverse][BISHOP]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getBishopMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
);
}

public static boolean isInCheck(final ChessBoard cb) {
final int kingIndex = cb.kingIndex[cb.colorToMove];

// put 'super-piece' in kings position
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.friendlyPieces[cb.colorToMove])
| (cb.pieces[cb.colorToMoveInverse][BISHOP]|cb.pieces[cb.colorToMoveInverse][QUEEN]) & MagicUtil.getBishopMoves(kingIndex, cb.allPieces, cb.friendlyPieces[cb.colorToMove])
| cb.pieces[cb.colorToMoveInverse][PAWN] & StaticMoves.PAWN_ALL_ATTACKS[cb.colorToMove][kingIndex]
) != 0;
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]];
case NIGHT:
return cb.pieces[cb.colorToMoveInverse][NIGHT] & StaticMoves.KNIGHT_MOVES[cb.kingIndex[cb.colorToMove]];
case BISHOP:
return cb.pieces[cb.colorToMoveInverse][BISHOP] & MagicUtil.getBishopMoves(cb.kingIndex[cb.colorToMove], cb.allPieces);
case ROOK:
return cb.pieces[cb.colorToMoveInverse][ROOK] & MagicUtil.getRookMoves(cb.kingIndex[cb.colorToMove], cb.allPieces);
case QUEEN:
return cb.pieces[cb.colorToMoveInverse][QUEEN] & MagicUtil.getRookMoves(cb.kingIndex[cb.colorToMove], cb.allPieces) |
cb.pieces[cb.colorToMoveInverse][QUEEN] & MagicUtil.getBishopMoves(cb.kingIndex[cb.colorToMove], cb.allPieces);
default:
//king can never set the other king in check
return 0;
}
}

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

// put 'super-piece' in kings position
return (enemyPieces[NIGHT] & StaticMoves.KNIGHT_MOVES[kingIndex]
| (enemyPieces[ROOK] | enemyPieces[QUEEN]) & MagicUtil.getRookMoves(kingIndex, allPieces, friendlyPieces)
| (enemyPieces[BISHOP] | enemyPieces[QUEEN]) & MagicUtil.getBishopMoves(kingIndex, allPieces, friendlyPieces)
| (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 isInCheckIncludingKing(final int kingIndex, final int colorToMove, final long friendlyPieces, final long[] enemyPieces, final long allPieces) {
public static boolean isInCheckIncludingKing(final int kingIndex, final int colorToMove, final long[] enemyPieces, final long allPieces) {

// put 'super-piece' in kings position
return (enemyPieces[NIGHT] & StaticMoves.KNIGHT_MOVES[kingIndex]
| (enemyPieces[ROOK] | enemyPieces[QUEEN]) & MagicUtil.getRookMoves(kingIndex, allPieces, friendlyPieces)
| (enemyPieces[BISHOP] | enemyPieces[QUEEN]) & MagicUtil.getBishopMoves(kingIndex, allPieces, friendlyPieces)
| (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[KING] & StaticMoves.KING_MOVES[kingIndex]
)!= 0;
Expand Down
Loading

0 comments on commit f6147f5

Please sign in to comment.