Exemple #1
0
static void ParseFile(const char *szFilePath) {
  int i, mv, mvMirror, nComp;
  PositionStruct pos, posMirror;
  PgnFileStruct pgn;

  if (pgn.Read(szFilePath)) {
    pos = posMirror = pgn.posStart;
    posMirror.Mirror();
    for (i = 0; i < pgn.nMaxMove; i ++) {
      mv = pgn.wmvMoveTable[i + 1];
      mvMirror = MOVE_MIRROR(mv);
      if (pos.zobr.dwLock1 < posMirror.zobr.dwLock1) {
        nComp = -1;
      } else if (pos.zobr.dwLock1 > posMirror.zobr.dwLock1) {
        nComp = 1;
      } else {
        if (pos.zobr.dwLock0 < posMirror.zobr.dwLock0) {
          nComp = -1;
        } else if (pos.zobr.dwLock0 > posMirror.zobr.dwLock0) {
          nComp = 1;
        } else {
          nComp = 0;
        }
      }
      if (nComp <= 0) {
        AddTemp(TempStruct(pos, mv, MoveValue(pos.sdPlayer, pgn.nResult)));
      }
      if (nComp >= 0) {
        AddTemp(TempStruct(posMirror, mvMirror, MoveValue(pos.sdPlayer, pgn.nResult)));
      }
      if (pos.ucpcSquares[DST(mv)] == 0) {
        pos.MakeMove(mv);
      } else {
        pos.MakeMove(mv);
        pos.SetIrrev();
      }
      if (posMirror.ucpcSquares[DST(mvMirror)] == 0) {
        posMirror.MakeMove(mvMirror);
      } else {
        posMirror.MakeMove(mvMirror);
        posMirror.SetIrrev();
      }  
    }  
  }
}
Exemple #2
0
static void AddEcco(const char *szPgnFile, const EccoApiStruct &EccoApi) {
  int i, nStatus;
  uint32_t dwEccoIndex, dwFileMove[20];
  PgnFileStruct pgn;
  PositionStruct pos;

  if (pgn.Read(szPgnFile, NO_ADVERT)) {
    pos.FromFen(cszStartFen);
    for (i = 1; i <= MIN(pgn.nMaxMove, 20); i ++) {
      dwFileMove[i - 1] = Move2File(pgn.wmvMoveTable[i], pos);
      TryMove(pos, nStatus, pgn.wmvMoveTable[i]);
    }
    if (pgn.nMaxMove < 20) {
      dwFileMove[pgn.nMaxMove] = 0;
    }
    dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove);
    strcpy(pgn.szEcco, (const char *) &dwEccoIndex);
    strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex));
    strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex));
    pgn.Write(szPgnFile);
  }
}
int Pgn2Xqf(const char *szPgnFile, const char *szXqfFile) {
  int i, nCommentLen;
  char szRed[MAX_STR_LEN * 2], szBlack[MAX_STR_LEN * 2];
  FILE *fp;
  PgnFileStruct pgn;
  XqfHeaderStruct xqfhd;
  XqfMoveStruct xqfmv;

  if (!pgn.Read(szPgnFile)) {
    return PGN2XQF_ERROR_OPEN;
  }
  fp = fopen(szXqfFile, "wb");
  if (fp == NULL) {
    return PGN2XQF_ERROR_CREATE;
  }
  memset(xqfhd.szTag, 0, sizeof(XqfHeaderStruct));
  xqfhd.szTag[0] = 'X';
  xqfhd.szTag[1] = 'Q';
  xqfhd.szTag[2] = 10;
  for (i = 0; i < 32; i ++) {
    xqfhd.szPiecePos[i] = ccSquare2Xqf[pgn.posStart.ucsqPieces[cpcXqf2Piece[i]]];
  }
  xqfhd.szResult[3] = cnResultTrans[pgn.nResult];
  xqfhd.szSetUp[0] = 2;
  SetXqfString(xqfhd.szEvent, pgn.szEvent, sizeof(xqfhd.szEvent));
  SetXqfString(xqfhd.szDate, pgn.szDate, sizeof(xqfhd.szDate));
  SetXqfString(xqfhd.szSite, pgn.szSite, sizeof(xqfhd.szSite));
  if (pgn.szRedTeam[0] == '\0') {
    SetXqfString(xqfhd.szRed, pgn.szRed, sizeof(xqfhd.szRed));
  } else {
    sprintf(szRed, "%s %s", pgn.szRedTeam, pgn.szRed);
    SetXqfString(xqfhd.szRed, szRed, sizeof(xqfhd.szRed));
  }
  if (pgn.szBlackTeam[0] == '\0') {
    SetXqfString(xqfhd.szBlack, pgn.szBlack, sizeof(xqfhd.szBlack));
  } else {
    sprintf(szBlack, "%s %s", pgn.szBlackTeam, pgn.szBlack);
    SetXqfString(xqfhd.szBlack, szBlack, sizeof(xqfhd.szBlack));
  }
  fwrite(&xqfhd, sizeof(xqfhd), 1, fp);
  memset(&xqfhd, 0, sizeof(xqfhd));
  fwrite(&xqfhd, sizeof(xqfhd), 1, fp);
  for (i = 0; i <= pgn.nMaxMove; i ++) {
    xqfmv.ucTag = (i == pgn.nMaxMove ? 0 : 240);
    if (i == 0) {
      xqfmv.ucSrc = 24;
      xqfmv.ucDst = 32;
      xqfmv.ucReserved = 255;
    } else {
      xqfmv.ucSrc = 24 + ccSquare2Xqf[SRC(pgn.wmvMoveTable[i])];
      xqfmv.ucDst = 32 + ccSquare2Xqf[DST(pgn.wmvMoveTable[i])];
      xqfmv.ucReserved = 0;
    }
    fwrite(&xqfmv, sizeof(XqfMoveStruct), 1, fp);
    nCommentLen = (pgn.szCommentTable[i] == NULL ? 0 : strlen(pgn.szCommentTable[i]));
    fwrite(&nCommentLen, sizeof(int), 1, fp);
    if (pgn.szCommentTable[i] != NULL) {
      fwrite(pgn.szCommentTable[i], nCommentLen, 1, fp);
    }
  }
  fclose(fp);
  return 0;
}
Exemple #4
0
int Xqf2Pgn(const char *szXqfFile, const char *szPgnFile, const EccoApiStruct &EccoApi) {
  int i, nArg0, nArgs[4];
  int nCommentLen, mv, nStatus;
  bool bHasNext;
  PgnFileStruct pgn;
  PositionStruct pos;

  FILE *fp;
  XqfHeaderStruct xqfhd;  
  XqfMoveStruct xqfmv;
  // 版本号和加密偏移值
  int nXqfVer, nPieceOff, nSrcOff, nDstOff, nCommentOff;
  // 密钥流
  int nEncStream[32];
  // 密钥流索引号
  int nEncIndex;
  // 局面初始位置
  int nPiecePos[32];

  uint32_t dwEccoIndex, dwFileMove[20];

  fp = fopen(szXqfFile, "rb");
  if (fp == NULL) {
    return XQF2PGN_ERROR_OPEN;
  }
  fread(&xqfhd, sizeof(xqfhd), 1, fp);
  fseek(fp, sizeof(xqfhd), SEEK_CUR);
  if (xqfhd.szTag[0] == 'X' && xqfhd.szTag[1] == 'Q') {
    // PGN文件可以打开,现在正式解析XQF文件
    nXqfVer = xqfhd.szTag[2];
    if (nXqfVer < 11) {
      nPieceOff = nSrcOff = nDstOff = nCommentOff = 0;
      for (i = 0; i < 32; i ++) {
        nEncStream[i] = 0;
      }
    } else {
      // 局面初始位置的加密偏移值
      nPieceOff = (uint8_t) (Square54Plus221((uint8_t) xqfhd.szTag[13]) * (uint8_t) xqfhd.szTag[13]);
      // 着法起点的加密偏移值
      nSrcOff = (uint8_t) (Square54Plus221((uint8_t) xqfhd.szTag[14]) * nPieceOff);
      // 着法终点的加密偏移值
      nDstOff = (uint8_t) (Square54Plus221((uint8_t) xqfhd.szTag[15]) * nSrcOff);
      // 注释的加密偏移值
      nCommentOff = ((uint8_t) xqfhd.szTag[12] * 256 + (uint8_t) xqfhd.szTag[13]) % 32000 + 767;
      // 基本掩码
      nArg0 = xqfhd.szTag[3];
      // 密钥 = 前段密钥 | (后段密钥 & 基本掩码)
       for (i = 0; i < 4; i ++) {
        nArgs[i] = xqfhd.szTag[8 + i] | (xqfhd.szTag[12 + i] & nArg0);
      }
      // 密钥流 = 密钥 & 密钥流掩码
      for (i = 0; i < 32; i ++) {
        nEncStream[i] = (uint8_t) (nArgs[i % 4] & cszEncStreamMask[i]);
      }
    }
    nEncIndex = 0;

    // 记录棋谱信息
    if (xqfhd.szEvent[0] == 0) {
      GetXqfString(pgn.szEvent, xqfhd.szTitle);
    } else {
      GetXqfString(pgn.szEvent, xqfhd.szEvent);
    }
    GetXqfString(pgn.szDate, xqfhd.szDate);
    GetXqfString(pgn.szSite, xqfhd.szSite);
    GetXqfString(pgn.szRed, xqfhd.szRed);
    GetXqfString(pgn.szBlack, xqfhd.szBlack);
    pgn.nResult = cnResultTrans[(int) xqfhd.szResult[3]];

    if (xqfhd.szSetUp[0] < 2) {
      // 如果是开局或者全局,那么直接设置起始局面
      pgn.posStart.FromFen(cszStartFen);
    } else {
      // 如果是中局或者排局,那么根据"xqfhd.szPiecePos[32]"的内容摆放局面
      // 当版本号达到12时,还要进一步解密局面初始位置
      if (nXqfVer < 12) {
        for (i = 0; i < 32; i ++) {
          nPiecePos[i] = (uint8_t) (xqfhd.szPiecePos[i] - nPieceOff);
        }
      } else {
        for (i = 0; i < 32; i ++) {
          nPiecePos[(nPieceOff + 1 + i) % 32] = (uint8_t) (xqfhd.szPiecePos[i] - nPieceOff);
        }
      }
      // 把"nPiecePos[32]"的数据放到"PositionStruct"中
      pgn.posStart.ClearBoard();
      for (i = 0; i < 32; i ++) {
        if (nPiecePos[i] < 90) {
          pgn.posStart.AddPiece(cucsqXqf2Square[nPiecePos[i]], cpcXqf2Piece[i]);
        }
      }
      pgn.posStart.SetIrrev();
    }
    pos = pgn.posStart;

    bHasNext = true;
    while (bHasNext && pgn.nMaxMove < MAX_MOVE_LEN) {
      // 读取着法记录
      if (nXqfVer < 11) {
        fread(&xqfmv, sizeof(xqfmv), 1, fp);
        fread(&nCommentLen, sizeof(int), 1, fp);
        if ((xqfmv.ucTag & 0xf0) == 0) {
          bHasNext = false;
        }
      } else {
        ReadAndDecrypt(fp, &xqfmv, sizeof(xqfmv), nEncStream, nEncIndex);
        if ((xqfmv.ucTag & 0x20) != 0) {
          ReadAndDecrypt(fp, &nCommentLen, sizeof(int), nEncStream, nEncIndex);
          nCommentLen -= nCommentOff;
        } else {
          nCommentLen = 0;
        }
        if ((xqfmv.ucTag & 0x80) == 0) {
          bHasNext = false;
        }
      }
      if (pgn.nMaxMove > 0) {
        // 记录着法
        mv = MOVE(cucsqXqf2Square[(uint8_t) (xqfmv.ucSrc - 24 - nSrcOff)], cucsqXqf2Square[(uint8_t) (xqfmv.ucDst - 32 - nDstOff)]);
        if (pgn.nMaxMove == 1) {
          if ((pgn.posStart.ucpcSquares[SRC(mv)] & 32) != 0) {
            pgn.posStart.ChangeSide();
            pos.ChangeSide();
          }
        }
        if (xqfhd.szSetUp[0] < 2 && pgn.nMaxMove <= 20) {
          dwFileMove[pgn.nMaxMove - 1] = Move2File(mv, pos);
        }
        TryMove(pos, nStatus, mv);
        pgn.wmvMoveTable[pgn.nMaxMove] = mv;
        if (pos.nMoveNum == MAX_MOVE_NUM) {
          pos.SetIrrev();
        }
      }
      if (nCommentLen > 0) {
        pgn.szCommentTable[pgn.nMaxMove] = new char[nCommentLen + 1];
        ReadAndDecrypt(fp, pgn.szCommentTable[pgn.nMaxMove], nCommentLen, nEncStream, nEncIndex);
        pgn.szCommentTable[pgn.nMaxMove][nCommentLen] = '\0';
      }
      pgn.nMaxMove ++;
    }
    pgn.nMaxMove --;

    // 解析ECCO
    if (xqfhd.szSetUp[0] < 2) {
      if (pgn.nMaxMove < 20) {
        dwFileMove[pgn.nMaxMove] = 0;
      }
      if (EccoApi.Available()) {
        dwEccoIndex = EccoApi.EccoIndex((const char *) dwFileMove);
        strcpy(pgn.szEcco, (const char *) &dwEccoIndex);
        strcpy(pgn.szOpen, EccoApi.EccoOpening(dwEccoIndex));
        strcpy(pgn.szVar, EccoApi.EccoVariation(dwEccoIndex));
      }
    }

    fclose(fp);
    return (pgn.Write(szPgnFile) ? XQF2PGN_OK : XQF2PGN_ERROR_CREATE);
  } else {
    fclose(fp);
    return XQF2PGN_ERROR_FORMAT;
  }
}