// //--------------------------------------------------------- // BOOL CEasyBDoc::ReadFilePBN(CArchive& ar) { int nLineCode, nValue, nCode; CString strMessage, string, strTag, strValue, partString, strModifier; double fValue; BOOL bValue; CString strLine; // init some flags m_bReviewingGame = FALSE; m_bGameReviewAvailable = FALSE; // preload the file numLines = PreloadPBNFile(ar, strLines); /* int sizeOf = strLines.GetSize(); // NCR DEBUG ONLY for(int xxx = 0; xxx < sizeOf; xxx++) { CString nxtStr = strLines.GetAt(xxx); ASSERT(!nxtStr.IsEmpty()); } */ // read in the ines pGameRecord = NULL; m_nLineNumber = 0; nGameIndex = 0; nPreviousTag = 0; int numGamesLoaded = 0; int numInvalidGames = 0; int numTagsRead = 0; int numDeclarers = 0; // NCR use to test reviewable deals ie no Declarer means no review // for(;;) { // check for EOF if (m_nLineNumber >= numLines) break; strBuf = strLines.GetAt(m_nLineNumber++); // strBuf.TrimLeft(); strBuf.TrimRight(); nLineLen = strBuf.GetLength(); // see if this is a blank line (but watch out for multiple empty lines) if (strBuf.IsEmpty()) { // flush out the current game if (pGameRecord) { pGameRecord->AnalyzePlayRecord(); if (pGameRecord->IsValid(isExportFile)) // NCR_PBNI added isExportFile { m_gameRecords.Add(pGameRecord); numGamesLoaded++; nGameIndex++; } else { delete pGameRecord; numInvalidGames++; } pGameRecord = NULL; nPreviousTag = 0; continue; } } // else parse the line for tokens nLineCode = ParseLinePBN(strBuf, strTag, strValue, nLineLen); // check for error if (nLineCode < 0) { // junk tag? if (m_nLineNumber == 0) { AfxMessageBox("This is not a proper PBN format file."); AfxThrowFileException(CFileException::generic); } continue; } // // else the tag is OK // // see if the value is "#" -- then substitute if ((strValue == "#") && (nGameIndex > 0)) { // look up the value from the previous game CGameRecord* pPrevGame = m_gameRecords[nGameIndex-1]; std::map<CString,CString>::const_iterator iter = pPrevGame->m_mapTagValues.find(strTag); if (iter != pPrevGame->m_mapTagValues.end()) strValue = (*iter).second; } // // get data value // nValue = atoi(strValue); fValue = atof(strValue); if ((strValue == "Yes") || (strValue == "1")) bValue = TRUE; else bValue = FALSE; // // if this is a valid tag, alloc a new game object // if ((!strTag.IsEmpty()) && (pGameRecord == NULL)) { pGameRecord = new CGameRecord; numTagsRead = 0; } // //------------------------------------------------------------------- // // process item // switch(nLineCode) { case TAG_EVENT: break; case TAG_SITE: // ignore for now break; case TAG_DATE: // ignore for now break; case TAG_ROUND: // ignore for now break; case TAG_BOARD: // ignore for now break; case TAG_WEST: // ignore for now break; case TAG_NORTH: // ignore for now break; case TAG_EAST: // ignore for now break; case TAG_SOUTH: // ignore for now break; // dealer case TAG_DEALER: if (!strValue.IsEmpty() && (strValue[0] != '?')) pGameRecord->m_nDealer = CharToPosition(strValue[0]); break; // vulnerability case TAG_VULNERABLE: if (strValue.CompareNoCase("NS") == 0) pGameRecord->m_nVulnerability = NORTH_SOUTH; else if (strValue.CompareNoCase("EW") == 0) pGameRecord->m_nVulnerability = EAST_WEST; else if ((strValue.CompareNoCase("All") == 0) || (strValue.CompareNoCase("Both") == 0)) pGameRecord->m_nVulnerability = BOTH; else if((strValue.CompareNoCase("None") == 0) || (strValue.CompareNoCase("-") == 0)) // NCR-PBNI pGameRecord->m_nVulnerability = NEITHER; else // error if not above AfxMessageBox("Invalid Vulnerabliity: " + strValue); break; case TAG_DEAL: // AssignCardsPBN(strValue); break; case TAG_SCORING: // ignore for now break; case TAG_DECLARER: if (!strValue.IsEmpty() && (strValue[0] != '?')) { pGameRecord->m_nDeclarer = CharToPosition(strValue[0]); numDeclarers++; // NCR count for need to do review } break; case TAG_CONTRACT: { // decipher the contract if ((strValue.GetLength() < 2) || (strValue[0] == '?')) { // contract has not yet been set theApp.SetValue(tbGameInProgress, FALSE); break; } int nContractLevel = atoi(strValue); int nContractSuit = CharToSuit(strValue[1]); int nContract = MAKEBID(nContractSuit, nContractLevel); int nContractModifier = 0; // pGameRecord->m_nContract = nContract; // get modifier if (nContractSuit == NOTRUMP) strModifier = strValue.Mid(3); else strModifier = strValue.Mid(2); if (strModifier.CompareNoCase("X") == 0) nContractModifier = 1; else if (strModifier.CompareNoCase("XX") == 0) nContractModifier = 2; // pGameRecord->m_nContractModifier = nContractModifier; break; } case TAG_RESULT: // ignore for now break; // ge the auction case TAG_AUCTION: if (strValue.IsEmpty()) break; // parse the bids nCode = ParseBidsPBN(ar, strValue); break; case TAG_PLAY: // read in the plays if (strValue.IsEmpty() || (strValue[0] == '?')) break; // parse the plays nCode = ParsePlaysPBN(ar, strValue); // mark this file as being reviewable if (ISBID(pGameRecord->m_nContract)) { // contract must also be valid m_bReviewingGame = TRUE; m_bGameReviewAvailable = TRUE; } break; case TAG_NOTE: // add to the appropriate list if (nPreviousTag == TAG_AUCTION) pGameRecord->m_strBiddingNotes.Add(strValue); else if (nPreviousTag == TAG_PLAY) pGameRecord->m_strPlayNotes.Add(strValue); break; case TAG_OPTIMUMSCORE: // NCR-776 for BridgeWebs files // ignore break; case TAG_TERMINATOR: // ignore for now break; } // end switch(nLineCode) // save this tag nPreviousTag = nLineCode; numTagsRead++; // save the tag-value pair in the map if (pGameRecord) { // but don't save notes here if (strTag.CompareNoCase("Note") != 0) pGameRecord->SetTagValue(strTag, strValue); } } // end for(;;) // see if the file ended with no ending empty line // if (nGameIndex == 0 && pGameRecord) if (pGameRecord && (numTagsRead >= 1)) { pGameRecord->AnalyzePlayRecord(); if (pGameRecord->IsValid(isExportFile)) // NCR-PBNI added isExportFile { m_gameRecords.Add(pGameRecord); numGamesLoaded++; nGameIndex++; } // pGameRecord = NULL; } // if the file has > 1 game record, set game review mode if (nGameIndex > 1) { m_bReviewingGame = TRUE; m_bGameReviewAvailable = TRUE; } // see if we have a dangling (invalid) game object if (pGameRecord) delete pGameRecord; // all done return TRUE; }
// //--------------------------------------------------------- // BOOL CEasyBDoc::ReadFile(CArchive& ar) { int i,nRtnCode,nLineCode,nSectionCode; int nIndex,nValue,nOffset,nLen; int nPlayOffset, nPos; int nBidIndex = 0; CString strMessage,string,partString; CCard* pCard; double fValue; BOOL bValue; BOOL bFileInfoFound = FALSE; // read m_nLineNumber = 0; try { for(;;) { nRtnCode = ReadLine(ar, strBuf); next: if (nRtnCode == EOF) break; if (nRtnCode == 0) continue; if ((strBuf[0] == '#') || (strBuf[0] == '*')) continue; nLineLen = nRtnCode; nLineCode = ParseLine(strBuf,nLineLen); if (nLineCode < 0) { // section signifier nSectionCode = -nLineCode; if (nSectionCode == BLOCK_FILEINFO) { // bFileInfoFound = TRUE; // file info; skip this section do { nRtnCode = ReadLine(ar, strBuf); } while ((nRtnCode != EOF) && (strBuf.Left(2) != "[[")); // goto next; } // if (nSectionCode == BLOCK_FILEDESC) { // file description; read until next block m_strFileDescription.Empty(); do { nRtnCode = ReadLine(ar, strBuf); if (strBuf.Left(2) != "[[") { strBuf += "\r\n"; m_strFileDescription += strBuf; } } while ((nRtnCode != EOF) && (strBuf.Left(2) != "[[")); // trim ending CR/LF int nLen = m_strFileDescription.GetLength(); if ((nLen >= 2) && (m_strFileDescription[nLen-1] == _T('\n'))) m_strFileDescription = m_strFileDescription.Left(nLen-2); // goto next; } else if (nSectionCode == BLOCK_COMMENTS) { // file comments for (;;) { nRtnCode = ReadLine(ar, strBuf); if ((nRtnCode == EOF) || (strBuf.Left(2) == "[[")) { // update file comments dialog if it's open CWnd* pWnd = pMAINFRAME->GetDialog(twFileCommentsDialog); if (pWnd) pWnd->SendMessage(WM_COMMAND, WMS_UPDATE_TEXT, FALSE); goto next; } strBuf += "\r\n"; m_strFileComments += strBuf; } } else if ((nSectionCode == BLOCK_SOUTH_ANALYSIS) || (nSectionCode == BLOCK_WEST_ANALYSIS) || (nSectionCode == BLOCK_NORTH_ANALYSIS) || (nSectionCode == BLOCK_EAST_ANALYSIS)) { // don't bother to save the analysis int nPlayer = nSectionCode - BLOCK_SOUTH_ANALYSIS; CString strAnalysisBiffer; do { nRtnCode = ReadLine(ar, strBuf); // strBuf += "\r\n"; // strAnalysisBiffer += strBuf; } while ((nRtnCode != EOF) && (strBuf.Left(2) != "[[")); // m_player[nPlayer].SetValueString(tszAnalysis, strAnalysisBiffer); goto next; } } else if (nLineCode > 0) { // first skip spaces nLen = strBuf.GetLength(); while ((nDataPosition < nLen) && (strBuf[nDataPosition] == ' ')) nDataPosition++; if (nDataPosition >= nLen) continue; // then get data item string = strBuf.Mid(nDataPosition); nValue = atoi(string); fValue = atof(string); if ((string == "Yes") || (string == "1")) bValue = TRUE; else bValue = FALSE; switch(nLineCode) { case ITEM_PROGRAM_ID: m_strFileProgTitle = string; break; case ITEM_MAJOR_VERSIONNO: m_nFileProgMajorVersion = nValue; break; case ITEM_MINOR_VERSIONNO: m_nFileProgMinorVersion = nValue; break; case ITEM_INCREMENT_VERSIONNO: m_nFileProgIncrementVersion = nValue; break; case ITEM_BUILD_NUMBER: m_nFileProgBuildNumber = nValue; break; case ITEM_BUILD_DATE: m_strFileProgBuildDate = string; break; case ITEM_FILE_DATE: m_strFileDate = string; break; // hand info, 10..19 case ITEM_CURRHAND_NORTH: AssignCards(string,NORTH); break; case ITEM_CURRHAND_EAST: AssignCards(string,EAST); break; case ITEM_CURRHAND_SOUTH: AssignCards(string,SOUTH); break; case ITEM_CURRHAND_WEST: AssignCards(string,WEST); break; case ITEM_ORIGHAND_NORTH: AssignCards(string,NORTH,TRUE); break; case ITEM_ORIGHAND_EAST: AssignCards(string,EAST,TRUE); break; case ITEM_ORIGHAND_SOUTH: AssignCards(string,SOUTH,TRUE); break; case ITEM_ORIGHAND_WEST: AssignCards(string,WEST,TRUE); break; // current round info case ITEM_CURR_ROUND_LEAD: m_nRoundLead = StringToPosition(string); break; case ITEM_NUM_CARDS_PLAYED_IN_ROUND: m_numCardsPlayedInRound = nValue; break; case ITEM_TRICK_CARD_1: m_pCurrTrick[0] = deck.GetCard(string); break; case ITEM_TRICK_CARD_2: m_pCurrTrick[1] = deck.GetCard(string); break; case ITEM_TRICK_CARD_3: m_pCurrTrick[2] = deck.GetCard(string); break; case ITEM_TRICK_CARD_4: m_pCurrTrick[3] = deck.GetCard(string); break; // game status info case ITEM_VIEW_STATUS_CODE: pVIEW->SetCurrentMode((CEasyBView::ScreenMode)nValue); break; case ITEM_RUBBER_IN_PROGRESS: theApp.SetValue(tbRubberInProgress, bValue); break; case ITEM_GAME_IN_PROGRESS: // TEMP // theApp.SetValue(tbGameInProgress, FALSE); theApp.SetValue(tbGameInProgress, bValue); break; case ITEM_BIDDING_IN_PROGRESS: theApp.SetValue(tbBiddingInProgress, bValue); break; case ITEM_HANDS_DEALT: m_bHandsDealt = bValue; break; case ITEM_CONTRACT_SUIT: nLen = string.GetLength(); m_nContractSuit = CharToSuit(string.GetAt(0)); break; case ITEM_CONTRACT_LEVEL: m_nContractLevel = nValue; break; case ITEM_CONTRACT_MODIFIER: switch(nValue) { case 0: m_bDoubled = FALSE; m_bRedoubled = FALSE; m_nContractModifier = 0; break; case 1: m_bDoubled = TRUE; m_bRedoubled = FALSE; m_nContractModifier = 1; break; case 2: m_bDoubled = FALSE; m_bRedoubled = TRUE; m_nContractModifier = 2; break; } break; case ITEM_DEALER: m_nDealer = StringToPosition(string); break; case ITEM_NUM_BIDS: // m_numBidsMade = nValue; break; case ITEM_BIDDING_HISTORY: strBiddingHistory = string; break; case ITEM_DECLARER: m_nDeclarer = StringToPosition(string); m_nContractTeam = GetPlayerTeam(m_nDeclarer); m_nDefendingTeam = (m_nContractTeam == NORTH_SOUTH)? EAST_WEST : NORTH_SOUTH; break; // game record case ITEM_NUM_TRICKS_PLAYED: m_numTricksPlayed = nValue; break; case ITEM_NUM_TRICKS_WON_NS: m_numTricksWon[0] = nValue; break; case ITEM_NUM_TRICKS_WON_EW: m_numTricksWon[1] = nValue; break; case ITEM_GAME_LEAD: m_nGameLead = StringToPosition(string); break; case ITEM_GAME_TRICK_1: case ITEM_GAME_TRICK_2: case ITEM_GAME_TRICK_3: case ITEM_GAME_TRICK_4: case ITEM_GAME_TRICK_5: case ITEM_GAME_TRICK_6: case ITEM_GAME_TRICK_7: case ITEM_GAME_TRICK_8: case ITEM_GAME_TRICK_9: case ITEM_GAME_TRICK_10: case ITEM_GAME_TRICK_11: case ITEM_GAME_TRICK_12: case ITEM_GAME_TRICK_13: try { nIndex = nLineCode - ITEM_GAME_TRICK_1; nOffset = 0; nLen = string.GetLength(); // first read the lead player for the trick partString = string.Mid(nOffset); m_nTrickLead[nIndex] = StringToPosition(partString); nOffset = string.Find(' '); // for(i=0;i<4;i++) { while((nOffset < nLen) && (string[nOffset] == ' ')) nOffset++; partString = string.Mid(nOffset); nOffset += 2; if (partString.IsEmpty()) { strMessage.Format("Incomplete Trick record at line %d;\n%s", m_nLineNumber, string); AfxMessageBox(strMessage); break; } // if (partString.Left(2) == "--") { m_pGameTrick[nIndex][i] = NULL; } else { pCard = deck.GetCard(partString); m_pGameTrick[nIndex][i] = pCard; } } // insert the trick record into the game record // in the proper order nPlayOffset = nIndex * 4; nPos = m_nTrickLead[nIndex]; for(i=0;i<4;i++) { CCard* pCard = m_pGameTrick[nIndex][nPos]; if (pCard) m_nPlayRecord[nPlayOffset+i] = pCard->GetDeckValue(); nPos = GetNextPlayer(nPos); } // and finally read the trick's winner while((nOffset < nLen) && (string[nOffset] == ' ')) nOffset++; partString = string.Mid(nOffset); m_nTrickWinner[nIndex] = StringToPosition(partString); } catch(...) { // error } break; // match info case ITEM_SCORE_NS_BONUS: m_nBonusScore[NORTH_SOUTH] = nValue; break; case ITEM_SCORE_NS_GAME0: m_nGameScore[0][NORTH_SOUTH] = nValue; break; case ITEM_SCORE_NS_GAME1: m_nGameScore[1][NORTH_SOUTH] = nValue; break; case ITEM_SCORE_NS_GAME2: m_nGameScore[2][NORTH_SOUTH] = nValue; break; case ITEM_SCORE_NS_GAMES_WON: m_numGamesWon[NORTH_SOUTH] = nValue; break; case ITEM_SCORE_EW_BONUS: m_nBonusScore[EAST_WEST] = nValue; break; case ITEM_SCORE_EW_GAME0: m_nGameScore[0][EAST_WEST] = nValue; break; case ITEM_SCORE_EW_GAME1: m_nGameScore[1][EAST_WEST] = nValue; break; case ITEM_SCORE_EW_GAME2: m_nGameScore[2][EAST_WEST] = nValue; break; case ITEM_SCORE_EW_GAMES_WON: m_numGamesWon[EAST_WEST] = nValue; break; case ITEM_CURRENT_GAME_INDEX: m_nCurrGame = nValue-1; break; case ITEM_BONUS_SCORE_RECORD: m_strArrayBonusPointsRecord.Add(StripQuotes(string)); break; case ITEM_GAME_SCORE_RECORD: m_strArrayTrickPointsRecord.Add(StripQuotes(string)); break; // misc info case ITEM_AUTOSHOW_COMMENTS: m_bShowCommentsUponOpen = bValue; break; case ITEM_AUTOSHOW_BID_HISTORY: m_bShowBidHistoryUponOpen = bValue; break; case ITEM_AUTOSHOW_PLAY_HISTORY: m_bShowPlayHistoryUponOpen = bValue; break; case ITEM_AUTOSHOW_ANALYSES: m_bShowAnalysesUponOpen = bValue; break; } } else { /* // unknown line strMessage.Format("Found Unknown line\n%s.\nContinue?",strBuf); if (AfxMessageBox(strMessage, MB_ICONEXCLAMATION | MB_OKCANCEL) == IDCANCEL) break; */ } } } catch(...) { // handle any improper file error here ClearAllInfo(); // AfxMessageBox("An error ocurred while reading the game file."); return FALSE; } // see if this was a valid file if (!bFileInfoFound) { AfxMessageBox("This is not a proper Easy Bridge game file."); AfxThrowFileException(CFileException::generic); } // // do some sanity checks // m_nContract = MAKEBID(m_nContractSuit, m_nContractLevel); if (!ISPLAYER(m_nDeclarer) || !ISBID(m_nContract)) theApp.SetValue(tbGameInProgress, FALSE); // // parse the bidding history // if (!ISPLAYER(m_nDeclarer)) m_nDeclarer = SOUTH; nPos = m_nDeclarer; m_nCurrPlayer = nPos; int nTeam = GetPlayerTeam(nPos); nOffset = 0; // nLen = strBiddingHistory.GetLength(); for(i=0;;i++) { // skip leading spaces while((nOffset < nLen) && (strBiddingHistory[nOffset] == ' ')) nOffset++; if (nOffset >= nLen) break; // grab the next bid partString = strBiddingHistory.Mid(nOffset); int nBid = ContractStringToBid(partString); // and record it m_nBiddingHistory[m_numBidsMade] = nBid; m_numBidsMade++; m_nCurrPlayer = GetNextPlayer(m_nCurrPlayer); int nBiddingRound = i % 4; m_nBidsByPlayer[nPos][nBiddingRound] = nBid; // see if this is an actual numeric bid if (ISBID(nBid)) { m_nValidBidHistory[m_numValidBidsMade] = nBid; m_numValidBidsMade++; m_nLastValidBid = nBid; m_nLastValidBidTeam = nTeam; } // skip over remainder of current bid string while((nOffset < nLen) && (strBiddingHistory[nOffset] != ' ')) nOffset++; // and move to the next player nPos = GetNextPlayer(nPos); nTeam = GetOpposingTeam(nTeam); } if (ISBID(m_nContract)) UpdateBiddingHistory(); // tally some figures m_nTotalScore[0] = m_nGameScore[0][0] + m_nGameScore[1][0] + m_nGameScore[2][0] + m_nBonusScore[0]; m_nTotalScore[1] = m_nGameScore[0][1] + m_nGameScore[1][1] + m_nGameScore[2][1] + m_nBonusScore[1]; // vulnerability if ((m_numGamesWon[0] > 0) && (m_numGamesWon[1] > 0)) { m_nVulnerableTeam = BOTH; m_bVulnerable[0] = m_bVulnerable[1] = TRUE; } else if (m_numGamesWon[0] > 0) { m_nVulnerableTeam = NORTH_SOUTH; m_bVulnerable[0] = TRUE; } else if (m_numGamesWon[1] > 0) { m_nVulnerableTeam = EAST_WEST; m_bVulnerable[1] = TRUE; } else { m_nVulnerableTeam = NEITHER; } // // set contract info // m_nContract = ContractParamsToBid(m_nContractSuit,m_nContractLevel); m_nTrumpSuit = m_nContractSuit; m_nBiddingRound = nBidIndex; // set play info if (ISBID(m_nContract) && ISPLAYER(m_nDeclarer)) { // contract has been reached m_nDummy = GetPartner((int) m_nDeclarer); m_nGameLead = GetNextPlayer(m_nDeclarer); m_nRoundLead = m_nGameLead; m_nCurrPlayer = m_nRoundLead; m_nTrickLead[0] = m_nRoundLead; // m_pPlayer[m_nDummy]->SetDummyFlag(TRUE); // m_pPlayer[m_nDeclarer]->SetDeclarerFlag(TRUE); } else { // contract has NOT been reached, so restart m_nCurrPlayer = m_nDealer; m_numBidsMade = 0; } // restore initial hands (temp?) for(i=0;i<4;i++) m_pPlayer[i]->RestoreInitialHand(); // not reviewing game m_bReviewingGame = FALSE; // all done return TRUE; }
GameState* MakeGameState(const bp::list& vec, uint32_t player, const std::string& suit) { PREF_ASSERT(bp::len(vec) == 3 && suit.size() == 1 && "wrong arguments list"); return new GameState({bp::extract<CardsSet>(vec[0]), bp::extract<CardsSet>(vec[1]), bp::extract<CardsSet>(vec[2])}, player, CharToSuit(suit[0])); }