aboutsummaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/ct1986.c3
-rw-r--r--src/ctlm.c89
-rw-r--r--src/cttei.c3
-rw-r--r--src/geminict.c4
-rw-r--r--src/nn_train.py31
5 files changed, 69 insertions, 61 deletions
diff --git a/src/ct1986.c b/src/ct1986.c
index 8a49ec1..d8b91db 100644
--- a/src/ct1986.c
+++ b/src/ct1986.c
@@ -30,7 +30,8 @@
static int human;
static char *gamelog = 0;
-tak_state_p state;
+static struct tak_state_s state_s;
+static tak_state_p state = &state_s;
static void new_game(uint8_t size) {
reset_state(state, size);
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;
}
diff --git a/src/cttei.c b/src/cttei.c
index f7fafa6..26250f8 100644
--- a/src/cttei.c
+++ b/src/cttei.c
@@ -137,7 +137,8 @@ int main(int argc, char **argv) {
fflush(stdout);
// Set default option
- tak_state_p state = new_tak_state(5);
+ struct tak_state_s state_s;
+ tak_state_p state = &state_s;
negamax_search_depth = 4;
negamax_init(5);
reset_state(state, 5);
diff --git a/src/geminict.c b/src/geminict.c
index 6f2d04b..2e94e7d 100644
--- a/src/geminict.c
+++ b/src/geminict.c
@@ -39,7 +39,8 @@
#define STR_CHF_BLK "b"
#define STR_CHF_WHT "w"
-static tak_state_p state;
+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) {
@@ -306,7 +307,6 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
};
- state = new_tak_state(5);
negamax_search_depth = 5;
new_game(5);
negamax_init(5);
diff --git a/src/nn_train.py b/src/nn_train.py
index f2550b4..03852f5 100644
--- a/src/nn_train.py
+++ b/src/nn_train.py
@@ -56,7 +56,7 @@ def train(size, model, data, iterations=1, epochs=10, batch=None):
tra_res = model.evaluate(tra_input, tra_outcome, verbose=False)
results.append((tra_res, val_res))
print(val_res)
- write_weights(model, str(i+1).zfill(len(str(iterations))), (tra_res, val_res))
+ write_weights(size, model, str(i+1).zfill(len(str(iterations))), (tra_res, val_res))
print("\nScores")
for i, data in enumerate(results):
print(f"Iteration {i+1}: {data}")
@@ -74,33 +74,34 @@ def make_model(size, magic):
return model
-def write_weights(model, iteration, performance):
+def write_weights(size, model, iteration, performance):
def fix(val):
string = str(np.array(val).tolist())
string = string.replace("[", "{").replace("]", "}")
return string
- dense1_weights = transpose(model.trainable_variables[0], perm=[1, 0])
- dense1_biases = model.trainable_variables[1]
+ size_str = "five" if size==5 else "six"
+ dense_weights = transpose(model.trainable_variables[0], perm=[1, 0])
+ dense_biases = model.trainable_variables[1]
output_weights = transpose(model.trainable_variables[2], perm=[1, 0])
output_bias = model.trainable_variables[3]
# Prepare output
- to_output = [("dense1_weights[DENSE_NUM][INP_NUM]", dense1_weights),
- ("dense1_biases[DENSE_NUM]", dense1_biases),
- ("output_weights[2][DENSE_NUM]", output_weights),
- ("output_bias[2]", output_bias)]
+ to_output = [(f"{size_str}_dense_weights[{size_str.upper()}_DENSE_NUM][{size_str.upper()}_INP_NUM]", dense_weights),
+ (f"{size_str}_dense_biases[{size_str.upper()}_DENSE_NUM]", dense_biases),
+ (f"{size_str}_output_weights[2][{size_str.upper()}_DENSE_NUM]", output_weights),
+ (f"{size_str}_output_bias[2]", output_bias)]
# Write to file
- f = open("weights-"+iteration+".txt", "w")
+ f = open(f"{size_str}_weights-"+iteration+".txt", "w")
f.write("/*\n")
model.summary(print_fn=lambda l: f.write(" * "+l+"\n"))
f.write(" * "+str(performance)+"\n*/\n\n")
- f.write("#include \"weights.h\"\n\n")
+ f.write(f"#include \"weights_{size}.h\"\n\n")
for (name, val) in to_output:
f.write("const float "+name+" =\n"+fix(val)+";\n\n")
f.close()
-data = load_data(5)
-model = make_model(5, 64)
-
-print("Before training", model.evaluate(data[1][0], data[1][1], verbose=False, batch_size=16))
-results = train(5, model, data, iterations=5, epochs=10, batch=128)
+for size in (5,6):
+ data = load_data(size)
+ model = make_model(size, 64)
+ print("Before training", model.evaluate(data[1][0], data[1][1], verbose=False, batch_size=16))
+ results = train(size, model, data, iterations=5, epochs=10, batch=128)