diff options
Diffstat (limited to 'src/ctlm.c')
| -rw-r--r-- | src/ctlm.c | 89 |
1 files changed, 47 insertions, 42 deletions
@@ -36,6 +36,9 @@ static const char *und = "\033[4m", *rst = "\033[0m"; #define CHAR_STN '/' #define CHAR_CAP '*' +static struct tak_state_s state_s; +static tak_state_p state = &state_s; + static void put_stone(const enum STONE_VARIANT stone, const enum COLOUR colour, const uint8_t top, const uint8_t beyond_carry_limit) { if (beyond_carry_limit) { @@ -64,8 +67,8 @@ static void put_stone(const enum STONE_VARIANT stone, const enum COLOUR colour, fputs(rst, stdout); } -static void print_cell_line(tak_state_p state, const uint8_t line, - const uint8_t col, const uint8_t row) { +static void print_cell_line(const uint8_t line, const uint8_t col, + const uint8_t row) { const uint8_t location = THE_COORDS(state->board_size, col, row), stack_size = COUNT_AT(state, location); @@ -97,7 +100,7 @@ static void print_cell_line(tak_state_p state, const uint8_t line, // It takes board_size*(SQUARE_H+1)+1 lines to print the board, they // may be requested in any order and at any time -static void print_board_line(tak_state_p state, const uint8_t line) { +static void print_board_line(const uint8_t line) { const uint8_t mod = line % (SQUARE_H + 1), row = state->board_size - line / (SQUARE_H + 1) - 1; @@ -121,7 +124,7 @@ static void print_board_line(tak_state_p state, const uint8_t line) { if (line < state->board_size * (SQUARE_H + 1)) { for (uint8_t x = 0; x < state->board_size; x++) { putchar('|'); - print_cell_line(state, mod - 1, x, row); + print_cell_line(mod - 1, x, row); } puts("|"); } else { @@ -139,15 +142,14 @@ static void print_board_line(tak_state_p state, const uint8_t line) { } // Simple wrapper to print the whole board in one go -static void print_board(tak_state_p state) { +static void print_board(void) { for (uint8_t k = 0; k < state->board_size * (SQUARE_H + 1) + 2; k++) { - print_board_line(state, k); + print_board_line(k); } } // Print the contents of a single square -static void print_square(tak_state_p state, const uint8_t col, - const uint8_t row) { +static void print_square(const uint8_t col, const uint8_t row) { if (row < state->board_size && col < state->board_size) { printf("%c%c: ", 'a' + col, '1' + row); const uint8_t stack_size = @@ -172,7 +174,7 @@ static void print_square(tak_state_p state, const uint8_t col, } } -static void print_info(tak_state_p state) { +static void print_info() { printf("Turn: %2d, %s%s%s%s\n", state->ply / 2 + 1, (state->ply & 1) ? blk : wht, (state->ply & 1) ? "Black" : "White", rst, (state->ply < 2) ? " (counter-play start)" : ""); @@ -185,8 +187,7 @@ static int human; static char *gamelog = NULL; static uint8_t auto_board = 0xFF, auto_info = 0xFF; -static int append_to_gamelog(tak_state_p state, 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' ? @@ -214,16 +215,16 @@ static int append_to_gamelog(tak_state_p state, const char *line, return EXIT_SUCCESS; } -static void end_game(tak_state_p state, char *line, char *win) { - append_to_gamelog(state, line, 0); - append_to_gamelog(state, win, 1); - print_board(state); +static void end_game(char *line, char *win) { + append_to_gamelog(line, 0); + append_to_gamelog(win, 1); + print_board(); puts("Game over:"); puts(gamelog); putchar('\n'); } -static int handle_turn(tak_state_p state, char *line) { +static int handle_turn(char *line) { // Track win state uint8_t new_win = (state->won == 0xFF); switch (do_ptn(state, line)) { @@ -246,23 +247,23 @@ static int handle_turn(tak_state_p state, char *line) { if (new_win) { switch (state->won) { case WIN_DRAW: { - end_game(state, line, "1/2-1/2"); + end_game(line, "1/2-1/2"); break; } case WIN_FLAT_BLACK: { - end_game(state, line, "0-F"); + end_game(line, "0-F"); break; } case WIN_FLAT_WHITE: { - end_game(state, line, "F-0"); + end_game(line, "F-0"); break; } case WIN_ROAD_BLACK: { - end_game(state, line, "0-R"); + end_game(line, "0-R"); break; } case WIN_ROAD_WHITE: { - end_game(state, line, "R-0"); + end_game(line, "R-0"); break; } } @@ -274,18 +275,18 @@ static int handle_turn(tak_state_p state, char *line) { } // Valid, append to game log case ACT_OK: { - append_to_gamelog(state, line, 0); + append_to_gamelog(line, 0); if (auto_board) - print_board(state); + print_board(); if (auto_info) - print_info(state); + print_info(); break; } } return EXIT_SUCCESS; } -static void new_game(tak_state_p state, uint8_t size) { +static void new_game(uint8_t size) { reset_state(state, size); printf("New %dx%d game! negamax at search depth %d.\n", size, size, negamax_search_depth); @@ -296,7 +297,7 @@ static void new_game(tak_state_p state, uint8_t size) { gamelog[0] = 0; } -static int load_ptn(tak_state_p state, const char *fn) { +static int load_ptn(const char *fn) { FILE *fh = NULL; fh = fopen(fn, "r"); @@ -325,14 +326,14 @@ static int load_ptn(tak_state_p state, const char *fn) { space2++; line[space2] = 0; // Try the first piece we found - r = handle_turn(state, line + space1); + r = handle_turn(line + space1); if (r) { printf("Error on: %s\n", line + space1); break; } // If there's a second piece, try it if (space2 + 1 < read) { - r = handle_turn(state, line + space2 + 1); + r = handle_turn(line + space2 + 1); if (r) { printf("Error on: %s", line + space2 + 1); break; @@ -384,21 +385,21 @@ static int negamax_turn(tak_state_p state) { puts("Opponent concedes!"); printf("Result: %s (%.2f, checked %.1e)\n", negamax_ptn, minimax * 100.0, num_check); - return handle_turn(state, negamax_ptn); + return handle_turn(negamax_ptn); } else { return EXIT_FAILURE; } } -static int input_is_not_turn(tak_state_p state, const char *line) { +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 <file.ptn>, log, new, play (b|w), self-play, square\ <col><row>, tps, <PTN>."); } else if (!strcmp(line, "board")) { - print_board(state); + print_board(); } else if (!strcmp(line, "info")) { - print_info(state); + print_info(); } else if (!strcmp(line, "eval")) { float eval = nn1986_evaluate_black_win(state) * 100; if (state->ply & 1) { @@ -408,8 +409,14 @@ help, info, load <file.ptn>, log, new, play (b|w), self-play, square\ } } else if (!strcmp(line, "log")) { puts(gamelog); - } else if (!strcmp(line, "new")) { - new_game(state, 5); + } else if (!strncmp(line, "new", 3)) { + if (strnlen(line, 5) == 5 && line[4] >= '5' && line[4] <= '6') { + new_game(line[4] - '0'); + negamax_free(); + negamax_init(state->board_size); + } else { + puts("Usage: size [56]."); + } } else if (!strcmp(line, "tps")) { char buf[1000]; generate_tps(state, buf); @@ -426,7 +433,7 @@ help, info, load <file.ptn>, log, new, play (b|w), self-play, square\ } } else if (!strncmp(line, "load", 4)) { if (strnlen(line, 6) >= 6) { - if (load_ptn(state, line + 5)) { + if (load_ptn(line + 5)) { printf("Errors in file %s\n", line); } } else { @@ -448,7 +455,7 @@ help, info, load <file.ptn>, log, new, play (b|w), self-play, square\ if (strnlen(line, 10) == 9 && line[7] >= 'a' && line[7] <= '`' + state->board_size && line[8] >= '1' && line[8] <= '0' + state->board_size) { - print_square(state, line[7] - 'a', line[8] - '1'); + print_square(line[7] - 'a', line[8] - '1'); } else { printf("Usage: square [a-%c][1-%c].\n", '`' + state->board_size, '0' + state->board_size); @@ -458,7 +465,7 @@ help, info, load <file.ptn>, log, new, play (b|w), self-play, square\ (line[5] == 'w' || line[5] == 'W'))) { // 'b' is even :) human = 1 - (line[5] & 1); - new_game(state, 5); + new_game(5); } else { puts("Usage: play (b|w)."); } @@ -480,10 +487,8 @@ int main(int argc, char **argv) { puts(license); - tak_state_p state = new_tak_state(5); - negamax_search_depth = 5; - new_game(state, 5); + new_game(5); negamax_init(5); char *line = NULL; @@ -498,8 +503,8 @@ int main(int argc, char **argv) { read = getline(&line, &alloc_size, stdin); if (read > 0) { line[read - 1] = 0; - if (input_is_not_turn(state, line)) { - int r = handle_turn(state, line); + if (input_is_not_turn(line)) { + int r = handle_turn(line); if (r == EXIT_SUCCESS && state->won == 0xFF) { human = 1; } |
