diff options
Diffstat (limited to 'include/ct1986.c')
| -rw-r--r-- | include/ct1986.c | 82 |
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; |
