summaryrefslogtreecommitdiff
path: root/board.cpp
blob: 5afcea190152ed47e86e4b1a60717a0dafbea10e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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];
}