summaryrefslogtreecommitdiff
path: root/include/ct1986.c
diff options
context:
space:
mode:
authortslil <tslil@posteo.de>2021-01-13 23:41:32 -0500
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commitcf7d665598e34e32d258775b583968e758c8f2fb (patch)
tree6bfda86535ffa051afd8ccfd70f1d4488701dfdf /include/ct1986.c
parent2ef0078ba2afd99c4fc2673497f3d3a39119cf5d (diff)
Fixed minimax (!), fixed bugs in tak.c
With minimax of depth 1 the evaluation function seems alright with the current method of training and generating weights
Diffstat (limited to 'include/ct1986.c')
-rw-r--r--include/ct1986.c82
1 files changed, 42 insertions, 40 deletions
diff --git a/include/ct1986.c b/include/ct1986.c
index 7295088..bc48110 100644
--- a/include/ct1986.c
+++ b/include/ct1986.c
@@ -93,10 +93,6 @@ ct1986_evaluate_black_win(void) {
// Truncated Pade approximant of logistic function
output = (12.0+output+50.0*output/(output*output+10.0))/24.0;
- /*
- * // Truncated Pade approximant of tanh
- * output = output/6+25*output/(6*(2*output*output+5));
- */
if (output > 1.0) return 1.0;
else if (output < 0.0) return 0.0;
@@ -118,10 +114,42 @@ previous_ply(void) {
}
}
+#define WIN_EVALUATE_OR_RECURSE(store) \
+ { w = 0xFF; \
+ if (ply >= 2*board_size - 2) w = check_win(); \
+ if (w < 0xFF) { \
+ if ((min == 0) && (w == WIN_ROAD_BLACK \
+ || w == WIN_FLAT_BLACK \
+ || w == WIN_DRAGON)) { \
+ this = +2; \
+ } else if ((min > 0) \
+ && (w == WIN_ROAD_WHITE \
+ || w == WIN_FLAT_WHITE \
+ || w == WIN_DRAGON)) { \
+ this = -2; \
+ } /* Otherwise decide what to do based on our depth */ \
+ } else if (cur_depth == max_depth) { \
+ /* We're at the bottom, evaluate */ \
+ this = ct1986_evaluate_black_win(); \
+ } else { \
+ /* We're not at the bottom, recurse first */ \
+ next_ply(); \
+ this = ct1986_minimax(cur_depth + 1, max_depth, 1-min); \
+ previous_ply(); \
+ } \
+ if ( (min && (this < optimal)) \
+ || ((min==0) && (this > optimal))) { \
+ optimal = this; \
+ if (cur_depth == 0) { store; }; \
+ } \
+ }
+
+
float
ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
const uint8_t min) {
enum E_RESULT r;
+ enum WIN_TYPE w;
uint16_t colours_backup[board_size];
uint8_t celldat_backup[board_size], drops[board_size];
const uint8_t white_count_backup = white_count,
@@ -177,28 +205,15 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
// If carry is still set here we're done
if (carry == 0) {
// Try it, and note that try_move will never return
- // GAME_END. It does not check for winners. We don't
- // presently do that either, trust in the magic
- // numbers :)
+ // GAME_END. It does not check for winners, but we do
+ // manually.
r = try_move(loc, dir, steps, drops);
if (r == ACT_OK) {
- // Decide what to do based on our depth
- if (cur_depth == max_depth) {
- // We're at the bottom, evaluate
- this = ct1986_evaluate_black_win();
- } else {
- // We're not at the bottom, recurse first
- next_ply();
- this = ct1986_minimax(cur_depth + 1, max_depth, 1-min);
- previous_ply();
- }
- // Update depending on min and optimal
- if ( (min && (this < optimal))
- || ((min==0) && (this > optimal))) {
- optimal = this;
- if (cur_depth == 0)
+ // First check for wins, if we're at the bottom
+ // evaluate, otherwise recurse
+ WIN_EVALUATE_OR_RECURSE({
generate_move(loc, dir, steps, drops, ct1986_ptn);
- }
+ });
// Reset the board data
if (dir <= M_DOWN) {
for (uint8_t y = 0; y < board_size; y++) {
@@ -226,24 +241,11 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth,
r = try_place(loc, current_colour, stone);
// Legal placement, evaluate it
if (r == ACT_OK) {
- // Decide what to do based on our depth
- if (cur_depth == max_depth) {
- // We're at the bottom, evaluate
- this = ct1986_evaluate_black_win();
- } else {
- // We're not at the bottom, recurse first
- next_ply();
- this = ct1986_minimax(cur_depth + 1, max_depth, 1-min);
- previous_ply();
- }
- // Update depending on min and optimal
- if ( (min && (this < optimal))
- || ((min==0) && (this > optimal))) {
- optimal = this;
- // Store the result if we're at the top
- if (cur_depth == 0)
+ // First check for wins, if we're at the bottom
+ // evaluate, otherwise recurse
+ WIN_EVALUATE_OR_RECURSE({
generate_place(loc, stone, ct1986_ptn);
- }
+ });
// Reset the state
celldat[loc] = 0;
white_count = white_count_backup;