Annotation of 43BSDReno/games/chess/Xchess/parse.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.