// // GetCheapestKingOrVoid() // // returns the next cheapest suit with a king or void // int CCueBidConvention::GetCheapestKingOrVoid(CHandHoldings& hand, int nBaseSuit, int nSecondSuit) { int i; // if (nBaseSuit < CLUBS) return NONE; // int nSuit; if (nBaseSuit == NOTRUMP) nSuit = CLUBS; else nSuit = GetNextSuit(nBaseSuit); for(i=0;i<4;i++) { // suit should be void or else have a king if ( ((hand.GetSuitLength(nSuit) == 0) || hand.SuitHasCard(nSuit, KING)) && (nSuit != nSecondSuit) ) break; nSuit = GetNextSuit(nSuit); } // if (i < 4) return nSuit; else return nBaseSuit; }
// // PickFinalDiscardSuit() // int CPlayEngine::PickFinalDiscardSuit(CHandHoldings& hand) { // this routine is called by the declarer & defender engined when // they absolutely can't find a card to discard int nDiscardSuit = NONE; // this means generally tha twe have no suits with losers, // or that the only one with losers in the current hand is the priority suit // so look through suits by preference for one that has losers for(int i=3;i>=0;i--) { int nSuit = hand.GetSuitsByPreference(i); CSuitHoldings& testSuit = hand.GetSuit(nSuit); // avoid letting go of winners! if ((testSuit.GetNumCards() > 0) && (testSuit.GetNumCards() > testSuit.GetNumWinners())) { nDiscardSuit = nSuit; break; } } // if we failed above, we aboslutely have no losers anywhere // so search for a suit that has winners but no outstanding cards // i.e., suits that we may not be able to cash if (!ISSUIT(nDiscardSuit)) { for(i=3;i>=0;i--) { int nSuit = hand.GetSuitsByPreference(i); // see if we have cards in this suit, and no outstanding cards in the suit if ((hand.GetNumCardsInSuit(nSuit) > 0) && (GetNumOutstandingCards(nSuit) == 0)) { nDiscardSuit = nSuit; break; } } } // finally, give up and get any old suit that has cards if (!ISSUIT(nDiscardSuit)) { for(i=3;i>=0;i--) { int nSuit = hand.GetSuitsByPreference(i); if (hand.GetNumCardsInSuit(nSuit) > 0) { nDiscardSuit = nSuit; break; } } } // ASSERT(ISSUIT(nDiscardSuit)); return nDiscardSuit; }
// //=============================================================================== // // 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; }
// // GetCheapestAce() // // returns the next cheapest suit with an Ace // used for cue bidding // int CCueBidConvention::GetCheapestAce(CHandHoldings& hand, int nBaseSuit, int nSecondSuit) { int i; // if (nBaseSuit < CLUBS) return NONE; // int nSuit; if (nBaseSuit == NOTRUMP) nSuit = CLUBS; else nSuit = GetNextSuit(nBaseSuit); for(i=0;i<4;i++) { if (hand.SuitHasCard(nSuit, ACE) && (nSuit != nSecondSuit)) break; nSuit = GetNextSuit(nSuit); } // if (i < 4) return nSuit; else return nBaseSuit; }
// //=============================================================================== // // TryConvention() // // check if we can use an Gambling 3NT Bid here // BOOL CGambling3NTConvention::TryConvention(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // // the requirements for opening a STANDARD Gambling 3NT Bid are: // 1: a solid 7+ card minor suit, // 2: 10-12 HCPs, // 3: no voids or small singletons, and // 4: no outside stoppers // // the requirements for opening an ACOL Gambling 3NT Bid are: // 1: a solid 7+ card minor suit, // 2: 16-21 HCPs, // 3: no voids or small singletons, and // 4: stoppers in at least 2 of the remaining 3 suits // see which version we're playing int bStandardGambling3NT = (pCurrConvSet->GetValue(tnGambling3NTVersion) == 0); // see if we have any small singletons bool bSmallSingletons = false; if (bidState.numSingletons > 0) { for(int i=0; i<4; i++) { CSuitHoldings& suit = hand.GetSuit(i); if ((suit.GetNumCards() == 1) && (suit[0]->GetFaceValue() < TEN)) { bSmallSingletons = true; break; } } } // see if we have a solid suit int nSuit = NONE; if (hand.GetSuit(CLUBS).IsSolid() && (bidState.numCardsInSuit[CLUBS] >= 7)) nSuit = CLUBS; else if (hand.GetSuit(DIAMONDS).IsSolid() && (bidState.numCardsInSuit[DIAMONDS] >= 7)) nSuit = DIAMONDS; // test for std and ACOL Gambling 3NT conditions int numValidBidsMade = pDOC->GetNumValidBidsMade(); if ( bStandardGambling3NT && (numValidBidsMade == 0) && (ISSUIT(nSuit)) && (bidState.fCardPts >= OPEN_PTS(10)) && (bidState.fCardPts <= OPEN_PTS(12)) && (bidState.numVoids == 0) && !bSmallSingletons && (bidState.numSuitsStopped == 1) ) { // passed the test for standard gambling 3NT status << "G3NT1! With a solid " & bidState.numCardsInSuit[nSuit] & "-card " & STSS(nSuit) & " suit, " & bidState.fCardPts & " HCPs, no voids, no small singletons, and no outside stoppers, " " go ahead and bid a Gambling 3NT.\n"; } else if ( !bStandardGambling3NT && (numValidBidsMade == 0) && (ISSUIT(nSuit)) && (bidState.fCardPts >= OPEN_PTS(16)) && (bidState.fCardPts <= OPEN_PTS(21)) && (bidState.numVoids == 0) && !bSmallSingletons && (bidState.numSuitsStopped >= 3) ) { // passed the test for ACOL gambling 3NT status << "G3NT2! With a solid " & bidState.numCardsInSuit[nSuit] & "-card " & STSS(nSuit) & " suit, " & bidState.fCardPts & " HCPs, no voids, no small singletons, and stoppers in " & ((bidState.numSuitsStopped == 4)? "all four suits" : "two outside suits") & ", go ahead and bid an ACOL Gambling 3NT.\n"; } else { return FALSE; } // OK, go ahead and bid 3NT bidState.SetBid(BID_3NT); bidState.SetConventionStatus(this, CONV_INVOKED); return TRUE; }
// //--------------------------------------------------------------- // // TryCueBid() // BOOL CCueBidConvention::TryCueBid(CHandHoldings& hand, CBidEngine& bidState, CPlayerStatusDialog& status) { // check basic requirements if (bidState.m_nAgreedSuit == NONE) return FALSE; // don't make a cue bid if we're already done with it int nStatus = bidState.GetConventionStatus(this); if (nStatus != CONV_INACTIVE) return FALSE; // get adjusted point count as declarer // NCR BIG PROBLEM HERE - This changes a global variable. The changes are now always wanted ??? bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, bidState.m_nAgreedSuit, TRUE); bidState.m_fMinTPPoints = bidState.fAdjPts + bidState.m_fPartnersMin; bidState.m_fMaxTPPoints = bidState.fAdjPts + bidState.m_fPartnersMax; bidState.m_fMinTPCPoints = bidState.fCardPts + bidState.m_fPartnersMin; bidState.m_fMaxTPCPoints = bidState.fCardPts + bidState.m_fPartnersMax; // // try a cue bid only if we have an interest in slam // if (bidState.m_fMinTPPoints < 30) return FALSE; // also, we shouldn't use cue bid if we have all four aces if (bidState.numAces == 4) return FALSE; // or if we're already at a slam level if (bidState.nPartnersBidLevel >= 6) return FALSE; int nLastBid = pDOC->GetLastValidBid(); if (nLastBid >= bidState.GetGameBid(BID_SUIT(nLastBid))) return FALSE; // special test -- dont' cue bid if partner just raised a suit that we // shifted to artificially if ((bidState.nPartnersSuit == bidState.nPreviousSuit) && ( (ISSUIT(bidState.m_nAgreedSuit) && (bidState.nPreviousSuit != bidState.m_nAgreedSuit)) || (ISSUIT(bidState.m_nIntendedSuit) && (bidState.nPreviousSuit != bidState.m_nIntendedSuit)) ) ) return FALSE; // // see what stage we're at // if (nStatus == CONV_INACTIVE) { // // showing first round controls // // bidState.SetConventionStatus(this, CONV_INVOKED_ROUND1); // find cheapest ace int nBid; int nAgreedSuit = bidState.m_nAgreedSuit; int nSuit = GetCheapestAce(hand, nAgreedSuit); // if ((nSuit != bidState.m_nAgreedSuit) && (nSuit != bidState.nPartnersSuit)) { // found a suit to cue bid // the bid must be at a level that commits the partnership to game // i.e., for a major, it must be > 3 of the suit; for a minor, > 4 nBid = bidState.GetCheapestShiftBid(nSuit); int nBidLevel = BID_LEVEL(nBid); // see if the bid is too high to qualify as a cue bid if ( (ISMAJOR(nAgreedSuit) && (nBidLevel >= 5)) || (ISMINOR(nAgreedSuit) && (nBidLevel >= 6)) ) return FALSE; // else if it's too low, adjust it upwards if ( (ISMAJOR(nAgreedSuit) && (nBid < MAKEBID(nAgreedSuit,3))) || (ISMINOR(nAgreedSuit) && (nBid < MAKEBID(nAgreedSuit,4))) ) nBid += 5; // alternatively, see if the bid is too high if (nBid > bidState.GetGameBid(nAgreedSuit)) return FALSE; status << "CUET10! With " & bidState.m_fMinTPPoints & "+ pts and possible slam aspirations, make a cue bid, showing the cheapest ace (" & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED_ROUND1); return TRUE; } else { // either we don't have any aces, or the ace is in the trump suit // either way, we can't make a cue bid with this holding return FALSE; } } else if (nStatus == CONV_INVOKED_ROUND1) { // // showing second round controls, necesary if we want to proceed to a grand slam // bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); // find cheapest king or void suit int nSuit = GetCheapestKingOrVoid(hand, bidState.m_nAgreedSuit); int nPartnersBid = bidState.nPartnersBid; // if (nSuit != bidState.m_nAgreedSuit) { // found a suit to cue bid int nBid = bidState.GetCheapestShiftBid(nSuit); status << "CUET20! Make a second-round cue bid, showing the cheapest " & ((hand.GetSuitLength(nSuit) == 0)? "void suit" : "king") & " (in " & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } else { // either we don't have any second-round control to show, // so stop cue bidding and return to the trump suit int nBid = bidState.GetCheapestShiftBid(bidState.m_nAgreedSuit); status << "CUET24! With no second-round controls to cue bid, we have to return to the trump suit at a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } } else if (nStatus == CONV_INVOKED_ROUND2) { // both we and partner have shown first and second-round controls, so // it;s time to put up or shut up } else { // error! AfxMessageBox("Error while attempting cue bid!"); bidState.SetConventionStatus(this, CONV_ERROR); } // return TRUE; }
// //--------------------------------------------------------------- // // HandleConventionResponse() // BOOL CCueBidConvention::HandleConventionResponse(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // check state int nStatus = bidState.GetConventionStatus(this); if (nStatus <= 0) return FALSE; // int nPartnersBid = bidState.nPartnersBid; int nPartnersBidLevel = bidState.nPartnersBidLevel; int nPartnersSuit = bidState.nPartnersSuit; int nPreviousBid = bidState.nPreviousBid; int nAgreedSuit = bidState.m_nAgreedSuit; int nBid; // // first check if partner returned to the trump suit, regardless of // which cue bidding round this is // if ( ((nStatus == CONV_INVOKED_ROUND1) || (nStatus == CONV_INVOKED_ROUND2)) && (nPartnersSuit == nAgreedSuit) ) { // first check for a strange response if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE)) { // we don't understand partner's bid return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status); } // first check for a direct raise to slam by partner in response to our // cue bid(unlikely, but hey...) if (nPartnersBidLevel >= 6) { status << "HRCB0! In response to our cue bid, partner returned to the agreed " & STSS(nAgreedSuit) & " trump suit with a slam bid at " & BTS(nPartnersBid) & ".\n"; // raise to a grand slam if possible if ((nPartnersBidLevel == 6) && (bidState.m_fMinTPPoints >= 37)) { nBid = MAKEBID(nAgreedSuit,7); status << "HRCB1! And with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, go ahead and raise to " & BTS(nBid) & ".\n"; } else { // sign off on the slam nBid = BID_PASS; status << "HRCB2! And with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, sign off on the slam bid and pass.\n"; } // bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // // otherwise partner returned to the agreed suit below slam, // a discouraging sign // status << "HRCB5! Partner returned to the agreed " & STSS(nAgreedSuit) & " trump suit in response to our cue bid of " & BTS(nPreviousBid) & ", which is a discouraging sign.\n"; // pass with < 33 team points if (bidState.m_fMinTPPoints < 33) { // nBid = BID_PASS; status << "HRCB6! And with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we have to forget about slam and pass.\n" & BTS(nBid) & ".\n"; } else if (bidState.m_fMinTPPoints < 37) { // with 33-36 pts, bid small slam anyway nBid = MAKEBID(nAgreedSuit, 6); status << "HRCB7! But with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, go ahead and bid a small slam anyway at " & BTS(nBid) & ".\n"; } else { // with 33-37 pts, bid a grand slam anyway nBid = MAKEBID(nAgreedSuit, 7); status << "HRCB8! But with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, go ahead and bid a grand slam anyway at " & BTS(nBid) & ".\n"; } // bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // //----------------------------------------------------------------- // // else partner made a responding cue bid, an encouraging sign // now see what stage we're at // if (nStatus == CONV_INVOKED_ROUND1) { // first check for a strange response if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE)) { // we don't understand partner's bid return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status); } // status << "HRCB40! Partner responded with a cue bid of " & BTS(nPartnersBid) & ", showing an Ace in " & STS(nPartnersSuit) & ".\n"; // // see if we want to proceed to a second round of cue bidding // we need 36+ pts and controls in all four suits // BOOL bAllFourControls; if ((bidState.numAces + 1) == 4) { status << "HRCB42! And with partner's " & STSS(nPartnersSuit) & ", we have all four Aces for full first-round control.\n"; bAllFourControls = TRUE; } else { status << "HRCB43! But even with partner's " & STSS(nPartnersSuit) & ", it's not clear we have all four Aces for full first-round control.\n"; bAllFourControls = FALSE; } // if ((bidState.m_fMinTPPoints < PTS_SLAM) || (!bAllFourControls)) { // gotta stop below slam nBid = bidState.GetCheapestShiftBid(nAgreedSuit); status << "HRCB46! With only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership" & ((bAllFourControls)? "," : "and without clear first round controls,") & " we can't afford to bid slam, so settle for a contract of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // else we have >= 33 pts and all four controls else if (bidState.m_fMinTPPoints < 36) { // can only make a small slam nBid = MAKEBID(nAgreedSuit, 6); status << "HRCB46! But with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we have to stop at a small with a contract of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // // at this point, we have 36+ points, so trigger another round of cue bidding // find cheapest king or void suit // int nSuit = GetCheapestKingOrVoid(hand, bidState.m_nAgreedSuit); if (nSuit != nAgreedSuit) { // found a suit to cue bid for second round nBid = bidState.GetCheapestShiftBid(nSuit); status << "HRCB60! Make a second-round cue bid, showing the cheapest " & ((hand.GetSuitLength(nSuit) == 0)? "void suit" : "king") & " (in " & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n"; } else { // either we don't have any second-round control to show, or the // second round card is in the trump // so stop cue bidding and return to the trump suit at a small slam nBid = MAKEBID(nAgreedSuit, 6); status << "HRCB80! With no second-round controls to cue bid, we have to return to the trump suit with a small slam at " & BTS(nBid) & ".\n"; } // bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else if (nStatus == CONV_INVOKED_ROUND2) { // first check for a strange response if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE)) { // we don't understand partner's bid return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status); } // // both we and partner have shown first and second-round controls, // so now it's time to put up or shut up // // if we like the controls and have enough points, bid grand slam; // else bid a small slam or game // // // see if we want to proceed to a second round of cue bidding // we need 36+ pts and controls in all four suits // BOOL bAllFourSecondRoundControls; if ((bidState.numKings + 1) == 4) { status << "HRCBS10! And with partner's " & STSS(nPartnersBid) & " bid showing a King or void, in " & STS(nPartnersSuit) & ", we have scond-round control of all four suits.\n"; bAllFourSecondRoundControls = TRUE; } else { status << "HRCBS12! But even with partner's " & STSS(nPartnersBid) & ", it's not clear we have all full second-round control.\n"; bAllFourSecondRoundControls = FALSE; } // if ((bidState.m_fMinTPPoints < 32) || (!bAllFourSecondRoundControls)) { // gotta stop below slam nBid = bidState.GetCheapestShiftBid(nAgreedSuit); status << "HRCBS20! With only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership " & ((bAllFourSecondRoundControls)? "," : "and without clear second round controls,") & " we can't afford to bid slam, so settle for a contract of " & BTS(nBid) & ".\n"; } // else we have >= 32 pts and all four controls else if (bidState.m_fMinTPPoints < 36) { // can only make a small slam nBid = MAKEBID(nAgreedSuit, 6); status << "HRCBS24! But with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we have to stop at a small with a contract of " & BTS(nBid) & ".\n"; } else { // // else we have 36+ points, so go ahead and bid a grand slam // int nBid = MAKEBID(nAgreedSuit, 7); status << "HRCBS40! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership and full first and second-round controls, go head and bid a grand slam at " & BTS(nBid) & ".\n"; } // bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else { // N/A return FALSE; } // return TRUE; }
// //=============================================================================== // // TryConvention() // // check if we can use a Michaels Cue Bid here // BOOL CMichaelsCueBidConvention::TryConvention(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // // the requirements for a Michaels Cue Bid are: // 1: RHO must have opened a suit (not NT) at the 1-level // 2: this must be our first bidding opportunity // 3: need a 2-suited hand; i.e., // - if RHO bid a minor, need 5/5 or 5/(good)4 in the majors // - if RHO bid a major, need 5 in the other major, plus 5 in a minor // the two suits should also be rather comparable // 4: need either 6-11 pts or 17+ pts // (with 12-16 pts, we generally overcall or double for takeout) // 5: if we have 12+ pts and playing takeout doubles, cannot have a // hand suitable for a takeout (???) // test conditions 1, 2, & 4 if ( ((bidState.nRHOBid >= BID_1C) && (bidState.nRHOBid <= BID_1S)) && ( ((bidState.fPts >= OPEN_PTS(6)) && (bidState.fPts <= OPEN_PTS(11))) || ((bidState.fPts >= OPEN_PTS(17))/*&& (bidState.fPts <= 18)*/) ) && (bidState.m_numBidTurns == 0) && (bidState.m_numPartnerBidTurns == 0) ) { // passed } else { return FALSE; } // test condition #3 int nOppSuit = bidState.nRHOSuit; BOOL bEnoughLength = FALSE; // if (ISMINOR(nOppSuit)) { // need 5/5 in the majors, or 5 + good 4 int numHearts = hand.GetNumCardsInSuit(HEARTS); int numSpades = hand.GetNumCardsInSuit(SPADES); if ((hand.GetSuitStrength(HEARTS) < SS_MARGINAL_OPENER) || (hand.GetSuitStrength(SPADES) < SS_MARGINAL_OPENER) || (Abs(hand.GetSuitStrength(HEARTS) - hand.GetSuitStrength(SPADES)) > 1) ) return FALSE; // if ((numHearts >= 5) && (numSpades >= 5)) { bEnoughLength = TRUE; status << "2MCL1! We have at least 5/5 in the majors, so we can make a Michaels cue bid.\n"; } else if ((numHearts >= 5) && (numSpades == 4) && (hand.GetSuitStrength(SPADES) >= SS_STRONG)) { bEnoughLength = TRUE; status << "2MCL2! We have 5/4 in the majors, but the 4 Spades are strong, so we can make a Michaels cue bid.\n"; } else if ((numHearts == 4) && (numSpades >= 5) && (hand.GetSuitStrength(HEARTS) >= SS_STRONG)) { bEnoughLength = TRUE; status << "2MCL3! We have 5/4 in the majors, but the 4 Hearts are strong, so we can make a Michaels cue bid.\n"; } } else { // need 5 in the unbid major, and 5 in a minor int nOtherMajor = (nOppSuit == HEARTS)? SPADES : HEARTS; int numMajors = hand.GetNumCardsInSuit(nOtherMajor); int numClubs = hand.GetNumCardsInSuit(CLUBS); int numDiamonds = hand.GetNumCardsInSuit(CLUBS); // check that the major suit is OK if ((numMajors < 5) || (hand.GetSuitStrength(nOtherMajor) < SS_MARGINAL_OPENER)) return FALSE; // then check the minor & compare the suits if ((numClubs >= 5) && (hand.GetSuitStrength(CLUBS) >= SS_MARGINAL_OPENER) && (Abs(hand.GetSuitStrength(nOtherMajor) - hand.GetSuitStrength(CLUBS)) <= 1) ) { bEnoughLength = TRUE; status << "2MCL5! We have 5+ cards in " & STS(nOtherMajor) & " and 5+ cards in a minor (Clubs), so we can make a Michaels cue bid.\n"; } else if ((numDiamonds >= 5) && (hand.GetSuitStrength(DIAMONDS) >= SS_MARGINAL_OPENER) && (Abs(hand.GetSuitStrength(nOtherMajor) - hand.GetSuitStrength(DIAMONDS)) <= 1) ) { bEnoughLength = TRUE; status << "2MCL5! We have 5+ cards in " & STS(nOtherMajor) & " and 5+ cards in a minor (Diamonds), so we can make a Michaels cue bid.\n"; } } // check condition if (!bEnoughLength) return FALSE; // OK, go ahead and cue-bid the enemy suit int nBid = MAKEBID(nOppSuit, 2); status << "MCL9! With a 2-suited hand, make a Michaels cue bid over RHO's " & STS(nOppSuit) & " with a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED); return TRUE; }
// //========================================================== // // Rebidding as opener after partner responds to a takeout double // BOOL CNegativeDoublesConvention::HandleConventionResponse(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // there's no code here for now return FALSE; // check status if ((bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND1) && (bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND2)) return FALSE; // // get some info // // int nBid; double fPts = bidState.fPts; double fAdjPts = bidState.fAdjPts; double fCardPts = bidState.fCardPts; int nPrefSuit = bidState.nPrefSuit; int nPrefSuitStrength = bidState.nPrefSuitStrength; int nPreviousSuit = bidState.nPreviousSuit; BOOL bBalanced = bidState.bBalanced; // int nPartnersBid = bidState.nPartnersBid; int nPartnersBidLevel = bidState.nPartnersBidLevel; int nPartnersSuit = bidState.nPartnersSuit; int nPartnersSuitSupport = bidState.nPartnersSuitSupport; int nPartnersPrevSuit = bidState.nPartnersPrevSuit; int numSupportCards = bidState.numSupportCards; // first check for a strange response if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE)) { // we don't understand partner's bid return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status); } // if (bidState.GetConventionStatus(this) == CONV_INVOKED_ROUND1) { // //-------------------------------------------------------- // responding to partner's forced bid // - estimate partner's strength // // // did partner pass? (horror of horrors!) // if (nPartnersBid == BID_PASS) { if (bidState.nLHOBid >= BID_PASS) status << "NGDRb10! After interference from the left-hand opponent, partner passed our takeout.\n"; else status << "NGDRb12! Partner unexpectedly passed our takeout double, which is supposed to be forcing. Bidding will proceed as if the takeout was not made\n"; bidState.SetConventionStatus(this, CONV_FINISHED); return FALSE; } // set team point estimates -- be conservative BOOL bPartnerJumped = FALSE; BOOL bPartnerJumpedToGame = FALSE; int nEnemyBid = pDOC->GetValidBidRecord(0); int nEnemyBidLevel = BID_LEVEL(nEnemyBid); int nEnemySuit = BID_SUIT(nEnemyBid); if (nPartnersBidLevel > (nEnemyBidLevel + 1)) bPartnerJumped = TRUE; if (nPartnersBid == bidState.GetGameBid(nPartnersSuit)) bPartnerJumpedToGame = TRUE; // flag to see if we doubled in preference to an overcall BOOL bWantedToOvercall = FALSE; // if (nPartnersSuit == NOTRUMP) { // if (nPartnersBid == BID_1NT) { // partner has 6-9 HCPs bidState.m_fPartnersMin = 6; bidState.m_fPartnersMax = 9; } else if (nPartnersBid == BID_2NT) { // partner has 10-12 HCPs, maybe more bidState.m_fPartnersMin = 10; bidState.m_fPartnersMax = 12; } else if (nPartnersBid == BID_3NT) { // partner has 13+ HCPs bidState.m_fPartnersMin = 13; bidState.m_fPartnersMax = 40 - fCardPts; status << "NGDRb20! Partner's response of 3NT to our takeout double indicates that the opponent's suit is well stopped.\n"; } else { // partner has 13+ HCPs??? status << "NGDRb21! Partner's response of " & BTS(nPartnersBid) & " to our takeout double is unorthodox; treating it like a 3NT response.\n"; bidState.m_fPartnersMin = 13; bidState.m_fPartnersMax = MIN(22, 40 - fCardPts); } // accept NT if we hold at least a semi-balanced // and we don't have a 6-card major if ( !(ISMAJOR(bidState.nPrefSuit) && (bidState.numPrefSuitCards >= 6)) && (bidState.bSemiBalanced) ) bidState.m_nAgreedSuit = NOTRUMP; // bidState.m_fMinTPPoints = fAdjPts + bidState.m_fPartnersMin; bidState.m_fMaxTPPoints = fAdjPts + bidState.m_fPartnersMax; bidState.m_fMinTPCPoints = fCardPts + bidState.m_fPartnersMin; bidState.m_fMaxTPCPoints = fCardPts + bidState.m_fPartnersMax; status << "NGDRb29! Partner's response of " & BTS(nPartnersBid) & " to our takeout double indicates " & bidState.m_fPartnersMin & "-" & bidState.m_fPartnersMax & " HCPs, for a total of " & bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints & " / " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership.\n"; } else { // partner bid a suit // see if we really intended to overcall last time if (bidState.GetConventionStatus(&overcallsConvention) == CONV_SUBSUMED) bWantedToOvercall = TRUE; // if (nPartnersSuit == nEnemySuit) { // partner bid the enemy suit, showing 13+ pts. status << "NEGDRb40! Partner has responded in the enemy suit, indicating 13+ pts but no long suits.\n"; bidState.m_fPartnersMin = 13; bidState.m_fPartnersMax = MIN(22, 40 - bidState.fCardPts); bidState.m_bGameForceActive = TRUE; } else if (bPartnerJumpedToGame) { // partner had 13+ pts & a 5-card major status << "NEGDRb41! Partner has jumped to game in " & STS(nPartnersSuit) & ", indicating 13+ pts and a 5+ card suit.\n"; bidState.m_fPartnersMin = 30; bidState.m_fPartnersMax = MIN(22, 40 - bidState.fCardPts); if (!bWantedToOvercall) bidState.m_nAgreedSuit = nPartnersSuit; } else if (bPartnerJumped) { // partner had 10-12 pts status << "NEGDRb42! Partner has made a jump response of " & BTS(nPartnersBid) & ", indicating 10-12 pts and a 4-5 card suit.\n"; bidState.m_fPartnersMin = 10; bidState.m_fPartnersMax = 12; if (!bWantedToOvercall) bidState.m_nAgreedSuit = nPartnersSuit; } else { // partner had <= 9 pts status << "NEGDRb43! Partner has made a minimum response of " & BTS(nPartnersBid) & ", indicating no more than 9 points.\n"; bidState.m_fPartnersMin = 0; bidState.m_fPartnersMax = 9; if (!bWantedToOvercall) bidState.m_nAgreedSuit = nPartnersSuit; } // bidState.m_fMinTPPoints = fAdjPts + bidState.m_fPartnersMin; bidState.m_fMaxTPPoints = fAdjPts + bidState.m_fPartnersMax; bidState.m_fMinTPCPoints = fCardPts + bidState.m_fPartnersMin; bidState.m_fMaxTPCPoints = fCardPts + bidState.m_fPartnersMax; status << "NGDRb49! The total point count in the partnership is therefore " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts.\n"; } // // see if RHO bid after partner's response -- that mitigates our responsibility // to bid again, unless partner's bid was game forcing // // if (bidState.nRHOBid > BID_PASS) if ((bidState.nRHOBid > BID_PASS) && (bidState.nRHOBid != BID_DOUBLE) && (bidState.nRHOBid != BID_REDOUBLE)) { status << "2NGDRb51! The right-hand opponent has " & ((bidState.nRHOBid == BID_DOUBLE)? "doubled" : "bid") & " after partner's response, interfering with our communication.\n"; } // //--------------------------------------------------------------------- // see if we have an agreed suit // int nBid; if (bidState.m_nAgreedSuit > NONE) { if (bidState.m_nAgreedSuit == NOTRUMP) { // we've agreed to play in NoTrump // see if we can raise partner to a higher NT contract if (bidState.BidNoTrumpAsAppropriate(FALSE,STOPPED_DONTCARE)) { bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // else pass nBid = BID_PASS; status << "NGDRb69! With a total of " & bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints & " HCPs in the partnership, we have insufficient strength to raise partner's " & BTS(nPartnersBid) & " bid, so we have to pass.\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else { // we've agreed on a suit, so raise if possible // if partner didn't jump, we may have credited him with // zero pts, so adjust rqmts accordingly // if partner jumped to game && we have < 32 pts, pass if ((bPartnerJumpedToGame) && (bidState.m_fMinTPPoints < 32)) { status << "NGDRb70! Partner jumped to game in his " & bidState.szPSS & " suit, so with a team total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points, we pass.\n"; bidState.SetBid(BID_PASS); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // raise partner if possible -- bearing in mind that // partner may have a wide range of points // raise a major to game with 23-31 pts and 4 trumps // or with 26-31 pts and 3 trumps // or raise to the 3-level with 20-24 pts and 3 trumps if ( (bidState.RaisePartnersSuit(SUIT_MAJOR,RAISE_TO_4,PTS_MAJOR_GAME-3,31,SUPLEN_4)) || (bidState.RaisePartnersSuit(SUIT_MAJOR,RAISE_TO_4,PTS_MAJOR_GAME,31,SUPLEN_3)) || (bidState.RaisePartnersSuit(SUIT_MAJOR,RAISE_TO_3,PTS_MAJOR_GAME-6,24,SUPLEN_3))) { if (!bPartnerJumped) status << "NGDRb71a! (we can assume partner has some strength in the " & bidState.szPSS & " suit, so we are shading the requirements slightly.\n"; bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } // raise a minor to game with 28-32 pts and 4 trumps // or with 29-32 pts and 3 trumps // or raise to the 4-level with 26-28 pts and 3 trumps // or raise to the 3-level with 23-25 pts and 3 trumps if ( (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_5,PTS_MINOR_GAME-1,PTS_SLAM-1,SUPLEN_4)) || (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_5,PTS_MINOR_GAME,PTS_SLAM-1,SUPLEN_3)) || (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_4,PTS_MINOR_GAME-3,PTS_MINOR_GAME-1,SUPLEN_3)) || (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_3,PTS_MINOR_GAME-6,PTS_MINOR_GAME-4,SUPLEN_3)) ) { if (!bPartnerJumped) status << "NGDRb71b! We can assume partner has some strength in the " & bidState.szPSS & " suit, so we can shade the requirements slightly.\n"; bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } // with 32+ pts, invoke Blackwood if (bidState.m_fMinTPCPoints >= 32) { bidState.InvokeBlackwood(bidState.m_nAgreedSuit); bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } // else pass nBid = BID_PASS; status << "NGDRb90! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we have insufficient strength to raise partner's " & BTS(nPartnersBid) & " bid, so we have to pass.\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } } // //-------------------------------------------------------------------------- // here, we have no suit agreement (e.g., partner bid the opponents' suit) // int nLastBid = pDOC->GetLastValidBid(); if (bBalanced) { // try notrumps if (hand.IsSuitProbablyStopped(nEnemySuit)) { status << "NGDRb80! Without clear suit agreement, and holding a blanaced hand, we want to steer towards a contract in No Trump.\n"; if (bidState.BidNoTrumpAsAppropriate(FALSE,STOPPED_DONTCARE)) { bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } } // else pass status << "NGDRb81! But as we do not have a proper hand to bid No Trump at the appropriate level, we have to pass.\n"; bidState.SetBid(BID_PASS); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else if (bidState.numPrefSuitCards >= 5) { // bid the suit nBid = bidState.GetCheapestShiftBid(nPrefSuit, nLastBid); if (bidState.IsBidSafe(nBid, 4)) { if (bWantedToOvercall) status << "NGDRb90! Partner's forced response of " & bidState.szPB & " not withstanding, we can now show the " & STSS(nPrefSuit) & " suit that we wanted to overcall with last round by bidding " & BTS(nBid) & ".\n"; else status << "NGDRb91! Without clear suit agreement, we bid our " & bidState.numPrefSuitCards & "-card " & STSS(bidState.nPrefSuit) & " suit at " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2); return TRUE; } } // //-------------------------------------------------------------------------- // else we have no other options, so pass status << "NEGDRb99! We see no good fit with partner and no other options, so pass.\n"; bidState.SetBid(BID_PASS); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else { // // responding after partner's second response to our takeout // // did partner pass? if (nPartnersBid == BID_PASS) { bidState.SetConventionStatus(this, CONV_FINISHED); return FALSE; } // // otherwise, consider the choices: // // - with suit agreement, raise if possible // S N S N S // e.g., X -> 1C -> 1S -> 2S -> ??? // - without suit agreement, // e.g., X -> 1C -> 1S -> 2H -? ??? // bid the 4th suit if we have the pts (26+) // - without suit agreement, but if partner bids NT, // or if we have a balanaced hand, bid NT // double fMinTPPoints = bidState.m_fMinTPPoints; double fMaxTPPoints = bidState.m_fMaxTPPoints; double fMinTPCPoints = bidState.m_fMinTPCPoints; double fMaxTPCPoints = bidState.m_fMaxTPCPoints; int nBid; // // see if we have suit agreement // if (nPartnersSuit == nPreviousSuit) { // partner raised our suit -- re-raise if possible bidState.m_nAgreedSuit = nPreviousSuit; if (nPartnersBid >= bidState.GetGameBid(nPreviousSuit)) { // partner bid game or beyond if ((nPartnersBidLevel == 7) || ((nPartnersBidLevel == 6) && (fMinTPPoints <= 36)) ) { nBid = BID_PASS; status << "NGDRc10! Partner raised our " & bidState.szPVSS & " suit to a slam, so pass.\n"; } else if ((nPartnersBidLevel <= 6) && (fMinTPPoints >= 37)) { nBid = MAKEBID(nPreviousSuit, 7); status << "NGDRc11! Partner raised our " & bidState.szPVSS & " suit to " & ((nPartnersBidLevel == 6)? "slam" : "game") & ", but we have the poitns to push to a grand slam, so bid " & BTS(nBid) & ".\n"; } else if ((nPartnersBidLevel < 6) && (fMinTPPoints >= 33)) { nBid = MAKEBID(nPreviousSuit, 6); status << "NGDRc12! Partner raised our " & bidState.szPVSS & " suit to game, but we have the poitns for a slam, so bid " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "NGDRc13! Partner raised our " & bidState.szPVSS & " suit to game, which is acceptable with " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, so pass.\n"; } } else { // partner raised below game // re-raise if possible if ( (ISMAJOR(nPreviousSuit) && (fMinTPPoints >= PTS_MAJOR_GAME)) || (ISMINOR(nPreviousSuit) && (fMinTPPoints >= PTS_MINOR_GAME)) ) { nBid = bidState.GetGameBid(nPreviousSuit); status << "NGDRc20! With a total of " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, raise to game in the " & bidState.szPVSS & " suit at " & BTS(nBid) & ".\n"; } else { // else try to raise cheaply nBid = bidState.GetCheapestShiftBid(nPreviousSuit); if (bidState.IsBidSafe(nBid)) { status << "NGDRc22! With a total of " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, we can raise again to " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "NGDRc29! With a total of " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, we cannot safely raise any partner further, so pass.\n"; } } } } else if ((nPartnersSuit == NOTRUMP) || (bidState.bBalanced)) { // // partner bid NT, or else we have a balanced hand // if (bidState.BidNoTrumpAsAppropriate(FALSE, STOPPED_DONTCARE)) { nBid = bidState.m_nBid; status << "NGDRc30! With a total of " & fMinTPCPoints & "-" & fMaxTPCPoints & " HCPs in the partnership, we can bid " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; if (nPartnersSuit == NOTRUMP) status << "NGDRc35! We're willing to accept a contract in NoTrumps, but don't have the points to raise further, so pass.\n"; else status << "NGDRc36! We'd like to play in NoTrumps, but don't have the points to bid agian, so pass.\n"; } } else { // // else we have no suit agreement, and can't play NT // // // bid the 4th suit if we have enough pts // int nSuit = bidState.GetFourthSuit(nPreviousSuit, nPartnersSuit, nPartnersPrevSuit); nBid = bidState.GetCheapestShiftBid(nSuit); if ((fMinTPPoints >= PTS_GAME) && (nBid < bidState.GetGameBid(nSuit))) { status << "NGDRc40! With a total of " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership and no suit agreement, bid another suit (" & STS(nSuit) & ") at " & BTS(nBid) & ".\n"; } else { // gotta pass nBid = BID_PASS; if (nPartnersBid >= bidState.GetGameBid(nPartnersSuit)) status << "NGDRc45! With a total of " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, partner has gone to game in his suit at " & bidState.szPB & ", so pass.\n"; else if (fMinTPPoints >= PTS_GAME) status << "NGDRc46! With a total of " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, but having run out of bidding room, we have to bail out and pass.\n"; else status << "NGDRc47! With a total of only " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, and no agreement in suits, we have to pass.\n"; } } // done with the second rebid bidState.SetBid(nBid); bidState.ClearConventionStatus(this); 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; }
// //----------------------------------------------------- // // respond to partner's negative double // BOOL CNegativeDoublesConvention::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; // // Bidding in response to partner's negative bid? check requirements // // the identifying marks of a negative double are: // 1: this must be round #1 or 2 // 2: we must have opened bidding, and // 3: LHO must have bid over our initial bid, up to 2S // int nBid; int nPartnersBid = bidState.nPartnersBid; int nMajorSuits[2] = { 1, 1 }; if (bidState.nPreviousSuit == HEARTS) nMajorSuits[0] = 0; else if (bidState.nPreviousSuit == SPADES) nMajorSuits[1] = 0; // if (bidState.nLHOSuit == HEARTS) nMajorSuits[0] = 0; else if (bidState.nLHOSuit == SPADES) nMajorSuits[1] = 0; // apply tests #1, 2, and 3 if ( (nPartnersBid == BID_DOUBLE) && ((bidState.nRound == 0) || (bidState.nRound == 1)) && (bidState.m_bOpenedBiddingForTeam) && (bidState.nLHOBid > BID_PASS) && (bidState.nLHOBid <= BID_2S) // NCR-195 bid must be suit && ISSUIT(BID_SUIT(bidState.nLHOBid)) ) { // status << "NEGDR2! Partner has bid a negative double, indicating 4+ cards in the unbid majors " & ((nMajorSuits[0] && nMajorSuits[1])? "(Hearts and Spades)" : nMajorSuits[0]? "(Hearts)" : "(Spades)") & ".\n"; } else { return FALSE; } // // estimate partner's strength // if (bidState.nLHOBidLevel == 1) { // 6-9 pts for a neg dbl the 1-level (NCR TryConvention uses 19 max???) bidState.m_fPartnersMin = OPEN_PTS(6); bidState.m_fPartnersMax = Min(OPEN_PTS(19),40 - bidState.fCardPts); // NCR changed 9 to 19 bidState.m_fMinTPPoints = bidState.fPts + bidState.m_fPartnersMin; bidState.m_fMaxTPPoints = bidState.fPts + bidState.m_fPartnersMax; bidState.m_fMinTPCPoints = bidState.fCardPts + bidState.m_fPartnersMin; bidState.m_fMaxTPCPoints = bidState.fCardPts + bidState.m_fPartnersMax; status << "2NEGDR8! Partner's negative double indicates " & bidState.m_fPartnersMin & "-" & bidState.m_fPartnersMax & " points, for a total in the partnership of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points.\n"; } else { // 11-18 pts for a neg double at the 2 level bidState.m_fPartnersMin = OPEN_PTS(11); bidState.m_fPartnersMax = Min(OPEN_PTS(18),40 - bidState.fCardPts); bidState.m_fMinTPPoints = bidState.fPts + bidState.m_fPartnersMin; bidState.m_fMaxTPPoints = bidState.fPts + bidState.m_fPartnersMax; bidState.m_fMinTPCPoints = bidState.fCardPts + bidState.m_fPartnersMin; bidState.m_fMaxTPCPoints = bidState.fCardPts + bidState.m_fPartnersMax; status << "2NEGDRT8! Partner's negative double indicates 11+ pts, for a total in the partnership of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points.\n"; } // // and respond to the bid // int nSuit; double fCardPts = bidState.fCardPts; double fPts = bidState.fPts; int nLHOBid = bidState.nLHOBid; int nRHOBid = bidState.nRHOBid; // // with support for one or the other major, raise // but discount the majors already bid by us or LHO // int numHearts = hand.GetNumCardsInSuit(HEARTS); int numSpades = hand.GetNumCardsInSuit(SPADES); // gotta beat RHO's bid if possible int nTopBid = nLHOBid; if ((nRHOBid > BID_PASS) && (nRHOBid != BID_REDOUBLE)) nTopBid = nRHOBid; // see if the majors are available if ( (nMajorSuits[0] && nMajorSuits[1]) && ((numHearts >= 3) || (numSpades >= 3)) ) { // both majors are available, so pick the better one int nSuit = bidState.PickSuperiorSuit(HEARTS,SPADES); nBid = bidState.GetCheapestShiftBid(nSuit, nTopBid); // see if the bid is affordable if (bidState.IsBidSafe(nBid)) { status << "NEGDTR20! With " & bidState.m_fMinTPPoints & " pts in the partnership and " & " both majors available in response to the negative double, go with the " & hand.GetNumCardsInSuit(nSuit) & "-card " & STSS(nSuit) & " suit and bid " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); } else { status << "NEGDTR21! We have both majors avaialblem but with " & bidState.m_fMinTPPoints & " pts in the partnership, we do not have enough points to bid either suit and have to pass.\n"; bidState.SetBid(BID_PASS); } bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else if ( ((nMajorSuits[0]) && (numHearts >= 3)) || ((nMajorSuits[1]) && (numSpades >= 3)) ) { // bid the suit if ((nMajorSuits[0]) && (numHearts >= 3)) nSuit = HEARTS; else nSuit = SPADES; nBid = bidState.GetCheapestShiftBid(nSuit, nTopBid); // see if the bid is affordable double fAdj = bidState.fAdjPts; // NCR-717 theApp.GetBiddingAgressiveness()*1.5; // NCR change test amt? if (bidState.IsBidSafe(nBid, fAdj)) // NCR adjust??? { status << "NEGDTR30! With " & bidState.m_fMinTPPoints & " pts in the partnership and " & hand.GetNumCardsInSuit(nSuit) & " cards available in " & STS(nSuit) &", bid " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); } else { status << "NEGDTR31! We have " & hand.GetNumCardsInSuit(nSuit) & " cards in the " & STSS(nSuit) & " suit, but with only " & bidState.m_fMinTPPoints & " pts in the partnership, we can't go any higher.\n"; bidState.SetBid(BID_PASS); } bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // // we have no majors available, so bid NT if possible // if (bidState.BidNoTrumpAsAppropriate(FALSE)) { bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // else bid something, anything nSuit = bidState.GetRebidSuit(bidState.nPreviousSuit); if(nSuit == NONE) { //NCR test for no rebidable suit return nBid = BID_1NT; // NCR Hardcoded ??? vs get cheapest }else{ nBid = bidState.GetCheapestShiftBid(nSuit, nTopBid); } // NCR-415 Test if safe bid if (!bidState.IsBidSafe(nBid, bidState.fDistPts) // NCR-592 set adj to dist pts && (bidState.nRHOBid > BID_PASS) ) // NCR-637 Only if RHO bid { nBid = BID_PASS; status << "NEGDTR36! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership, we cannot safely bid further, so pass.\n"; } // end NCR-415 else { if (!ISMAJOR(nSuit)) status << "NEGDTR40! Unfortunately we don't have a major to respond with, so bid " & BTS(nBid) & ".\n"; else status << "NEGDTR41! Our best response is " & BTS(nBid) & ".\n"; } bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; }
// //--------------------------------------------------------------- // // InvokeGerber() // // Start the Gerber convention // BOOL CGerberConvention::InvokeGerber(CHandHoldings& hand, CBidEngine& bidState, CPlayerStatusDialog& status, int nEventualSuit) { // record intended suit for later use ASSERT(nEventualSuit != NONE); bidState.m_nAgreedSuit = nEventualSuit; double fMinTPPoints = bidState.m_fMinTPPoints; double fMaxTPPoints = bidState.m_fMaxTPPoints; double fMinTPCPoints = bidState.m_fMinTPCPoints; double fMaxTPCPoints = bidState.m_fMaxTPCPoints; double fCardPts = bidState.fCardPts; double fPts = bidState.fPts; double fAdjPts = bidState.fAdjPts; int nBid; // if Gerber has already been used, return if (bidState.GetConventionStatus(this) >= CONV_INVOKED) return FALSE; // // if Gerber is not enabled, just bid slam directly // if (!pCurrConvSet->IsConventionEnabled(tidGerber)) { // no Gerber? go ahead and bid slam directly status << "2GERBX! we have " & fCardPts & "/" & fPts & "/" & fAdjPts & " points in hand, for a total of approx. " & fMinTPPoints & "-" & fMaxTPPoints & " / " & fMinTPCPoints & "-" & fMaxTPCPoints & " pts in the partnership, but we can't use Gerber to investigate Aces and Kings since it's currently not enabled.\n"; // bid a grand slam if we have 37+ pts and the trump ace // or a small slam with 32+ points // or make the cheapest shift bid otherwise (D'oh!) if ((fMinTPPoints >= PTS_GRAND_SLAM+1) && (hand.SuitHasCard(nEventualSuit, ACE))) { nBid = MAKEBID(nEventualSuit, 7); status << "2GERBX1! but since we have the points for a grand slam and we hold the trump ace, go ahead and bid " & BTS(nBid) & ".\n"; } else if (fMinTPPoints >= PTS_SLAM) { nBid = MAKEBID(nEventualSuit, 6); status << "2GERBX2! but since we have the points for a small slam, go ahead and bid " & BTS(nBid) & ".\n"; } else { // get cheapest shift bid nBid = bidState.GetCheapestShiftBid(nEventualSuit); status << "2GERBX3! so we just bid " & BTS(nBid) & ".\n"; } // bidState.SetBid(nBid); return TRUE; } // // shouldn't use Gerber if we have all four aces // if (bidState.numAces == 4) { // no Gerber? go ahead and bid slam directly status << "2GERBY! Unfortunately, since we hold all four aces, Gerber is of little value to us.\n"; // bid a grand slam if we have 37+ pts and the trump ace // or a small slam with 32+ points // or make the cheapest shift bid otherwise (D'oh!) if ((fMinTPPoints >= PTS_SLAM+1) // NCR-324 added NOTRUMP test && ((nEventualSuit == NOTRUMP) || (hand.SuitHasCard(nEventualSuit, ACE)))) { nBid = MAKEBID(nEventualSuit, 7); status << "2GERBY1! so since we have the points for a grand slam, go ahead and bid " & BTS(nBid) & ".\n"; } else if (fMinTPPoints >= PTS_SLAM) { nBid = MAKEBID(nEventualSuit, 6); status << "2GERBY2! so since we have the points for a small slam, go ahead and bid " & BTS(nBid) & ".\n"; } else { nBid = bidState.GetCheapestShiftBid(nEventualSuit, pDOC->GetLastValidBid()); status << "2GERBY3! so without quite enough points for a slam, we just bid " & BTS(nBid) & ".\n"; } // bidState.SetBid(nBid); return TRUE; } // // else we're playing Gerber and do not hold all four aces // so make the bid to ask for aces // int nPartnersbid = bidState.nPartnersBid; if ((nPartnersbid == BID_1NT) || (nPartnersbid == BID_2NT) // NCR-246a Allow Gerber after Stayman 2C || ((nPartnersbid < BID_3NT) && bidState.nPreviousBid == BID_2C) ) { nBid = BID_4C; status << "GERBD! with " & bidState.fCardPts & "/" & bidState.fPts & "/" & bidState.fAdjPts & " points in the hand, for a total of approx. " & fMinTPCPoints & "-" & fMaxTPCPoints & " / " & fMinTPPoints & "-" & fMaxTPPoints & " pts in the partnership, explore slam possibilities with Gerber at " & BTS(nBid) & ".\n"; } else { nBid = BID_PASS; status << "GERBDx! we'd like to use Gerber, but partner has already bid higher than 4C, so we have to pass.\n"; } bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED_ROUND1); // done return TRUE; }
// //----------------------------------------------------- // // respond to partner's Jacoby 2NT Bid // BOOL CJacoby2NTConvention::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 nPreviousBid = bidState.nPreviousBid; int numTotalBidTurns = pDOC->GetNumBidsMade(); // int nBid; 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 Jacoby 2NT bid? // // the requirements for a Jacoby 2NT Bid are: // 1: we must have opened the bidding with 1 of a major // 2: Partner responded with 2NT int nOpeningBid = pDOC->GetOpeningBid(); // test conditions if ( (bidState.m_numBidTurns == 1) && (ISMAJOR(BID_SUIT(nPreviousBid))) && (nOpeningBid == nPreviousBid) && (BID_LEVEL(nPreviousBid) == 1) && (bidState.nPartnersBid == BID_2NT) ) { // passed the test } else { return FALSE; } status << "J2N20! Partner has made a Jacoby 2NT inquiry bid, indicating " & OPEN_PTS(13) & " pts and 4+ card support.\n"; // adjust points as declarer int nSuit = bidState.nPreviousSuit; bidState.SetAgreedSuit(nSuit); fPts = bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, nSuit, TRUE); // partner has 13+ pts bidState.AdjustPartnershipPoints(13, 13); // // our options are as follows, in order: // // - with 18+ pts, rebid the suit at the 3 level // - with 15-17 pts and a strong 5-card side suit, bid that suit at the 4-level // - with 15-17 pts and a short suit, bid the short suit at the 3 level // - with 15-17 pts an no short suit, bid 3NT // - otherwise, sign off in game at the 4-level // check point count if (fPts >= 18) { nBid = MAKEBID(nSuit, 3); status << "J2N21! With " & fPts & " points in hand, " "respond to partner's Jacoby 2NT inquiry with a bid of " & BTS(nBid) & ".\n"; } else if (fPts >= 15) { // see if we have a strong side suit int nSideSuit = NONE; for(int i=0;i<4;i++) { if ((i != nSuit) && (bidState.nSuitStrength[i] <= SS_STRONG) && (bidState.numCardsInSuit[i] >= 5)) break; } // if (i < 4) { // bid the suit at the 4 level nSuit = i; nBid = MAKEBID(nSuit, 4); status << "J2N22! With " & fPts & " points in hand and a good " & bidState.numCardsInSuit[nSuit] & "-card suit in " & STS(nSuit) & ", respond to partner's Jacoby 2NT inquiry with " & BTS(nBid) & ".\n"; } else if (bidState.numVoids >= 1) { // bid the void suit for(nSuit=0;nSuit<4;nSuit++) { if (bidState.numCardsInSuit[nSuit] == 0) break; } nBid = MAKEBID(nSuit, 3); status << "J2N24! With " & fPts & " points in hand and a void suit in " & STS(nSuit) & ", respond to partner's Jacoby 2NT inquiry with a bid of " & BTS(nBid) & ".\n"; } else if (bidState.numSingletons >= 1) { // bid the singleton for(nSuit=0;nSuit<4;nSuit++) { if (bidState.numCardsInSuit[nSuit] == 1) break; } nBid = MAKEBID(nSuit, 3); status << "J2N26! With " & fPts & " points in hand and a singleton in " & STS(nSuit) & ", respond to partner's Jacoby 2NT inquiry with a bid of " & BTS(nBid) & ".\n"; } else { // bid 3NT nBid = BID_3NT; status << "J2N28! With " & fPts & " points in hand and no short suits, " " respond to partner's Jacoby 2NT inquiry with a bid of " & BTS(nBid) & ".\n"; } } else { // sign off at the 4-level nBid = MAKEBID(nSuit, 4); status << "J2N31! With only " & fPts & " points in hand, sign off in game at " & BTS(nBid) & ".\n"; } // and return bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // return FALSE; }
// //=============================================================================== // // TryConvention() // // check if we can open with a preemptive 3 or 4 bid // BOOL CShutoutBidsConvention::TryConvention(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) { // basic requirements: no non-pass bid must have been entered yet if (bidState.nLastValidRecordedBid != BID_PASS) return FALSE; // someone else has opened already // //-------------------------------------------------------- // // Now check for a shutout bid of 3 or 4 // // at the very minimum, should have a 6-card suit // if (hand.GetNumSuitsOfAtLeast(6) < 1) return FALSE; // // first find (a) long suit // /* for(i=0;i<4;i++) { if (hand.numCardsInSuit[i] >= 6) { // a 7-card suit needs 2 honors, and a a 6-card suit needs 3 if ( ((hand.GetNumCardsInSuit(i) >= 7) && (hand.GetNumhonorsInSuit(i) >= 2)) || ((hand.GetNumCardsInSuit(i) == 6) && (hand.GetNumhonorsInSuit(i) >= 3)) ) break; } } */ // assume the long suit is the preferred one int nSuit = hand.GetPreferredSuit(); CSuitHoldings& suit = hand.GetSuit(nSuit); int numCards = suit.GetNumCards(); int numHonors = suit.GetNumHonors(); // a 6-card suit needs 3 honors, and a 7+ card suit needs 2 if ( ((numCards == 6) && (numHonors < 3)) || ((numCards >= 7) && (numHonors < 2)) ) return FALSE; // // then check for Aces, Kings, or Queens in outside suits int nBid; BOOL bViolation = FALSE; for(int i=0;i<4;i++) { if (i == nSuit) continue; // a solitary Q is okay for a Shutout bid, but any higher honors // are not CSuitHoldings& suit = hand.GetSuit(i); if (suit.HasAce() || suit.HasKing()) return FALSE; } // if (bidState.numCardsInSuit[nSuit] >= 8) { nBid = MAKEBID(nSuit,4); status << "D00! Have a " & bidState.numCardsInSuit[nSuit] & "-card " & STSS(nSuit) & " suit with no tricks outside the suit, so make a shutout bid of " & BTS(nBid) & ".\n"; } else if (bidState.numCardsInSuit[nSuit] >= 7) { nBid = MAKEBID(nSuit,3); status << "D04! Have a " & bidState.numCardsInSuit[nSuit] & "-card " & STSS(nSuit) & " suit with no tricks outside the suit, so make a shutout bid of " & BTS(nBid) & ".\n"; } bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_INVOKED); return TRUE; }
// //--------------------------------------------------------------- // // RespondToConvention() // BOOL CCueBidConvention::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() && (bidState.GetActiveConvention() != this)) return FALSE; // basic test -- see if we had agreed on a suit last time if (bidState.m_nAgreedSuit == NONE) return FALSE; // get status int nStatus = bidState.GetConventionStatus(this); // int nPartnersBid = bidState.nPartnersBid; int nPartnersBidLevel = bidState.nPartnersBidLevel; int nPartnersSuit = bidState.nPartnersSuit; int nPartnersPrevSuit = bidState.nPartnersPrevSuit; int nAgreedSuit = bidState.m_nAgreedSuit; int nSupportLevel = bidState.nPartnersSuitSupport; int nBid; // see if partner made a cue bid // it needs to be a bid that commits the partnership to game, // after a suit has been agreed upon if ((nAgreedSuit != NONE) && (nPartnersSuit != NOTRUMP) && (nPartnersSuit != nAgreedSuit) && ((nPartnersBid > MAKEBID(nAgreedSuit,3)) && (nPartnersBid < bidState.GetGameBid(nAgreedSuit)))) { //NCR what if suit was previously bid by this player??? // EG: N->1H, S->2C, N->3C, S->3H 3H is NOT a cue bid, it's a response to this player's previous bid // NCR how to test if partner's current bid was in suit previously bid ??? // NCR what about a game bid??? int nSuit = BID_SUIT(nPartnersBid); for(int i=0; i < player.GetNumBidsMade(); i++) { // NCR had to add const to this function def int nSuitBid = pDOC->GetBidByPlayer(player.GetPosition(), i); if(BID_SUIT(nSuitBid) == nSuit) return FALSE; // NCR not cue if partner bid before ??? } // NCR-295 game bid in agreed suit??? if(bidState.IsGameBid(nPartnersBid) && (nSuit == nAgreedSuit) ) // || CheckIfSuitBid(player, BID_SUIT(nPartnersBid))) { return FALSE; //NCR don't treat Game bid as cue bid } // met the requirements status << "CUR0! Partner made a cue bid of " & BTS(nPartnersBid) & ", hinting at slam prospects.\n"; } else { // this is not a cue bid return FALSE; } // // respond to a cue bid only if we have an interest in slam // // only qualify if we have 30+ team points, _OR_ // strong trump support and 28+ poitns // if (bidState.m_fMinTPPoints >= 30) { // 30+ team points status << "2CUR1! And since we have " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & "+ points in the partnership, we want to respond favorably.\n"; } else if ((nSupportLevel >= SS_GOOD_SUPPORT) && (bidState.m_fMinTPPoints >= 28)) { // good support (4 good or 5 moderate cards) status << "2CUR2! And since we have " & bidState.SLTS(nPartnersSuit) & " trump support, " & ((bidState.m_fMinTPPoints >= 30)? " as well as " : " albeit only with ") & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we want to respond favorably.\n"; } else { // insufficient strength for slam -- correct back to the agreed suit nBid = bidState.GetCheapestShiftBid(nAgreedSuit); status << "CUR4! But we don't have the points (only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " pts in the partnership) or the excellent trump support needed for a marginal slam, so we decline by returning to the agreed suit at a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // // else we're playing along -- find the cheapest response // if (nStatus == CONV_INACTIVE) { // first invocation -- find the cheapest Ace int nSuit = GetCheapestAce(hand, nPartnersSuit, bidState.m_nAgreedSuit); // found a suit with an ace? if ((nSuit != nPartnersSuit) && (nSuit != nAgreedSuit)) { // found a suit to cue bid nBid = bidState.GetCheapestShiftBid(nSuit); status << "CUR20! Respond to partner's cue bid, showing our cheapest ace (" & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND1); return TRUE; } else { // found no ace, or else it's in the trump suit, so either way // just sign off at the agreed suit nBid = bidState.GetCheapestShiftBid(nAgreedSuit); if (hand.SuitHasCard(nSuit, ACE)) status << "CUR22! But our only Ace is in the trump suit of " & STSS(nAgreedSuit) & ", so sign off at a bid of " & BTS(nBid) & ".\n"; else status << "CUR24! We have no other Aces to offer, so sign off with the agreed " & STSS(nAgreedSuit) & " suit at a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } } else if (nStatus == CONV_RESPONDED_ROUND1) { // second invocation -- find cheapest King or void // first invocation -- find teh cheapest Ace int nSuit = GetCheapestKingOrVoid(hand, nPartnersSuit, bidState.m_nAgreedSuit); // found an appropriate suit? if ((nSuit != nPartnersSuit) && (nSuit != nAgreedSuit)) { // found a suit to cue bid nBid = bidState.GetCheapestShiftBid(nSuit); status << "CUR30! Respond to partner's cue bid, showing our cheapest " & ((hand.GetSuitLength(nSuit) > 0)? "King" : "void suit") & " (in " & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); // bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND2); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } else { // found no king or void, or else found a king in the trump suit, // so either way, just sign off at the agreed suit nBid = bidState.GetCheapestShiftBid(nAgreedSuit); if (hand.SuitHasCard(nSuit, KING)) status << "CUR32! But our only Ace is in the trump suit of " & STSS(nAgreedSuit) & ", so sign off at a bid of " & BTS(nBid) & ".\n"; else status << "CUR34 We have no other Kings or void suits to offer, so sign off with the agreed " & STSS(nAgreedSuit) & " suit at a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } } else { // error! bidState.SetConventionStatus(this, CONV_ERROR); return FALSE; } }
// //----------------------------------------------------- // // handle an artificial 2C opening bid (23+ pts) // BOOL CArtificial2ClubConvention::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() && (bidState.GetActiveConvention() != this)) return FALSE; // // Bidding in response to an opening 2C bid? check requirements // int nPartnersBid = bidState.nPartnersBid; int nPartnersSuit = bidState.nPartnersSuit; int nPartnersSuitSupport = bidState.nPartnersSuitSupport; int numSupportCards = bidState.numSupportCards; int nPartnersBidLevel = bidState.nPartnersBidLevel; int numPartnerBidsMade = bidState.m_numPartnerBidsMade; int nBid; // see if this is our second response to partner's opening 2C bid if (bidState.GetConventionStatus(this) == CONV_RESPONDED) { // see if we responded 2D last time if (bidState.nPreviousBid == BID_2D) { status << "R2CLR2! Partner showed his best suit of " & bidState.szPS & " in response to our negative 2D response.\n"; // what to do here??? // if partner shows a suit, adjust point count as dummy double fAdjPts = bidState.fAdjPts = (ISSUIT(bidState.nPartnersSuit))? hand.RevalueHand(REVALUE_DUMMY, bidState.nPartnersSuit, TRUE) : bidState.fPts; double fCardPts = bidState.fCardPts; // adjust partnership point count minimums & maximums bidState.m_fMinTPPoints = fAdjPts + bidState.m_fPartnersMin; bidState.m_fMaxTPPoints = fAdjPts + bidState.m_fPartnersMax; bidState.m_fMinTPCPoints = fCardPts + bidState.m_fPartnersMin; bidState.m_fMaxTPCPoints = fCardPts + bidState.m_fPartnersMax; // if (bidState.m_fMinTPPoints <= PTS_GAME-2) { nBid = BID_PASS; status << "R2CLR10! But with only " & bidState.m_fMinTPPoints & " points in the partnership, we have to pass.\n"; } else { // either shift to our own suit, raise partner to game, or bid 3NT if ((nPartnersSuitSupport >= SS_MODERATE_SUPPORT) && (nPartnersBid < bidState.GetGameBid(nPartnersSuit))) { nBid = bidState.GetGameBid(nPartnersSuit); status << "R2CLR20! Raise partner's & " & bidState.szPS & " to game at "& BTS(nBid) & ".\n"; } else if (bidState.IsSuitOpenable(bidState.nPrefSuit) && (nPartnersBidLevel <= 3)) { nBid = bidState.GetCheapestShiftBid(bidState.nPrefSuit); status << "R2CLR22! Bid our own " & bidState.szPrefSS & " suit in preference to partner's " & bidState.szPSS & " suit .\n"; } else if (nPartnersBid < BID_3NT) { nBid = BID_3NT; status << "R2CLR25! With only " & bidState.SLTS(nPartnersSuit) & " support for partner and no good suit of our own, bid 3NT.\n"; } else { nBid = BID_PASS; status << "R2CLR30! With only " & bidState.SLTS(nPartnersSuit) & " support for partner and no good suit of our own, we have to pass.\n"; } } // bidState.SetBid(nBid); bidState.SetConventionStatus(this, CONV_FINISHED); return TRUE; } // mark this convention as completed bidState.SetConventionStatus(this, CONV_FINISHED); return FALSE; } // // // partner must've bid 2 Club at his first opportunity, // and partner's bid must have been the first bid made // if ((nPartnersBid == BID_2C) && (bidState.m_bPartnerOpenedForTeam) && (numPartnerBidsMade == 1) && (nPartnersBid == pDOC->GetValidBidRecord(0))) { // condition valid // record that we responded bidState.SetConventionStatus(this, CONV_RESPONDED); } else { return FALSE; } // state expectations status << "R2CLUB! Partner made an artificial bid of 2 Clubs, showing either a game suit or " & pCurrConvSet->GetValue(tn2ClubOpeningPoints) & "+ points. We want to respond positively if interested in a slam.\n"; // the bid is forcing to game bidState.m_bGameForceActive = TRUE; // double fPts = bidState.fPts; double fAdjPts = bidState.fAdjPts; double fCardPts = bidState.fCardPts; int nPrefSuit = bidState.nPrefSuit; int nPrefSuitStrength = bidState.nPrefSuitStrength; // bidState.AdjustPartnershipPoints(pCurrConvSet->GetValue(tn2ClubOpeningPoints), 40 - fCardPts); // respond negatively (2D) with < 33 points if (bidState.m_fMinTPPoints < PTS_SLAM) { nBid = BID_2D; status << "R2C04! With only " & fCardPts & "/" & fPts & " points, we deny interest in slam by making the negative response of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); return TRUE; } // // else with 33+ points, state slam hopes // status << "2R2C08! With a total of " & bidState.m_fMinTPPoints & "+ points in the partnership, we want to invite slam.\n"; // show an openable suit if (nPrefSuitStrength >= SS_OPENABLE) { if (ISMAJOR(nPrefSuit)) nBid = MAKEBID(nPrefSuit,2); else nBid = MAKEBID(nPrefSuit,3); status << "R2C14! With " & fCardPts & "/" & fPts & " points in hand, and a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we express possible interest in slam by showing our best suit (" & bidState.szPrefS & ") with a bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); return TRUE; } // or a SOLID suit (jump shift) if (bidState.bPrefSuitIsSolid) { if (ISMAJOR(nPrefSuit)) nBid = MAKEBID(nPrefSuit,3); else nBid = MAKEBID(nPrefSuit,4); status << "R2C18! With " & fCardPts & "/" & fPts & " points in hand and a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & " points in the partnership, we express interest in a slam by showing our solid " & bidState.szPrefSS & " suit in a jump bid of " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); return TRUE; } // else assume a balanced hand // with a balanced hand & >= 26 total HCPs, bid 3NT; // with < 26 total HCPs, 2NT if (bidState.bBalanced) { if (bidState.m_fMinTPCPoints >= PTS_NT_GAME) nBid = BID_3NT; else nBid = BID_2NT; status << "R2C22! With " & fCardPts & " HCPs and a balanced hand, and a total of " & bidState.m_fMinTPCPoints & "+ HCPs in the partnership, we respond with " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); return TRUE; } // else just bid the best suit nBid = bidState.GetCheapestShiftBid(nPrefSuit, BID_2C); status << "R2C26! With " & fCardPts & "/" & fPts & " points but with no strong suit and an unbalanced hand, we have to respond with our best suit of " & bidState.szPrefS & " by bidding " & BTS(nBid) & ".\n"; bidState.SetBid(nBid); return TRUE; } // end of 2C opening section
// //----------------------------------------------------- // // 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; }