|
|
1.1 ! root 1: /* This file contains code for X-CHESS. ! 2: Copyright (C) 1986 Free Software Foundation, Inc. ! 3: ! 4: This file is part of X-CHESS. ! 5: ! 6: X-CHESS is distributed in the hope that it will be useful, ! 7: but WITHOUT ANY WARRANTY. No author or distributor ! 8: accepts responsibility to anyone for the consequences of using it ! 9: or for whether it serves any particular purpose or works at all, ! 10: unless he says so in writing. Refer to the X-CHESS General Public ! 11: License for full details. ! 12: ! 13: Everyone is granted permission to copy, modify and redistribute ! 14: X-CHESS, but only under the conditions described in the ! 15: X-CHESS General Public License. A copy of this license is ! 16: supposed to have been given to you along with X-CHESS so you ! 17: can know your rights and responsibilities. It should be in a ! 18: file named COPYING. Among other things, the copyright notice ! 19: and this notice must be preserved on all copies. */ ! 20: ! 21: ! 22: /* RCS Info: $Revision: 1.2 $ on $Date: 86/11/23 17:17:59 $ ! 23: * $Source: /users/faustus/xchess/RCS/parse.c,v $ ! 24: * Copyright (c) 1986 Wayne A. Christopher, U. C. Berkeley CAD Group ! 25: * Permission is granted to do anything with this code except sell it ! 26: * or remove this message. ! 27: * ! 28: * Parse a sequence of chess moves... ! 29: */ ! 30: ! 31: #include "xchess.h" ! 32: ! 33: bool loading_flag = false; ! 34: bool loading_paused = false; ! 35: ! 36: static char *line; ! 37: ! 38: /* Load a record file in. This returns a number of things -- the board, the ! 39: * list of moves, and whose turn it is. ! 40: */ ! 41: ! 42: void ! 43: load_game(file) ! 44: char *file; ! 45: { ! 46: FILE *fp; ! 47: char buf[BSIZE]; ! 48: bool eflag; ! 49: move *m; ! 50: board *tmpboard = alloc(board); ! 51: ! 52: if (eq(file, "xchess.game") && saveflag) { ! 53: message_add(win1, ! 54: "Oops, I just overwrote the\nfile xchess.game...\n", ! 55: true); ! 56: message_add(win1, "I hope you had another copy.\n", true); ! 57: return; ! 58: } ! 59: if (!(fp = fopen(file, "r"))) { ! 60: perror(file); ! 61: return; ! 62: } ! 63: ! 64: /* Get a few lines... */ ! 65: fgets(buf, BSIZE, fp); ! 66: message_add(win1, buf, false); ! 67: if (!oneboard) ! 68: message_add(win2, buf, false); ! 69: ! 70: fgets(buf, BSIZE, fp); ! 71: message_add(win1, buf, false); ! 72: if (!oneboard) ! 73: message_add(win2, buf, false); ! 74: ! 75: fgets(buf, BSIZE, fp); ! 76: if (eq(buf, "\tenglish\n")) ! 77: eflag = true; ! 78: else if (eq(buf, "\talgebraic\n")) ! 79: eflag = false; ! 80: else { ! 81: fprintf(stderr, "Can't decide whether this is english...\n"); ! 82: return; ! 83: } ! 84: ! 85: board_init(tmpboard); ! 86: line = NULL; ! 87: m = parse_file(fp, tmpboard, eflag); ! 88: tfree(tmpboard); ! 89: ! 90: /* Now apply these moves to the board we were given... */ ! 91: loading_flag = true; ! 92: while (m) { ! 93: if (!quickflag) ! 94: XSync(win1->display, 0); ! 95: win_process(true); ! 96: if (!quickflag) ! 97: sleep(1); ! 98: if (!loading_paused) { ! 99: prog_move(m); ! 100: m = m->next; ! 101: } ! 102: } ! 103: loading_flag = false; ! 104: if (line) ! 105: message_add(win1, line, false); ! 106: ! 107: while (fgets(buf, BSIZE, fp)) ! 108: message_add(win1, buf, false); ! 109: ! 110: fclose(fp); ! 111: ! 112: return; ! 113: } ! 114: ! 115: /* Given a starting position (usually the beginning board configuration), ! 116: * read in a file of moves. ! 117: */ ! 118: ! 119: move * ! 120: parse_file(fp, b, english) ! 121: FILE *fp; ! 122: board *b; ! 123: bool english; ! 124: { ! 125: move *mvs = NULL, *end = NULL; ! 126: char buf[BSIZE], *s, *t; ! 127: ! 128: while (fgets(buf, BSIZE, fp)) { ! 129: if (*buf == '#') ! 130: continue; ! 131: s = buf; ! 132: ! 133: /* The move number... */ ! 134: if (!(t = gettok(&s))) ! 135: break; ! 136: if (!isdigit(*t)) { ! 137: line = copy(buf); ! 138: break; ! 139: } ! 140: ! 141: if (!(t = gettok(&s))) ! 142: break; ! 143: if (end) ! 144: end = end->next = (english ? parse_move(b, t, WHITE) : ! 145: parse_imove(b, t, WHITE)); ! 146: else ! 147: mvs = end = (english ? parse_move(b, t, WHITE) : ! 148: parse_imove(b, t, WHITE)); ! 149: if (!end) { ! 150: fprintf(stderr, "Can't parse %s\n", buf); ! 151: return (NULL); ! 152: } ! 153: board_move(b, end); ! 154: ! 155: if (!(t = gettok(&s))) ! 156: break; ! 157: if (end) ! 158: end = end->next = (english ? parse_move(b, t, BLACK) : ! 159: parse_imove(b, t, BLACK)); ! 160: else ! 161: mvs = end = (english ? parse_move(b, t, BLACK) : ! 162: parse_imove(b, t, BLACK)); ! 163: if (!end) { ! 164: fprintf(stderr, "Can't parse %s\n", buf); ! 165: return (NULL); ! 166: } ! 167: board_move(b, end); ! 168: } ! 169: ! 170: return (mvs); ! 171: } ! 172: ! 173: /* Parse a move. The move format accepted is as follows - ! 174: * move: spec-spec ! 175: * capture: specxspec ! 176: * kcastle: 2 o's ! 177: * qcastle: 3 o's ! 178: * A spec is either piece/pos, piece, or just pos. A pos consists of a column ! 179: * name followed by a row number. If the column name is kr, kn, kb, k, q, ! 180: * qb, qn, or qr, then the row number is according to the english system, ! 181: * or if it is a-h then it is according to the international system. ! 182: * ! 183: *** As of now the spec must include the position. ! 184: */ ! 185: ! 186: move * ! 187: parse_move(b, str, w) ! 188: board *b; ! 189: char *str; ! 190: color w; ! 191: { ! 192: move *m = alloc(move); ! 193: char *s; ! 194: char spec1[16], spec2[16]; ! 195: int i, j; ! 196: ! 197: if (debug) fprintf(stderr, "parsing %s\n", str); ! 198: ! 199: /* Check for castles. */ ! 200: for (s = str, i = 0; *s; s++) ! 201: if ((*s == 'o') || (*s == 'O')) ! 202: i++; ! 203: if (i == 2) { ! 204: m->type = KCASTLE; ! 205: m->piece.type = KING; ! 206: m->piece.color = w; ! 207: return (m); ! 208: } else if (i == 3) { ! 209: m->type = QCASTLE; ! 210: m->piece.type = KING; ! 211: m->piece.color = w; ! 212: return (m); ! 213: } ! 214: if (index(str, '-')) ! 215: m->type = MOVE; ! 216: else if (index(str, 'x')) ! 217: m->type = CAPTURE; ! 218: else ! 219: return (NULL); ! 220: for (i = 0; str[i]; i++) ! 221: if ((str[i] == 'x') || (str[i] == '-')) ! 222: break; ! 223: else ! 224: spec1[i] = str[i]; ! 225: spec1[i] = '\0'; ! 226: for (i++, j = 0; str[i]; i++, j++) ! 227: if ((str[i] == 'x') || (str[i] == '-')) ! 228: break; ! 229: else ! 230: spec2[j] = str[i]; ! 231: spec2[j] = '\0'; ! 232: ! 233: /* Now decode the specifications. */ ! 234: s = spec1; ! 235: switch (*s) { ! 236: case 'p': case 'P': ! 237: m->piece.type = PAWN; break; ! 238: case 'r': case 'R': ! 239: m->piece.type = ROOK; break; ! 240: case 'n': case 'N': ! 241: m->piece.type = KNIGHT; break; ! 242: case 'b': case 'B': ! 243: m->piece.type = BISHOP; break; ! 244: case 'q': case 'Q': ! 245: m->piece.type = QUEEN; break; ! 246: case 'k': case 'K': ! 247: m->piece.type = KING; break; ! 248: default: ! 249: return (NULL); ! 250: } ! 251: m->piece.color = w; ! 252: s += 2; ! 253: ! 254: /* Now get the {q,k}{,b,n,r}n string... */ ! 255: if ((s[0] == 'q') && (s[1] == 'r')) ! 256: m->fromx = 0, s += 2; ! 257: else if ((s[0] == 'q') && (s[1] == 'n')) ! 258: m->fromx = 1, s += 2; ! 259: else if ((s[0] == 'q') && (s[1] == 'b')) ! 260: m->fromx = 2, s += 2; ! 261: else if ((s[0] == 'q') && isdigit(s[1])) ! 262: m->fromx = 3, s += 1; ! 263: else if ((s[0] == 'k') && isdigit(s[1])) ! 264: m->fromx = 4, s += 1; ! 265: else if ((s[0] == 'k') && (s[1] == 'b')) ! 266: m->fromx = 5, s += 2; ! 267: else if ((s[0] == 'k') && (s[1] == 'n')) ! 268: m->fromx = 6, s += 2; ! 269: else if ((s[0] == 'k') && (s[1] == 'r')) ! 270: m->fromx = 7, s += 2; ! 271: m->fromy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1)); ! 272: ! 273: if ((b->square[m->fromy][m->fromx].color != w) || ! 274: (b->square[m->fromy][m->fromx].type != m->piece.type)) { ! 275: fprintf(stderr, "Error: bad stuff\n"); ! 276: return (NULL); ! 277: } ! 278: ! 279: s = spec2; ! 280: if (m->type == CAPTURE) { ! 281: switch (*s) { ! 282: case 'p': case 'P': ! 283: m->taken.type = PAWN; break; ! 284: case 'r': case 'R': ! 285: m->taken.type = ROOK; break; ! 286: case 'n': case 'N': ! 287: m->taken.type = KNIGHT; break; ! 288: case 'b': case 'B': ! 289: m->taken.type = BISHOP; break; ! 290: case 'q': case 'Q': ! 291: m->taken.type = QUEEN; break; ! 292: case 'k': case 'K': ! 293: m->taken.type = KING; break; ! 294: default: ! 295: return (NULL); ! 296: } ! 297: m->taken.color = ((w == WHITE) ? BLACK : WHITE); ! 298: s += 2; ! 299: } ! 300: ! 301: /* Now get the {q,k}{,b,n,r}n string... */ ! 302: if ((s[0] == 'q') && (s[1] == 'r')) ! 303: m->tox = 0, s += 2; ! 304: else if ((s[0] == 'q') && (s[1] == 'n')) ! 305: m->tox = 1, s += 2; ! 306: else if ((s[0] == 'q') && (s[1] == 'b')) ! 307: m->tox = 2, s += 2; ! 308: else if ((s[0] == 'q') && isdigit(s[1])) ! 309: m->tox = 3, s += 1; ! 310: else if ((s[0] == 'k') && isdigit(s[1])) ! 311: m->tox = 4, s += 1; ! 312: else if ((s[0] == 'k') && (s[1] == 'b')) ! 313: m->tox = 5, s += 2; ! 314: else if ((s[0] == 'k') && (s[1] == 'n')) ! 315: m->tox = 6, s += 2; ! 316: else if ((s[0] == 'k') && (s[1] == 'r')) ! 317: m->tox = 7, s += 2; ! 318: m->toy = ((w == WHITE) ? (SIZE - atoi(s)) : (atoi(s) - 1)); ! 319: ! 320: if ((m->type == CAPTURE) && ((b->square[m->toy][m->tox].color != ! 321: m->taken.color) || (b->square[m->toy][m->tox].type != ! 322: m->taken.type))) { ! 323: fprintf(stderr, "Error: bad stuff\n"); ! 324: return (NULL); ! 325: } ! 326: ! 327: return (m); ! 328: } ! 329: ! 330: /* Parse an algebraic notation move. This is a lot easier... */ ! 331: ! 332: move * ! 333: parse_imove(b, buf, w) ! 334: board *b; ! 335: char *buf; ! 336: color w; ! 337: { ! 338: char *s; ! 339: move *m = alloc(move); ! 340: int n; ! 341: ! 342: if (debug) fprintf(stderr, "(alg) parsing %s\n", buf); ! 343: ! 344: for (s = buf, n = 0; *s; s++) ! 345: if ((*s == 'o') || (*s == 'O')) ! 346: n++; ! 347: s = buf; ! 348: ! 349: if (n == 2) ! 350: m->type = KCASTLE; ! 351: else if (n == 3) ! 352: m->type = QCASTLE; ! 353: else { ! 354: m->fromx = *s++ - 'a'; ! 355: m->fromy = SIZE - (*s++ - '0'); ! 356: m->tox = *s++ - 'a'; ! 357: m->toy = SIZE - (*s++ - '0'); ! 358: m->piece = b->square[m->fromy][m->fromx]; ! 359: m->taken = b->square[m->toy][m->tox]; ! 360: if (m->taken.color == NONE) ! 361: m->type = MOVE; ! 362: else ! 363: m->type = CAPTURE; ! 364: /* for pawns we must account for en passant */ ! 365: if (m->piece.type == PAWN) { ! 366: if (m->type == MOVE && m->fromx != m->tox) { ! 367: m->enpassant = 1; ! 368: m->type = CAPTURE; ! 369: } ! 370: } ! 371: } ! 372: ! 373: if (m->piece.color != w) { ! 374: fprintf(stderr, "Error: parse_imove: piece of wrong color!\n"); ! 375: return (NULL); ! 376: } ! 377: if ((m->piece.type == KING) && (m->fromy == m->toy) && (m->fromx == 4) ! 378: && (m->tox == 6)) ! 379: m->type = KCASTLE; ! 380: else if ((m->piece.type == KING) && (m->fromy == m->toy) && ! 381: (m->fromx == 4) && (m->tox == 2)) ! 382: m->type = QCASTLE; ! 383: ! 384: return (m); ! 385: } ! 386:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.