aboutsummaryrefslogtreecommitdiff
path: root/src/geminict.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/geminict.c')
-rw-r--r--src/geminict.c203
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();