Created
June 30, 2020 10:23
-
-
Save Ravenslofty/0a053b8b56612141a0bd8d753b00c977 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
typedef signed long long I64; | |
typedef unsigned long long U64; | |
#define C64(constantU64) constantU64##ULL | |
const U64 notAFile = 0xfefefefefefefefe; | |
const U64 notABFile = 0xfcfcfcfcfcfcfcfc; | |
const U64 notGHFile = 0x3f3f3f3f3f3f3f3f; | |
const U64 notHFile = 0x7f7f7f7f7f7f7f7f; | |
U64 soutOccl(U64 gen, U64 pro) { | |
gen |= pro & (gen >> 8); | |
pro &= (pro >> 8); | |
gen |= pro & (gen >> 16); | |
pro &= (pro >> 16); | |
gen |= pro & (gen >> 32); | |
return gen; | |
} | |
U64 nortOccl(U64 gen, U64 pro) { | |
gen |= pro & (gen << 8); | |
pro &= (pro << 8); | |
gen |= pro & (gen << 16); | |
pro &= (pro << 16); | |
gen |= pro & (gen << 32); | |
return gen; | |
} | |
U64 eastOccl(U64 gen, U64 pro) { | |
pro &= notAFile; | |
gen |= pro & (gen << 1); | |
pro &= (pro << 1); | |
gen |= pro & (gen << 2); | |
pro &= (pro << 2); | |
gen |= pro & (gen << 4); | |
return gen; | |
} | |
U64 noEaOccl(U64 gen, U64 pro) { | |
pro &= notAFile; | |
gen |= pro & (gen << 9); | |
pro &= (pro << 9); | |
gen |= pro & (gen << 18); | |
pro &= (pro << 18); | |
gen |= pro & (gen << 36); | |
return gen; | |
} | |
U64 soEaOccl(U64 gen, U64 pro) { | |
pro &= notAFile; | |
gen |= pro & (gen >> 7); | |
pro &= (pro >> 7); | |
gen |= pro & (gen >> 14); | |
pro &= (pro >> 14); | |
gen |= pro & (gen >> 28); | |
return gen; | |
} | |
U64 westOccl(U64 gen, U64 pro) { | |
pro &= notHFile; | |
gen |= pro & (gen >> 1); | |
pro &= (pro >> 1); | |
gen |= pro & (gen >> 2); | |
pro &= (pro >> 2); | |
gen |= pro & (gen >> 4); | |
return gen; | |
} | |
U64 soWeOccl(U64 gen, U64 pro) { | |
pro &= notHFile; | |
gen |= pro & (gen >> 9); | |
pro &= (pro >> 9); | |
gen |= pro & (gen >> 18); | |
pro &= (pro >> 18); | |
gen |= pro & (gen >> 36); | |
return gen; | |
} | |
U64 noWeOccl(U64 gen, U64 pro) { | |
pro &= notHFile; | |
gen |= pro & (gen << 7); | |
pro &= (pro << 7); | |
gen |= pro & (gen << 14); | |
pro &= (pro << 14); | |
gen |= pro & (gen << 28); | |
return gen; | |
} | |
U64 soutOne (U64 b) {return b >> 8;} | |
U64 nortOne (U64 b) {return b << 8;} | |
U64 eastOne (U64 b) {return (b << 1) & notAFile;} | |
U64 noEaOne (U64 b) {return (b << 9) & notAFile;} | |
U64 soEaOne (U64 b) {return (b >> 7) & notAFile;} | |
U64 westOne (U64 b) {return (b >> 1) & notHFile;} | |
U64 soWeOne (U64 b) {return (b >> 9) & notHFile;} | |
U64 noWeOne (U64 b) {return (b << 7) & notHFile;} | |
U64 soutAttacks (U64 rooks, U64 empty) {return soutOne(soutOccl(rooks, empty));} | |
U64 nortAttacks (U64 rooks, U64 empty) {return nortOne(nortOccl(rooks, empty));} | |
U64 eastAttacks (U64 rooks, U64 empty) {return eastOne(eastOccl(rooks, empty));} | |
U64 noEaAttacks (U64 bishops, U64 empty) {return noEaOne(noEaOccl(bishops, empty));} | |
U64 soEaAttacks (U64 bishops, U64 empty) {return soEaOne(soEaOccl(bishops, empty));} | |
U64 westAttacks (U64 rooks, U64 empty) {return westOne(westOccl(rooks, empty));} | |
U64 soWeAttacks (U64 bishops, U64 empty) {return soWeOne(soWeOccl(bishops, empty));} | |
U64 noWeAttacks (U64 bishops, U64 empty) {return noWeOne(noWeOccl(bishops, empty));} | |
U64 noNoEa(U64 b) {return (b << 17) & notAFile ;} | |
U64 noEaEa(U64 b) {return (b << 10) & notABFile;} | |
U64 soEaEa(U64 b) {return (b >> 6) & notABFile;} | |
U64 soSoEa(U64 b) {return (b >> 15) & notAFile ;} | |
U64 noNoWe(U64 b) {return (b << 15) & notHFile ;} | |
U64 noWeWe(U64 b) {return (b << 6) & notGHFile;} | |
U64 soWeWe(U64 b) {return (b >> 10) & notGHFile;} | |
U64 soSoWe(U64 b) {return (b >> 17) & notHFile ;} | |
U64 wPawnEastAttacks(U64 wpawns) {return noEaOne(wpawns);} | |
U64 wPawnWestAttacks(U64 wpawns) {return noWeOne(wpawns);} | |
U64 wPawnAttacks(U64 wpawns) {return wPawnEastAttacks(wpawns) | wPawnWestAttacks(wpawns);} | |
U64 bPawnEastAttacks(U64 bpawns) {return soEaOne(bpawns);} | |
U64 bPawnWestAttacks(U64 bpawns) {return soWeOne(bpawns);} | |
U64 knightAttacks(U64 knights) { | |
U64 l1 = (knights >> 1) & C64(0x7f7f7f7f7f7f7f7f); | |
U64 l2 = (knights >> 2) & C64(0x3f3f3f3f3f3f3f3f); | |
U64 r1 = (knights << 1) & C64(0xfefefefefefefefe); | |
U64 r2 = (knights << 2) & C64(0xfcfcfcfcfcfcfcfc); | |
U64 h1 = l1 | r1; | |
U64 h2 = l2 | r2; | |
return (h1<<16) | (h1>>16) | (h2<<8) | (h2>>8); | |
} | |
typedef enum { | |
NORTH, | |
NORTHEAST, | |
EAST, | |
SOUTHEAST, | |
SOUTH, | |
SOUTHWEST, | |
WEST, | |
NORTHWEST | |
} enumDir; | |
U64 rayAttacks[8][64]; | |
U64 getPositiveRayAttacks(U64 occupied, enumDir dir8, unsigned long square) { | |
U64 attacks = rayAttacks[dir8][square]; | |
U64 blocker = attacks & occupied; | |
square = __builtin_ctzll(blocker | C64(0x8000000000000000)); | |
return attacks ^ rayAttacks[dir8][square]; | |
} | |
U64 getNegativeRayAttacks(U64 occupied, enumDir dir8, unsigned long square) { | |
U64 attacks = rayAttacks[dir8][square]; | |
U64 blocker = attacks & occupied; | |
square = __builtin_clzll(blocker | C64(1)); | |
return attacks ^ rayAttacks[dir8][square]; | |
} | |
U64 slidingRayNoWeAttacks(int square, U64 occ) { | |
return getPositiveRayAttacks(occ, NORTHWEST, square); | |
} | |
U64 slidingRayNortAttacks(int square, U64 occ) { | |
return getPositiveRayAttacks(occ, NORTH, square); | |
} | |
U64 slidingRayNoEaAttacks(int square, U64 occ) { | |
return getPositiveRayAttacks(occ, NORTHEAST, square); | |
} | |
U64 slidingRayEastAttacks(int square, U64 occ) { | |
return getPositiveRayAttacks(occ, EAST, square); | |
} | |
U64 slidingRaySoEaAttacks(int square, U64 occ) { | |
return getNegativeRayAttacks(occ, SOUTHEAST, square); | |
} | |
U64 slidingRaySoutAttacks(int square, U64 occ) { | |
return getNegativeRayAttacks(occ, SOUTH, square); | |
} | |
U64 slidingRaySoWeAttacks(int square, U64 occ) { | |
return getNegativeRayAttacks(occ, SOUTHWEST, square); | |
} | |
U64 slidingRayWestAttacks(int square, U64 occ) { | |
return getNegativeRayAttacks(occ, WEST, square); | |
} | |
U64 kingAttacks(U64 kingSet) { | |
U64 attacks = eastOne(kingSet) | westOne(kingSet); | |
kingSet |= attacks; | |
attacks |= nortOne(kingSet) | soutOne(kingSet); | |
return attacks; | |
} | |
enum { | |
PAWN, | |
KNIGHT, | |
BISHOP, | |
ROOK, | |
QUEEN, | |
KING | |
}; | |
enum { | |
WHITE, | |
BLACK, | |
}; | |
enum { | |
eNort, | |
eNoEa, | |
eEast, | |
eSoEa, | |
eSout, | |
eSoWe, | |
eWest, | |
eNoWe, | |
eNoNoEa, | |
eNoEaEa, | |
eSoEaEa, | |
eSoSoEa, | |
eSoSoWe, | |
eSoWeWe, | |
eNoWeWe, | |
eNoNoWe | |
}; | |
struct board { | |
U64 pieces[6]; | |
U64 colors[2]; | |
unsigned char ep; | |
}; | |
void dirgolem(struct board* b, U64* m_moveTargets) { | |
U64 horInbetween, verInbetween, diaInbetween, antInbetween; | |
U64 wKSuperAttacksOrth, wKSuperAttacksDia, bAnyAttacks; | |
U64 _bAttacks, _wKSuperAttacks; | |
U64 m_bPawns = b->pieces[PAWN] & b->colors[BLACK]; | |
U64 m_bKnights = b->pieces[KNIGHT] & b->colors[BLACK]; | |
U64 m_bBishops = b->pieces[BISHOP] & b->colors[BLACK]; | |
U64 m_bRooks = b->pieces[ROOK] & b->colors[BLACK]; | |
U64 m_bQueens = b->pieces[QUEEN] & b->colors[BLACK]; | |
U64 m_bKbb = b->pieces[KING] & b->colors[BLACK]; | |
U64 m_wPawns = b->pieces[PAWN] & b->colors[WHITE]; | |
U64 m_wKnights = b->pieces[KNIGHT] & b->colors[WHITE]; | |
U64 m_wBishops = b->pieces[BISHOP] & b->colors[WHITE]; | |
U64 m_wRooks = b->pieces[ROOK] & b->colors[WHITE]; | |
U64 m_wQueens = b->pieces[QUEEN] & b->colors[WHITE]; | |
U64 m_wKbb = b->pieces[KING] & b->colors[WHITE]; | |
int m_wKsq = __builtin_ctzll(m_wKbb); | |
U64 m_wPieces = b->colors[WHITE]; | |
U64 m_bPieces = b->colors[BLACK]; | |
U64 m_occ = b->colors[WHITE] | b->colors[BLACK]; | |
unsigned char m_epTarget = b->ep; | |
/* black rooks and queens west */ | |
_bAttacks = westAttacks (m_bRooks | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks = _bAttacks; | |
_wKSuperAttacks = slidingRayEastAttacks(m_wKsq, m_occ); | |
wKSuperAttacksOrth = _wKSuperAttacks; | |
horInbetween = _bAttacks & _wKSuperAttacks; | |
/* black rooks and queens east */ | |
_bAttacks = eastAttacks (m_bRooks | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRayWestAttacks(m_wKsq, m_occ); | |
wKSuperAttacksOrth |= _wKSuperAttacks; | |
horInbetween |= _bAttacks & _wKSuperAttacks; | |
/* black rooks and queens north */ | |
_bAttacks = nortAttacks (m_bRooks | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRaySoutAttacks(m_wKsq, m_occ); | |
wKSuperAttacksOrth |= _wKSuperAttacks; | |
verInbetween = _bAttacks & _wKSuperAttacks; | |
/* black rooks and queens south */ | |
_bAttacks = soutAttacks (m_bRooks | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRayNortAttacks(m_wKsq, m_occ); | |
wKSuperAttacksOrth |= _wKSuperAttacks; | |
verInbetween |= _bAttacks & _wKSuperAttacks; | |
/* black bishops and queens north east */ | |
_bAttacks = noEaAttacks (m_bBishops | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRaySoWeAttacks(m_wKsq, m_occ); | |
wKSuperAttacksDia = _wKSuperAttacks; | |
diaInbetween = _bAttacks & _wKSuperAttacks; | |
/* black bishops and queens south west */ | |
_bAttacks = soWeAttacks (m_bBishops | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRayNoEaAttacks(m_wKsq, m_occ); | |
wKSuperAttacksDia |= _wKSuperAttacks; | |
diaInbetween |= _bAttacks & _wKSuperAttacks; | |
/* black bishops and queens north west */ | |
_bAttacks = noWeAttacks (m_bBishops | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRaySoEaAttacks(m_wKsq, m_occ); | |
wKSuperAttacksDia |= _wKSuperAttacks; | |
antInbetween = _bAttacks & _wKSuperAttacks; | |
/* black bishops and queens south east */ | |
_bAttacks = soEaAttacks (m_bBishops | m_bQueens, m_occ ^ m_wKbb); | |
bAnyAttacks |= _bAttacks; | |
_wKSuperAttacks = slidingRayNoWeAttacks(m_wKsq, m_occ); | |
wKSuperAttacksDia |= _wKSuperAttacks; | |
antInbetween |= _bAttacks & _wKSuperAttacks; | |
/* black knight attacks */ | |
bAnyAttacks |= knightAttacks (m_bKnights); | |
/* black pawn attacks */ | |
bAnyAttacks |= bPawnEastAttacks(m_bPawns); | |
bAnyAttacks |= bPawnWestAttacks(m_bPawns); | |
/* black king attacks */ | |
bAnyAttacks |= kingAttacks(m_bKbb); | |
U64 _blocks, _checkFrom, _checkTo, targetMask; | |
U64 allInbetween = horInbetween | verInbetween | diaInbetween | antInbetween; | |
_blocks = allInbetween & ~m_occ; /* in case of distant check */ | |
_checkFrom = (wKSuperAttacksOrth & (m_bRooks | m_bQueens) ) | |
| (wKSuperAttacksDia & (m_bBishops| m_bQueens) ) | |
| (knightAttacks(m_wKbb) & m_bKnights ) | |
| (wPawnAttacks (m_wKbb) & m_bPawns ) | |
; | |
I64 _nullIfcheck = ( (I64)( bAnyAttacks & m_wKbb ) - 1) >> 63; /* signed shifts */ | |
I64 _nullIfDblCheck = ( (I64)( _checkFrom & (_checkFrom-1) ) - 1) >> 63; | |
_checkTo = _checkFrom | _blocks | _nullIfcheck; | |
targetMask = ~m_wPieces & _checkTo & _nullIfDblCheck; | |
U64 _sliders; | |
/* horizontal rook and queen moves */ | |
_sliders = (m_wRooks | m_wQueens) & ~(allInbetween ^ horInbetween); | |
m_moveTargets[eWest] = westAttacks (_sliders, m_occ) & targetMask; | |
m_moveTargets[eEast] = eastAttacks (_sliders, m_occ) & targetMask; | |
/* vertical rook and queen moves*/ | |
_sliders = (m_wRooks | m_wQueens) & ~(allInbetween ^ verInbetween); | |
m_moveTargets[eNort] = nortAttacks (_sliders, m_occ) & targetMask; | |
m_moveTargets[eSout] = soutAttacks (_sliders, m_occ) & targetMask; | |
/* diagonal bishop and queen moves */ | |
_sliders = (m_wBishops | m_wQueens) & ~(allInbetween ^ diaInbetween); | |
m_moveTargets[eNoEa] = noEaAttacks (_sliders, m_occ) & targetMask; | |
m_moveTargets[eSoWe] = soWeAttacks (_sliders, m_occ) & targetMask; | |
/* antidiagonal bishop and queen moves */ | |
_sliders = (m_wBishops | m_wQueens) & ~(allInbetween ^ antInbetween); | |
m_moveTargets[eNoWe] = noWeAttacks (_sliders, m_occ) & targetMask; | |
m_moveTargets[eSoEa] = soEaAttacks (_sliders, m_occ) & targetMask; | |
U64 _pawns, _pawnPushs, _rank4, _knights, _targets; | |
/* knight moves */ | |
_knights = m_wKnights & ~allInbetween; | |
m_moveTargets[eNoNoEa] = noNoEa(_knights) & targetMask; | |
m_moveTargets[eNoEaEa] = noEaEa(_knights) & targetMask; | |
m_moveTargets[eSoEaEa] = soEaEa(_knights) & targetMask; | |
m_moveTargets[eSoSoEa] = soSoEa(_knights) & targetMask; | |
m_moveTargets[eNoNoWe] = noNoWe(_knights) & targetMask; | |
m_moveTargets[eNoWeWe] = noWeWe(_knights) & targetMask; | |
m_moveTargets[eSoWeWe] = soWeWe(_knights) & targetMask; | |
m_moveTargets[eSoSoWe] = soSoWe(_knights) & targetMask; | |
/* pawn captures and en passant */ | |
_targets = ( m_bPieces & targetMask) | (C64(1) << m_epTarget); | |
_pawns = m_wPawns & ~(allInbetween ^ diaInbetween); | |
m_moveTargets[eNoEa] |= noEaOne (_pawns) & _targets ; | |
_pawns = m_wPawns & ~(allInbetween ^ antInbetween); | |
m_moveTargets[eNoWe] |= noWeOne(_pawns) & _targets; | |
/* pawn pushes ... */ | |
_pawns = m_wPawns & ~(allInbetween ^ verInbetween); | |
_pawnPushs = nortOne (_pawns) & ~m_occ; | |
m_moveTargets[eNort] |= _pawnPushs & targetMask; | |
/* and double pushs */ | |
_rank4 = C64(0x00000000FF000000); | |
m_moveTargets[eNort] |= nortOne (_pawnPushs) & ~m_occ & targetMask & _rank4; | |
/* king moves */ | |
targetMask = ~(m_wPieces | bAnyAttacks); | |
m_moveTargets[eWest] |= westOne (m_wKbb) & targetMask; | |
m_moveTargets[eEast] |= eastOne (m_wKbb) & targetMask; | |
m_moveTargets[eNort] |= nortOne (m_wKbb) & targetMask; | |
m_moveTargets[eSout] |= soutOne (m_wKbb) & targetMask; | |
m_moveTargets[eNoEa] |= noEaOne (m_wKbb) & targetMask; | |
m_moveTargets[eSoWe] |= soWeOne (m_wKbb) & targetMask; | |
m_moveTargets[eNoWe] |= noWeOne (m_wKbb) & targetMask; | |
m_moveTargets[eSoEa] |= soEaOne (m_wKbb) & targetMask; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment