diff options
Diffstat (limited to 'board.cpp')
-rw-r--r-- | board.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/board.cpp b/board.cpp new file mode 100644 index 0000000..5afcea1 --- /dev/null +++ b/board.cpp @@ -0,0 +1,81 @@ +#include <array> +#include "board.h" + +using namespace std; + + +Board Board::empty() { + Board B; + B.bd[0] = B.bd[1] = 0; + return B; +} + +Board Board::uninitialised() { + return Board(); +} + +void Board::drop(int xy, int v) { + uint64_t mask = 0xfULL << (4 * xy), stkbot = 0x1ULL << (4 * xy); + uint64_t bit = ((bd[0] | bd[1]) & mask) + stkbot; + bd[v] |= bit; +} + +bool Board::stkFull(int xy) const { + uint64_t mask = 0xfULL << (4 * xy); + return ((bd[0] | bd[1]) & mask) == mask; +} + +static array<uint64_t, 61> winmasks = { + 0xfULL, 0xf0ULL, 0xf00ULL, 0x1111ULL, + 0x2222ULL, 0x4444ULL, 0x8421ULL, 0x8888ULL, + 0xf000ULL, 0xf0000ULL, 0xf00000ULL, 0xf000000ULL, + 0x11110000ULL, 0x22220000ULL, 0x44440000ULL, 0x84210000ULL, + 0x88880000ULL, 0xf0000000ULL, 0xf00000000ULL, 0xf000000000ULL, + 0xf0000000000ULL, 0x111100000000ULL, 0x222200000000ULL, 0x444400000000ULL, + 0x842100000000ULL, 0x888800000000ULL, 0xf00000000000ULL, 0x1000100010001ULL, + 0x2000200020002ULL, 0x4000400040004ULL, 0x8000400020001ULL, 0x8000800080008ULL, + 0xf000000000000ULL, 0x10001000100010ULL, 0x20002000200020ULL, 0x40004000400040ULL, + 0x80004000200010ULL, 0x80008000800080ULL, 0xf0000000000000ULL, 0x100010001000100ULL, + 0x200020002000200ULL, 0x400040004000400ULL, 0x800040002000100ULL, 0x800080008000800ULL, + 0xf00000000000000ULL, 0x1000010000100001ULL, 0x1000100010001000ULL, 0x1111000000000000ULL, + 0x2000020000200002ULL, 0x2000200020002000ULL, 0x2222000000000000ULL, 0x4000040000400004ULL, + 0x4000400040004000ULL, 0x4444000000000000ULL, 0x8000040000200001ULL, 0x8000080000800008ULL, + 0x8000400020001000ULL, 0x8000800080008000ULL, 0x8421000000000000ULL, 0x8888000000000000ULL, + 0xf000000000000000ULL, +}; + +win_t Board::checkWin() const { + if ((bd[0] | bd[1]) == ~0ULL) return WIN_DRAW; + + for (int i = 0; i < (int)winmasks.size(); i++) { + if ((bd[0] & winmasks[i]) == winmasks[i]) return WIN_P0; + if ((bd[1] & winmasks[i]) == winmasks[i]) return WIN_P1; + } + + return WIN_NONE; +} + +uint64_t Board::hash() const { + return bd[0] ^ ((bd[1] << 29) | (bd[1] >> (64 - 29))); +} + +int Board::numFilled() const { + return __builtin_popcountll(bd[0] | bd[1]); +} + +bool Board::isEmpty() const { + return bd[0] == 0 && bd[1] == 0; +} + +int Board::numValidMoves() const { + uint64_t topsMask = 0x8888'8888'8888'8888ULL; + return 16 - __builtin_popcountll((bd[0] | bd[1]) & topsMask); +} + +int Board::playerToMove() const { + return numFilled() % 2; +} + +bool Board::operator==(const Board &other) const { + return bd[0] == other.bd[0] && bd[1] == other.bd[1]; +} |