bpaul-chess

UCI chess engine to replace Omelette Chess Engine
Log | Files | Refs | README | LICENSE

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:
Msrc/bb.c | 13+++++++++++++
Msrc/bb.h | 2++
Msrc/gen.c | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/pos.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/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