Skip to content

Commit

Permalink
Merge branch 'main' into avx512
Browse files Browse the repository at this point in the history
Bench: 3680773
  • Loading branch information
jhonnold committed Oct 6, 2023
2 parents eb27cf8 + c0646c5 commit b515281
Show file tree
Hide file tree
Showing 21 changed files with 191 additions and 328 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Below is a list of many chess engine lists throughout the web (*variance in Elo

- [TCEC](https://tcec-chess.com/)
- [CCC](https://www.chess.com/computer-chess-championship)
- [Graham's Broadcasts](https://tlcv.net)
- [Graham's Broadcasts](https://ccrl.live/)

## Funcational Details

Expand Down Expand Up @@ -58,8 +58,6 @@ Below is a list of many chess engine lists throughout the web (*variance in Elo
- [Extensions](https://www.chessprogramming.org/Extensions)
- [Singular](https://www.chessprogramming.org/Singular_Extensions)
- [Check](https://www.chessprogramming.org/Check_Extensions)
- [Recapture](https://www.chessprogramming.org/Recapture_Extensions)
- History

### Evaluation

Expand Down
Binary file removed src/bitbases/KBPvK.bb
Binary file not shown.
Binary file removed src/bitbases/KPvK.bb
Binary file not shown.
14 changes: 7 additions & 7 deletions src/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,15 +407,15 @@ void MakeMoveUpdate(Move move, Board* board, int update) {
}

if (PieceType(piece) == PAWN) {
if (IsDP(move)) {
if ((from ^ to) == 16) {
int epSquare = to - PawnDir(board->stm);

if (GetPawnAttacks(epSquare, board->stm) & PieceBB(PAWN, board->xstm)) {
board->epSquare = epSquare;
board->zobrist ^= ZOBRIST_EP_KEYS[board->epSquare];
}
} else if (Promo(move)) {
int promoted = Promo(move);
} else if (IsPromo(move)) {
int promoted = PromoPiece(move, board->stm);
FlipBit(board->pieces[piece], to);
FlipBit(board->pieces[promoted], to);

Expand Down Expand Up @@ -471,8 +471,8 @@ void UndoMove(Move move, Board* board) {
board->threatened = board->history[board->histPly].threatened;
board->easyCapture = board->history[board->histPly].easyCapture;

if (Promo(move)) {
int promoted = Promo(move);
if (IsPromo(move)) {
int promoted = PromoPiece(move, board->stm);
FlipBit(board->pieces[piece], to);
FlipBit(board->pieces[promoted], to);
board->squares[to] = piece;
Expand Down Expand Up @@ -647,7 +647,7 @@ int IsPseudoLegal(Move move, Board* board) {
return 1;
}

if (Promo(move)) {
if (IsPromo(move)) {
if (BitCount(board->checkers) > 1)
return 0;

Expand Down Expand Up @@ -746,7 +746,7 @@ void InitCuckoo() {
if (!GetBit(GetPieceAttacks(s1, 0, pcType), s2))
continue;

Move move = BuildMove(s1, s2, pc, NO_PROMO, QUIET);
Move move = BuildMove(s1, s2, pc, QUIET_FLAG);
uint64_t hash = ZOBRIST_PIECES[pc][s1] ^ ZOBRIST_PIECES[pc][s2] ^ ZOBRIST_SIDE_KEY;

uint32_t i = Hash1(hash);
Expand Down
194 changes: 1 addition & 193 deletions src/endgame.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,165 +16,10 @@

#include "endgame.h"

#include <stdlib.h>

#include "bits.h"
#include "board.h"
#include "search.h"
#include "see.h"
#include "types.h"
#include "util.h"

#define INCBIN_PREFIX
#define INCBIN_STYLE INCBIN_STYLE_CAMEL
#include "incbin.h"

INCBIN(KPK, "bitbases/KPvK.bb");
INCBIN(KBPK, "bitbases/KBPvK.bb");

INLINE int PushTogether(int sq1, int sq2) {
return 70 - Distance(sq1, sq2);
}

INLINE int PushToEdge(int sq) {
int rankDistance = Min(Rank(sq), 7 - Rank(sq));
int fileDistance = Min(File(sq), 7 - File(sq));

return 20 - (rankDistance * rankDistance) - (fileDistance * fileDistance);
}

INLINE int MaterialValue(Board* board, const int side) {
int staticScore = 0;
for (int piece = PAWN; piece <= QUEEN; piece++)
staticScore += BitCount(PieceBB(piece, side)) * SEE_VALUE[piece];

return staticScore;
}

// The following KPK code is modified for my use from Cheng (as is the dataset)
INLINE uint32_t KPKIndex(int winningKing, int losingKing, int pawn, int stm) {
int file = File(pawn);
int x = file > 3 ? 7 : 0;

winningKing ^= x;
losingKing ^= x;
pawn ^= x;
file ^= x;

uint32_t p = (((pawn & 0x38) - 8) >> 1) | file;

return (uint32_t) winningKing | ((uint32_t) losingKing << 6) | ((uint32_t) stm << 12) | ((uint32_t) p << 13);
}

INLINE uint8_t KPKDraw(int winningSide, int winningKing, int losingKing, int pawn, int stm) {
uint32_t x = (winningSide == WHITE) ? 0 : 56;
uint32_t idx = KPKIndex(winningKing ^ x, losingKing ^ x, pawn ^ x, winningSide ^ stm);

return (uint8_t) (KPKData[idx >> 3] & (1U << (idx & 7)));
}

INLINE int EvaluateKPK(Board* board, const int winningSide) {
const int losingSide = winningSide ^ 1;
int score = WINNING_ENDGAME + MaterialValue(board, winningSide);

int winningKing = LSB(PieceBB(KING, winningSide));
int losingKing = LSB(PieceBB(KING, losingSide));
int pawn = winningSide == WHITE ? LSB(PieceBB(PAWN, WHITE)) : MSB(PieceBB(PAWN, BLACK));

if (KPKDraw(winningSide, winningKing, losingKing, pawn, board->stm))
return 0;

score += winningSide == WHITE ? (7 - Rank(pawn)) : Rank(pawn);

return winningSide == board->stm ? score : -score;
}

INLINE int EvaluateKXK(Board* board, const int winningSide) {
const int losingSide = winningSide ^ 1;
int score = WINNING_ENDGAME + MaterialValue(board, winningSide);

int winningKing = LSB(PieceBB(KING, winningSide));
int losingKing = LSB(PieceBB(KING, losingSide));

score += PushTogether(winningKing, losingKing) + PushToEdge(losingKing);

score = winningSide == board->stm ? score : -score;
return Min(TB_WIN_BOUND - 1, Max(-TB_WIN_BOUND + 1, score));
}

INLINE int EvaluateKBNK(Board* board, const int winningSide) {
const int losingSide = winningSide ^ 1;
int score = WINNING_ENDGAME + MaterialValue(board, winningSide);

int winningKing = LSB(PieceBB(KING, winningSide));
int losingKing = LSB(PieceBB(KING, losingSide));

score += PushTogether(winningKing, losingKing);

if (DARK_SQS & PieceBB(BISHOP, winningSide)) {
score += 50 * (7 - Min(MDistance(losingKing, A1), MDistance(losingKing, H8)));
} else {
score += 50 * (7 - Min(MDistance(losingKing, A8), MDistance(losingKing, H1)));
}

score = winningSide == board->stm ? score : -score;
return Min(TB_WIN_BOUND - 1, Max(-TB_WIN_BOUND + 1, score));
}

INLINE uint32_t KBPKIndex(int wking, int lking, int bishop, int pawn, int stm) {
int file = File(pawn);
int x = file > 3 ? 7 : 0;

wking ^= x, lking ^= x, bishop ^= x, pawn ^= x;

uint32_t p = (pawn >> 3) - 1;
uint32_t b = bishop >> 1;

return (uint32_t) wking | ((uint32_t) lking << 6) | (b << 12) | ((uint32_t) stm << 17) | (p << 18);
}

INLINE uint8_t KBPKDraw(int winningSide, int winningKing, int losingKing, int bishop, int pawn, int stm) {
int x = winningSide == WHITE ? 0 : 56;
uint32_t idx = KBPKIndex(winningKing ^ x, losingKing ^ x, bishop ^ x, pawn ^ x, winningSide ^ stm);

return !(uint8_t) (KBPKData[idx >> 3] & (1U << (idx & 7)));
}

INLINE int EvaluateKBPK(Board* board, const int winningSide) {
const int losingSide = winningSide ^ 1;

int pawn = winningSide == WHITE ? LSB(PieceBB(PAWN, WHITE)) : MSB(PieceBB(PAWN, BLACK));
int promotionSq = winningSide == WHITE ? File(pawn) : A1 + File(pawn);
int darkPromoSq = !!GetBit(DARK_SQS, promotionSq);
int darkBishop = !!(DARK_SQS & PieceBB(BISHOP, winningSide));

uint8_t files = PawnFiles(PieceBB(PAWN, winningSide));

// "Winning" if not a rook pawn or have right bishop
if ((files != 0x01 && files != 0x80) || darkPromoSq == darkBishop) {
int score = WINNING_ENDGAME + MaterialValue(board, winningSide);

score += winningSide == WHITE ? (7 - Rank(pawn)) : Rank(pawn);
score = winningSide == board->stm ? score : -score;

return Min(TB_WIN_BOUND - 1, Max(-TB_WIN_BOUND + 1, score));
}

// Utilize bitbase for everything else
int winningKing = LSB(PieceBB(KING, winningSide));
int losingKing = LSB(PieceBB(KING, losingSide));
int bishop = LSB(PieceBB(BISHOP, winningSide));

if (KBPKDraw(winningSide, winningKing, losingKing, bishop, pawn, board->stm))
return 0;

int score = WINNING_ENDGAME + MaterialValue(board, winningSide);

score += winningSide == WHITE ? (7 - Rank(pawn)) : Rank(pawn);
score = winningSide == board->stm ? score : -score;

return Min(TB_WIN_BOUND - 1, Max(-TB_WIN_BOUND + 1, score));
}

int EvaluateKnownPositions(Board* board) {
switch (board->piecesCounts) {
// See IsMaterialDraw
Expand All @@ -190,43 +35,6 @@ int EvaluateKnownPositions(Board* board) {
case 0x100100: // KNkb
case 0x110000: // KBkb
return 0;
case 0x1: // KPk
return EvaluateKPK(board, WHITE);
case 0x10: // Kkp
return EvaluateKPK(board, BLACK);
case 0x10100: // KBNk
return EvaluateKBNK(board, WHITE);
case 0x101000: // Kkbn
return EvaluateKBNK(board, BLACK);
default: break;
}

if (BitCount(OccBB(BLACK)) == 1) {
// KBPK
if ((board->piecesCounts ^ 0x10000) <= 0xF)
return EvaluateKBPK(board, WHITE);

// stacked rook pawns
if (board->piecesCounts <= 0xF) {
uint8_t files = PawnFiles(PieceBB(PAWN, WHITE));
if (files == 0x1 || files == 0x80)
return EvaluateKPK(board, WHITE);
}

return EvaluateKXK(board, WHITE);
} else if (BitCount(OccBB(WHITE)) == 1) {
// Kkbp
if ((board->piecesCounts ^ 0x100000) <= 0xF0)
return EvaluateKBPK(board, BLACK);

// stacked rook pawns
if (board->piecesCounts <= 0xF0) {
uint8_t files = PawnFiles(PieceBB(PAWN, BLACK));
if (files == 0x1 || files == 0x80)
return EvaluateKPK(board, BLACK);
}

return EvaluateKXK(board, BLACK);
}

return UNKNOWN;
Expand Down
2 changes: 0 additions & 2 deletions src/endgame.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
#include "types.h"
#include "util.h"

#define WINNING_ENDGAME 25000

int EvaluateKnownPositions(Board* board);

#endif
2 changes: 1 addition & 1 deletion src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Score Evaluate(Board* board, ThreadData* thread) {
// scaled based on phase [1, 1.5]
score = (128 + board->phase) * score / 128;

return Min(TB_WIN_BOUND - 1, Max(-TB_WIN_BOUND + 1, score));
return Min(2047, Max(-2048, score));
}

void EvaluateTrace(Board* board) {
Expand Down
2 changes: 1 addition & 1 deletion src/history.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void UpdateHistories(SearchStack* ss,
AddHistoryHeuristic(&HH(stm, bestMove, board->threatened), inc);
UpdateCH(ss, bestMove, inc);

if (Promo(bestMove) < WHITE_QUEEN) {
if (PromoPT(bestMove) != QUEEN) {
AddKillerMove(ss, bestMove);

if ((ss - 1)->move)
Expand Down
4 changes: 2 additions & 2 deletions src/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
EXE = berserk
SRC = *.c nn/*.c pyrrhic/tbprobe.c
CC = gcc
VERSION = 20230913b
MAIN_NETWORK = networks/berserk-a1f765e06a78.nn
VERSION = 20231006
MAIN_NETWORK = networks/berserk-d1b801c65262.nn
EVALFILE = $(MAIN_NETWORK)
DEFS = -DVERSION=\"$(VERSION)\" -DEVALFILE=\"$(EVALFILE)\" -DNDEBUG

Expand Down
12 changes: 3 additions & 9 deletions src/move.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

const char* PIECE_TO_CHAR = "PpNnBbRrQqKk";

const char* PROMOTION_TO_CHAR = "--nnbbrrqq--";
const char* PROMOTION_TO_CHAR = "-nbrq-";

const int CHAR_TO_PIECE[] = {
['P'] = WHITE_PAWN, //
Expand Down Expand Up @@ -95,17 +95,11 @@ char* MoveToStr(Move move, Board* board) {
if (CHESS_960 && IsCas(move))
to = board->cr[CASTLING_ROOK[to]];

if (Promo(move)) {
sprintf(buffer, "%s%s%c", SQ_TO_COORD[from], SQ_TO_COORD[to], PROMOTION_TO_CHAR[Promo(move)]);
if (IsPromo(move)) {
sprintf(buffer, "%s%s%c", SQ_TO_COORD[from], SQ_TO_COORD[to], PROMOTION_TO_CHAR[PromoPT(move)]);
} else {
sprintf(buffer, "%s%s", SQ_TO_COORD[from], SQ_TO_COORD[to]);
}

return buffer;
}

inline int IsRecapture(SearchStack* ss, Move move) {
return IsCap(move) && //
((IsCap((ss - 1)->move) && To((ss - 1)->move) == To(move)) || //
(IsCap((ss - 3)->move) && To((ss - 3)->move) == To(move)));
}
37 changes: 24 additions & 13 deletions src/move.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,39 @@

#define NULL_MOVE 0

#define QUIET_FLAG 0b0000
#define CASTLE_FLAG 0b0001
#define CAPTURE_FLAG 0b0100
#define EP_FLAG 0b0110
#define PROMO_FLAG 0b1000
#define KNIGHT_PROMO_FLAG 0b1000
#define BISHOP_PROMO_FLAG 0b1001
#define ROOK_PROMO_FLAG 0b1010
#define QUEEN_PROMO_FLAG 0b1011

extern const int CHAR_TO_PIECE[];
extern const char* PIECE_TO_CHAR;
extern const char* PROMOTION_TO_CHAR;
extern const char* SQ_TO_COORD[64];
extern const int CASTLE_ROOK_DEST[64];
extern const int CASTLING_ROOK[64];

#define BuildMove(from, to, piece, promo, flags) \
(from) | ((to) << 6) | ((piece) << 12) | ((promo) << 16) | ((flags) << 20)
#define From(move) ((int) (move) &0x3f)
#define To(move) (((int) (move) &0xfc0) >> 6)
#define Moving(move) (((int) (move) &0xf000) >> 12)
#define Promo(move) (((int) (move) &0xf0000) >> 16)
#define IsCap(move) (((int) (move) &0x100000) >> 20)
#define IsDP(move) (((int) (move) &0x200000) >> 21)
#define IsEP(move) (((int) (move) &0x400000) >> 22)
#define IsCas(move) (((int) (move) &0x800000) >> 23)
// just mask the from/to bits into a single int for indexing butterfly tables
#define FromTo(move) ((int) (move) &0xfff)
#define BuildMove(from, to, piece, flags) (from) | ((to) << 6) | ((piece) << 12) | ((flags) << 16)
#define FromTo(move) (((int) (move) &0x00fff) >> 0)
#define From(move) (((int) (move) &0x0003f) >> 0)
#define To(move) (((int) (move) &0x00fc0) >> 6)
#define Moving(move) (((int) (move) &0x0f000) >> 12)
#define Flags(move) (((int) (move) &0xf0000) >> 16)

#define IsCap(move) (!!(Flags(move) & CAPTURE_FLAG))
#define IsEP(move) (Flags(move) == EP_FLAG)
#define IsCas(move) (Flags(move) == CASTLE_FLAG)

#define IsPromo(move) (!!(Flags(move) & PROMO_FLAG))
#define PromoPT(move) ((Flags(move) & 0x3) + KNIGHT)
#define PromoPiece(move, stm) (Piece(PromoPT(move), stm))

Move ParseMove(char* moveStr, Board* board);
char* MoveToStr(Move move, Board* board);
int IsRecapture(SearchStack* ss, Move move);

#endif
Loading

0 comments on commit b515281

Please sign in to comment.