diff options
author | Tom Smeding <tom.smeding@gmail.com> | 2019-02-19 10:34:15 +0100 |
---|---|---|
committer | Tom Smeding <tom.smeding@gmail.com> | 2019-02-19 10:34:15 +0100 |
commit | dfac9e7da9ec4534384c73a9501061d8972ad10d (patch) | |
tree | 7e20555958eaad4d621609014e2e72ec4c1ff0dd /ai_str.cpp | |
parent | bffa3deadebb56cf44e93140ed3a3cec6311a105 (diff) |
Diffstat (limited to 'ai_str.cpp')
-rw-r--r-- | ai_str.cpp | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/ai_str.cpp b/ai_str.cpp new file mode 100644 index 0000000..de83a3f --- /dev/null +++ b/ai_str.cpp @@ -0,0 +1,99 @@ +#include <iostream> +#include <algorithm> +#include <array> +#include <climits> +#include <cassert> +#include "ai_str.h" + +using namespace std; + + +static const int deltaxy[8][2] = { + {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1} +}; + +static const int deltaidx[8] = { +#define ITEM(_i) (BSZ * deltaxy[_i][1] + deltaxy[_i][0]) + ITEM(0), ITEM(1), ITEM(2), ITEM(3), ITEM(4), ITEM(5), ITEM(6), ITEM(7) +#undef ITEM +}; + +static int findExtent(const Board &bd, int idx, int dir, uint8_t clr) { + const int dx = deltaxy[dir][0], dy = deltaxy[dir][1], didx = deltaidx[dir]; + + int x = idx % BSZ, y = idx / BSZ; + x += dx; y += dy; idx += didx; + + for (int i = 0; i < RLEN - 1 && x > 0 && x < BSZ - 1 && y > 0 && y < BSZ - 1; i++) { + if (bd[idx] != 0 && bd[idx] != clr) return i; + x += dx; y += dy; idx += didx; + } + + return RLEN - 1; +} + +static int count(const Board &bd, int idx, int didx, uint8_t clr) { + int res = 0; + for (int i = 0; i < RLEN; i++) { + res += bd[idx] == clr; + idx += didx; + } + return res; +} + +static int calcScore(const Board &bd, int idx, uint8_t myclr) { + array<array<int, NC>, 8> exts; + for (int dir = 0; dir < 8; dir++) { + for (int clr = 1; clr <= NC; clr++) { + exts[dir][clr - 1] = findExtent(bd, idx, dir, clr); + } + } + + array<int, NC> score; + score.fill(0); + for (int dir = 0; dir < 4; dir++) { + const int dx = deltaxy[dir][0], dy = deltaxy[dir][1]; + const int didx = deltaidx[dir]; + assert(deltaxy[dir + 4][0] == -dx && deltaxy[dir + 4][1] == -dy); + + for (int clr = 1; clr <= NC; clr++) { + int length = exts[dir][clr - 1] + exts[dir + 4][clr - 1] + 1; + if (length < RLEN) continue; + + int start = idx + exts[dir][clr - 1] * didx; + + int maxcnt = -1; + for (int i = 0; i < length - 4; i++) { + int cnt = count(bd, start, -didx, clr); + maxcnt = max(maxcnt, cnt); + + start += -didx; + } + + // Square the count to lay emphasis on larger lines + score[clr - 1] += maxcnt * maxcnt; + } + } + + int tot = 0; + for (int i = 0; i < NC; i++) tot += score[i]; + + return -tot + 3 * score[myclr - 1]; +} + +int STR::calcMove(Board &bd, uint8_t myclr) { + assert(bd.bag.totalLeft() > 0); + + int maxscore = INT_MIN, maxat = -1; + + vector<int> moves = bd.getEdgeCells(); + for (int idx : moves) { + int score = calcScore(bd, idx, myclr); + if (score > maxscore) { + maxscore = score; + maxat = idx; + } + } + + return maxat; +} |