Annotation of 43BSDReno/games/chess/Xchess/parse.c, revision 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.