aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2021-01-21 00:11:01 -0500
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commit232013bda72120f69c1780c4af381884ca111ef4 (patch)
treea5e30ed460329366137743ad46a65db44c7c1f36 /include
parent2ac4a6e1d3b6440de22d95f48454d6282c78726d (diff)
Experimenting
Diffstat (limited to 'include')
-rw-r--r--include/minimax_cnn1986.c120
-rw-r--r--include/minimax_cnn1986.h12
2 files changed, 64 insertions, 68 deletions
diff --git a/include/minimax_cnn1986.c b/include/minimax_cnn1986.c
index e89e5a6..38edb33 100644
--- a/include/minimax_cnn1986.c
+++ b/include/minimax_cnn1986.c
@@ -36,7 +36,7 @@ static union u_f fudge;
#define RELU(x) ((x) = ((x)<0)?0:(x))
float
-ct1986_evaluate_black_win(void) {
+ct1986_evaluate_win(void) {
/* ------------------ *
* Convolution layer *
* ------------------ */
@@ -114,10 +114,16 @@ ct1986_evaluate_black_win(void) {
DOXORSHIFT;
output += fudge.f;
#endif
- if (output > 1.0) return 1.0;
- else if (output < 0.0) return 0.0;
+ if (output > 1.0) {
+ if (ply & 1) return 1.0;
+ else return -1.0;
+ }
+ else if (output < 0.0) {
+ if (ply & 1) return -1.0;
+ else return 1.0;
+ }
- return output;
+ return (ply & 1) ? 2.0*output-1.0 : 1.0-2*output;
}
// ===================================================================
@@ -138,41 +144,41 @@ previous_ply(void) {
static float val;
static enum WIN_TYPE w;
-#define WIN_EVALUATE_OR_RECURSE(store) { \
+#define WIN_EVALUATE_OR_RECURSE(store,reset) { \
w = 0xFF; \
if (ply >= 2*5 - 2) w = check_win(); \
if (w < 0xFF) { \
- /* Somebody won, assign weights accordingly */ \
- if (min == 0) { \
- if (w == WIN_ROAD_BLACK || w == WIN_FLAT_BLACK) \
- val = infty; \
- else val = -infty; \
- } else { \
+ /* Somebody won, assign weights accordingly. Note in particular
+ that draws are only worth ∞/2 ;) \
+ */ \
+ if (ply & 1) { \
if (w == WIN_ROAD_WHITE || w == WIN_FLAT_WHITE) \
val = -infty; \
+ else if (w == WIN_DRAW) val = infty/2.0; \
+ else val = infty; \
+ } else { \
+ if (w == WIN_ROAD_BLACK || w == WIN_FLAT_BLACK) \
+ val = -infty; \
+ else if (w == WIN_DRAW) val = infty/2.0; \
else val = infty; \
} \
} else if (cur_depth == max_depth) { \
/* We're at the bottom, evaluate */ \
- val = ct1986_evaluate_black_win(); \
- if ((ply & 1) == 0) val = val - 1.0; \
+ val = ct1986_evaluate_win(); \
} else { \
/* We're not at the bottom, recurse first */ \
next_ply(); \
- val = ct1986_minimax(cur_depth + 1, max_depth, 1-min, alpha, beta); \
+ val = -ct1986_negamax(cur_depth + 1, max_depth, -beta, -alpha); \
previous_ply(); \
} \
- /* Update the optimal value */ \
- if (((min > 0) && (val <= optimal)) \
- || ((min == 0) && (val >= optimal))) { \
+ { reset }; \
+ /* Prune */ \
+ if (val >= beta) return val; \
+ /* Update the optimal value, which alpha carries */ \
+ if (val > optimal) { \
optimal = val; \
- if (cur_depth == 0) (store); \
- } \
- /* Update alpha and beta */ \
- if (min) { \
- if (optimal < beta) beta = optimal; \
- } else { \
- if (optimal > alpha) alpha = optimal; \
+ if (val > alpha) alpha = val; \
+ if (cur_depth == 0) { store }; \
} \
}
@@ -180,16 +186,15 @@ static enum WIN_TYPE w;
static const int8_t deltas[4] = { +5, -5, -1, +1};
float
-ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
- const uint8_t min, float alpha, float beta) {
+ct1986_negamax(const uint8_t cur_depth, const uint8_t max_depth,
+ float alpha, float beta) {
const uint8_t black = (ply & 1),
material = (black) ? black_count : white_count,
flat = material & 127,
cap = (ply > 2 && (material & 128)),
standing = (ply > 2 && (material & 127));
- // 1.0 is a `certain' black win, -1.0 is a `certain' white win.
- float optimal = (min) ? infty : -infty;
+ float optimal = -infty;
// Step across the board
for (uint8_t row = 0; row < 5; row++) {
@@ -297,21 +302,21 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
// If we did update the optimal value, store
// this move
generate_move(loc, dir, steps, drops, ct1986_ptn);
+ },{
+ // Reset the board data after recursing or
+ // before returning
+ if (dir <= M_DOWN) {
+ for (uint8_t y = 0; y < 5; y++) {
+ colours[THE_COORDS(col, y)] = colours_backup[y];
+ celldat[THE_COORDS(col, y)] = celldat_backup[y];
+ }
+ } else {
+ for (uint8_t x = 0; x < 5; x++) {
+ colours[THE_COORDS(x, row)] = colours_backup[x];
+ celldat[THE_COORDS(x, row)] = celldat_backup[x];
+ }
+ }
});
- // Reset the board data
- if (dir <= M_DOWN) {
- for (uint8_t y = 0; y < 5; y++) {
- colours[THE_COORDS(col, y)] = colours_backup[y];
- celldat[THE_COORDS(col, y)] = celldat_backup[y];
- }
- } else {
- for (uint8_t x = 0; x < 5; x++) {
- colours[THE_COORDS(x, row)] = colours_backup[x];
- celldat[THE_COORDS(x, row)] = celldat_backup[x];
- }
- }
- // Prune
- if (alpha >= beta) return optimal;
}
/*
* With thanks to
@@ -337,13 +342,12 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
WIN_EVALUATE_OR_RECURSE({
// If we did update the optimal value, store
generate_place(loc, STONE_FLAT, ct1986_ptn);
+ },{
+ // Reset the state
+ celldat[loc] = 0;
+ if (black) black_count++;
+ else white_count++;
});
- // Reset the state
- celldat[loc] = 0;
- if (black) black_count++;
- else white_count++;
- // Prune
- if (alpha >= beta) return optimal;
// Do the same for walls, can't happen without flats
if (standing) {
@@ -353,11 +357,11 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
celldat[loc] = NUM_INC | STONE_STANDING;
WIN_EVALUATE_OR_RECURSE({
generate_place(loc, STONE_STANDING, ct1986_ptn);
+ },{
+ celldat[loc] = 0;
+ if (black) black_count++;
+ else white_count++;
});
- celldat[loc] = 0;
- if (black) black_count++;
- else white_count++;
- if (alpha >= beta) return optimal;
}
}
@@ -369,20 +373,20 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
celldat[loc] = NUM_INC | STONE_CAPSTONE;
WIN_EVALUATE_OR_RECURSE({
generate_place(loc, STONE_CAPSTONE, ct1986_ptn);
+ },{
+ celldat[loc] = 0;
+ if (black) black_count |= 128;
+ else white_count |= 128;
});
- celldat[loc] = 0;
- if (black) black_count |= 128;
- else white_count |= 128;
- if (alpha >= beta) return optimal;
}
}
ct1986_display_progress(cur_depth);
}
}
- return optimal;
+ return alpha;
}
inline float
ct1986_generate(const uint8_t max_depth) {
- return ct1986_minimax(0, 1+2*max_depth, (ply & 1) ? 0 : 1, -infty, infty);
+ return ct1986_negamax(0, max_depth, -infty, infty);
}
diff --git a/include/minimax_cnn1986.h b/include/minimax_cnn1986.h
index 3ccc004..dd529e6 100644
--- a/include/minimax_cnn1986.h
+++ b/include/minimax_cnn1986.h
@@ -7,22 +7,14 @@ extern char ct1986_ptn[9];
extern inline void ct1986_display_progress(const uint8_t);
float
-ct1986_evaluate_black_win(void);
+ct1986_evaluate_win(void);
// Generate PTN of the ````best'''' action and store it in ct1986_ptn,
// along with its value as the return. The ct1986_display_progress
// function pointer is called on every new square.
-float ct1986_generate(const uint8_t max_depth);
-
-// Access to the internal method
-float
-ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
- const uint8_t min, float alpha, float beta);
-
extern char ct1986_ptn[9];
-extern float ct1986_optimal;
-
+float ct1986_generate(const uint8_t max_depth);
void
ct1986_generate_ptn(void display_progress(void));