summaryrefslogtreecommitdiff
path: root/board.h
blob: 06540ee41e4633860c19cce5210727dfd0cb7ffb (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
86
87
88
89
90
91
#pragma once

#include <iostream>
#include <vector>
#include <array>
#include <bitset>
#include <functional>
#include <cstdint>
#include "params.h"
#include "util.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.
	const vector<int>& getEdgeCells() const;

	void write(ostream &os) const;

	Bounds computeBounds() const;
	bool checkEdge(int idx) const;

private:
	// 0 = empty, 1...NC = coloured stones
	array<uint8_t, BSZ * BSZ> bd;

	// The cells that are neighbour to a stone on the board, i.e. those cells
	// that can take a stone in the next move.
	vector<int> edgeCells;

	// Where a particular cell is in edgeCells (or -1 if not present).
	array<int, BSZ * BSZ> inEdgeCells;

	Board() = default;

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

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

#define EDGE_STR "\x1B[36m+\x1B[0m"
#define OPEN_STR "ยท"

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