diff options
| author | tslil <tslil@posteo.de> | 2021-01-14 13:00:18 -0500 |
|---|---|---|
| committer | tslil <tslil@posteo.de> | 2026-08-28 19:37:41 +0100 |
| commit | 2a7b485265997d62625dc0ee5d8e91ede1c5f99f (patch) | |
| tree | e15e8e46743e8ce8bbaa0271834abbca82a784f1 | |
| parent | b75526290b97e26d3fc3bbefef79f50a7febfe7d (diff) | |
So after a small tweak, it actually plays well!
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | include/ct1986.c | 10 | ||||
| -rw-r--r-- | include/ct1986.h | 1 | ||||
| -rw-r--r-- | src/ctaklm.c | 169 |
4 files changed, 107 insertions, 75 deletions
@@ -1,6 +1,6 @@ IDIR=include TPDIR=3rd-party -CFLAGS=-O3 -Wall -Wextra -std=c99 -D_DEFAULT_SOURCE -I$(IDIR) -I$(TPDIR) +CFLAGS=-Os -Wall -Wextra -std=c99 -D_DEFAULT_SOURCE -I$(IDIR) -I$(TPDIR) LIBS= SRCS=$(wildcard include/*.c) $(wildcard 3rd-party/*.c) diff --git a/include/ct1986.c b/include/ct1986.c index 706640e..8378f8c 100644 --- a/include/ct1986.c +++ b/include/ct1986.c @@ -4,6 +4,7 @@ // Globals // =================================================================== +const float infty = 3.0; char ct1986_ptn[9]; void (*ct1986_display_progress)(const uint8_t); @@ -121,16 +122,17 @@ previous_ply(void) { if ((min == 0) && (w == WIN_ROAD_BLACK \ || w == WIN_FLAT_BLACK \ || w == WIN_DRAGON)) { \ - this = +3; \ + this = infty; \ } else if ((min > 0) \ && (w == WIN_ROAD_WHITE \ || w == WIN_FLAT_WHITE \ || w == WIN_DRAGON)) { \ - this = -3; \ + this = -infty; \ } /* 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(); \ + if (min == 0) this = this - 1.0;\ } else { \ /* We're not at the bottom, recurse first */ \ next_ply(); \ @@ -160,7 +162,7 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth, black_count_backup = black_count; // 1.0 is a `certain' black win, -1.0 is a `certain' white win. - float this = 0, optimal = (min) ? 2.0 : -2.0; + float this = 0, optimal = (min) ? infty : -infty; // Step across the board for (uint8_t row = 0; row < board_size; row++) { @@ -269,5 +271,5 @@ ct1986_minimax(const uint8_t cur_depth, const uint8_t max_depth, inline float ct1986_generate(const uint8_t max_depth) { - return ct1986_minimax(0, max_depth, 0, -10, 10); + return ct1986_minimax(0, max_depth, (ply & 1) ? 0 : 1, -infty, infty); } diff --git a/include/ct1986.h b/include/ct1986.h index ef56c1f..3f2568d 100644 --- a/include/ct1986.h +++ b/include/ct1986.h @@ -2,6 +2,7 @@ #include "tak.h" #include "weights.h" +extern const float infty; extern char ct1986_ptn[9]; extern void (*ct1986_display_progress)(const uint8_t); diff --git a/src/ctaklm.c b/src/ctaklm.c index fdeccc8..cf7d0c4 100644 --- a/src/ctaklm.c +++ b/src/ctaklm.c @@ -6,8 +6,8 @@ #include <tak.h> #include <ct1986.h> -const char *blk = "\033[41m", *wht = "\033[44m"; -const char *rev = "\033[7m", *und = "\033[4m", *rst = "\033[0m"; +static const char *blk = "\033[41m", *wht = "\033[44m"; +static const char *und = "\033[4m", *rst = "\033[0m"; #define SQUARE_W 5 #define SQUARE_H 3 @@ -235,9 +235,12 @@ handle_turn(char *line) { return EXIT_SUCCESS; } +static int human = 1; + static void new_game(uint8_t size) { reset_state(size); + human = 0; printf("New %dx%d game!\n",size,size); if (gamelog) gamelog = realloc(gamelog, sizeof(char)); else gamelog = malloc(sizeof(char)); @@ -305,85 +308,111 @@ dot(const uint8_t depth) { } } +static void +ct1986_turn(const uint8_t max_depth) { + // Prepare progress bar + fputs("Computing [", stdout); + for (int k = 0; k < board_size * board_size; k++) putchar(' '); + fputs("]\033[26D",stdout); + fflush(stdout); + // Run the minimax + float minimax = ct1986_generate(max_depth); + if (minimax < -infty) { + puts("] Opponent concedes!"); + } else { + printf("] Result: %s (%.3f)\n", + ct1986_ptn, + minimax*100.0); + handle_turn(ct1986_ptn); + } +} + +static int +input_is_not_turn(const char *line) { + if (!strncmp(line,"help",5)) { + puts("Valid commands: auto (board|info), board, help, info,\ +log, square, new [56], <PTN>."); + } else if (!strncmp(line,"board",6)) { + print_board(); + } else if (!strncmp(line,"info",5)) { + print_info(); + } else if (!strncmp(line,"eval",5)) { + float eval = ct1986_evaluate_black_win()*100; + if (ply & 1) { + printf("Black heuristic chance: %s%.2f%s\n", + blk, eval, rst); + } else { + printf("White heruistic chance: %s%.2f%s\n", + wht, 100-eval, rst); + } + } else if (!strncmp(line,"log",3)) { + puts(gamelog); + } else if (!strncmp(line,"load",4)) { + if (strnlen(line,6) >= 6) { + load_ptn(line+5); + } else { + puts("Usage: load <file.ptn>."); + } + } else if (!strncmp(line,"auto",4)) { + if (!strncmp(line,"auto board",10)) { + auto_board = ~auto_board; + printf("Automatic board display %s.\n", + (auto_board) ? "Enabled" : "Disabled"); + } else if (!strncmp(line,"auto info",9)) { + auto_info = ~auto_info; + printf("Automatic info display %s.\n", + (auto_info) ? "Enabled" : "Disabled"); + } else { + puts("Usage: auto (board|info)."); + } + } else if (!strncmp(line,"square",6)) { + if (strnlen(line, 9) >= 9 + && line[7] >= 'a' && line[7] <= '`'+board_size + && line[8] >= '1' && line[8] <= '0'+board_size) { + print_square(line[7]-'a', line[8]-'1'); + } else { + printf("Usage: square [a-%c][1-%c]\n",'`'+board_size,'0'+board_size); + } + } else if (!strncmp(line,"new",3)) { + if (line[3] == 0) { + new_game(5); + } else if (strnlen(line,5) >= 5 && line[4] >= '5' && line[4] <= '6') { + new_game(line[4]-'0'); + } else { + puts("Usage: new [56]."); + } + } else { + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + int main(int argc, char **argv) { (void)(argc); (void)(argv); - new_game(5); + // Set up output function for ct1986 ct1986_display_progress = ˙ + new_game(5); char *line; - while((line = linenoise("ctaklm> ")) != NULL) { - if (!strncmp(line,"help",5)) { - puts("Valid commands: auto (board|info), board, help, info,\ - log, square, new [56], <PTN>."); - } else if (!strncmp(line,"board",6)) { - print_board(); - } else if (!strncmp(line,"info",5)) { - print_info(); - } else if (!strncmp(line,"eval",5)) { - printf("Valuation: %s%.6f%s\n", - blk, ct1986_evaluate_black_win(), rst); - } else if (!strncmp(line,"log",3)) { - puts(gamelog); - } else if (!strncmp(line,"load",4)) { - if (strnlen(line,6) >= 6) { - load_ptn(line+5); - } else { - puts("Usage: load <file.ptn>."); - } - } else if (!strncmp(line,"auto",4)) { - if (!strncmp(line,"auto board",10)) { - auto_board = ~auto_board; - printf("Automatic board display %s.\n", - (auto_board) ? "Enabled" : "Disabled"); - } else if (!strncmp(line,"auto info",9)) { - auto_info = ~auto_info; - printf("Automatic info display %s.\n", - (auto_info) ? "Enabled" : "Disabled"); - } else { - puts("Usage: auto (board|info)."); - } - } else if (!strncmp(line,"square",6)) { - if (strnlen(line, 9) >= 9 - && line[7] >= 'a' && line[7] <= '`'+board_size - && line[8] >= '1' && line[8] <= '0'+board_size) { - print_square(line[7]-'a', line[8]-'1'); - } else { - printf("Usage: square [a-%c][1-%c]\n",'`'+board_size,'0'+board_size); - } - } else if (!strncmp(line,"new",3)) { - if (line[3] == 0) { - new_game(5); - } else if (strnlen(line,5) >= 5 && line[4] >= '5' && line[4] <= '6') { - new_game(line[4]-'0'); - } else { - puts("Usage: new [56]."); - } - } else { - int r = handle_turn(line); - if (r == EXIT_SUCCESS && won == 0xFF) { - // Prepare progress bar - fputs("Computing [", stdout); - for (int k = 0; k < board_size * board_size; k++) putchar(' '); - fputs("]\033[26D",stdout); - fflush(stdout); - // Run the minimax - float minimax = ct1986_generate(2); - if (minimax < 0 || minimax > 1) { - puts("] Opponent concedes!"); - } else { - printf("] Result: %s (%.3f)\n", - ct1986_ptn, - minimax*100.0); - handle_turn(ct1986_ptn); + for (int playing = 1; playing;) { + while(human && (line = linenoise("ctaklm> ")) != NULL) { + if (input_is_not_turn(line)) { + int r = handle_turn(line); + if (r == EXIT_SUCCESS && won == 0xFF) { + human = 0; } } + free(line); + } + if (human && line == NULL) { + playing = 0; + } else { + ct1986_turn(1); + human = 1; } - - free(line); } return 0; - } |
