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