diff options
Diffstat (limited to 'src/geminict.c')
| -rw-r--r-- | src/geminict.c | 203 |
1 files changed, 105 insertions, 98 deletions
diff --git a/src/geminict.c b/src/geminict.c index 387c219..6f2d04b 100644 --- a/src/geminict.c +++ b/src/geminict.c @@ -39,6 +39,8 @@ #define STR_CHF_BLK "b" #define STR_CHF_WHT "w" +static tak_state_p state; + 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) { @@ -46,18 +48,18 @@ static void put_stone(const enum STONE_VARIANT stone, const enum COLOUR colour, } else { if (top) { switch (stone) { - case STONE_FLAT: { - fputs((colour == C_BLACK) ? STR_FLT_BLK : STR_FLT_WHT, stdout); - break; - } - case STONE_STANDING: { - fputs((colour == C_BLACK) ? STR_STN_BLK : STR_STN_WHT, stdout); - break; - } - case STONE_CAPSTONE: { - fputs((colour == C_BLACK) ? STR_CAP_BLK : STR_CAP_WHT, stdout); - break; - } + case STONE_FLAT: { + fputs((colour == C_BLACK) ? STR_FLT_BLK : STR_FLT_WHT, stdout); + break; + } + case STONE_STANDING: { + fputs((colour == C_BLACK) ? STR_STN_BLK : STR_STN_WHT, stdout); + break; + } + case STONE_CAPSTONE: { + fputs((colour == C_BLACK) ? STR_CAP_BLK : STR_CAP_WHT, stdout); + break; + } } } else { fputs((colour == C_BLACK) ? STR_HFL_BLK : STR_HFL_WHT, stdout); @@ -68,8 +70,8 @@ static void put_stone(const enum STONE_VARIANT stone, const enum COLOUR colour, static void print_cell_line(const uint8_t line, const uint8_t col, const uint8_t row) { - const uint8_t location = THE_COORDS(col, row), - stack_size = COUNT_AT(location); + const uint8_t location = THE_COORDS(5, col, row), + stack_size = COUNT_AT(state, location); uint8_t idx; for (uint8_t k = 0; k < SQUARE_W; k++) { @@ -87,20 +89,20 @@ static void print_cell_line(const uint8_t line, const uint8_t col, } } if (idx < stack_size) { - put_stone(STONE_AT(location), - (colours[location] & (1 << idx)) ? C_BLACK : C_WHITE, idx == 0, - idx >= board_size); + put_stone(STONE_AT(state, location), + (state->colours[location] & (1 << idx)) ? C_BLACK : C_WHITE, + idx == 0, idx >= 5); } else { putchar(' '); } } } -// It takes board_size*(SQUARE_H+1)+1 lines to print the board, they +// It takes 5*(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(const uint8_t line) { const uint8_t mod = line % (SQUARE_H + 1), - row = board_size - line / (SQUARE_H + 1) - 1; + row = 5 - line / (SQUARE_H + 1) - 1; // Print leader, either row number if half-way through square or // padding spaces otherwise @@ -111,7 +113,7 @@ static void print_board_line(const uint8_t line) { // Top and bottom of squares receive borders if (mod == 0) { - for (uint8_t x = 0; x < board_size; x++) { + for (uint8_t x = 0; x < 5; x++) { putchar('+'); for (uint8_t k = 0; k < SQUARE_W; k++) putchar('-'); @@ -119,15 +121,15 @@ static void print_board_line(const uint8_t line) { puts("+"); } else { // Interior of board should be filled by borders and pieces - if (line < board_size * (SQUARE_H + 1)) { - for (uint8_t x = 0; x < board_size; x++) { + if (line < 5 * (SQUARE_H + 1)) { + for (uint8_t x = 0; x < 5; x++) { putchar('|'); print_cell_line(mod - 1, x, row); } puts("|"); } else { // Bottom of board has column markers - for (uint8_t x = 0; x < board_size; x++) { + for (uint8_t x = 0; x < 5; x++) { for (uint8_t k = 0; k <= SQUARE_W / 2; k++) putchar(' '); printf("%c.", x + 'a'); @@ -141,19 +143,19 @@ static void print_board_line(const uint8_t line) { // Simple wrapper to print the whole board in one go static void print_board(void) { - for (uint8_t k = 0; k < board_size * (SQUARE_H + 1) + 2; k++) { + for (uint8_t k = 0; k < 5 * (SQUARE_H + 1) + 2; k++) { print_board_line(k); } putchar('\n'); } static void print_info(void) { - printf("Turn: %2d, %s%s\n", ply / 2 + 1, - (ply & 1) ? "Black" : "White", - (ply < 2) ? " (counter-play start)" : ""); - printf("Flats/Caps remaining: %02d/%d, %02d/%d\n", - white_count & 127, white_count >> 7, black_count & 127, - black_count >> 7); + printf("Turn: %2d, %s%s\n", state->ply / 2 + 1, + (state->ply & 1) ? "Black" : "White", + (state->ply < 2) ? " (counter-play start)" : ""); + printf("Flats/Caps remaining: %02d/%d, %02d/%d\n", state->white_count & 127, + state->white_count >> 7, state->black_count & 127, + state->black_count >> 7); } static char *gamelog = NULL; @@ -176,14 +178,15 @@ static int append_to_gamelog(const char *line, const uint8_t win_line) { 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); + realloc(gamelog, strlen(gamelog) + strlen(prepend) + strlen(line) + 1); // TODO: trap errno strcat(gamelog, prepend); strcat(gamelog, line); @@ -203,64 +206,64 @@ static void end_game(char *line, char *win) { enum TURN_RESULT { T_ERR, T_OK, T_WIN }; static enum TURN_RESULT handle_turn(char *line) { // Track win state - uint8_t new_win = (won == 0xFF); - switch (do_ptn(line)) { - // Errors - case ACT_INVALID_PTN: { - puts("Invalid PTN."); - return T_ERR; - } - case ACT_ILLEGAL: { - puts("Illegal action."); - return T_ERR; - } - case ACT_OVERFLOW: { - puts("Move would cause internal overflow, select another."); - return T_ERR; - } - // 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 T_WIN; + uint8_t new_win = (state->won == 0xFF); + switch (do_ptn(state, line)) { + // Errors + case ACT_INVALID_PTN: { + puts("Invalid PTN."); + return T_ERR; + } + case ACT_ILLEGAL: { + puts("Illegal action."); + return T_ERR; + } + case ACT_OVERFLOW: { + puts("Move would cause internal overflow, select another."); + return T_ERR; + } + // 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; } - if (!new_win) - return T_ERR; - break; - } - // Valid, append to game log - case ACT_OK: { - append_to_gamelog(line, 0); - 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 T_WIN; } + if (!new_win) + return T_ERR; + break; + } + // Valid, append to game log + case ACT_OK: { + append_to_gamelog(line, 0); + break; + } } return T_OK; } static void new_game(uint8_t size) { - reset_state(size); + reset_state(state, size); if (gamelog) gamelog = realloc(gamelog, sizeof(char)); else @@ -281,16 +284,16 @@ inline void negamax_display_progress(const uint8_t cur_depth, } static enum TURN_RESULT negamax_turn(void) { - if (won == 0xFF) { + if (state->won == 0xFF) { // Run the minimax num_check = 0; - float minimax = negamax_generate(); + float minimax = negamax_generate(state); putchar('\n'); // Failed to find a non-losing move? if (minimax <= -infty) puts("Opponent concedes!"); - printf("ct1986 says: %s (minmax %.2f, checked %.1e)\n\n", negamax_ptn, minimax * 100.0, - num_check); + printf("ct1986 says: %s (minmax %.2f, checked %.1e)\n\n", negamax_ptn, + minimax * 100.0, num_check); return handle_turn(negamax_ptn); } else { return T_ERR; @@ -303,13 +306,14 @@ int main(int argc, char **argv) { return EXIT_FAILURE; }; + state = new_tak_state(5); negamax_search_depth = 5; new_game(5); negamax_init(5); enum TURN_RESULT tr; - char* line = argv[1]; + char *line = argv[1]; // Some maximum length we're willing to parse uint32_t len = strnlen(line, 65535); if (!line || len < 2 || len == 65535) { @@ -318,7 +322,7 @@ int main(int argc, char **argv) { } // strip quotes - if (line[0]=='\'') { + if (line[0] == '\'') { line++; len--; } else { @@ -326,8 +330,8 @@ int main(int argc, char **argv) { return EXIT_FAILURE; } - if (line[len-1]=='\'') { - line[len-1]=0; + if (line[len - 1] == '\'') { + line[len - 1] = 0; len--; } else { puts("Malformed input."); @@ -337,7 +341,8 @@ int main(int argc, char **argv) { uint32_t start = 0, end = 0; while (start < len) { // Find first separator - while (end < len && line[end] != '.') end++; + while (end < len && line[end] != '.') + end++; // If still on line if (end < len) { // Mark the split @@ -345,10 +350,11 @@ int main(int argc, char **argv) { // Try the first piece we found tr = handle_turn(line + start); if (tr == T_ERR) { - printf("Error on: %s\n", line + start); - print_everything(); - return EXIT_FAILURE; - } else if (tr == T_WIN) return EXIT_SUCCESS; + printf("Error on: %s\n", line + start); + print_everything(); + return EXIT_FAILURE; + } else if (tr == T_WIN) + return EXIT_SUCCESS; start = ++end; } else { puts("Malformed input."); @@ -362,7 +368,8 @@ int main(int argc, char **argv) { puts("This shouldn't happen, ct1986 encountered an error."); print_everything(); return EXIT_FAILURE; - } else if (tr == T_WIN) return EXIT_SUCCESS; + } else if (tr == T_WIN) + return EXIT_SUCCESS; print_everything(); |
