ref: c1ded1119a9e646894d398e0e833624969a1afef
parent: e0a7e3b7a9c0258a03edc4ff5d4de372ae7f3213
author: zamfofex <zamfofex@twdb.moe>
date: Sun Oct 13 22:45:54 EDT 2024
add preliminary PGN support to analysis TUI
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,4 @@
!/tools/https.c
!/tools/perft.c
!/tools/learn.c
+!/tools/pgn.c
--- a/makefile
+++ b/makefile
@@ -19,6 +19,7 @@
$(cc) $(filter %.c,$^) -o $@ $(cflags) -D_POSIX_C_SOURCE=200809L
play analyse: cflags := -pthread
+analyse: tools/pgn.c
lichess chat: tools/https.c
lichess: cflags := -ltls -lssl -lcrypto -lcjson
chat: cflags := -ltls -lssl -lcrypto
--- a/tools/analyse.c
+++ b/tools/analyse.c
@@ -570,6 +570,8 @@
{int i;
+ if (fancy->in == NULL) return;
+
fancy->taken = 0;
if (fancy->idle == 0) fancy->stop = 1;
@@ -644,6 +646,7 @@
static struct moonfish_arg args[] =
{ {"F", "fen", "<FEN>", NULL, "the position to analyse"},+ {"G", "pgn", "<file-name>", NULL, "PGN game to load"}, {NULL, NULL, NULL, NULL, NULL},};
@@ -660,6 +663,7 @@
char *value;
char **options;
int i;
+ FILE *file;
/* handle command line arguments */
@@ -668,6 +672,8 @@
if (command_count < 1) moonfish_usage(args, format, argv[0]);
options = command;
+ if (args[0].value != NULL && args[1].value != NULL) moonfish_usage(args, format, argv[0]);
+
for (;;)
{value = strchr(*command, '=');
@@ -704,6 +710,9 @@
fancy->pv[0] = 0;
fancy->idle = 1;
fancy->stop = 0;
+ fancy->fen = NULL;
+ fancy->in = NULL;
+ fancy->out = NULL;
fancy->x = 0;
fancy->y = 0;
@@ -722,14 +731,39 @@
fancy->plies[0].best[0] = 0;
moonfish_chess(&fancy->plies[0].chess);
- if (args[0].value == NULL)
+
+ if (args[0].value != NULL)
{- fancy->fen = NULL;
+ fancy->fen = args[0].value;
+ if (moonfish_from_fen(&fancy->plies[0].chess, fancy->fen) != 0)
+ {+ fprintf(stderr, "%s: invalid FEN\n", argv[0]);
+ }
}
- else
+
+ if (args[1].value != NULL)
{- fancy->fen = args[0].value;
- moonfish_from_fen(&fancy->plies[0].chess, fancy->fen);
+ file = fopen(args[1].value, "r");
+ if (file == NULL)
+ {+ perror(argv[0]);
+ return 1;
+ }
+
+ for (;;)
+ {+ if (moonfish_pgn(file, &fancy->plies[fancy->i].chess, &move, fancy->i == 0 ? 1 : 0) != 0) break;
+ moonfish_play(fancy, &move);
+ }
+
+ fancy->fen = malloc(128);
+ if (fancy->fen == NULL)
+ {+ perror(argv[0]);
+ return 1;
+ }
+
+ moonfish_to_fen(&fancy->plies[0].chess, fancy->fen);
}
/* configure the terminal for displaying the user interface */
--- /dev/null
+++ b/tools/pgn.c
@@ -1,0 +1,192 @@
+/* moonfish is licensed under the AGPL (v3 or later) */
+/* copyright 2023, 2024 zamfofex */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "../moonfish.h"
+#include "tools.h"
+
+static int moonfish_pgn_token(FILE *file)
+{+ int ch;
+
+ for (;;)
+ {+ ch = getc(file);
+ if (ch == EOF) return ch;
+
+ if (ch == '{')+ {+ for (;;)
+ {+ ch = getc(file);
+ if (ch == EOF) return ch;
+ if (ch == '}') break;
+ }
+ continue;
+ }
+
+ if (ch == ';')
+ {+ for (;;)
+ {+ ch = getc(file);
+ if (ch == EOF) return ch;
+ if (ch == '\r' || ch == '\n') break;
+ }
+ continue;
+ }
+
+ if (strchr("\r\n\t ", ch) == NULL) return ch;+ }
+}
+
+static int moonfish_isalnum(int ch)
+{+ if (ch == '-' || ch == '_' || ch == '/') return 1;
+ if (isalnum(ch)) return 1;
+ return 0;
+}
+
+static int moonfish_pgn_skip(FILE *file, int ch)
+{+ if (ch == '"')
+ {+ for (;;)
+ {+ ch = getc(file);
+ if (ch == '\\') ch = getc(file);
+ if (ch == EOF) return 1;
+ if (ch == '"') break;
+ }
+ return 0;
+ }
+
+ if (ch == '(')+ {+ for (;;)
+ {+ ch = moonfish_pgn_token(file);
+ if (ch == EOF) return 1;
+ if (ch == ')') break;
+ }
+ return 0;
+ }
+
+ for (;;)
+ {+ ch = getc(file);
+ if (ch == EOF) return 1;
+ if (moonfish_isalnum(ch) == 0) return 0;
+ }
+}
+
+int moonfish_pgn(FILE *file, struct moonfish_chess *chess, struct moonfish_move *move, int allow_attr)
+{+ int i;
+ char buffer[256];
+ int ch;
+
+ ch = moonfish_pgn_token(file);
+
+ for (;;)
+ {+ if (ch == EOF) return -1;
+ if (ch == '*') return 1;
+
+ if (moonfish_isalnum(ch) != 0)
+ {+ i = 0;
+ buffer[i++] = ch;
+
+ for (;;)
+ {+ ch = getc(file);
+ if (moonfish_isalnum(ch) == 0) break;
+ if (i >= (int) sizeof buffer - 1) break;
+ buffer[i++] = ch;
+ }
+
+ buffer[i] = 0;
+
+ if (!strcmp(buffer, "1/2-1/2")) return 1;
+ if (!strcmp(buffer, "1-0")) return 1;
+ if (!strcmp(buffer, "0-1")) return 1;
+
+ if (buffer[0] >= '0' && buffer[0] <= '9')
+ {+ ch = moonfish_pgn_token(file);
+ continue;
+ }
+
+ if (moonfish_from_san(chess, move, buffer) != 0) return -1;
+ return 0;
+ }
+
+ if (ch == '[')
+ {+ if (allow_attr == 0) return -1;
+
+ i = 0;
+ ch = moonfish_pgn_token(file);
+ if (ch == EOF) return -1;
+ if (moonfish_isalnum(ch) == 0) return -1;
+ buffer[i++] = ch;
+
+ for (;;)
+ {+ ch = moonfish_pgn_token(file);
+ if (ch == EOF) return -1;
+ if (moonfish_isalnum(ch) == 0) break;
+ if (i >= (int) sizeof buffer - 1)
+ {+ if (moonfish_pgn_skip(file, ch) != 0) return -1;
+ break;
+ }
+ buffer[i++] = ch;
+ }
+
+ buffer[i] = 0;
+ if (strcmp(buffer, "FEN"))
+ {+ for (;;)
+ {+ ch = moonfish_pgn_token(file);
+ if (ch == EOF) return -1;
+ if (ch == ']') break;
+ if (moonfish_pgn_skip(file, ch) != 0) return -1;
+ }
+
+ ch = moonfish_pgn_token(file);
+ continue;
+ }
+
+ i = 0;
+ ch = moonfish_pgn_token(file);
+ if (ch != '"') return -1;
+
+ for (;;)
+ {+ ch = getc(file);
+ if (ch == '"') break;
+ if (ch == '\\') ch = getc(file);
+ if (ch == EOF) return -1;
+ if (i >= (int) sizeof buffer - 1) return -1;
+ buffer[i++] = ch;
+ }
+
+ buffer[i] = 0;
+ if (moonfish_from_fen(chess, buffer) != 0) return -1;
+
+ ch = moonfish_pgn_token(file);
+ if (ch != ']') return -1;
+
+ ch = moonfish_pgn_token(file);
+ continue;
+ }
+
+ moonfish_pgn_skip(file, ch);
+ ch = moonfish_pgn_token(file);
+ }
+}
--- a/tools/tools.h
+++ b/tools/tools.h
@@ -15,6 +15,9 @@
char *description;
};
+struct moonfish_chess;
+struct moonfish_move;
+
void moonfish_spawn(char **argv, FILE **in, FILE **out, char *directory);
char *moonfish_next(FILE *file);
@@ -23,5 +26,7 @@
void moonfish_usage(struct moonfish_arg *args, char *rest_format, char *argv0);
int moonfish_int(char *arg, int *result);
+
+int moonfish_pgn(FILE *file, struct moonfish_chess *chess, struct moonfish_move *move, int allow_attr);
#endif
--
⑨