refactor: (bb64)occupied -> ~(Bb64)PIECE_EMPTY
This commit is contained in:
@@ -197,10 +197,6 @@ static void board_print(struct pos const* pos, struct move* move, FILE* out, boo
|
|||||||
bg = (i+j) % 2 ? 45 : 43;
|
bg = (i+j) % 2 ? 45 : 43;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((pos->occupied[SIDE_WHITE] | pos->occupied[SIDE_BLACK]) & MASK_FROM_SQ(n)) {
|
|
||||||
bg += 60; /* make bright */
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(out, "\033[%d;%dm", fg, bg);
|
fprintf(out, "\033[%d;%dm", fg, bg);
|
||||||
|
|
||||||
if (buf[i][j]) {
|
if (buf[i][j]) {
|
||||||
|
|||||||
@@ -2,25 +2,24 @@ let exports;
|
|||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
const resp = await fetch("./chess.wasm");
|
const resp = await fetch("./chess.wasm");
|
||||||
if (!resp.ok) {
|
if (!resp.ok) throw new Error(`fetch wasm failed ${resp.status} ${resp.statusText}`);
|
||||||
throw new Error("fetch wasm failed ${resp.status} ${resp.statusText}");
|
|
||||||
}
|
|
||||||
|
|
||||||
const { instance } =
|
|
||||||
await WebAssembly.instantiateStreaming(resp, {});
|
|
||||||
|
|
||||||
|
const { instance } = await WebAssembly.instantiateStreaming(resp, {});
|
||||||
exports = instance.exports;
|
exports = instance.exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
await init();
|
await init();
|
||||||
self.postMessage({ type: "ready" });
|
self.postMessage({ type: "ready" });
|
||||||
|
|
||||||
self.onmessage = (e) => {
|
self.onmessage = (e) => {
|
||||||
const { id, method, args = [] } = e.data;
|
const { id, method, args = [] } = e.data;
|
||||||
try {
|
try {
|
||||||
const value = exports[method](...args);
|
let value;
|
||||||
|
value = exports[method](...args);
|
||||||
self.postMessage({ id, ok: true, value });
|
self.postMessage({ id, ok: true, value });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
self.postMessage({ id, ok: false, error: String(err?.message ?? err) });
|
self.postMessage({
|
||||||
|
id, ok: false, error: String(err?.message ?? err)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ static Bb64 diagonals(Bb64 p)
|
|||||||
* ==================
|
* ==================
|
||||||
*
|
*
|
||||||
* All piece attack functions rely on the caller masking their own pieces.
|
* All piece attack functions rely on the caller masking their own pieces.
|
||||||
* e.g. `knight_attacks(knights) & ~our_occupied`
|
* e.g. `knight_attacks(knights) & empty`
|
||||||
* */
|
* */
|
||||||
|
|
||||||
static Bb64 knight_attacks(Bb64 p)
|
static Bb64 knight_attacks(Bb64 p)
|
||||||
@@ -522,7 +522,7 @@ static Bb64 attacks_to(struct pos const* pos,
|
|||||||
Bb64 pretend_occupied,
|
Bb64 pretend_occupied,
|
||||||
Bb64 pretend_empty)
|
Bb64 pretend_empty)
|
||||||
{
|
{
|
||||||
Bb64 const occ_orig = pos->occupied[SIDE_WHITE] | pos->occupied[SIDE_BLACK];
|
Bb64 const occ_orig = ~(pos->pieces[SIDE_WHITE][PIECE_EMPTY] & pos->pieces[SIDE_BLACK][PIECE_EMPTY]);
|
||||||
Bb64 const occ = (occ_orig & ~pretend_empty) | pretend_occupied;
|
Bb64 const occ = (occ_orig & ~pretend_empty) | pretend_occupied;
|
||||||
|
|
||||||
Bb64 const* pw = pos->pieces[SIDE_WHITE];
|
Bb64 const* pw = pos->pieces[SIDE_WHITE];
|
||||||
@@ -563,15 +563,15 @@ static
|
|||||||
Bb64 checkers(struct pos const* pos, Side8 us)
|
Bb64 checkers(struct pos const* pos, Side8 us)
|
||||||
{
|
{
|
||||||
/* TODO: specialize */
|
/* TODO: specialize */
|
||||||
return attacks_to(pos, pos->pieces[us][PIECE_KING], 0ULL, 0ULL) & ~pos->occupied[us];
|
return attacks_to(pos, pos->pieces[us][PIECE_KING], 0ULL, 0ULL) & pos->pieces[us][PIECE_EMPTY];
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
Bb64 pinning_lines_to_target(struct pos const* pos, Side8 us, Sq8 tsq)
|
Bb64 pinning_lines_to_target(struct pos const* pos, Side8 us, Sq8 tsq)
|
||||||
{
|
{
|
||||||
Side8 const them = other_side(us);
|
Side8 const them = other_side(us);
|
||||||
Bb64 const our_occ = pos->occupied[us];
|
Bb64 const our_occ = ~pos->pieces[us][PIECE_EMPTY];
|
||||||
Bb64 const their_occ = pos->occupied[them];
|
Bb64 const their_occ = ~pos->pieces[them][PIECE_EMPTY];
|
||||||
|
|
||||||
Bb64 const* p = pos->pieces[them];
|
Bb64 const* p = pos->pieces[them];
|
||||||
Bb64 const bqs = p[PIECE_QUEEN] | p[PIECE_BISHOP];
|
Bb64 const bqs = p[PIECE_QUEEN] | p[PIECE_BISHOP];
|
||||||
@@ -595,7 +595,7 @@ Bb64 pinning_lines_to_target(struct pos const* pos, Side8 us, Sq8 tsq)
|
|||||||
static
|
static
|
||||||
Bb64 all_threats_from_side(struct pos const * pos, Side8 who)
|
Bb64 all_threats_from_side(struct pos const * pos, Side8 who)
|
||||||
{
|
{
|
||||||
Bb64 const occ = pos->occupied[SIDE_WHITE] | pos->occupied[SIDE_BLACK];
|
Bb64 const occ = ~(pos->pieces[SIDE_WHITE][PIECE_EMPTY] & pos->pieces[SIDE_BLACK][PIECE_EMPTY]);
|
||||||
|
|
||||||
Bb64 const* p = pos->pieces[who];
|
Bb64 const* p = pos->pieces[who];
|
||||||
Bb64 t = 0ULL;
|
Bb64 t = 0ULL;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ struct board {
|
|||||||
Side8 moving_side;
|
Side8 moving_side;
|
||||||
bool castling_illegal[SIDE_COUNT][CASTLE_COUNT];
|
bool castling_illegal[SIDE_COUNT][CASTLE_COUNT];
|
||||||
Bb64 ep_targets;
|
Bb64 ep_targets;
|
||||||
Bb64 occupied[SIDE_COUNT];
|
|
||||||
|
|
||||||
int halfmoves; /* FIXME: this duplicates the hist.length value */
|
int halfmoves; /* FIXME: this duplicates the hist.length value */
|
||||||
int fullmoves;
|
int fullmoves;
|
||||||
@@ -44,6 +43,7 @@ struct board {
|
|||||||
.fullmoves = 1, \
|
.fullmoves = 1, \
|
||||||
.pieces = { \
|
.pieces = { \
|
||||||
[SIDE_WHITE] = { \
|
[SIDE_WHITE] = { \
|
||||||
|
[PIECE_EMPTY] = RANK_MASK_3 | RANK_MASK_4 | RANK_MASK_5 | RANK_MASK_6 | RANK_MASK_7 | RANK_MASK_8, \
|
||||||
[PIECE_PAWN] = RANK_MASK_2, \
|
[PIECE_PAWN] = RANK_MASK_2, \
|
||||||
[PIECE_ROOK] = SQMASK_A1 | SQMASK_H1, \
|
[PIECE_ROOK] = SQMASK_A1 | SQMASK_H1, \
|
||||||
[PIECE_KNIGHT] = SQMASK_B1 | SQMASK_G1, \
|
[PIECE_KNIGHT] = SQMASK_B1 | SQMASK_G1, \
|
||||||
@@ -52,6 +52,7 @@ struct board {
|
|||||||
[PIECE_KING] = SQMASK_E1, \
|
[PIECE_KING] = SQMASK_E1, \
|
||||||
}, \
|
}, \
|
||||||
[SIDE_BLACK] = { \
|
[SIDE_BLACK] = { \
|
||||||
|
[PIECE_EMPTY] = RANK_MASK_1 | RANK_MASK_2 | RANK_MASK_3 | RANK_MASK_4 | RANK_MASK_5 | RANK_MASK_6, \
|
||||||
[PIECE_PAWN] = RANK_MASK_7, \
|
[PIECE_PAWN] = RANK_MASK_7, \
|
||||||
[PIECE_ROOK] = SQMASK_A8 | SQMASK_H8, \
|
[PIECE_ROOK] = SQMASK_A8 | SQMASK_H8, \
|
||||||
[PIECE_KNIGHT] = SQMASK_B8 | SQMASK_G8, \
|
[PIECE_KNIGHT] = SQMASK_B8 | SQMASK_G8, \
|
||||||
@@ -60,16 +61,6 @@ struct board {
|
|||||||
[PIECE_KING] = SQMASK_E8, \
|
[PIECE_KING] = SQMASK_E8, \
|
||||||
} \
|
} \
|
||||||
}, \
|
}, \
|
||||||
.occupied = { \
|
|
||||||
[SIDE_WHITE] = \
|
|
||||||
RANK_MASK_2 | SQMASK_A1 | SQMASK_H1 | \
|
|
||||||
SQMASK_B1 | SQMASK_G1 | SQMASK_C1 | \
|
|
||||||
SQMASK_F1 | SQMASK_D1 | SQMASK_E1, \
|
|
||||||
[SIDE_BLACK] = \
|
|
||||||
RANK_MASK_7 | SQMASK_A8 | SQMASK_H8 | \
|
|
||||||
SQMASK_B8 | SQMASK_G8| SQMASK_C8 | \
|
|
||||||
SQMASK_F8| SQMASK_D8| SQMASK_E8, \
|
|
||||||
}, \
|
|
||||||
.hash = ~0ULL, \
|
.hash = ~0ULL, \
|
||||||
}, \
|
}, \
|
||||||
.mailbox = { \
|
.mailbox = { \
|
||||||
@@ -156,13 +147,20 @@ static bool board_load_fen_unsafe(struct board* b, char const* fen_str)
|
|||||||
struct piece_side const p = piece_and_side_from_char[(uint8_t)ch];
|
struct piece_side const p = piece_and_side_from_char[(uint8_t)ch];
|
||||||
Bb64 const sq_mask = MASK_FROM_RF(ri, fi);
|
Bb64 const sq_mask = MASK_FROM_RF(ri, fi);
|
||||||
b->pos.pieces[p.side][p.piece] |= sq_mask;
|
b->pos.pieces[p.side][p.piece] |= sq_mask;
|
||||||
b->pos.occupied[p.side] |= sq_mask;
|
b->pos.pieces[p.side][PIECE_EMPTY] &= ~sq_mask;
|
||||||
b->mailbox[SQ_FROM_RF(ri, fi)] = p.piece;
|
b->mailbox[SQ_FROM_RF(ri, fi)] = p.piece;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(void)BUF_GETCHAR(fen); /* discard '/' or ' ' */
|
(void)BUF_GETCHAR(fen); /* discard '/' or ' ' */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b->pos.pieces[SIDE_WHITE][PIECE_EMPTY] = ~0ULL;
|
||||||
|
b->pos.pieces[SIDE_BLACK][PIECE_EMPTY] = ~0ULL;
|
||||||
|
for (Piece8 p = PIECE_BEGIN; p < PIECE_COUNT; ++p) {
|
||||||
|
b->pos.pieces[SIDE_WHITE][PIECE_EMPTY] &= ~b->pos.pieces[SIDE_WHITE][p];
|
||||||
|
b->pos.pieces[SIDE_BLACK][PIECE_EMPTY] &= ~b->pos.pieces[SIDE_BLACK][p];
|
||||||
|
}
|
||||||
|
|
||||||
{ /* active color */
|
{ /* active color */
|
||||||
char const ch = BUF_GETCHAR(fen);
|
char const ch = BUF_GETCHAR(fen);
|
||||||
if (ch == 'w') {
|
if (ch == 'w') {
|
||||||
@@ -238,13 +236,6 @@ enum move_result {
|
|||||||
MR_CHECKMATE,
|
MR_CHECKMATE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct move_undo {
|
|
||||||
Piece8 captured_piece;
|
|
||||||
Piece8 moved_piece;
|
|
||||||
Sq8 captured_square;
|
|
||||||
Sq8 moved_square;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* does not check validity */
|
/* does not check validity */
|
||||||
static enum move_result move_piece(struct pos* restrict pos,
|
static enum move_result move_piece(struct pos* restrict pos,
|
||||||
Side8 us,
|
Side8 us,
|
||||||
@@ -252,8 +243,6 @@ static enum move_result move_piece(struct pos* restrict pos,
|
|||||||
Piece8 mailbox[restrict static SQ_COUNT],
|
Piece8 mailbox[restrict static SQ_COUNT],
|
||||||
struct move move)
|
struct move move)
|
||||||
{
|
{
|
||||||
struct move_undo undo;
|
|
||||||
|
|
||||||
//Side8 const us = pos->moving_side;
|
//Side8 const us = pos->moving_side;
|
||||||
Side8 const them = other_side(us);
|
Side8 const them = other_side(us);
|
||||||
|
|
||||||
@@ -277,7 +266,7 @@ static enum move_result move_piece(struct pos* restrict pos,
|
|||||||
do { \
|
do { \
|
||||||
Bb64 const x = MASK_FROM_SQ(from) | MASK_FROM_SQ(to); \
|
Bb64 const x = MASK_FROM_SQ(from) | MASK_FROM_SQ(to); \
|
||||||
pos->pieces[side][piece] ^= x; \
|
pos->pieces[side][piece] ^= x; \
|
||||||
pos->occupied[side] ^= x; \
|
pos->pieces[side][PIECE_EMPTY] ^= x; \
|
||||||
pos->hash = tt_hash_update(pos->hash, from, side, piece); \
|
pos->hash = tt_hash_update(pos->hash, from, side, piece); \
|
||||||
pos->hash = tt_hash_update(pos->hash, to, side, piece); \
|
pos->hash = tt_hash_update(pos->hash, to, side, piece); \
|
||||||
mailbox[to] = piece; \
|
mailbox[to] = piece; \
|
||||||
@@ -288,7 +277,7 @@ static enum move_result move_piece(struct pos* restrict pos,
|
|||||||
do { \
|
do { \
|
||||||
Bb64 const x = MASK_FROM_SQ(at); \
|
Bb64 const x = MASK_FROM_SQ(at); \
|
||||||
pos->pieces[owner][piece] &= ~x; \
|
pos->pieces[owner][piece] &= ~x; \
|
||||||
pos->occupied[owner] &= ~x; \
|
pos->pieces[owner][PIECE_EMPTY] |= x; \
|
||||||
pos->hash = tt_hash_update(pos->hash, at, owner, piece); \
|
pos->hash = tt_hash_update(pos->hash, at, owner, piece); \
|
||||||
hist->length = 0; \
|
hist->length = 0; \
|
||||||
pos->halfmoves = 0; \
|
pos->halfmoves = 0; \
|
||||||
@@ -298,7 +287,7 @@ static enum move_result move_piece(struct pos* restrict pos,
|
|||||||
do { \
|
do { \
|
||||||
Bb64 const x = MASK_FROM_SQ(at); \
|
Bb64 const x = MASK_FROM_SQ(at); \
|
||||||
pos->pieces[owner][piece] |= x; \
|
pos->pieces[owner][piece] |= x; \
|
||||||
pos->occupied[owner] |= x; \
|
pos->pieces[owner][PIECE_EMPTY] &= ~x; \
|
||||||
pos->hash = tt_hash_update(pos->hash, at, owner, piece); \
|
pos->hash = tt_hash_update(pos->hash, at, owner, piece); \
|
||||||
mailbox[at] = piece; \
|
mailbox[at] = piece; \
|
||||||
pos->halfmoves = 0; \
|
pos->halfmoves = 0; \
|
||||||
@@ -325,7 +314,7 @@ static enum move_result move_piece(struct pos* restrict pos,
|
|||||||
else {
|
else {
|
||||||
POS_MOVE(us, from_piece, move.from, move.to);
|
POS_MOVE(us, from_piece, move.from, move.to);
|
||||||
/* capture */
|
/* capture */
|
||||||
if (to_mask & pos->occupied[them]) {
|
if (to_mask & ~pos->pieces[them][PIECE_EMPTY]) {
|
||||||
POS_REMOVE(them, to_piece, move.to);
|
POS_REMOVE(them, to_piece, move.to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,23 +22,7 @@ struct move move_make(struct pos const* restrict pos,
|
|||||||
(void)piece;
|
(void)piece;
|
||||||
(void)pos;
|
(void)pos;
|
||||||
(void)add_attr;
|
(void)add_attr;
|
||||||
#if 0
|
|
||||||
Side8 const us = pos->moving_side;
|
|
||||||
Side8 const them = other_side(us);
|
|
||||||
Bb64 const their_occ = pos->occupied[them];
|
|
||||||
Bb64 const tomask = MASK_FROM_SQ(to);
|
|
||||||
Bb64 const finishline = (us == SIDE_WHITE ? RANK_MASK_8 : RANK_MASK_1);
|
|
||||||
|
|
||||||
uint8_t attr = 0ULL;
|
|
||||||
#define MASK_IF8(x) ((~(uint8_t)0U) + (uint8_t)!(x))
|
|
||||||
attr |= MATTR_CAPTURE & MASK_IF8(tomask & their_occ);
|
|
||||||
attr |= MATTR_CAPTURE & MASK_IF8((piece == PIECE_PAWN) && tomask & pos->ep_targets);
|
|
||||||
attr |= MATTR_PROMOTE & MASK_IF8((piece == PIECE_PAWN) && (tomask & finishline));
|
|
||||||
attr |= add_attr;
|
|
||||||
#undef MASK_IF8
|
|
||||||
|
|
||||||
return (struct move){.from = from, .to = to, .attr = attr};
|
|
||||||
#endif
|
|
||||||
return (struct move){.from = from, .to = to, .attr = add_attr};
|
return (struct move){.from = from, .to = to, .attr = add_attr};
|
||||||
}
|
}
|
||||||
#define MOVE_MAX 128
|
#define MOVE_MAX 128
|
||||||
@@ -63,8 +47,8 @@ static void all_pseudolegal_from_piece(struct pos const* restrict pos,
|
|||||||
|
|
||||||
Side8 them = other_side(us);
|
Side8 them = other_side(us);
|
||||||
|
|
||||||
Bb64 const our_occ = pos->occupied[us];
|
Bb64 const our_occ = ~pos->pieces[us][PIECE_EMPTY];
|
||||||
Bb64 const all_occ = pos->occupied[SIDE_WHITE] | pos->occupied[SIDE_BLACK];
|
Bb64 const all_occ = ~(pos->pieces[SIDE_WHITE][PIECE_EMPTY] & pos->pieces[SIDE_BLACK][PIECE_EMPTY]);
|
||||||
|
|
||||||
if (type == MG_CHECKS) {
|
if (type == MG_CHECKS) {
|
||||||
allowed &= non_pawn_piece_attacks(piece, pos->pieces[them][PIECE_KING], all_occ);
|
allowed &= non_pawn_piece_attacks(piece, pos->pieces[them][PIECE_KING], all_occ);
|
||||||
@@ -93,7 +77,7 @@ static void all_pseudolegal_pawn_moves_##side(struct pos const* restrict pos,\
|
|||||||
size_t* restrict out_count,\
|
size_t* restrict out_count,\
|
||||||
struct move out[restrict static MOVE_MAX])\
|
struct move out[restrict static MOVE_MAX])\
|
||||||
{\
|
{\
|
||||||
Bb64 const all_occ = pos->occupied[SIDE_WHITE] | pos->occupied[SIDE_BLACK];\
|
Bb64 const all_occ = ~(pos->pieces[SIDE_WHITE][PIECE_EMPTY] & pos->pieces[SIDE_BLACK][PIECE_EMPTY]);\
|
||||||
\
|
\
|
||||||
if (type == MG_CHECKS) {\
|
if (type == MG_CHECKS) {\
|
||||||
allowed &= pawn_attacks_##opp_side(pos->pieces[other_side(side_enum)][PIECE_KING]);\
|
allowed &= pawn_attacks_##opp_side(pos->pieces[other_side(side_enum)][PIECE_KING]);\
|
||||||
@@ -127,7 +111,7 @@ static void all_pseudolegal_pawn_attacks_##side(struct pos const* restrict pos,\
|
|||||||
size_t* restrict out_count,\
|
size_t* restrict out_count,\
|
||||||
struct move out[restrict static MOVE_MAX])\
|
struct move out[restrict static MOVE_MAX])\
|
||||||
{\
|
{\
|
||||||
Bb64 const their_occ = pos->occupied[other_side(side_enum)];\
|
Bb64 const their_occ = ~pos->pieces[other_side(side_enum)][PIECE_EMPTY];\
|
||||||
\
|
\
|
||||||
if (type == MG_CHECKS) {\
|
if (type == MG_CHECKS) {\
|
||||||
allowed &= pawn_attacks_##opp_side(pos->pieces[other_side(side_enum)][PIECE_KING]);\
|
allowed &= pawn_attacks_##opp_side(pos->pieces[other_side(side_enum)][PIECE_KING]);\
|
||||||
@@ -177,7 +161,7 @@ static void all_pseudolegal_moves(struct pos const* restrict pos,
|
|||||||
|
|
||||||
Bb64 const their_threats = all_threats_from_side(pos, them);
|
Bb64 const their_threats = all_threats_from_side(pos, them);
|
||||||
|
|
||||||
Bb64 const their_occ = pos->occupied[them];
|
Bb64 const their_occ = ~pos->pieces[them][PIECE_EMPTY];
|
||||||
|
|
||||||
Bb64 allowed;
|
Bb64 allowed;
|
||||||
if (type == MG_CAPTURES) {
|
if (type == MG_CAPTURES) {
|
||||||
@@ -243,7 +227,7 @@ static void all_pseudolegal_moves(struct pos const* restrict pos,
|
|||||||
/* castling */
|
/* castling */
|
||||||
if (!chk && type != MG_CAPTURES) {
|
if (!chk && type != MG_CAPTURES) {
|
||||||
bool can_castle_kingside, can_castle_queenside;
|
bool can_castle_kingside, can_castle_queenside;
|
||||||
Bb64 const blocked = pos->occupied[SIDE_WHITE] | pos->occupied[SIDE_BLACK] | their_threats;
|
Bb64 const blocked = ~(pos->pieces[SIDE_WHITE][PIECE_EMPTY] & pos->pieces[SIDE_BLACK][PIECE_EMPTY]) | their_threats;
|
||||||
if (us == SIDE_WHITE) {
|
if (us == SIDE_WHITE) {
|
||||||
can_castle_kingside = !(blocked & (SQMASK_F1 | SQMASK_G1))
|
can_castle_kingside = !(blocked & (SQMASK_F1 | SQMASK_G1))
|
||||||
&& (pos->pieces[us][PIECE_ROOK] & SQMASK_H1)
|
&& (pos->pieces[us][PIECE_ROOK] & SQMASK_H1)
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ static char const* side_str[SIDE_COUNT] = {
|
|||||||
/* https://en.wikipedia.org/wiki/X_macro */
|
/* https://en.wikipedia.org/wiki/X_macro */
|
||||||
/* enum value white char white unicode black char black unicode */
|
/* enum value white char white unicode black char black unicode */
|
||||||
#define PIECES \
|
#define PIECES \
|
||||||
|
X(PIECE_EMPTY, 0.0f, ' ', ' ', ' ', ' ') \
|
||||||
X(PIECE_PAWN, 1.0f, 'P', 0x2659, 'p', 0x265F) \
|
X(PIECE_PAWN, 1.0f, 'P', 0x2659, 'p', 0x265F) \
|
||||||
X(PIECE_KNIGHT, 3.1f, 'N', 0x2658, 'n', 0x265E) \
|
X(PIECE_KNIGHT, 3.1f, 'N', 0x2658, 'n', 0x265E) \
|
||||||
X(PIECE_BISHOP, 3.2f, 'B', 0x2657, 'b', 0x265D) \
|
X(PIECE_BISHOP, 3.2f, 'B', 0x2657, 'b', 0x265D) \
|
||||||
@@ -207,8 +208,8 @@ typedef enum piece : uint8_t {
|
|||||||
#define X(e, v, wc, wu, bc, bu) e,
|
#define X(e, v, wc, wu, bc, bu) e,
|
||||||
PIECES
|
PIECES
|
||||||
PIECE_COUNT,
|
PIECE_COUNT,
|
||||||
PIECE_BEGIN = 0,
|
PIECE_BEGIN = PIECE_PAWN,
|
||||||
PIECE_POISONED, /* used as default undefined value in debug builds */
|
PIECE_POISONED, /* used as undefined value in debug builds */
|
||||||
#undef X
|
#undef X
|
||||||
} Piece8;
|
} Piece8;
|
||||||
|
|
||||||
@@ -273,6 +274,25 @@ struct move {
|
|||||||
#define APPEAL_MAX UINT8_MAX
|
#define APPEAL_MAX UINT8_MAX
|
||||||
uint8_t appeal;
|
uint8_t appeal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move32 layout:
|
||||||
|
* f (from piece): 3 bits
|
||||||
|
* F (from square): 6 bits
|
||||||
|
* t (to piece): 3 bits
|
||||||
|
* T (to square): 6 bits
|
||||||
|
* p (promotion): ? bits (likely 3)
|
||||||
|
* [x,x,x,x,x,x,x,x,x,x,x,p,p,p,T,T,T,T,T,T,t,t,t,F,F,F,F,F,F,f,f,f]
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef uint32_t Move32;
|
||||||
|
|
||||||
|
#define MOVE_FROM_PIECE(m) (m & 0b000000000000000000111)
|
||||||
|
#define MOVE_FROM_SQUARE(m) (m & 0b000000000000111111000)
|
||||||
|
#define MOVE_TO_PIECE(m) (m & 0b000000000111000000000)
|
||||||
|
#define MOVE_TO_SQUARE(m) (m & 0b000111111000000000000)
|
||||||
|
#define MOVE_PROMOTION(m) (m & 0b111000000000000000000)
|
||||||
|
|
||||||
_Static_assert(sizeof(struct move) == 4,
|
_Static_assert(sizeof(struct move) == 4,
|
||||||
"this static assuming is here to check when sizeof(move) changes");
|
"this static assuming is here to check when sizeof(move) changes");
|
||||||
|
|
||||||
|
|||||||
23
engine.h
23
engine.h
@@ -36,14 +36,17 @@ static void move_compute_appeal(struct move* restrict m,
|
|||||||
Side8 them = other_side(us);
|
Side8 them = other_side(us);
|
||||||
Piece8 const atk = mailbox[m->from];
|
Piece8 const atk = mailbox[m->from];
|
||||||
|
|
||||||
uint8_t n = 1;
|
uint8_t n = 0;
|
||||||
if (MASK_FROM_SQ(m->to) & pos->occupied[them]) {
|
if ((MASK_FROM_SQ(m->to) & pos->pieces[them][PIECE_EMPTY]) == 0) {
|
||||||
n += (uint8_t)piece_value[mailbox[m->to]];
|
n += (uint8_t)piece_value[mailbox[m->to]];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t mmv_lva_bonus = (uint8_t)(16.0f*(float)n - piece_value[atk]);
|
/* TODO: remove branch */
|
||||||
|
if (n) {
|
||||||
m->appeal = mmv_lva_bonus;
|
m->appeal = (uint8_t)(16.0f*(float)n - piece_value[atk]);
|
||||||
|
} else {
|
||||||
|
m->appeal = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static float board_score_heuristic(struct pos const* pos)
|
static float board_score_heuristic(struct pos const* pos)
|
||||||
@@ -52,9 +55,8 @@ static float board_score_heuristic(struct pos const* pos)
|
|||||||
eventually flipping the sign based on `pos` */
|
eventually flipping the sign based on `pos` */
|
||||||
float score = 0.0f;
|
float score = 0.0f;
|
||||||
|
|
||||||
Bb64 const occw = pos->occupied[SIDE_WHITE];
|
Bb64 const occw = ~pos->pieces[SIDE_WHITE][PIECE_EMPTY];
|
||||||
Bb64 const occb = pos->occupied[SIDE_BLACK];
|
Bb64 const occb = ~pos->pieces[SIDE_BLACK][PIECE_EMPTY];
|
||||||
Bb64 const occall = occw | occb;
|
|
||||||
|
|
||||||
enum game_progress const gp = endgameness(pos);
|
enum game_progress const gp = endgameness(pos);
|
||||||
|
|
||||||
@@ -172,8 +174,9 @@ float quiesce(struct pos const* pos,
|
|||||||
|
|
||||||
all_pseudolegal_moves(pos, MG_CAPTURES, us, &move_count, moves);
|
all_pseudolegal_moves(pos, MG_CAPTURES, us, &move_count, moves);
|
||||||
if (move_count == 0) {
|
if (move_count == 0) {
|
||||||
return -(SCORE_CHECKMATE + (float)depth);
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < move_count; ++i) {
|
for (size_t i = 0; i < move_count; ++i) {
|
||||||
move_compute_appeal(&moves[i], pos, us, mailbox);
|
move_compute_appeal(&moves[i], pos, us, mailbox);
|
||||||
}
|
}
|
||||||
@@ -181,7 +184,7 @@ float quiesce(struct pos const* pos,
|
|||||||
while (move_count) {
|
while (move_count) {
|
||||||
struct move m = moves_linear_search(moves, &move_count);
|
struct move m = moves_linear_search(moves, &move_count);
|
||||||
|
|
||||||
assuming((pos->occupied[them] | pos->ep_targets) & MASK_FROM_SQ(m.to));
|
assuming((~pos->pieces[them][PIECE_EMPTY] | pos->ep_targets) & MASK_FROM_SQ(m.to));
|
||||||
|
|
||||||
struct pos poscpy = *pos;
|
struct pos poscpy = *pos;
|
||||||
|
|
||||||
|
|||||||
3
tests.c
3
tests.c
@@ -440,9 +440,6 @@ int main()
|
|||||||
//board_print_fen(b->pos, stdout);
|
//board_print_fen(b->pos, stdout);
|
||||||
board_print(&b->pos, NULL, stdout, print_threats);
|
board_print(&b->pos, NULL, stdout, print_threats);
|
||||||
|
|
||||||
struct move moves[MOVE_MAX];
|
|
||||||
size_t move_count;
|
|
||||||
|
|
||||||
for (int turn = 0; turn < 200; ++turn) {
|
for (int turn = 0; turn < 200; ++turn) {
|
||||||
/*
|
/*
|
||||||
move_count = 0;
|
move_count = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user