summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2018-07-01 23:50:52 +0200
committerTom Smeding <tom.smeding@gmail.com>2018-07-01 23:51:42 +0200
commit6d6292cc9d2da6b570a3a44ede78b098fccd7537 (patch)
tree5c993de409432d50b59c62b806ecf781ef6fe6f3
parente0446e8653df1789893cb8530aafd3dd052b32ca (diff)
Actually break loop in Board::forEachMove
-rw-r--r--ai_mm.cpp1
-rw-r--r--ai_rand.cpp3
-rw-r--r--board.h55
3 files changed, 31 insertions, 28 deletions
diff --git a/ai_mm.cpp b/ai_mm.cpp
index 4400a84..10d2fae 100644
--- a/ai_mm.cpp
+++ b/ai_mm.cpp
@@ -94,6 +94,7 @@ Move AI::MM::findMove(const Board &bd, int player) {
bestScore = score;
bestMove = mv;
}
+ return false;
});
cerr << ']' << endl;
diff --git a/ai_rand.cpp b/ai_rand.cpp
index 9bd3eed..8b71670 100644
--- a/ai_rand.cpp
+++ b/ai_rand.cpp
@@ -5,8 +5,9 @@ Move AI::Rand::findMove(const Board &bd, int player) {
Move poss[N * N * N];
int nposs = 0;
- bd.forEachMove(player, [&bd, &poss, &nposs](Move mv) {
+ bd.forEachMove(player, [&poss, &nposs](Move mv) {
poss[nposs++] = mv;
+ return false;
});
if (nposs == 0) return Move(-1, -1);
diff --git a/board.h b/board.h
index 1ab0646..3b0895d 100644
--- a/board.h
+++ b/board.h
@@ -3,6 +3,7 @@
#include <iostream>
#include <optional>
#include <string_view>
+#include <type_traits>
#include <cstdint>
using namespace std;
@@ -37,8 +38,33 @@ struct Board {
// 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;
+ template <typename F,
+ typename = enable_if_t<is_invocable_r<bool, F, Move>::value>>
+ void 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) {
+ bool ret = callback(Move(N * y + x, N * y2 + x2));
+ if (ret) goto stop_iteration;
+ }
+
+ x2 += deltas[i][0];
+ y2 += deltas[i][1];
+ }
+ }
+ }
+
+ stop_iteration: ;
+ }
private:
Board();
@@ -51,28 +77,3 @@ private:
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];
- }
- }
- }
-}