diff options
Diffstat (limited to 'src/ct1986.c')
| -rw-r--r-- | src/ct1986.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/src/ct1986.c b/src/ct1986.c new file mode 100644 index 0000000..b930b13 --- /dev/null +++ b/src/ct1986.c @@ -0,0 +1,197 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <tak.h> +#include <minimax_cnn1986.h> + +const char* esc = "\x1B[L"; + +FILE *lcd = NULL; +static char *gamelog = 0; +static int human, search_depth; + +static void +write_line(const char *line) { + fprintf(lcd, "%s\n", line); + fflush(lcd); +} + +static void +append_to_gamelog(const char *line, const uint8_t win_line) { + // I _could_ dynamically compute the size but ... don't let + // `perfect' be the enemy of `good' ? + char prepend[8]; + + if (win_line) { + prepend[0] = '\n'; + prepend[1] = 0; + } else if (ply & 1) { + snprintf(prepend, 7, "%s%d. ", + (ply == 1) ? "" : "\n", ply/2+1); + } else { + strcpy(prepend, " "); + } + // Make room for this line + gamelog = realloc(gamelog, + strlen(gamelog) + + strlen(prepend) + + strlen(line) + 1); + strcat(gamelog,prepend); + strcat(gamelog,line); +} + +static void +end_game(char *line, char *win) { + append_to_gamelog(line, 0); + append_to_gamelog(win, 1); + fprintf(lcd, "Game over: %s\n", win); + fflush(lcd); +} + +static int +handle_turn(char *line) { + // Track win state + uint8_t new_win = (won == 0xFF); + switch (do_ptn(line)) { + // Errors + case PTN_INVALID: { write_line("Invalid PTN."); break; } + case ACT_ILLEGAL: { write_line("Illegal ply."); break; } + case ACT_OVERFLOW: { write_line("Overflow."); break; } + // Game has ended + case GAME_END: { + // Did it end this turn? + if (new_win) { + switch (won) { + case WIN_DRAW: { end_game(line,"1/2-1/2"); break; } + case WIN_FLAT_BLACK: { end_game(line,"0-F"); break; } + case WIN_FLAT_WHITE: { end_game(line,"F-0"); break; } + case WIN_ROAD_BLACK: { end_game(line,"0-R"); break; } + case WIN_ROAD_WHITE: { end_game(line,"R-0"); break; } + } + return EXIT_SUCCESS; + } else { + write_line("Game over."); + break; + } + } + // Valid, append to game log + default: { + append_to_gamelog(line, 0); + return EXIT_SUCCESS; + } + } + return EXIT_FAILURE; +} + +static void +new_game(uint8_t size) { + reset_state(size); + write_line("New 5x5 game."); + if (gamelog) gamelog = realloc(gamelog, sizeof(char)); + else gamelog = malloc(sizeof(char)); + gamelog[0] = 0; +} + +// Set up output function for ct1986 + +static uint8_t perc; +inline void +ct1986_display_progress(const uint8_t depth) { + if (depth == 0) { + perc++; + // back four spaces and clear line, followed by perc% + fprintf(lcd, "%sl%sl%sl%sl%sk%3d%%", + esc, esc, esc, esc, esc, + perc*4); + fflush(lcd); + } +} + +static int +ct1986_turn(const uint8_t search_depth) { + // Prepare progress bar + fputs("Computing: ", lcd); fflush(lcd); + // Run the minimax + perc = 0; + float minimax = ct1986_generate(search_depth); + fputc('\n', lcd); fflush(lcd); + // Failed to find a move? + if (minimax <= -infty) { + fprintf(lcd, "%s concedes!\n", (ply & 1) ? "Black" : "White"); + return EXIT_FAILURE; + } else { + fprintf(lcd, "%s: %s\n", + (ply & 1) ? "Black" : "White", + ct1986_ptn); + handle_turn(ct1986_ptn); + return EXIT_SUCCESS; + } +} + +static void +do_game_log(void) { + fputs(gamelog, lcd); +} + +static int +input_is_not_turn(const char *line) { + switch (line[0]) { + case 'l': { do_game_log(); break; } + case 'n': { new_game(5); break; } + case 'd': { + search_depth = line[1] - '0'; + fprintf(lcd, "Search depth: %d\n", search_depth); + fflush(lcd); + break; + } + case 'b': { human = 1; new_game(5); break; } + case 'w': { human = 0; new_game(5); break; } + default: return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +int +main(int argc, char **argv) { + (void)(argc); + (void)(argv); + + lcd = fopen("/dev/lcd", "w"); + if (lcd == NULL) return EXIT_FAILURE; + + human = 0; + search_depth = 1; + new_game(5); + fprintf(lcd, "%sB", esc); + fflush(lcd); + + char *line = NULL; + ssize_t read; + size_t alloc_size; + + for (int playing = 1; playing;) { + while (human == 0) { + if (ply & 1) write_line("Black: "); + else write_line("White: "); + read = getline(&line, &alloc_size, stdin); + if (read > 0) { + line[read - 1] = 0; + if (input_is_not_turn(line)) { + int r = handle_turn(line); + if (r == EXIT_SUCCESS && won == 0xFF) { + human = 1; + } + } + } else if (read == -1) { + playing = 0; + break; + } + } + ct1986_turn(search_depth); + human = 0; + } + + fclose(lcd); + return EXIT_SUCCESS; +} |
