aboutsummaryrefslogtreecommitdiff
path: root/gnu/games/chess/Xchess/parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/games/chess/Xchess/parse.c')
-rw-r--r--gnu/games/chess/Xchess/parse.c386
1 files changed, 386 insertions, 0 deletions
diff --git a/gnu/games/chess/Xchess/parse.c b/gnu/games/chess/Xchess/parse.c
new file mode 100644
index 000000000000..19f473952e6c
--- /dev/null
+++ b/gnu/games/chess/Xchess/parse.c
@@ -0,0 +1,386 @@
+/* This file contains code for X-CHESS.
+ Copyright (C) 1986 Free Software Foundation, Inc.
+
+This file is part of X-CHESS.
+
+X-CHESS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY. No author or distributor
+accepts responsibility to anyone for the consequences of using it
+or for whether it serves any particular purpose or works at all,
+unless he says so in writing. Refer to the X-CHESS General Public
+License for full details.
+
+Everyone is granted permission to copy, modify and redistribute
+X-CHESS, but only under the conditions described in the
+X-CHESS General Public License. A copy of this license is
+supposed to have been given to you along with X-CHESS so you
+can know your rights and responsibilities. It should be in a
+file named COPYING. Among other things, the copyright notice
+and this notice must be preserved on all copies. */
+
+
+/* RCS Info: $Revision: 1.1.1.1 $ on $Date: 1993/06/12 14:41:06 $
+ * $Source: /home/cvs/386BSD/src/gnu/games/chess/Xchess/parse.c,v $
+ * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group
+ * Permission is granted to do anything with this code except sell it
+ * or remove this message.
+ *
+ * Parse a sequence of chess moves...
+ */
+
+#include "xchess.h"
+
+bool loading_flag = false;
+bool loading_paused = false;
+
+static char *line;
+
+/* Load a record file in. This returns a number of things -- the board, the
+ * list of moves, and whose turn it is.
+ */
+
+void
+load_game(file)
+ char *file;
+{
+ FILE *fp;
+ char buf[BSIZE];
+ bool eflag;
+ move *m;
+ board *tmpboard = alloc(board);
+
+ if (eq(file, "xchess.game") && saveflag) {
+ message_add(win1,
+ "Oops, I just overwrote the\nfile xchess.game...\n",
+ true);
+ message_add(win1, "I hope you had another copy.\n", true);
+ return;
+ }
+ if (!(fp = fopen(file, "r"))) {
+ perror(file);
+ return;
+ }
+
+ /* Get a few lines... */
+ fgets(buf, BSIZE, fp);
+ message_add(win1, buf, false);
+ if (!oneboard)
+ message_add(win2, buf, false);
+
+ fgets(buf, BSIZE, fp);
+ message_add(win1, buf, false);
+ if (!oneboard)
+ message_add(win2, buf, false);
+
+ fgets(buf, BSIZE, fp);
+ if (eq(buf, "\tenglish\n"))
+ eflag = true;
+ else if (eq(buf, "\talgebraic\n"))
+ eflag = false;
+ else {
+ fprintf(stderr, "Can't decide whether this is english...\n");
+ return;
+ }
+
+ board_init(tmpboard);
+ line = NULL;
+ m = parse_file(fp, tmpboard, eflag);
+ tfree(tmpboard);
+
+ /* Now apply these moves to the board we were given... */
+ loading_flag = true;
+ while (m) {
+ if (!quickflag)
+ XSync(win1->display, 0);
+ win_process(true);
+ if (!quickflag)
+ sleep(1);
+ if (!loading_paused) {
+ prog_move(m);
+ m = m->next;
+ }
+ }
+ loading_flag = false;
+ if (line)
+ message_add(win1, line, false);
+
+ while (fgets(buf, BSIZE, fp))
+ message_add(win1, buf, false);
+
+ fclose(fp);
+
+ return;
+}
+
+/* Given a starting position (usually the beginning board configuration),
+ * read in a file of moves.
+ */
+
+move *
+parse_file(fp, b, english)
+ FILE *fp;
+ board *b;
+ bool english;
+{
+ move *mvs = NULL, *end = NULL;
+ char buf[BSIZE], *s, *t;
+
+ while (fgets(buf, BSIZE, fp)) {
+ if (*buf == '#')
+ continue;
+ s = buf;
+
+ /* The move number... */
+ if (!(t = gettok(&s)))
+ break;
+ if (!isdigit(*t)) {
+ line = copy(buf);
+ break;
+ }
+
+ if (!(t = gettok(&s)))
+ break;
+ if (end)
+ end = end->next = (english ? parse_move(b, t, WHITE) :
+ parse_imove(b, t, WHITE));
+ else
+ mvs = end = (english ? parse_move(b, t, WHITE) :
+ parse_imove(b, t, WHITE));
+ if (!end) {
+ fprintf(stderr, "Can't parse %s\n", buf);
+ return (NULL);
+ }
+ board_move(b, end);
+
+ if (!(t = gettok(&s)))
+ break;
+ if (end)
+ end = end->next = (english ? parse_move(b, t, BLACK) :
+ parse_imove(b, t, BLACK));
+ else
+ mvs = end = (english ? parse_move(b, t, BLACK) :
+ parse_imove(b, t, BLACK));
+ if (!end) {
+ fprintf(stderr, "Can't parse %s\n", buf);
+ return (NULL);
+ }
+ board_move(b, end);
+ }
+
+ return (mvs);
+}
+
+/* Parse a move. The move format accepted is as follows -
+ * move: spec-spec
+ * capture: specxspec
+ * kcastle: 2 o's
+ * qcastle: 3 o's
+ * A spec is either piece/pos, piece, or just pos. A pos consists of a column
+ * name followed by a row number. If the column name is kr, kn, kb, k, q,
+ * qb, qn, or qr, then the row number is according to the english system,
+ * or if it is a-h then it is according to the international system.
+ *
+ *** As of now the spec must include the position.
+ */
+
+move *
+parse_move(b, str, w)
+ board *b;
+ char *str;
+ color w;
+{
+ move *m = alloc(move);
+ char *s;
+ char spec1[16], spec2[16];
+ int i, j;
+
+if (debug) fprintf(stderr, "parsing %s\n", str);
+
+ /* Check for castles. */
+ for (s = str, i = 0; *s; s++)
+ if ((*s == 'o') || (*s == 'O'))
+ i++;
+ if (i == 2) {
+ m->type = KCASTLE;
+ m->piece.type = KING;
+ m->piece.color = w;
+ return (m);
+ } else if (i == 3) {
+ m->type = QCASTLE;
+ m->piece.type = KING;
+ m->piece.color = w;
+ return (m);
+ }
+ if (index(str, '-'))
+ m->type = MOVE;
+ else if (index(str, 'x'))
+ m->type = CAPTURE;
+ else
+ return (NULL);
+ for (i = 0; str[i]; i++)
+ if ((str[i] == 'x') || (str[i] == '-'))
+ break;
+ else
+ spec1[i] = str[i];
+ spec1[i] = '\0';
+ for (i++, j = 0; str[i]; i++, j++)
+ if ((str[i] == 'x') || (str[i] == '-'))
+ break;
+ else
+ spec2[j] = str[i];
+ spec2[j] = '\0';
+
+ /* Now decode the specifications. */
+ s = spec1;
+ switch (*s) {
+ case 'p': case 'P':
+ m->piece.type = PAWN; break;
+ case 'r': case 'R':
+ m->piece.type = ROOK; break;
+ case 'n': case 'N':
+ m->piece.type = KNIGHT; break;
+ case 'b': case 'B':
+ m->piece.type = BISHOP; break;
+ case 'q': case 'Q':
+ m->piece.type = QUEEN; break;
+ case 'k': case 'K':
+ m->piece.type = KING; break;
+ default:
+ return (NULL);
+ }
+ m->piece.color = w;
+ s += 2;
+
+ /* Now get the {q,k}{,b,n,r}n string... */
+ if ((s[0] == 'q') && (s[1] == 'r'))
+ m->fromx = 0, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'n'))
+ m->fromx = 1, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'b'))
+ m->fromx = 2, s += 2;
+ else if ((s[0] == 'q') && isdigit(s[1]))
+ m->fromx = 3, s += 1;
+ else if ((s[0] == 'k') && isdigit(s[1]))
+ m->fromx = 4, s += 1;
+ else if ((s[0] == 'k') && (s[1] == 'b'))
+ m->fromx = 5, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'n'))
+ m->fromx = 6, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'r'))
+ m->fromx = 7, s += 2;
+ m->fromy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1));
+
+ if ((b->square[m->fromy][m->fromx].color != w) ||
+ (b->square[m->fromy][m->fromx].type != m->piece.type)) {
+ fprintf(stderr, "Error: bad stuff\n");
+ return (NULL);
+ }
+
+ s = spec2;
+ if (m->type == CAPTURE) {
+ switch (*s) {
+ case 'p': case 'P':
+ m->taken.type = PAWN; break;
+ case 'r': case 'R':
+ m->taken.type = ROOK; break;
+ case 'n': case 'N':
+ m->taken.type = KNIGHT; break;
+ case 'b': case 'B':
+ m->taken.type = BISHOP; break;
+ case 'q': case 'Q':
+ m->taken.type = QUEEN; break;
+ case 'k': case 'K':
+ m->taken.type = KING; break;
+ default:
+ return (NULL);
+ }
+ m->taken.color = ((w == WHITE) ? BLACK : WHITE);
+ s += 2;
+ }
+
+ /* Now get the {q,k}{,b,n,r}n string... */
+ if ((s[0] == 'q') && (s[1] == 'r'))
+ m->tox = 0, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'n'))
+ m->tox = 1, s += 2;
+ else if ((s[0] == 'q') && (s[1] == 'b'))
+ m->tox = 2, s += 2;
+ else if ((s[0] == 'q') && isdigit(s[1]))
+ m->tox = 3, s += 1;
+ else if ((s[0] == 'k') && isdigit(s[1]))
+ m->tox = 4, s += 1;
+ else if ((s[0] == 'k') && (s[1] == 'b'))
+ m->tox = 5, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'n'))
+ m->tox = 6, s += 2;
+ else if ((s[0] == 'k') && (s[1] == 'r'))
+ m->tox = 7, s += 2;
+ m->toy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1));
+
+ if ((m->type == CAPTURE) && ((b->square[m->toy][m->tox].color !=
+ m->taken.color) || (b->square[m->toy][m->tox].type !=
+ m->taken.type))) {
+ fprintf(stderr, "Error: bad stuff\n");
+ return (NULL);
+ }
+
+ return (m);
+}
+
+/* Parse an algebraic notation move. This is a lot easier... */
+
+move *
+parse_imove(b, buf, w)
+ board *b;
+ char *buf;
+ color w;
+{
+ char *s;
+ move *m = alloc(move);
+ int n;
+
+if (debug) fprintf(stderr, "(alg) parsing %s\n", buf);
+
+ for (s = buf, n = 0; *s; s++)
+ if ((*s == 'o') || (*s == 'O'))
+ n++;
+ s = buf;
+
+ if (n == 2)
+ m->type = KCASTLE;
+ else if (n == 3)
+ m->type = QCASTLE;
+ else {
+ m->fromx = *s++ - 'a';
+ m->fromy = SIZE - (*s++ - '0');
+ m->tox = *s++ - 'a';
+ m->toy = SIZE - (*s++ - '0');
+ m->piece = b->square[m->fromy][m->fromx];
+ m->taken = b->square[m->toy][m->tox];
+ if (m->taken.color == NONE)
+ m->type = MOVE;
+ else
+ m->type = CAPTURE;
+ /* for pawns we must account for en passant */
+ if (m->piece.type == PAWN) {
+ if (m->type == MOVE && m->fromx != m->tox) {
+ m->enpassant = 1;
+ m->type = CAPTURE;
+ }
+ }
+ }
+
+ if (m->piece.color != w) {
+ fprintf(stderr, "Error: parse_imove: piece of wrong color!\n");
+ return (NULL);
+ }
+ if ((m->piece.type == KING) && (m->fromy == m->toy) && (m->fromx == 4)
+ && (m->tox == 6))
+ m->type = KCASTLE;
+ else if ((m->piece.type == KING) && (m->fromy == m->toy) &&
+ (m->fromx == 4) && (m->tox == 2))
+ m->type = QCASTLE;
+
+ return (m);
+}
+