diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ct1986.c | 14 | ||||
| -rw-r--r-- | src/ctaklm.c | 32 | ||||
| -rw-r--r-- | src/pptdb.c | 6 | ||||
| -rw-r--r-- | src/tei.c | 163 |
4 files changed, 193 insertions, 22 deletions
diff --git a/src/ct1986.c b/src/ct1986.c index 2c2d875..aeff13a 100644 --- a/src/ct1986.c +++ b/src/ct1986.c @@ -84,9 +84,17 @@ handle_turn(char *line) { uint8_t new_win = (won == 0xFF); switch (do_ptn(line)) { // Errors - case PTN_INVALID: { 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; } + 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? diff --git a/src/ctaklm.c b/src/ctaklm.c index d790769..0948fa7 100644 --- a/src/ctaklm.c +++ b/src/ctaklm.c @@ -22,6 +22,7 @@ #include <string.h> #include <tak.h> +#include <tps.h> #include <negamax.h> static const char *blk = "\033[41m", *wht = "\033[44m"; @@ -220,7 +221,7 @@ handle_turn(char *line) { uint8_t new_win = (won == 0xFF); switch (do_ptn(line)) { // Errors - case PTN_INVALID: { puts("Invalid PTN."); return -1; break; } + case ACT_INVALID_PTN: { puts("Invalid PTN."); return -1; break; } case ACT_ILLEGAL: { puts("Illegal action."); return -1; break; } case ACT_OVERFLOW: { puts("Move would cause internal overflow, select another."); @@ -244,7 +245,6 @@ handle_turn(char *line) { break; } // Valid, append to game log - case PTN_VALID: case ACT_OK: { append_to_gamelog(line, 0); if (auto_board) print_board(); @@ -274,7 +274,7 @@ load_ptn(const char* fn) { if (fh == NULL) return EXIT_FAILURE; int space1, space2; - enum E_RESULT r; + enum ACT_RESULT r; ssize_t read; size_t alloc_size; @@ -315,7 +315,6 @@ load_ptn(const char* fn) { if (line) free(line); fclose(fh); - return EXIT_SUCCESS; } @@ -348,16 +347,12 @@ negamax_turn(void) { float minimax = negamax_generate(); putchar('\n'); // Failed to find a move? - if (minimax <= -infty) { - puts("Opponent failed to find a move!"); - return EXIT_FAILURE; - } else { - printf("Result: %s (%.2f, checked %.1e)\n", - negamax_ptn, - minimax*100.0, - num_check); - return handle_turn(negamax_ptn); - } + if (minimax <= -infty) puts("Opponent concedes!"); + printf("Result: %s (%.2f, checked %.1e)\n", + negamax_ptn, + minimax*100.0, + num_check); + return handle_turn(negamax_ptn); } else { return EXIT_FAILURE; } @@ -366,8 +361,9 @@ negamax_turn(void) { static int input_is_not_turn(const char *line) { if (!strcmp(line,"help")) { - puts("Valid commands: auto (board|info), board, depth [0-9], eval, help,\ -info, load, log, new, play (b|w), self-play, square <col><row>, <PTN>."); + puts("Valid commands: auto (board|info), board, depth [0-9], eval,\ + help, info, load <file.ptn>, log, new, play (b|w), self-play, square\ + <col><row>, tps, <PTN>."); } else if (!strcmp(line,"board")) { print_board(); } else if (!strcmp(line,"info")) { @@ -385,6 +381,10 @@ info, load, log, new, play (b|w), self-play, square <col><row>, <PTN>."); puts(gamelog); } else if (!strcmp(line,"new")) { new_game(5); + } else if (!strcmp(line,"tps")) { + char buf[1000]; + generate_tps(buf); + puts(buf); } else if (!strcmp(line,"self-play")) { while (negamax_turn() == 0); } else if (!strncmp(line,"depth",5)) { diff --git a/src/pptdb.c b/src/pptdb.c index e3fd687..bb94987 100644 --- a/src/pptdb.c +++ b/src/pptdb.c @@ -75,10 +75,10 @@ write_input(const int dx, const int dy, const uint8_t swap) { } // Warning: performs _no_ checks on input whatsoever -static enum E_RESULT +static enum ACT_RESULT parse_line(const char *pt, const ssize_t read) { ssize_t idx; - enum E_RESULT r; + enum ACT_RESULT r; int total_plies = 0; for (idx=0;idx<read;idx++) { @@ -159,7 +159,7 @@ This program comes with ABSOLUTELY NO WARRANTY; and is made available under the int main(int argc, char **argv) { (void)(argc); - enum E_RESULT r; + enum ACT_RESULT r; enum WIN_TYPE win; uint32_t games = 0, overflow=0, illegal = 0; uint32_t road_wins=0, flat_wins=0, road_turns=0, flat_turns=0, diff --git a/src/tei.c b/src/tei.c new file mode 100644 index 0000000..93c67ce --- /dev/null +++ b/src/tei.c @@ -0,0 +1,163 @@ +/* + ctaktei, a TEI interface to the ctak library & its computer opponent + + Copyright (C) 2021, tslil clingman + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <tak.h> +#include <tps.h> +#include <negamax.h> + +// Set up output function for negamax +inline void +negamax_display_progress(const uint8_t cur_depth, + const uint8_t init_depth, + const uint32_t length) { + (void)(cur_depth); + (void)(init_depth); + (void)(length); +} + +enum TEI_RETURN { TEI_QUIT, TEI_OK, TEI_FAILURE }; + +// expects ``(startpos|tps <tps>) moves <ptn>'' +static enum TEI_RETURN +parse_position_string(char *line) { + // Find the word ``moves'' + char *beg = strstr(line, "moves"); + + if (!strncasecmp(line, "tps", 3)) { + // Split the string on the space before moves + if (beg) *(beg-1) = 0; + // so that we can load it as a TPS description + load_tps(line + 4); + } else if (!strncasecmp(line, "startpos", 8)) { + reset_state(board_size); + } else { + return TEI_FAILURE; + } + + if (beg == NULL) return TEI_OK; + + // parse the PTN sequence + strtok(beg, " "); + char *ptn = strtok(NULL, " "); + while (ptn != NULL) { + if (do_ptn(ptn) != ACT_OK) return TEI_FAILURE; + ptn = strtok(NULL, " "); + } + + return TEI_OK; +} + +static enum TEI_RETURN +handle_tei(char *line) { + if (!strcmp(line, "quit")) { + return TEI_QUIT; + } if (!strcmp(line, "isready")) { + puts("readyok"); + } else if (!strncmp(line, "setoption Depth value ", 22)) { + negamax_search_depth = atoi(line + 23); + } else if (!strncmp(line, "go", 2)) { + // TODO: for now we ignore all of the parameters + float minimax = negamax_generate(); + enum ACT_RESULT r = do_ptn(negamax_ptn); + if (r != ACT_OK && r != GAME_END) return TEI_FAILURE; + printf("info score cp %f pv %s\nbestmove %s\n", + minimax, negamax_ptn, negamax_ptn); + } else if (!strncmp(line, "position", 8)) { + return parse_position_string(line + 9); + } else if (!strncmp(line, "teinewgame", 10)) { + if (line[11] != '5') return TEI_FAILURE; + const uint8_t size = line[11] - '0'; + if (size != board_size) { + negamax_free(); + reset_state(size); + negamax_init(size); + } else { + reset_state(size); + } + } + fflush(stdout); + return TEI_OK; +} + +const char* license = "ctaktei, a TEI interface to the ctak library & its computer opponent\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"; + +int main(int argc, char **argv) { + (void)(argc); + (void)(argv); + + puts(license); + + char *line = NULL; + ssize_t read = -1; + size_t alloc_size; + + // Wait for tei + while ((read = getline(&line, &alloc_size, stdin))) { + if (read > 0 && !strncmp("tei", line, 3)) { + break; + } else return EXIT_FAILURE; + } + + if (line) free(line); + line = NULL; + + // Identify ourselves, and send the options + puts("id name ct1986"); + puts("id author tslil clingman"); + puts("option name Depth type spin default 4 min 2 max 6"); + puts("teiok"); + fflush(stdout); + + // Set default option + negamax_search_depth = 4; + negamax_init(5); + reset_state(5); + + for (int playing = 1; playing;) { + if ((read = getline(&line, &alloc_size, stdin)) > 0) { + line[read-1] = 0; + switch (handle_tei(line)) { + case TEI_FAILURE: return EXIT_FAILURE; + case TEI_QUIT: playing = 0; // fall-through + case TEI_OK: { + if (line) { + free(line); + line = NULL; + } + break; + } + } + } else { + break; + } + } + + if (line) free(line); + negamax_free(); + + return EXIT_SUCCESS; +} |
