Skip to content

Instantly share code, notes, and snippets.

@Ravenslofty
Created June 30, 2020 10:23
Show Gist options
  • Save Ravenslofty/0a053b8b56612141a0bd8d753b00c977 to your computer and use it in GitHub Desktop.
Save Ravenslofty/0a053b8b56612141a0bd8d753b00c977 to your computer and use it in GitHub Desktop.
#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