#pragma once #include #include #include #include #include #include #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& getEdgeCells() const; void write(ostream &os) const; Bounds computeBounds() const; bool checkEdge(int idx) const; private: // 0 = empty, 1...NC = coloured stones array 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 edgeCells; // Where a particular cell is in edgeCells (or -1 if not present). array 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);