示例#1
0
文件: pgntags.c 项目: zbrad/xboard-1
/* Returns 0 for success, nonzero for error */
int
ReplaceTags (char *tags, GameInfo *gameInfo)
{
    ChessMove moveType;
    int err;

    ClearGameInfo(gameInfo);
    yynewstr(tags);
    for (;;) {
	yyboardindex = 0;
	moveType = (ChessMove) Myylex();
	if (moveType == (ChessMove) 0) {
	    break;
	} else if (moveType == PGNTag) {
	    err = ParsePGNTag(yy_text, gameInfo);
	    if (err != 0) return err;
	}
    }
    /* just one problem...if there is a result in the new tags,
     * DisplayMove() won't ever show it because ClearGameInfo() set
     * gameInfo->resultDetails to NULL. So we must plug something in if there
     * is a result.
     */
    if (gameInfo->result != GameUnfinished) {
      if (gameInfo->resultDetails) free(gameInfo->resultDetails);
      gameInfo->resultDetails = strdup("");
    }
    return 0;
}
示例#2
0
/* Build the list of games in the open file f.
 * Returns 0 for success or error number.
 */
int
GameListBuild (FILE *f)
{
    ChessMove cm, lastStart;
    int gameNumber;
    ListGame *currentListGame = NULL;
    int error, scratch=100, plyNr=0, fromX, fromY, toX, toY;
    int offset;
    char lastComment[MSG_SIZ], buf[MSG_SIZ];
    TimeMark t, t2;

    GetTimeMark(&t);
    GameListFree(&gameList);
    yynewfile(f);
    gameNumber = 0;
    movePtr = 0;

    lastStart = (ChessMove) 0;
    yyskipmoves = FALSE;
    do {
        yyboardindex = scratch;
	offset = yyoffset();
	quickFlag = plyNr + 1;
	cm = (ChessMove) Myylex();
	switch (cm) {
	  case GNUChessGame:
	    if ((error = GameListNewGame(&currentListGame))) {
		rewind(f);
		yyskipmoves = FALSE;
		return(error);
	    }
	    currentListGame->number = ++gameNumber;
	    currentListGame->offset = offset;
	    if(1) { CopyBoard(boards[scratch], initialPosition); plyNr = 0; currentListGame->moves = PackGame(boards[scratch]); }
	    if (currentListGame->gameInfo.event != NULL) {
		free(currentListGame->gameInfo.event);
	    }
	    currentListGame->gameInfo.event = StrSave(yy_text);
	    lastStart = cm;
	    break;
	  case XBoardGame:
	    lastStart = cm;
	    break;
	  case MoveNumberOne:
	    switch (lastStart) {
	      case GNUChessGame:
		break;		/*  ignore  */
	      case PGNTag:
		lastStart = cm;
		break;		/*  Already started */
	      case (ChessMove) 0:
	      case MoveNumberOne:
	      case XBoardGame:
		if ((error = GameListNewGame(&currentListGame))) {
		    rewind(f);
		    yyskipmoves = FALSE;
		    return(error);
		}
		currentListGame->number = ++gameNumber;
		currentListGame->offset = offset;
		if(1) { CopyBoard(boards[scratch], initialPosition); plyNr = 0; currentListGame->moves = PackGame(boards[scratch]); }
		lastStart = cm;
		break;
	      default:
		break;		/*  impossible  */
	    }
	    break;
	  case PGNTag:
	    lastStart = cm;
	    if ((error = GameListNewGame(&currentListGame))) {
		rewind(f);
		yyskipmoves = FALSE;
		return(error);
	    }
	    currentListGame->number = ++gameNumber;
	    currentListGame->offset = offset;
	    ParsePGNTag(yy_text, &currentListGame->gameInfo);
	    do {
		yyboardindex = 1;
		offset = yyoffset();
		cm = (ChessMove) Myylex();
		if (cm == PGNTag) {
		    ParsePGNTag(yy_text, &currentListGame->gameInfo);
		}
	    } while (cm == PGNTag || cm == Comment);
	    if(1) {
		int btm=0;
		if(currentListGame->gameInfo.fen) ParseFEN(boards[scratch], &btm, currentListGame->gameInfo.fen, FALSE);
		else CopyBoard(boards[scratch], initialPosition);
		plyNr = (btm != 0);
		currentListGame->moves = PackGame(boards[scratch]);
	    }
	    if(cm != NormalMove) break;
	  case IllegalMove:
		if(appData.testLegality) break;
	  case NormalMove:
	    /* Allow the first game to start with an unnumbered move */
	    yyskipmoves = FALSE;
	    if (lastStart == (ChessMove) 0) {
	      if ((error = GameListNewGame(&currentListGame))) {
		rewind(f);
		yyskipmoves = FALSE;
		return(error);
	      }
	      currentListGame->number = ++gameNumber;
	      currentListGame->offset = offset;
	      if(1) { CopyBoard(boards[scratch], initialPosition); plyNr = 0; currentListGame->moves = PackGame(boards[scratch]); }
	      lastStart = MoveNumberOne;
	    }
	  case WhiteCapturesEnPassant:
	  case BlackCapturesEnPassant:
	  case WhitePromotion:
	  case BlackPromotion:
	  case WhiteNonPromotion:
	  case BlackNonPromotion:
	  case WhiteKingSideCastle:
	  case WhiteQueenSideCastle:
	  case BlackKingSideCastle:
	  case BlackQueenSideCastle:
	  case WhiteKingSideCastleWild:
	  case WhiteQueenSideCastleWild:
	  case BlackKingSideCastleWild:
	  case BlackQueenSideCastleWild:
	  case WhiteHSideCastleFR:
	  case WhiteASideCastleFR:
	  case BlackHSideCastleFR:
	  case BlackASideCastleFR:
		fromX = currentMoveString[0] - AAA;
		fromY = currentMoveString[1] - ONE;
		toX = currentMoveString[2] - AAA;
		toY = currentMoveString[3] - ONE;
		plyNr++;
		ApplyMove(fromX, fromY, toX, toY, currentMoveString[4], boards[scratch]);
		if(currentListGame && currentListGame->moves) PackMove(fromX, fromY, toX, toY, boards[scratch][toY][toX]);
	    break;
        case WhiteWins: // [HGM] rescom: save last comment as result details
        case BlackWins:
        case GameIsDrawn:
        case GameUnfinished:
	    if(!currentListGame) break;
	    if(currentListGame->gameInfo.result == GameUnfinished)
		currentListGame->gameInfo.result = cm; // correct result tag with actual result
	    if (currentListGame->gameInfo.resultDetails != NULL) {
		free(currentListGame->gameInfo.resultDetails);
	    }
	    if(yy_text[0] == '{') {
		char *p;
		safeStrCpy(lastComment, yy_text+1, sizeof(lastComment)/sizeof(lastComment[0]));
		if((p = strchr(lastComment, '}'))) *p = 0;
		currentListGame->gameInfo.resultDetails = StrSave(lastComment);
	    }
	    break;
	  default:
	    break;
	}
	if(gameNumber % 1000 == 0) {
	    snprintf(buf, MSG_SIZ, _("Reading game file (%d)"), gameNumber);
	    DisplayTitle(buf); DoEvents();
	}
    }
    while (cm != (ChessMove) 0);

 if(currentListGame) {
    if(!currentListGame->moves) DisplayError("Game cache overflowed\nPosition-searching might not work properly", 0);

    if (appData.debugMode) {
	for (currentListGame = (ListGame *) gameList.head;
	     currentListGame->node.succ;
	     currentListGame = (ListGame *) currentListGame->node.succ) {

	    fprintf(debugFP, "Parsed game number %d, offset %ld:\n",
		    currentListGame->number, currentListGame->offset);
	    PrintPGNTags(debugFP, &currentListGame->gameInfo);
	}
    }
  }
    if(appData.debugMode) { GetTimeMark(&t2);printf("GameListBuild %ld msec\n", SubtractTimeMarks(&t2,&t)); }
    quickFlag = 0;
    PackGame(boards[scratch]); // for appending end-of-game marker.
    DisplayTitle("WinBoard");
    rewind(f);
    yyskipmoves = FALSE;
    return 0;
}