summaryrefslogtreecommitdiff
path: root/board.h
blob: a144ed7896381960ec9756e358cbe07f2bbecd42 (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
82
83
84
85
#pragma once

#include <iostream>
#include <vector>
#include <bitset>
#include <functional>
#include <cstdint>
#include "params.h"

using namespace std;


class Bag {
public:
	static Bag uninitialised();
	static Bag makeFull();

	int numLeft(uint8_t clr) const;
	int totalLeft() const;
	uint8_t drawRandom();
	uint8_t peekRandom() const;  // picks random colour but doesn't draw
	void drawColour(uint8_t clr);
	void replace(uint8_t clr);

private:
	// Number of stones left of the given colours. Index with clr-1.
	int num[NC];

	// Sum of num[0 .. NC-1].
	int sum;

	Bag() = default;
};

struct Bounds {
	int left = BSZ, right = -1, top = BSZ, bottom = -1;
};

class Board {
public:
	// Up to the user to keep this in sync with the board. (It is initialised
	// in makeEmpty().)
	Bag bag = Bag::uninitialised();

	static Board makeEmpty();

	inline const uint8_t& operator[](int idx) const { return bd[idx]; }

	void put(int idx, uint8_t clr);
	void undo(int idx);

	uint8_t putCW(int idx, uint8_t clr);

	// The callback may modify the board, but must leave it as it was after returning.
	void forEachMove(const function<void(int idx)> &f);

	void write(ostream &os) const;

	Bounds computeBounds() const;

private:
	// 0 = empty, 1...NC = coloured stones
	uint8_t bd[BSZ * BSZ];

	// Candidates for edge cells; all cells that can take a stone must be
	// elements of this list, but there may be more.
	vector<int> edgeCands;

	// Whether a particular cell is in edgeCands.
	bitset<BSZ * BSZ> inEdgeCands;

	Board() = default;

	int countStones(uint8_t clr, int idx, int delta) const;
	void newEdgeCand(int idx);
	bool checkEdge(int idx) const;
};

struct Stone {
	uint8_t clr;
	inline Stone(uint8_t clr) : clr(clr) {}
};

ostream& operator<<(ostream &os, Stone stone);
ostream& operator<<(ostream &os, const Board &bd);