summaryrefslogtreecommitdiff
path: root/board.h
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2018-06-30 00:30:14 +0200
committerTom Smeding <tom.smeding@gmail.com>2018-06-30 00:30:14 +0200
commit44421af15c2f361764b8741bb93f9fddda3f8a8b (patch)
tree15e541b25d145595279de6067cb839ebbb16b982 /board.h
Initial
Diffstat (limited to 'board.h')
-rw-r--r--board.h78
1 files changed, 78 insertions, 0 deletions
diff --git a/board.h b/board.h
new file mode 100644
index 0000000..1ab0646
--- /dev/null
+++ b/board.h
@@ -0,0 +1,78 @@
+#pragma once
+
+#include <iostream>
+#include <optional>
+#include <string_view>
+#include <cstdint>
+
+using namespace std;
+
+const int N = 9;
+const int BOARDMID = N * (N/2) + N/2;
+
+const uint8_t EMPTY = 0, WHITE = 1, KING = 2, BLACK = 4;
+
+
+struct Move {
+ int from, to;
+
+ Move() = default;
+ Move(int from, int to);
+
+ static optional<Move> parse(string_view str);
+};
+
+struct Board {
+ uint8_t cells[N * N];
+
+ static Board makeInitial();
+
+ void apply(Move mv);
+ int applyCW(Move mv);
+ int checkWin() const; // 1=win white, -1=win black, 0=none yet
+
+ bool isValid(Move mv, int player) const;
+
+ // Calls the callback for each valid move of the specified player.
+ // F should have a signature compatible with bool F(Move mv).
+ // If the callback returns true, iteration is stopped.
+ // Callback should not modify this Board instance.
+ template <typename F>
+ void forEachMove(int player, F callback) const;
+
+private:
+ Board();
+
+ bool isValid(Move mv) const;
+ bool stoneFlankedH(int pos, uint8_t by) const;
+ bool stoneFlankedV(int pos, uint8_t by) const;
+ bool kingEncircled(int pos) const;
+};
+
+ostream& operator<<(ostream &os, const Move &mv);
+ostream& operator<<(ostream &os, const Board &bd);
+
+
+template <typename F>
+void Board::forEachMove(int player, F callback) const {
+ static const int deltas[4][2] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
+
+ for (int y = 0; y < N; y++)
+ for (int x = 0; x < N; x++) {
+ uint8_t v = cells[N * y + x];
+ if (player == 1 ? v != WHITE && v != KING : v != BLACK) continue;
+
+ for (int i = 0; i < 4; i++) {
+ int x2 = x + deltas[i][0], y2 = y + deltas[i][1];
+ while (x2 >= 0 && x2 < N && y2 >= 0 && y2 < N) {
+ if (cells[N * y2 + x2] != EMPTY) break;
+ if (N * y2 + x2 != BOARDMID) {
+ callback(Move(N * y + x, N * y2 + x2));
+ }
+
+ x2 += deltas[i][0];
+ y2 += deltas[i][1];
+ }
+ }
+ }
+}