summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/engine/bitboard.c20
-rw-r--r--src/engine/bitboard.h26
-rw-r--r--src/engine/moves.c100
-rw-r--r--src/engine/moves.h35
-rw-r--r--src/engine/moves/bishop.c22
-rw-r--r--src/engine/moves/king.c10
-rw-r--r--src/engine/moves/knight.c11
-rw-r--r--src/engine/moves/pawn.c50
-rw-r--r--src/engine/moves/rook.c21
-rw-r--r--src/engine/moves/vec.c17
10 files changed, 234 insertions, 78 deletions
diff --git a/src/engine/bitboard.c b/src/engine/bitboard.c
index 80cdb78..565f425 100644
--- a/src/engine/bitboard.c
+++ b/src/engine/bitboard.c
@@ -47,26 +47,6 @@ bool check_valid_position(position_t position) {
return true;
}
-bitboard_t whites(position_t position) {
- return
- position.bitboards[WHITE_KING] |
- position.bitboards[WHITE_QUEEN] |
- position.bitboards[WHITE_ROOK] |
- position.bitboards[WHITE_BISHOP] |
- position.bitboards[WHITE_KNIGHT] |
- position.bitboards[WHITE_PAWN];
-}
-
-bitboard_t blacks(position_t position) {
- return
- position.bitboards[BLACK_KING] |
- position.bitboards[BLACK_QUEEN] |
- position.bitboards[BLACK_ROOK] |
- position.bitboards[BLACK_BISHOP] |
- position.bitboards[BLACK_KNIGHT] |
- position.bitboards[BLACK_PAWN];
-}
-
void print_bitboard(bitboard_t bitboard) {
printf("Bitboard(%" PRIu64 ")\n", bitboard);
for (int i = 7; i >= 0; i--) {
diff --git a/src/engine/bitboard.h b/src/engine/bitboard.h
index 8515f5d..ecd8c35 100644
--- a/src/engine/bitboard.h
+++ b/src/engine/bitboard.h
@@ -23,10 +23,10 @@ enum {
};
enum {
- WHITE_SHORT_CASTLE = 1 << 0,
- WHITE_LONG_CASTLE = 1 << 1,
- BLACK_SHORT_CASTLE = 1 << 2,
- BLACK_LONG_CASTLE = 1 << 3,
+ WHITE_SHORT_CASTLE = 1 << 0,
+ WHITE_LONG_CASTLE = 1 << 1,
+ BLACK_SHORT_CASTLE = 1 << 2,
+ BLACK_LONG_CASTLE = 1 << 3,
};
enum {
@@ -65,8 +65,22 @@ typedef struct {
position_t position_starting();
void assert_valid_position(position_t position);
bool check_valid_position(position_t position);
-bitboard_t whites(position_t position);
-bitboard_t blacks(position_t position);
+#define whites(position) \
+ position.bitboards[WHITE_KING] | \
+ position.bitboards[WHITE_QUEEN] | \
+ position.bitboards[WHITE_ROOK] | \
+ position.bitboards[WHITE_BISHOP] | \
+ position.bitboards[WHITE_KNIGHT] | \
+ position.bitboards[WHITE_PAWN]
+
+#define blacks(position) \
+ position.bitboards[BLACK_KING] | \
+ position.bitboards[BLACK_QUEEN] | \
+ position.bitboards[BLACK_ROOK] | \
+ position.bitboards[BLACK_BISHOP] | \
+ position.bitboards[BLACK_KNIGHT] | \
+ position.bitboards[BLACK_PAWN]
+
void print_bitboard(bitboard_t bitboard);
diff --git a/src/engine/moves.c b/src/engine/moves.c
index ac9fbba..d338cc2 100644
--- a/src/engine/moves.c
+++ b/src/engine/moves.c
@@ -1,3 +1,5 @@
+#include "moves.h"
+#include "bitboard.h"
#include "moves/vec.c"
#include "moves/king.c"
#include "moves/knight.c"
@@ -5,6 +7,7 @@
#include "moves/rook.c"
#include "moves/bishop.c"
#include "moves/queen.c"
+#include <assert.h>
void get_moves(moves_t* moves, position_t position) {
get_pawn_moves(moves, position);
@@ -14,3 +17,100 @@ void get_moves(moves_t* moves, position_t position) {
get_bishop_moves(moves, position);
get_queen_moves(moves, position);
}
+
+int find_piece_on_square(position_t* p, int square) {
+ if ((p->bitboards[WHITE_KING] >> square) & 1) return WHITE_KING;
+ if ((p->bitboards[WHITE_QUEEN] >> square) & 1) return WHITE_QUEEN;
+ if ((p->bitboards[WHITE_ROOK] >> square) & 1) return WHITE_ROOK;
+ if ((p->bitboards[WHITE_BISHOP] >> square) & 1) return WHITE_BISHOP;
+ if ((p->bitboards[WHITE_KNIGHT] >> square) & 1) return WHITE_KNIGHT;
+ if ((p->bitboards[WHITE_PAWN] >> square) & 1) return WHITE_PAWN;
+ if ((p->bitboards[BLACK_KING] >> square) & 1) return BLACK_KING;
+ if ((p->bitboards[BLACK_QUEEN] >> square) & 1) return BLACK_QUEEN;
+ if ((p->bitboards[BLACK_ROOK] >> square) & 1) return BLACK_ROOK;
+ if ((p->bitboards[BLACK_BISHOP] >> square) & 1) return BLACK_BISHOP;
+ if ((p->bitboards[BLACK_KNIGHT] >> square) & 1) return BLACK_KNIGHT;
+ if ((p->bitboards[BLACK_PAWN] >> square) & 1) return BLACK_PAWN;
+ assert(0);
+}
+
+void position_make_move(position_t* position, move_t* move) {
+ if (move->flags & MOVE_LONG_CASTLE) {
+ if (position->turn == WHITE_TURN) {
+ assert(position->bitboards[WHITE_KING] == 16);
+ assert((position->bitboards[WHITE_ROOK] >> 0) & 1);
+
+ position->bitboards[WHITE_KING] = 2;
+ position->bitboards[WHITE_ROOK] += 3;
+ } else if (position->turn == BLACK_TURN) {
+ assert(position->bitboards[BLACK_KING] == 1152921504606846976ULL);
+ assert((position->bitboards[BLACK_ROOK] >> 56) & 1);
+
+ position->bitboards[BLACK_KING] = 144115188075855872ULL;
+ position->bitboards[WHITE_ROOK] &= ~((bitboard_t)1 << 56);
+ position->bitboards[WHITE_ROOK] |= (bitboard_t)1 << 58;
+ }
+ return;
+ }
+ if (move->flags & MOVE_SHORT_CASTLE) {
+ if (position->turn == WHITE_TURN) {
+ assert(position->bitboards[WHITE_KING] == 16);
+ assert((position->bitboards[WHITE_ROOK] >> 7) & 1);
+
+ position->bitboards[WHITE_KING] = 64;
+ position->bitboards[WHITE_ROOK] &= ~((bitboard_t)1 << 7);
+ position->bitboards[WHITE_ROOK] |= (bitboard_t)1 << 5;
+ } else if (position->turn == BLACK_TURN) {
+ assert(position->bitboards[BLACK_KING] == 1152921504606846976ULL);
+ assert((position->bitboards[BLACK_ROOK] >> 63) & 1);
+
+ position->bitboards[WHITE_KING] = 4611686018427387904ULL;
+ position->bitboards[WHITE_ROOK] &= ~((bitboard_t)1 << 63);
+ position->bitboards[WHITE_ROOK] |= (bitboard_t)1 << 61;
+ }
+ return;
+ }
+
+ int piece_type = find_piece_on_square(position, move->from);
+ position->bitboards[piece_type] &= ~(1 << move->from);
+ if (move->flags & MOVE_PROMOTE_Q) {
+ int q_type = position->turn == WHITE_TURN ? WHITE_QUEEN : BLACK_QUEEN;
+ position->bitboards[q_type] |= 1 << move->to;
+ return;
+ }
+ if (move->flags & MOVE_PROMOTE_R) {
+ int q_type = position->turn == WHITE_TURN ? WHITE_ROOK : BLACK_ROOK;
+ position->bitboards[q_type] |= 1 << move->to;
+ return;
+ }
+ if (move->flags & MOVE_PROMOTE_B) {
+ int q_type = position->turn == WHITE_TURN ? WHITE_BISHOP : BLACK_BISHOP;
+ position->bitboards[q_type] |= 1 << move->to;
+ return;
+ }
+ if (move->flags & MOVE_PROMOTE_N) {
+ int q_type = position->turn == WHITE_TURN ? WHITE_KNIGHT : BLACK_KNIGHT;
+ position->bitboards[q_type] |= 1 << move->to;
+ return;
+ }
+ if (move->flags & MOVE_EN_PASSANT) {
+ int target_sqr;
+ if (position->turn == WHITE_TURN) target_sqr = move->to - 8;
+ else target_sqr = move->to + 8;
+
+ int to_remove_piece_type = find_piece_on_square(position, target_sqr);
+ position->bitboards[piece_type] |= 1 << move->to;
+ position->bitboards[to_remove_piece_type] &= ~(1 << target_sqr);
+ return;
+ }
+
+ if (move->flags & MOVE_CAPTURE) {
+ int to_remove_piece_type = find_piece_on_square(position, move->to);
+ position->bitboards[to_remove_piece_type] &= ~(1 << move->to);
+ }
+
+ // i can't put this above the find_piece_on_square function, because there
+ // is a possibility that piece_type would resolve to the piece that is being
+ // moved, which would mess with the ~(1 << to_sqr)
+ position->bitboards[piece_type] |= 1 << move->to;
+}
diff --git a/src/engine/moves.h b/src/engine/moves.h
index b63b9e2..bd88eeb 100644
--- a/src/engine/moves.h
+++ b/src/engine/moves.h
@@ -6,9 +6,27 @@
typedef u8 square_t;
+// think about the chess move notation
+// e4, Nf6, Qh3+, Qe1#, a8=Q, i need to store the information needed to
+// recreate this in move_t
+enum {
+ MOVE_CAPTURE = 1,
+ MOVE_SHORT_CASTLE = 1 << 1,
+ MOVE_LONG_CASTLE = 1 << 2,
+
+ // technically these promotation flags can be compressed to only use 2 bits..
+ MOVE_PROMOTE_Q = 1 << 3, // 1 << 5
+ MOVE_PROMOTE_R = 1 << 4, // 2 << 5
+ MOVE_PROMOTE_B = 1 << 5, // 3 << 5
+ MOVE_PROMOTE_N = 1 << 6, // 4 << 5 ? nvm it uses 3
+ MOVE_EN_PASSANT = 1 << 7,
+ MOVE_CHECK = 1 << 8,
+};
+
typedef struct {
square_t from;
square_t to;
+ u16 flags;
} move_t;
void position_make_move(position_t* position, move_t* move);
@@ -21,7 +39,22 @@ typedef struct {
moves_t moves_init();
moves_t moves_init_wcapacity(u32 capacity);
moves_t moves_empty();
-void add_move(moves_t* moves, square_t from, square_t to);
+
+struct add_move_params {
+ u16 flags;
+};
+#define add_move(moves, from, to, ...) _add_move(\
+ moves, \
+ from, \
+ to, \
+ (struct add_move_params) { .flags = 0, __VA_ARGS__ }\
+)
+void _add_move(
+ moves_t* moves,
+ square_t from,
+ square_t to,
+ struct add_move_params params
+);
void get_pawn_moves(moves_t* moves, position_t position);
void get_knight_moves(moves_t* moves, position_t position);
diff --git a/src/engine/moves/bishop.c b/src/engine/moves/bishop.c
index 52b90b3..c51d405 100644
--- a/src/engine/moves/bishop.c
+++ b/src/engine/moves/bishop.c
@@ -14,10 +14,11 @@ void __forloop_bishop_moves_gen(
int og_file = from % 8; // range: [0, 7]
int rank = og_rank + 1, file = og_file + 1, index = rank * 8 + file;
-
+ bitboard_t occupied;
while ((rank < 8 && file < 8) && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = ++rank * 8 + ++file;
@@ -25,8 +26,9 @@ void __forloop_bishop_moves_gen(
rank = og_rank - 1, file = og_file - 1, index = rank * 8 + file;
while ((rank >= 0 && file >= 0) && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = --rank * 8 + --file;
@@ -34,8 +36,9 @@ void __forloop_bishop_moves_gen(
rank = og_rank - 1, file = og_file + 1, index = rank * 8 + file;
while ((rank >= 0 && file < 8) && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = --rank * 8 + ++file;
@@ -43,8 +46,9 @@ void __forloop_bishop_moves_gen(
rank = og_rank + 1, file = og_file - 1, index = rank * 8 + file;
while ((rank < 8 && file >= 0) && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = ++rank * 8 + --file;
diff --git a/src/engine/moves/king.c b/src/engine/moves/king.c
index 29bca79..e954ae5 100644
--- a/src/engine/moves/king.c
+++ b/src/engine/moves/king.c
@@ -7,11 +7,14 @@ void get_king_moves(moves_t* moves, position_t position) {
bitboard_t friendly_king;
int king_square;
bitboard_t friendly_pieces;
+ bitboard_t enemy_pieces;
if (position.turn == WHITE_TURN) {
friendly_pieces = whites(position);
+ enemy_pieces = blacks(position);
friendly_king = position.bitboards[WHITE_KING];
} else {
friendly_pieces = blacks(position);
+ enemy_pieces = whites(position);
friendly_king = position.bitboards[BLACK_KING];
}
king_square = __builtin_ctzll(friendly_king);
@@ -32,7 +35,12 @@ void get_king_moves(moves_t* moves, position_t position) {
while (movement) {
int to = __builtin_ctzll(movement);
movement &= movement - 1;
- add_move(moves, king_square, to);
+ add_move(
+ moves,
+ king_square,
+ to,
+ .flags = ((enemy_pieces >> to) & 1) ? MOVE_CAPTURE : 0,
+ );
}
}
diff --git a/src/engine/moves/knight.c b/src/engine/moves/knight.c
index 5f5f9ad..20d072f 100644
--- a/src/engine/moves/knight.c
+++ b/src/engine/moves/knight.c
@@ -79,11 +79,14 @@ void get_knight_moves(moves_t* moves, position_t position) {
bitboard_t friendly_knights;
bitboard_t friendly_pieces;
+ bitboard_t enemy_pieces;
if (position.turn == WHITE_TURN) {
friendly_pieces = whites(position);
+ enemy_pieces = blacks(position);
friendly_knights = position.bitboards[WHITE_KNIGHT];
} else {
friendly_pieces = blacks(position);
+ enemy_pieces = whites(position);
friendly_knights = position.bitboards[BLACK_KNIGHT];
}
@@ -95,7 +98,13 @@ void get_knight_moves(moves_t* moves, position_t position) {
while (ATTACK_MASK) {
int to = __builtin_ctzll(ATTACK_MASK);
ATTACK_MASK &= ATTACK_MASK - 1;
- add_move(moves, from, to);
+ int capture = 0;
+ add_move(
+ moves,
+ from,
+ to,
+ .flags = ((enemy_pieces >> to) & 1) ? MOVE_CAPTURE : 0,
+ );
}
}
}
diff --git a/src/engine/moves/pawn.c b/src/engine/moves/pawn.c
index 3cd28b8..0b8993f 100644
--- a/src/engine/moves/pawn.c
+++ b/src/engine/moves/pawn.c
@@ -1,14 +1,14 @@
#include "../moves.h"
+#define add_promote_moves(other_flags) \
+ add_move(moves, from, to, .flags = other_flags | MOVE_PROMOTE_Q); \
+ add_move(moves, from, to, .flags = other_flags | MOVE_PROMOTE_R); \
+ add_move(moves, from, to, .flags = other_flags | MOVE_PROMOTE_B); \
+ add_move(moves, from, to, .flags = other_flags | MOVE_PROMOTE_N)
+
bitboard_t get_white_pawn_forwardmoves(moves_t* moves, position_t position) {
bitboard_t enemy_bitboard = blacks(position);
- bitboard_t friendly_pieces =
- position.bitboards[WHITE_KING] |
- position.bitboards[WHITE_QUEEN] |
- position.bitboards[WHITE_ROOK] |
- position.bitboards[WHITE_BISHOP] |
- position.bitboards[WHITE_KNIGHT] |
- position.bitboards[WHITE_PAWN];
+ bitboard_t friendly_pieces = whites(position);
bitboard_t friendly_pawns = position.bitboards[WHITE_PAWN];
bitboard_t y = friendly_pieces | enemy_bitboard;
bitboard_t x = ~((friendly_pawns << 8) & y) & (friendly_pawns << 8);
@@ -21,13 +21,7 @@ bitboard_t get_white_pawn_forwardmoves(moves_t* moves, position_t position) {
}
bitboard_t get_black_pawn_forwardmoves(moves_t* moves, position_t position) {
bitboard_t enemy_bitboard = whites(position);
- bitboard_t friendly_pieces =
- position.bitboards[BLACK_KING] |
- position.bitboards[BLACK_QUEEN] |
- position.bitboards[BLACK_ROOK] |
- position.bitboards[BLACK_BISHOP] |
- position.bitboards[BLACK_KNIGHT] |
- position.bitboards[BLACK_PAWN];
+ bitboard_t friendly_pieces = blacks(position);
bitboard_t friendly_pawns = position.bitboards[BLACK_PAWN];
bitboard_t y = friendly_pieces | enemy_bitboard;
bitboard_t x = ~((friendly_pawns >> 8) & y) & (friendly_pawns >> 8);
@@ -84,7 +78,9 @@ void get_pawn_moves(moves_t* moves, position_t position) {
if (pawns == 0) next_from = 64;
}
item &= (item - 1);
- add_move(moves, from, to);
+ if (to >= 56 || to <= 7) {
+ add_promote_moves(0);
+ } else add_move(moves, from, to);
}
}
@@ -108,20 +104,24 @@ void get_pawn_moves(moves_t* moves, position_t position) {
if (left != 0) {
bitboard_t MASK = file_masks[left - 1] & friendly_pawns & PASSANT_RANK;
if (MASK != 0) {
- add_move(
- moves,
- left + rank_shift + from_shift,
- position.passantable_file + rank_shift - 1
+ int from = left + rank_shift + from_shift;
+ int to = position.passantable_file + rank_shift - 1;
+ if (to >= 56 || to <= 7) {
+ add_promote_moves(MOVE_EN_PASSANT | MOVE_CAPTURE);
+ } else add_move(
+ moves, from, to, .flags = MOVE_EN_PASSANT | MOVE_CAPTURE
);
}
}
if (right != 0) {
bitboard_t MASK = file_masks[right - 1] & friendly_pawns & PASSANT_RANK;
if (MASK != 0) {
- add_move(
- moves,
- right + rank_shift + from_shift,
- position.passantable_file + rank_shift - 1
+ int from = right + rank_shift + from_shift;
+ int to = position.passantable_file + rank_shift - 1;
+ if (to >= 56 || to <= 7) {
+ add_promote_moves(MOVE_EN_PASSANT | MOVE_CAPTURE);
+ } else add_move(
+ moves, from, to, .flags = MOVE_EN_PASSANT | MOVE_CAPTURE
);
}
}
@@ -157,7 +157,9 @@ void get_pawn_moves(moves_t* moves, position_t position) {
while (MASK) {
int to = __builtin_ctzll(MASK);
MASK &= MASK - 1;
- add_move(moves, from, to);
+ if (to >= 56 || to <= 7) {
+ add_promote_moves(MOVE_CAPTURE);
+ } else add_move(moves, from, to, .flags = MOVE_CAPTURE);
}
}
}
diff --git a/src/engine/moves/rook.c b/src/engine/moves/rook.c
index c5867d5..dfd9c32 100644
--- a/src/engine/moves/rook.c
+++ b/src/engine/moves/rook.c
@@ -15,9 +15,11 @@ void __forloop_rook_moves_gen(
int rank = og_rank + 1, file = og_file, index = rank * 8 + file;
+ bitboard_t occupied;
while (rank < 8 && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = ++rank * 8 + file;
@@ -25,8 +27,9 @@ void __forloop_rook_moves_gen(
rank = og_rank - 1, file = og_file, index = rank * 8 + file;
while (rank >= 0 && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = --rank * 8 + file;
@@ -34,8 +37,9 @@ void __forloop_rook_moves_gen(
rank = og_rank, file = og_file + 1, index = rank * 8 + file;
while (file < 8 && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = rank * 8 + ++file;
@@ -43,8 +47,9 @@ void __forloop_rook_moves_gen(
rank = og_rank, file = og_file - 1, index = rank * 8 + file;
while (file >= 0 && !occupied_by(friendly_pieces, index)) {
- add_move(moves, from, index);
- if (occupied_by(enemy_pieces, index)) {
+ occupied = occupied_by(enemy_pieces, index);
+ add_move(moves, from, index, .flags = occupied ? MOVE_CAPTURE : 0);
+ if (occupied) {
break;
}
index = rank * 8 + --file;
diff --git a/src/engine/moves/vec.c b/src/engine/moves/vec.c
index 6192706..6a5f3c6 100644
--- a/src/engine/moves/vec.c
+++ b/src/engine/moves/vec.c
@@ -2,10 +2,6 @@
#include <assert.h>
#include <stdlib.h>
-void position_make_move(position_t* position, move_t* move) {
-
-}
-
moves_t moves_init() {
return moves_init_wcapacity(16);
}
@@ -32,7 +28,12 @@ int min(int a, int b) {
return a;
}
-void add_move(moves_t* moves, square_t from, square_t to) {
+void _add_move(
+ moves_t* moves,
+ square_t from,
+ square_t to,
+ struct add_move_params params
+) {
assert(moves->moves != 0);
assert(from != to);
@@ -43,9 +44,9 @@ void add_move(moves_t* moves, square_t from, square_t to) {
moves->capacity * sizeof(*moves->moves)
);
}
- moves->moves[moves->length] = (move_t){
+ moves->moves[moves->length++] = (move_t) {
.from = from,
- .to = to
+ .to = to,
+ .flags = params.flags,
};
- moves->length++;
}