// // FlashButton() // // used to temporarily flash a button's border // void CBidDialogSmall::FlashButton(int nBid) { // CWnd *pWnd1 = NULL, *pWnd2 = NULL; // if (ISBID(nBid)) { int nLevel = BID_LEVEL(nBid); int nSuit = BID_SUIT(nBid); pWnd1 = GetDlgItem(IDC_BID_LEVEL_1 + nLevel - 1); pWnd2 = GetDlgItem(IDC_SUIT_CLUBS + nSuit); } else if (nBid == BID_PASS) pWnd1 = GetDlgItem(IDC_BID_PASS); else if (nBid == BID_DOUBLE) pWnd1 = GetDlgItem(IDC_BID_DOUBLE); else if (nBid == BID_REDOUBLE) pWnd1 = GetDlgItem(IDC_BID_REDOUBLE); // if (pWnd1 == NULL) return; // FlashWindow(pWnd1, pWnd2); }
// // PressBidButton() // // used to make a button it appear pressed // void CBidDialogSmall::PressBidButton(int nBid) { // CButton *pButton1 = NULL, *pButton2 = NULL; // if (ISBID(nBid)) { int nLevel = BID_LEVEL(nBid); int nSuit = BID_SUIT(nBid); pButton1 = (CButton*) GetDlgItem(IDC_BID_LEVEL_1 + nLevel - 1); pButton2 = (CButton*) GetDlgItem(IDC_SUIT_CLUBS + nSuit); } else if (nBid == BID_PASS) pButton1 = (CButton*) GetDlgItem(IDC_BID_PASS); else if (nBid == BID_DOUBLE) pButton1 = (CButton*) GetDlgItem(IDC_BID_DOUBLE); else if (nBid == BID_REDOUBLE) pButton1 = (CButton*) GetDlgItem(IDC_BID_REDOUBLE); // if (pButton1 == NULL) return; // BOOL bWindow2Enabled = pButton2? pButton2->IsWindowEnabled() : FALSE; // pButton1->SetState(TRUE); if (pButton2) { pButton2->EnableWindow(TRUE); pButton2->SetState(TRUE); } // Sleep(300); // pButton1->SetState(FALSE); if (pButton2) { pButton2->SetState(FALSE); pButton2->EnableWindow(bWindow2Enabled); } // done return; }
// //=============================================================================== // // TryConvention() // // check if we can use an Jacoby 2NT Bid here // BOOL CJacoby2NTConvention::TryConvention(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // // the requirements for an Jacoby 2NT Bid are: // 1: Partner must have opened with 1 of a major // 2: we must not have bid yet // 3: we have 13+ points and 4+ card trump support int nOpeningBid = pDOC->GetOpeningBid(); int nPartnersBid = bidState.nPartnersBid; // test conditions 1 - 4 if ( ISBID(nOpeningBid) && (nOpeningBid == nPartnersBid) && (ISMAJOR(BID_SUIT(bidState.nPartnersBid))) && (bidState.nPartnersBidLevel == 1) && (bidState.m_numBidTurns == 0) && (bidState.fPts >= OPEN_PTS(13)) && (bidState.numSupportCards >= 4) ) { // passed the test } else { return FALSE; } // calc adjusted pts int nSuit = bidState.nPartnersSuit; bidState.SetAgreedSuit(nSuit); bidState.fAdjPts = hand.RevalueHand(REVALUE_DUMMY, nSuit, TRUE); // status << "J2N1! Partner opened " & BTS(nPartnersBid) & ", and with " & bidState.fAdjPts & " pts in hand and " & bidState.numSupportCards & "-card trump support, we can bid Jacoby 2NT to ask for partner's strength.\n"; bidState.SetBid(BID_2NT); bidState.SetConventionStatus(this, CONV_INVOKED); return TRUE; }
BOOL CEasyBDoc::ExportGameInfo(CArchive& ar) { // export game info // export hands WriteText(ar, "[Dealt Hands]\r\n"); CString strHands = FormatOriginalHands(); WriteText(ar, strHands); // export bidding history WriteText(ar, "\r\n\r\n"); WriteText(ar, "[Bidding History]\r\n"); const CString strBiddingHistory = pMAINFRAME->GetBiddingHistory(); WriteText(ar, strBiddingHistory); if (ISBID(GetContract())) { int nDeclarer = GetDeclarerPosition(); CString strContract = FormString("Contract: %s by %s; %s leads", pDOC->GetContractString(), PositionToString(nDeclarer), PositionToString(GetNextPlayer(nDeclarer))); // WriteText(pFile, strContract); } // export play history WriteText(ar, "\r\n\r\n\r\n"); WriteText(ar, "[Play History]\r\n"); const CString strPlayHistory = pMAINFRAME->GetPlayHistory(); WriteText(ar, strPlayHistory); // export current hands if (GetNumTricksPlayed() > 0) { WriteText(ar, "\r\n\r\n\r\n"); WriteText(ar, "[Current Hands]\r\n"); CString strHands = pDOC->FormatCurrentHands(); WriteText(ar, strHands); } // done ar.Flush(); 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; }
// //--------------------------------------------------------- // 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; }
// //=============================================================================== // // TryConvention() // // check if we can bid a takeout double here // BOOL CNegativeDoublesConvention::TryConvention(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // // Negative doubles are made in the third position after // partner opens and RHO overcalls up to 2S. // The requirements for a negative doubles are: // 1: partner must have opened the bidding, // 2: we must either have passesed or not bid yet // 3: RHO must have overcalled at a level no higher than 2S, // 4: have 4+ cards in each unbid major, (5+ at the 2-level), // 5: holding 6+ points at the 1-level, or 11+ at the 2-level, and finally, // 6: don't have decent support for partner's suit // test conditions 1, 2, 3, and 5 if ((bidState.m_bPartnerOpenedForTeam) && (bidState.m_numBidTurns <= 1) && (bidState.nLHOBid <= BID_PASS) && (bidState.nRHOBid > BID_PASS) // NCR-145 Can't do NegDouble over Opening bid of Double && (bidState.nPartnersOpeningBid != BID_DOUBLE) // NCR-294 Can't do NegDbl over NT && (bidState.nRHOSuit != NOTRUMP) // NCR-116 split test into 2 parts depending on bid level && (((bidState.nRHOBid <= BID_1S) && (bidState.fCardPts >= OPEN_PTS(6))) // NCR-116 higher level takes more points || ((bidState.nRHOBid <= BID_2S) && (bidState.fCardPts >= OPEN_PTS(11)))) && !ISBID(bidState.nPreviousBid)) // NCR test if we made a previous bid { // passed the initial tests } else { return FALSE; } // test condition #6 // if we can raise partner or shift over the opponent, // don't bother with a negative double int nRHOBid = bidState.nRHOBid; int nRHOBidLevel = bidState.nRHOBidLevel; int nRHOSuit = bidState.nRHOSuit; // if (nRHOBidLevel == 1) { /* // see if we can raise partner at the 2-level if (pCurrConvSet->IsConventionEnabled(tidLimitRaises)) { if ((bidState.numSupportCards >= 3) && (bidState.fPts >= OPEN_PTS(6))) { // we can raise partner at the 2-level, so forget the neg double return FALSE; } else if (bidState.numSupportCards >= 3) && (bidState.fPts >= OPEN_PTS(6))) { // likewise, w/o limit raises return FALSE; } } */ if ((bidState.numSupportCards >= 3) && (bidState.numSupportCards >= 3) && (bidState.fPts >= OPEN_PTS(6))) { // if we can raise partner at the 2-level, forget the neg double if (pCurrConvSet->IsConventionEnabled(tidLimitRaises) && (bidState.fPts >= OPEN_PTS(11)) && (bidState.fPts < OPEN_PTS(13))) return FALSE; // limit raise else if (!pCurrConvSet->IsConventionEnabled(tidLimitRaises) && (bidState.fPts >= OPEN_PTS(13)) && (bidState.fPts < OPEN_PTS(17))) return FALSE; // single raise } // check up to 2 suits for (int i=0;i<2;i++) { // see if we can switch to this suit int nSuit = hand.GetSuitsByPreference(i); if (bidState.IsSuitShiftable(nSuit) && (nSuit > nRHOSuit)) return FALSE; } } // if (nRHOBidLevel == 2) { // see if we can safely raise partner at the 2-level if ((bidState.numSupportCards >= 3) && (bidState.fPts >= OPEN_PTS(6)) && (bidState.nPartnersSuit > nRHOSuit)) { // we can raise partner at the 2-level, so forget the neg double return FALSE; } // see if we can raise partner to the 3-level (either 11 or 13 pts) double nReqPts = pCurrConvSet->IsConventionEnabled(tidLimitRaises)? OPEN_PTS(11) : OPEN_PTS(13); if ((bidState.numSupportCards >= 4) && (bidState.fPts >= nReqPts)) { // we can raise partner to the 3-level, so forget the neg double return FALSE; } // check up to 2 suits for a shift at the 2-level for (int i=0;i<2;i++) { // see if we can switch to this suit int nSuit = hand.GetSuitsByPreference(i); if (bidState.IsSuitShiftable(nSuit)) { // we can shift to the suit, but see if we have the pts if ((nSuit < bidState.nPartnersSuit) && (bidState.fPts >= OPEN_PTS(10))) return FALSE; // can shift to a lower suit at the 2-level else if ((nSuit > bidState.nPartnersSuit) && (bidState.fPts >= OPEN_PTS(19))) return FALSE; // can (jump) shift to a higher suit at the 2-level } } } else if (nRHOBidLevel == 3) { // opp. overcalled at 3-level; too high a level for a neg. double return FALSE; } // test condition 4 // mark which majors are unbid int nMajorSuits[2] = { 1, 1 }; if (bidState.nPartnersSuit == HEARTS) nMajorSuits[0] = 0; // Hearts have been bid else if (bidState.nPartnersSuit == SPADES) nMajorSuits[1] = 0; // spades have been bid // if (bidState.nRHOSuit == HEARTS) nMajorSuits[0] = 0; else if (bidState.nRHOSuit == SPADES) nMajorSuits[1] = 0; // if both majors have been bid, we can't use negative doubles if ((!nMajorSuits[0]) && (!nMajorSuits[1])) return FALSE; // if (bidState.nRHOBidLevel == 1) { // at the 1-level, need 4+ cards in each unbid major and 6+ pts if ( ((nMajorSuits[0]) && (hand.GetNumCardsInSuit(HEARTS) < 4)) || ((nMajorSuits[1]) && (hand.GetNumCardsInSuit(SPADES) < 4)) || (bidState.fPts < OPEN_PTS(6))) return FALSE; } else { // at the 2-level, need 5+ cards in each unbid major and 11+ pts if ( ((nMajorSuits[0]) && (hand.GetNumCardsInSuit(HEARTS) < 5)) || ((nMajorSuits[1]) && (hand.GetNumCardsInSuit(SPADES) < 5)) || (bidState.fPts < OPEN_PTS(11))) return FALSE; } // // finally, see if we have _too many_ points for a neg. double (19+) // if (bidState.fPts >= OPEN_PTS(19)) { // status << "NEGDBLX! We have the holdings for a negative double, but our " & // bidState.fPts & " points are too much\n"; return FALSE; } // // we've now passed all the tests, so make the bid // if (bidState.nRHOBidLevel == 1) status << "NEGDBL1! With " & bidState.fPts & "/" & bidState.fPts & " points and 4 cards in the unbid majors, bid a negative double.\n"; else status << "NEGDBL2! With " & bidState.fPts & "/" & bidState.fPts & " points and 5+ cards in the unbid majors, bid a negative double.\n"; int nBid = BID_DOUBLE; bidState.SetBid(nBid); // bidState.SetConventionStatus(this, CONV_INVOKED); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; }
// //--------------------------------------------------------- // // PBN File output routine // BOOL CEasyBDoc::WriteFilePBN(CArchive& ar) { pFile = ar.GetFile(); ASSERT(pFile != NULL); // write header WriteComment(""); WriteComment("EXPORT"); WriteComment("PBN Format 1.0"); WriteComment(FormString("File generated by Easy Bridge version %s", theApp.GetProgramVersionString())); WriteComment(""); // // write the data // // Event tag WriteLine(TAG_EVENT, FormString("%s Game", theApp.GetValue(tstrProgramTitle))); // Site Tag WriteLine(TAG_SITE, "At Home"); // NCR added At Home // Date Tag CTime time = CTime::GetCurrentTime(); WriteLine(TAG_DATE, time.Format("%Y.%m.%d")); /* * skip the round tag -- no longer mandatory in PBN 0.91+ * // Round Tag WriteLine(TAG_ROUND, ""); */ // Board Tag WriteLine(TAG_BOARD, "1"); // NCR added 1 // West/North/East/South Tags WriteLine(TAG_WEST, "Computer"); WriteLine(TAG_NORTH, "Computer"); WriteLine(TAG_EAST, "Computer"); WriteLine(TAG_SOUTH, "Human Player"); // Dealer Tag WriteLine(TAG_DEALER, FormString("%c", PositionToChar(m_nDealer))); // Vulnerable Tag CString strVulnerable; if ((m_bVulnerable[NORTH_SOUTH]) && (m_bVulnerable[EAST_WEST])) strVulnerable = "Both"; else if (m_bVulnerable[NORTH_SOUTH]) strVulnerable = "NS"; else if (m_bVulnerable[EAST_WEST]) strVulnerable = "EW"; else strVulnerable = "None"; WriteLine(TAG_VULNERABLE, strVulnerable); // deal tag CString strDeal = "W:"; int nPos = WEST; int i; // NCR-FFS added here, removed below for(/*int*/ i=0;i<4;i++) { CCardHoldings& cards = m_pPlayer[nPos]->GetHand().GetInitialHand(); strDeal += cards.GetGIBFormatHoldingsString(); nPos = GetNextPlayer(nPos); if (i < 3) strDeal += ' '; } WriteLine(TAG_DEAL, strDeal); // Scoring tag if (theApp.IsRubberInProgress()) WriteLine(TAG_SCORING, _T("Rubber")); else WriteLine(TAG_SCORING, _T("None")); // Declarer Tag if (ISPOSITION(m_nDeclarer)) WriteLine(TAG_DECLARER, FormString("%c", PositionToChar(m_nDeclarer))); else WriteLine(TAG_DECLARER, "?"); // Contract Tag if (ISBID(m_nContract)) { // NCR Include ContractToString() here as PBN file does NOT have space before X CString strBid; strBid.Format("%d%s", BID_LEVEL(m_nContract), szSuitNameShort[BID_SUIT(m_nContract)]); int nModifier = pDOC->GetContractModifier(); if (nModifier > 0) strBid += FormString("%s", ((nModifier == 1)? "X" : "XX")); // w/o space WriteLine(TAG_CONTRACT, strBid); // NCR replaced ContractToString(m_nContract) } else WriteLine(TAG_CONTRACT, "?"); // Result tag if (m_numTricksPlayed == 13) WriteLine(TAG_RESULT, FormString("%d", m_numTricksWon[m_nContractTeam])); // NCR removed extra "s else WriteLine(TAG_RESULT, "?"); // // write out the hands in comment form // CString strHands = "{\r\n" + pDOC->FormatOriginalHands() + "}"; WriteLine(strHands); // // write out auction // CString strBids = FormString("[Auction \"%c\"]", PositionToChar(m_nDealer)); // NCR Lowercased if (m_numBidsMade > 0) strBids += "\r\n"; nPos = m_nDealer; for(i=0;i<m_numBidsMade;i++) { strBids += FormString("%s ", ::BidToPBNString(m_nBiddingHistory[i])); nPos = ::GetNextPlayer(nPos); if ( (((i+1) % 4) == 0) && (i < m_numBidsMade-1) ) strBids += "\r\n"; } // add marker if needed if (!ISBID(m_nContract)) strBids += "\r\n*"; // and write out WriteLine(strBids); // // write out plays // CString strPlays = FormString("[Play \"%c\"]", PositionToChar(m_nGameLead)); // NCR Lowercased if (m_numTricksPlayed> 0) strPlays += "\r\n"; bool bLastRowFnd = false; // NCR added - only output single row with -s for(i=0;i<m_numTricksPlayed;i++) { int nPos = m_nGameLead; for(int j=0;j<4;j++) { CCard* pCard = m_pGameTrick[i][nPos]; if (pCard == NULL) { strPlays += "- "; bLastRowFnd = true; // NCR this row will end the output } else strPlays += FormString("%s ", pCard->GetName()); nPos = ::GetNextPlayer(nPos); } // end for(j) thru poisitions if (i < m_numTricksPlayed-1) strPlays += "\r\n"; if(bLastRowFnd) break; // NCR finished output plays on line with -s } // end for(i) thru tricks // add marker if needed if (m_numTricksPlayed < 13) strPlays += "\r\n*"; // and write out WriteLine(strPlays); // Generator Tag WriteLine(TAG_GENERATOR, FormString("Easy Bridge version %s", theApp.GetProgramVersionString())); // Description Tag WriteLine(TAG_DESCRIPTION, m_strFileDescription); // blank line // SkipLine(); // // write out the auction // // // All done // ar.Flush(); return TRUE; }
void CBidDialog::UpdateBidDisplay(int nPos, int nBid, BOOL bPrompt, BOOL bTentative) { int nTextID = IDC_BID_SOUTH + nPos; int nIconID = IDCI_BID_SOUTH + nPos; // see if we're using text for bids if (!UsingSuitSymbols() || !ISBID(nBid) || bTentative) { // show bid text GetDlgItem(nIconID)->ShowWindow(FALSE); GetDlgItem(nTextID)->ShowWindow(TRUE); CString strTemp; // show text if ((nPos == SOUTH) && (bPrompt)) { SetDlgItemText(nTextID, "??"); } else if (nBid == -2) { SetDlgItemText(nTextID, "?"); } else if (nBid == -1) { SetDlgItemText(nTextID, ""); } else if (bTentative) { strTemp = BidToShortString(nBid) + _T('?'); SetDlgItemText(nTextID, (LPCTSTR)strTemp); } else { // real bid strTemp = BidToShortString(nBid); SetDlgItemText(nTextID, (LPCTSTR)strTemp); } GetDlgItem(nTextID)->UpdateWindow(); } else { // show bid icon GetDlgItem(nTextID)->ShowWindow(FALSE); GetDlgItem(nIconID)->ShowWindow(TRUE); CStatic* pStatic = (CStatic*) GetDlgItem(nIconID); if (ISBID(nBid)) { int nSuit = (nBid-1) % 5; int nLevel = (nBid-1) / 5; pStatic->SetIcon(m_buttonIcons[nSuit][nLevel]); } else { pStatic->SetIcon(NULL); } // pStatic->UpdateWindow(); } /* CString strTemp; // show text if ((nPos == SOUTH) && (bPrompt)) { SetDlgItemText(IDC_BID_SOUTH, "??"); } else if (nBid == -2) { SetDlgItemText(IDC_BID_SOUTH+nPos, "?"); } else if (nBid == -1) { SetDlgItemText(IDC_BID_SOUTH+nPos, ""); } else if (bTentative) { strTemp = BidToShortString(nBid) + _T('?'); SetDlgItemText(IDC_BID_SOUTH+nPos, (LPCTSTR)strTemp); } else { // real bid strTemp = BidToShortString(nBid); // play sound if appropriate if (m_bSpeechEnabled) { CString strDir = theApp.GetValueString(tszProgramDirectory); // CString strPath = strDir + _T("\\Sounds\\") + PositionToString(nPos) + strTemp + _T(".wav"); CString strPath = strDir + _T("\\Sounds\\") + strTemp + _T(".wav"); CFile file; if (file.Open(strPath, CFile::modeRead)) { file.Close(); PlaySound(strPath, NULL, SND_SYNC | SND_NOSTOP | SND_NOWAIT); } } // show bid SetDlgItemText(IDC_BID_SOUTH+nPos, (LPCTSTR)strTemp); } */ }
// //----------------------------------------------------- // // respond to partner's Michaels Cue Bid // BOOL CMichaelsCueBidConvention::RespondToConvention(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // first see if another convention is active if ((bidState.GetActiveConvention() != NULL) && (bidState.GetActiveConvention() != this)) return FALSE; // // make a responding bid // int nPartnersBid = bidState.nPartnersBid; int nPartnersBidLevel = bidState.nPartnersBidLevel; int nPartnersSuit = bidState.nPartnersSuit; int nPartnersPrevSuit = bidState.nPartnersPrevSuit; // int nBid, nSuit; double fPts = bidState.fPts; double fCardPts = bidState.fCardPts; // // see what round this is // int nStatus = bidState.GetConventionStatus(this); if (nStatus == CONV_INACTIVE) { // // Bidding in response to partner's Michael's bid? check requirements // // the identifying marks of a Michaels bid are: // 1: we must not have bid yet // 2: LHO must have bid a suit at the 1 level, and // 3: partner overcalled LHO's suit at the 2 level int nLastValidBid = pDOC->GetLastValidBid(); // apply tests #1, 2, and 3 int nOpeningBid = pDOC->GetOpeningBid(); int nOpeningBidder = pDOC->GetOpeningBidder(); BOOL bLHOMajor = ISMAJOR(nOpeningBid); if (ISBID(nOpeningBid) && (GetPlayerTeam(nOpeningBidder) != player.GetTeam()) && ((nOpeningBid >= BID_1C) && (nOpeningBid <= BID_1S)) && (nPartnersSuit == bidState.nLHOSuit) && (nPartnersBidLevel == 2) && (bidState.m_numBidsMade == 0) ) { // status << "MCLR10! Partner has made a Michaels Cue bid of " & BTS(nPartnersBid) & ", indicating 5/5 length in " & (bLHOMajor? ((bidState.nLHOSuit == HEARTS)? "Spades and a minor" : "Hearts and a minor") : "the majors") & ".\n"; } else { return FALSE; } // did partner bid a minor, indicating both majors? if (ISMINOR(nPartnersSuit)) { // Pard has both majors -- pick the preferred one nSuit = bidState.PickSuperiorSuit(HEARTS, SPADES); if (hand.GetNumCardsInSuit(nSuit) < 3) { // should have at least 3 trumps int nOtherSuit = (nSuit == HEARTS)? SPADES : HEARTS; if (hand.GetNumCardsInSuit(nOtherSuit) >= 3) nSuit = nOtherSuit; } } else if (nPartnersSuit == HEARTS) { // pard has Spades + a minor // see if Spades are decent (3-card support) // if ((hand.GetNumCardsInSuit(SPADES) >= 3) && (hand.GetSuitStrength(SPADES) >= SS_MODERATE_SUPPORT)) if (hand.GetNumCardsInSuit(SPADES) >= 3) { // fine, go with Spades nSuit = SPADES; } else { // Spades are too weak; look for a minor if ((hand.GetSuitStrength(CLUBS) >= SS_MODERATE_SUPPORT) || (hand.GetSuitStrength(DIAMONDS) >= SS_MODERATE_SUPPORT)) nSuit = NOTRUMP; else nSuit = SPADES; // minors are no good either, so go with Spades } } else { // pard has Hearts + a minor // see if Hearts are decent (3-card support) // if ((hand.GetNumCardsInSuit(HEARTS) >= 3) && (hand.GetSuitStrength(HEARTS) >= SS_MODERATE_SUPPORT)) if (hand.GetNumCardsInSuit(HEARTS) >= 3) { // fine, go with Hearts nSuit = HEARTS; } else { // Spades are too weak; look for a minor if ((hand.GetSuitStrength(CLUBS) >= SS_MODERATE_SUPPORT) || (hand.GetSuitStrength(DIAMONDS) >= SS_MODERATE_SUPPORT)) nSuit = NOTRUMP; else nSuit = HEARTS; // minors are no good either, so go with Hearts } } // now adjust point count if (ISSUIT(nSuit)) { bidState.SetAgreedSuit(nSuit); fPts = bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, nSuit, TRUE); } // partner may have 6-11 OR 17+ pts; assume it's a weak hand bidState.AdjustPartnershipPoints(6, 11); // and make a responding bid CString strChoices = ISMINOR(nPartnersSuit)? "the two majors" : (nPartnersSuit == HEARTS)? "Spades and a minor" : "Hearts and an unknown minor"; int numTrumps = ISSUIT(nSuit)? hand.GetNumCardsInSuit(nSuit) : 0; // set initial convention status to finished bidState.SetConventionStatus(this, CONV_FINISHED); // see if we need to look at the minor if (nSuit == NOTRUMP) { // bid 2NT to ask for the minor nBid = BID_2NT; if (nBid > nLastValidBid) { if (nPartnersSuit == HEARTS) status << "MCLR12! Given a choice between a " & hand.GetNumCardsInSuit(SPADES) & "-card Spade suit and an unknown minor, we're forced to ask for the minor by bidding " & BTS(nBid) & ".\n"; else status << "MCLR12! Given a choice between a " & hand.GetNumCardsInSuit(HEARTS) & "-card Heart suit and an unknown minor, we're forced to ask for the minor by bidding " & BTS(nBid) & ".\n"; // this convention will go another round bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND1); } else { nBid = BID_PASS; status << "MCLR13! We'd like to bid 2NT to ask for partner's minor, but we can't do so after RHO's interference, so we have to pass.\n"; } } else if ((numTrumps >= 5) && (bidState.m_fMinTPPoints <= PT_COUNT(20)) && ISMAJOR(nSuit) && (MAKEBID(nSuit, 4) > nLastValidBid)) { // make a preemptive bid if possible nBid = MAKEBID(nSuit, 4); status << "MCLR15! With " & numTrumps & " " & STS(nSuit) & " and a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, make a shutout bid in " & STS(nSuit) & " by jumping to " & BTS(nBid) & ".\n"; } else if (bidState.m_fMinTPPoints <= PT_COUNT(21)) { // respond at the 2-level nBid = bidState.GetCheapestShiftBid(nSuit, nLastValidBid); if (BID_LEVEL(nBid) == 2) { status << "MCLR20! Given a choice between " & strChoices & ", respond to partner's Michaels with the preferred " & STSS(nSuit) & " suit with a bid of " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "MCLR21! After RHO interference, we don't have the points to go to the 3-level in response to partner's Michaels, so pass.\n"; } } else if (bidState.m_fMinTPPoints <= PT_COUNT(24)) { // bid at the 3-level nBid = MAKEBID(nSuit, 3); if (nBid > nLastValidBid) { status << "MCLR24! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership and a choice between " & strChoices & ", invite game in " & STS(nSuit) & " by jumping to " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "MCLR25! After RHO interference, we don't have the points to go to the 4-level in response to partner's Michaels, so pass.\n"; } } else if (ISMINOR(nSuit) && (bidState.m_fMinTPPoints <= PT_COUNT(27))) { // with 25+ pts, bid game nBid = bidState.GetGameBid(nSuit); if (nBid > nLastValidBid) { status << "MCLR27! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership and a choice between " & strChoices & ", jump to the 4-level in " & STS(nSuit) & " with a bid of " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "MCLR28! After RHO interference, we don't have the points to go to the 5-level in response to partner's Michaels, so pass.\n"; } } else { // with 25+ pts in a major, or 28+ pts in a minor, bid game nBid = bidState.GetGameBid(nSuit); if (nBid > nLastValidBid) { status << "MCLR30! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership and a choice between " & strChoices & ", jump to game in " & STS(nSuit) & " at " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "MCLR31! After RHO interference, we don't want to bid past game, so pass.\n"; } } // done! bidState.SetBid(nBid); return TRUE; } else if (nStatus == CONV_RESPONDED_ROUND1) { // // round 2 -- we must've bid 2NT last time to ask for partner's minor // // see if partner cue bid the enemy suit again if (nPartnersSuit == nPartnersPrevSuit) { // partner has 17+ pts bidState.AdjustPartnershipPoints(OPEN_PTS(17), MIN(17,40 - bidState.fCardPts)); // bid 4NT to ask for the minor again if (fPts >= PT_COUNT(15)) { // else make a natural game bid nBid = BID_4NT; status << "MCLR35! Partner cue bid the enemy suit again, indicating a strong Michaels opening hand with " & OPEN_PTS(17) & "+ pts; so with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, ask for the other minor by bidding " & BTS(nBid) & ".\n"; bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND2); } else { // else make a natural 3NT game bid nBid = BID_3NT; status << "MCLR36! Partner cue bid the enemy suit again, indicating a strong Michaels opening hand with " & OPEN_PTS(17) & "+ pts; but with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, stop at game with a natural bid of " & BTS(nBid) & ".\n"; bidState.SetConventionStatus(this, CONV_FINISHED); } // done bidState.SetBid(nBid); return TRUE; } // see if partner's bid is valid if (!ISMINOR(nPartnersSuit)) { status << "MCLR40! After his opening Michaels Cue Bid, partner did not respond properly to our 2NT minor suit inquiry, so michaels is off.\n"; bidState.SetConventionStatus(this, CONV_ERROR); return FALSE; } // see if we can live with partner's minor int nAgreedSuit; if (hand.GetNumCardsInSuit(nPartnersSuit) >= 3) { // stick with the minor status << "4MCLR41! Since we have " & hand.GetNumCardsInSuit(nPartnersSuit) & " cards in the " & STSS(nPartnersSuit) & " suit, choose that suit for our response.\n"; nAgreedSuit = nPartnersSuit; } else { // minor's not so great; select the better of the minor or the major nAgreedSuit = bidState.PickSuperiorSuit(nPartnersSuit, bidState.nPartnersPrevSuit); if (nAgreedSuit == nPartnersSuit) status << "4MCLR42! The " & STSS(nPartnersSuit) & " suit isn't great, but it's better than " & STS(bidState.nPartnersPrevSuit) & ", so choose that suit for our response.\n"; else status << "4MCLR43! The " & STSS(nPartnersSuit) & " suit is poor, so pick the major suit ("& STS(bidState.nPartnersPrevSuit) & ") for our response.\n"; bidState.SetAgreedSuit(bidState.PickSuperiorSuit(nPartnersSuit, bidState.nPartnersPrevSuit)); } // recalc points as dummy bidState.SetAgreedSuit(nAgreedSuit); fPts = bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, nAgreedSuit, TRUE); bidState.AdjustPartnershipPoints(); // select the bid level if (ISMINOR(nAgreedSuit)) { // Clubs or Diamonds if (bidState.m_fMinTPPoints <= PTS_MINOR_GAME-6) // <= 22 nBid = BID_PASS; else if (bidState.m_fMinTPPoints <= PTS_MINOR_GAME-4) // <= 24 nBid = MAKEBID(nPartnersBid, 4); else nBid = MAKEBID(nPartnersBid, 5); // go for game // if (nBid == BID_PASS) status << "MCLR45! Partner showed his minor to be " & STS(nPartnersSuit) & ", which we can support with " & hand.GetNumCardsInSuit(nPartnersSuit) & " trumps, but with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, we have to pass.\n"; else status << "MCLR46! Partner showed his minor to be " & STS(nPartnersSuit) & ", which we can support with " & hand.GetNumCardsInSuit(nPartnersSuit) & " trumps, so with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, we bid " & BTS(nBid) & ".\n"; } else { // sticking with the major (though not a very good one!) // sign off at the 3-level or go to game if (bidState.m_fMinTPPoints < PTS_MAJOR_GAME) // < 25 nBid = MAKEBID(nPartnersBid, 3); else nBid = MAKEBID(nPartnersBid, 4); // if (BID_LEVEL(nBid) == 3) status << "MCLR47! With " & hand.GetNumCardsInSuit(nAgreedSuit) & "-card support for partner's " & STS(nAgreedSuit) & ", and with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, we have to pass.\n"; else status << "MCLR47! With " & hand.GetNumCardsInSuit(nAgreedSuit) & "-card support for partner's " & STS(nAgreedSuit) & ", and with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, we can go to game at " & BTS(nBid) & ".\n"; } // done! bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else if (nStatus == CONV_RESPONDED_ROUND2) { // // round 3 -- we must've bid 4NT last time to ask for partner's minor // after partner's second Michaels cue bid // } // return FALSE; }