diff options
Diffstat (limited to 'src/ct1986.c')
| -rw-r--r-- | src/ct1986.c | 260 |
1 files changed, 142 insertions, 118 deletions
diff --git a/src/ct1986.c b/src/ct1986.c index f9046ce..8a49ec1 100644 --- a/src/ct1986.c +++ b/src/ct1986.c @@ -23,47 +23,46 @@ #include <ncurses.h> -#include <tak.h> -#include <negamax.h> #include <lcdlib.h> - +#include <negamax.h> +#include <tak.h> static int human; static char *gamelog = 0; -static void -new_game(uint8_t size) { - reset_state(size); - lcd_printf_line(L_SCROLL, "New 5s game @ D%d", - negamax_search_depth); - if (gamelog) gamelog = realloc(gamelog, sizeof(char)); - else gamelog = malloc(sizeof(char)); +tak_state_p state; + +static void new_game(uint8_t size) { + reset_state(state, size); + lcd_printf_line(L_SCROLL, "New 5s game @ D%d", negamax_search_depth); + if (gamelog) + gamelog = realloc(gamelog, sizeof(char)); + else + gamelog = malloc(sizeof(char)); gamelog[0] = 0; } -static int -append_to_gamelog(const char *line, const uint8_t win_line) { +static int 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' ? - if (gamelog == NULL) return EXIT_FAILURE; + if (gamelog == NULL) + return EXIT_FAILURE; 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 if (state->ply & 1) { + snprintf(prepend, 7, "%s%d. ", (state->ply == 1) ? "" : "\n", + state->ply / 2 + 1); } else { strcpy(prepend, " "); } // Make room for this line - gamelog = realloc(gamelog, - strlen(gamelog) - + strlen(prepend) - + strlen(line) + 1); + gamelog = + realloc(gamelog, strlen(gamelog) + strlen(prepend) + strlen(line) + 1); // TODO: trap errno strcat(gamelog, prepend); strcat(gamelog, line); @@ -71,127 +70,151 @@ append_to_gamelog(const char *line, const uint8_t win_line) { return EXIT_SUCCESS; } -static void -end_game(char *line, char *win) { +static void end_game(char *line, char *win) { append_to_gamelog(line, 0); append_to_gamelog(win, 1); lcd_printf_line(L_SCROLL, "Game over: %s", win); } -static int -handle_turn(char *line) { +static int handle_turn(char *line) { // Track win state - uint8_t new_win = (won == 0xFF); - switch (do_ptn(line)) { - // Errors - case ACT_INVALID_PTN: { - lcd_put_line(L_SCROLL, "Invalid PTN."); - break; - } - case ACT_ILLEGAL: { - lcd_put_line(L_SCROLL, "Illegal ply."); - break; } - case ACT_OVERFLOW: { - lcd_put_line(L_SCROLL, "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 { - lcd_put_line(L_SCROLL, "Game over."); - break; + uint8_t new_win = (state->won == 0xFF); + switch (do_ptn(state, line)) { + // Errors + case ACT_INVALID_PTN: { + lcd_put_line(L_SCROLL, "Invalid PTN."); + break; + } + case ACT_ILLEGAL: { + lcd_put_line(L_SCROLL, "Illegal state->ply."); + break; + } + case ACT_OVERFLOW: { + lcd_put_line(L_SCROLL, "Overflow."); + break; + } + // Game has ended + case GAME_END: { + // Did it end this turn? + if (new_win) { + switch (state->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; + } } - } - // Valid, append to game log - default: { - append_to_gamelog(line, 0); return EXIT_SUCCESS; + } else { + lcd_put_line(L_SCROLL, "Game over."); + break; } } + // Valid, append to game log + default: { + append_to_gamelog(line, 0); + return EXIT_SUCCESS; + } + } return EXIT_FAILURE; } - // Set up output function for negamax static uint32_t perc; -inline void -negamax_display_progress(const uint8_t depth, const uint32_t length) { - if (depth == negamax_search_depth) { - lcd_printf_line(L_OVERWRITE, "Computing: %d%%", - (++perc*100)/length); +inline void negamax_display_progress(const uint8_t cur_depth, + const uint8_t init_depth, + const uint32_t length) { + (void)init_depth; + if (cur_depth == negamax_search_depth) { + lcd_printf_line(L_OVERWRITE, "Computing: %d%%", (++perc * 100) / length); } } -static int -negamax_turn() { +static int negamax_turn() { // Prepare progress bar perc = 0; lcd_put_line(L_SCROLL, "Computing: 0%"); // Run the minimax - float minimax = negamax_generate(); + float minimax = negamax_generate(state); // Failed to find a move? if (minimax < -infty) { lcd_printf_line(L_SCROLL, "%s concedes!", - (ply & 1) ? "Black" : "White"); + (state->ply & 1) ? "Black" : "White"); return EXIT_FAILURE; } else { - lcd_printf_line(L_SCROLL, "%s: %s", - (ply & 1) ? "Black" : "White", - negamax_ptn); + lcd_printf_line(L_SCROLL, "%s: %s", (state->ply & 1) ? "Black" : "White", + negamax_ptn); return handle_turn(negamax_ptn); } } -static void -do_game_log(void) { - lcd_put_line(L_SCROLL, "TODO!"); -} +static void do_game_log(void) { lcd_put_line(L_SCROLL, "TODO!"); } -static int -input_is_not_turn(const char *line) { +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': { - negamax_search_depth = line[1] - '0'; - lcd_printf_line(L_SCROLL, "Search depth: %d", - negamax_search_depth); - break; - } - case 'B': { human = 1; new_game(5); break; } - case 'W': { human = 0; new_game(5); break; } - default: return EXIT_FAILURE; + case 'l': { + do_game_log(); + break; + } + case 'n': { + new_game(5); + break; + } + case 'D': { + negamax_search_depth = line[1] - '0'; + lcd_printf_line(L_SCROLL, "Search depth: %d", negamax_search_depth); + break; + } + case 'B': { + human = 1; + new_game(5); + break; + } + case 'W': { + human = 0; + new_game(5); + break; + } + default: + return EXIT_FAILURE; } return EXIT_SUCCESS; } -const char* license = "ct1986, an interface to the ct library designed to be embedded on a Raspberry Pi Zero\n\ +const char *license = + "ct1986, an interface to the ct library designed to be embedded on a Raspberry Pi Zero\n\ \n\ Copyright (C) 2021, tslil clingman\n\ \n\ This program comes with ABSOLUTELY NO WARRANTY; and is made available under the terms of the GNU GPL v3 license. This is free software, and you are welcome to redistribute it under certain conditions; see COPYING for details.\n"; #define LINE_BUFF_LEN 9 -static char line[LINE_BUFF_LEN+1]; +static char line[LINE_BUFF_LEN + 1]; -static int -poll_input(void) { +static int poll_input(void) { char c, *prompt; int idx = 0, polling = 1; - if (ply & 1) prompt = "Black: "; - else prompt = "White: "; + if (state->ply & 1) + prompt = "Black: "; + else + prompt = "White: "; lcd_put_line(L_SCROLL, prompt); @@ -200,24 +223,25 @@ poll_input(void) { lcd_printf_line(L_OVERWRITE, "%s%s", prompt, line); c = getchar(); switch (c) { - case 0x7F: { - if (idx>0) idx--; - line[idx] = 0; - break; - } - case 0xFF: // fall-through - case '\r': // fall-through - case '\n': { - polling = 0; - break; - } - default: { - if (idx+1<LINE_BUFF_LEN) { - line[idx] = c; - line[++idx] = 0; - } - break; + case 0x7F: { + if (idx > 0) + idx--; + line[idx] = 0; + break; + } + case 0xFF: // fall-through + case '\r': // fall-through + case '\n': { + polling = 0; + break; + } + default: { + if (idx + 1 < LINE_BUFF_LEN) { + line[idx] = c; + line[++idx] = 0; } + break; + } } } return idx; @@ -243,15 +267,15 @@ int main(int argc, char **argv) { while (human == 0) { lcd_set_blink(); if (poll_input() > 0) { - if (input_is_not_turn(line)) { - int r = handle_turn(line); - if (r == EXIT_SUCCESS && won == 0xFF) { - human = 1; - } - } + if (input_is_not_turn(line)) { + int r = handle_turn(line); + if (r == EXIT_SUCCESS && state->won == 0xFF) { + human = 1; + } + } } else { - playing = 0; - human = 1; + playing = 0; + human = 1; } } lcd_stop_blink(); |
