commit e3aeeedd9412925c205d300e6c7c5b534f540898
parent b2f12e32a27d08f7318fd824c0ca627bacbe1de6
Author: Benjamin Paul <bpaul@bpaul.xyz>
Date: Thu, 28 Oct 2021 01:10:58 +1000
Sliding attacks and progress on move generation
Diffstat:
M | src/bb.c | | | 13 | +++++++++++++ |
M | src/bb.h | | | 2 | ++ |
M | src/gen.c | | | 59 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
M | src/pos.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
M | src/pos.h | | | 14 | ++++++++++++++ |
5 files changed, 164 insertions(+), 5 deletions(-)
diff --git a/src/bb.c b/src/bb.c
@@ -31,3 +31,16 @@ poplsb(bb *b) {
*b &= *b - 1;
return bit;
}
+
+bb
+shift(bb b, char s) {
+ if (s < 0)
+ return b >> -s;
+ else
+ return b << s;
+}
+
+char
+popcnt(bb b) {
+ return __builtin_popcountll(b);
+}
diff --git a/src/bb.h b/src/bb.h
@@ -7,4 +7,6 @@ bool testbit(bb, unsigned char);
void setbit(bb *, unsigned char);
void popbit(bb *, unsigned char);
unsigned char poplsb(bb *);
+bb shift(bb, char);
+char popcnt(bb);
#endif
diff --git a/src/gen.c b/src/gen.c
@@ -46,10 +46,13 @@ storemove(char from, char to, char movetype, char extra) {
void
gen_pseudo(pos *p) {
char from, to;
- bb our_pieces[6], att;
+ bb our_pieces[6], att, occ, us;
+
+ occ = p->sides[WHITE] | p->sides[BLACK];
+ us = p->sides[p->turn];
for (char pc = PAWN; pc <= KING; pc++) {
- our_pieces[pc] = p->pieces[pc] & p->sides[p->turn];
+ our_pieces[pc] = p->pieces[pc] & us;
}
while ((from = poplsb(&our_pieces[KNIGHT]))) {
@@ -68,5 +71,55 @@ gen_pseudo(pos *p) {
}
}
- return;
+ while ((from = poplsb(&our_pieces[BISHOP]))) {
+ att = bishop_att(from, occ);
+ while ((to = poplsb(&att))) {
+ /* add to move list somehow */
+ storemove(from, to, 0, 0);
+ }
+ }
+
+ while ((from = poplsb(&our_pieces[ROOK]))) {
+ att = rook_att(from, occ);
+ while ((to = poplsb(&att))) {
+ /* add to move list somehow */
+ storemove(from, to, 0, 0);
+ }
+ }
+
+ while ((from = poplsb(&our_pieces[QUEEN]))) {
+ att = queen_att(from, occ);
+ while ((to = poplsb(&att))) {
+ /* add to move list somehow */
+ storemove(from, to, 0, 0);
+ }
+ }
+
+ /* Generate castle */
+
+ /* Generate pawn moves */
+
+ bb push1, push2, leftatt, rightatt;
+
+ push1 = our_pieces[PAWN] << 8 & ~occ;
+ push2 = (push1 & 0xFF0000) << 8 & ~occ;
+ leftatt = (our_pieces[PAWN] & 0x7F7F7F7F7F7F7F7F) << 9 & ~us;
+ rightatt = (our_pieces[PAWN] & 0xFEFEFEFEFEFEFEFE) << 7 & ~us;
+
+ /* Account for promotion too! */
+ while ((to = poplsb(&push1))) {
+ storemove(to-8, to, 0, 0);
+ }
+ while ((to = poplsb(&push2))) {
+ storemove(to-16, to, 0, 0);
+ }
+ while ((to = poplsb(&leftatt))) {
+ storemove(to-9, to, 0, 0);
+ }
+ while ((to = poplsb(&rightatt))) {
+ storemove(to-7, to, 0, 0);
+ }
+
+ /* En passant */
+
}
diff --git a/src/pos.c b/src/pos.c
@@ -1,6 +1,8 @@
#include <assert.h>
+#include <immintrin.h>
#include <stdbool.h>
#include <stdio.h>
+#include <stdlib.h>
#include "bb.h"
#include "pos.h"
@@ -16,8 +18,18 @@ piece(unsigned char p) {
}
unsigned char
-square(unsigned char r, unsigned char c) {
- return r*8 + c;
+rank(unsigned char sq) {
+ return sq >> 3;
+}
+
+unsigned char
+file(unsigned char sq) {
+ return sq & 7;
+}
+
+unsigned char
+square(unsigned char r, unsigned char f) {
+ return r*8 + f;
}
void
@@ -172,8 +184,16 @@ print_board(pos *p) {
/* Piece attack bitboards */
+int
+slider_idx(char sq, bb occ, magic magic) {
+ return _pext_u64(occ, magic.mask);
+}
+
+
bb knight_attacks[64];
bb king_attacks[64];
+magic bishop_magics[64];
+magic rook_magics[64];
bb
knight_att(char sq) {
@@ -185,6 +205,21 @@ king_att(char sq) {
return king_attacks[sq];
}
+bb
+bishop_att(char sq, bb occ) {
+ return bishop_magics[sq].attacks[slider_idx(sq, occ, bishop_magics[sq])];
+}
+
+bb
+rook_att(char sq, bb occ) {
+ return rook_magics[sq].attacks[slider_idx(sq, occ, rook_magics[sq])];
+}
+
+bb
+queen_att(char sq, bb occ) {
+ return bishop_att(sq, occ) | rook_att(sq, occ);
+}
+
void
gen_knight_attacks(void) {
char sq;
@@ -215,6 +250,48 @@ gen_king_attacks(void) {
}
}
+/* Sliding attacks are weird */
+
+bb
+get_slider_attack(char sq, bb occ, char dirs[4]) {
+ char dir;
+ bb s, att;
+ for (dir = 0; dir < 4; dir++) {
+ s = 1ULL << sq;
+ while ((s = shift(s, dirs[dir]))) {
+ att |= s;
+ s &= ~occ;
+ }
+ }
+ return att;
+}
+
+void
+gen_magic(char sq, magic magics[64], char dirs[4]) {
+ bb occ, edges;
+
+ edges = 0xFF000000000000FF & ~(0xFF << 8*rank(sq));
+ edges |= 0x8181818181818181 & ~(0x0101010101010101 << file(sq));
+
+ occ = magics[sq].mask = get_slider_attack(sq, 0, dirs) & ~edges;
+
+ magics[sq].attacks = malloc((1 << popcnt(occ)) * sizeof(bb));
+ /* Magic bit hacking to loop over all relevant occupancies */
+ do {
+ magics[sq].attacks[slider_idx(sq, occ, magics[sq])] =
+ get_slider_attack(sq, occ, dirs);
+ } while ((occ = (occ - 1) & magics[sq].mask));
+}
+
+void
+init_sliders(void) {
+ char sq, bishop_dirs[4] = {9,7,-7,-9}, rook_dirs[4] = {8,1,-1,-8};
+ for (sq = 0; sq < 64; sq++) {
+ gen_magic(sq, bishop_magics, bishop_dirs);
+ gen_magic(sq, rook_magics, rook_dirs);
+ }
+}
+
void
init_attacks(void) {
gen_knight_attacks();
diff --git a/src/pos.h b/src/pos.h
@@ -25,6 +25,7 @@ enum {
};
typedef struct pos pos;
+typedef struct magic magic;
struct pos {
bb sides[2];
@@ -37,6 +38,16 @@ struct pos {
char turn;
};
+struct magic {
+ bb mask;
+ bb *attacks;
+#ifdef MAGIC
+ /* I am going to do this later it is too much work */
+ unsigned long long magic;
+ char shift;
+#endif
+};
+
void reset_board(pos *);
void parse_fen(pos *, char *);
#ifndef NDEBUG
@@ -44,4 +55,7 @@ void print_board(pos *);
#endif
bb knight_att(char);
bb king_att(char);
+bb bishop_att(char, bb);
+bb rook_att(char, bb);
+bb queen_att(char, bb);
#endif