aboutsummaryrefslogtreecommitdiff
path: root/src/ctlm.c
diff options
context:
space:
mode:
authortslil clingman <tslil@posteo.de>2023-01-21 19:30:45 +0100
committertslil <tslil@posteo.de>2026-08-28 19:37:41 +0100
commit0e81096d5ecb6027814e7aae10b461e774f96407 (patch)
tree6cedfe4b3fad3770a5210f5e5d5ad205c17f4b0f /src/ctlm.c
parentcb2b78ced27fc7996ed11c3450f69138d7d1b61f (diff)
might as well enable size 6
Same network architecture, same training principle. Predictably this is too slow. Also statically allocate state in driver programmes.
Diffstat (limited to 'src/ctlm.c')
-rw-r--r--src/ctlm.c89
1 files changed, 47 insertions, 42 deletions
diff --git a/src/ctlm.c b/src/ctlm.c
index fa27274..dc4a17e 100644
--- a/src/ctlm.c
+++ b/src/ctlm.c
@@ -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;
}