//
//===============================================================================
//
// TryConvention()
//
// check if we can open with a strong 2C bid
//
BOOL CArtificial2ClubConvention::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

	// check for a really strong hand with 23+ high card points 
	// or 10+ playing tricks 
	double fMinPts = pCurrConvSet->GetValue(tn2ClubOpeningPoints);
	if ((bidState.fCardPts >= fMinPts) || (bidState.numLikelyWinners >= 10)) 
	{
		int nBid = BID_2C;
		status << "STR2C! Have " & bidState.fCardPts & "/" & 
				   bidState.fPts &" points and " & bidState.numLikelyWinners & 
				   " playing tricks, so bid an artificial strong " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_INVOKED_ROUND1);
		return TRUE;
	}
	//
	return FALSE;
}
Example #2
0
BOOL CConvention::HandleConventionResponse(const CPlayer& player, const CConventionSet& conventions, CHandHoldings& hand, CCardLocation& cardLocation, CGuessedHandHoldings** ppGuessedHands, CBidEngine& bidState, CPlayerStatusDialog& status) 
{
	// called here if the derived class did not understand the response
	int nPartnersBid = bidState.nPartnersBid;
	if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
	{
		// the convention is cancelled!
//		status << "4CNVX0: We do not understand partner's " & BTS(nPartnersBid) & 
//				  " in this context, so cancel the current convention.\n";
		bidState.SetConventionStatus(this, CONV_ERROR);
		return FALSE;
	}

	//
	if (bidState.GetConventionStatus(this) > 0)
		bidState.SetConventionStatus(this, CONV_INACTIVE);
	return FALSE;
}
Example #3
0
BOOL CConvention::CheckForOtherConventions(CBidEngine& bidState) 
{
	// check to see if another convention is present
	CConvention* pActiveConvention = bidState.GetActiveConvention();
	if ((pActiveConvention) && (pActiveConvention != this))
		return TRUE;
	else
		return FALSE;
}
//
//===============================================================================
//
// 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;
}
//
//==========================================================
//
// HandleConventionResponse()
//
// Rebidding after an opening shutout bid
//
//
CShutoutBidsConvention::HandleConventionResponse(const CPlayer& player, 
											     const CConventionSet& conventions, 
											     CHandHoldings& hand, 
											     CCardLocation& cardLocation, 
												 CGuessedHandHoldings** ppGuessedHands,
											     CBidEngine& bidState,  
											     CPlayerStatusDialog& status)
{
	if (bidState.GetConventionStatus(this) != CONV_INVOKED)
		return FALSE;

	//
	//
	//
	return FALSE;
}
//
//---------------------------------------------------------------
//
// 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;
}
//
//===============================================================================
//
// RespondToConvention()
//
// partner bid at the 2-level (strong 2 bid)
//
// in general, partner's opening 2-bid denotes an extremely
// powerful hand.  So the question is whether to try for game
// or slam.  Therefore, we respond positively if we want attempt 
// a slam, or negatively for game
//
BOOL CStrongTwoBidsConvention::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())
		return FALSE;

	//
	// Bidding in response to an opening strong 2 bid? check requirements
	//
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersSuitSupport = bidState.nPartnersSuitSupport;
	int numSupportCards = bidState.numSupportCards;
	int numPartnerBidsMade = bidState.m_numPartnerBidsMade;
	//
	//
	// partner must've bid at the 2 level, but not 2C,
	// and partner's bid must have been the first bid made
	//
	if ((nPartnersBidLevel == 2) && (nPartnersBid != BID_2C) &&
					(bidState.m_bPartnerOpenedForTeam) &&
					(numPartnerBidsMade == 1) &&
					(nPartnersBid == pDOC->GetValidBidRecord(0)))
	{
		// okay, met requirements
	}
	else
	{
		// 
		return FALSE;
	}

	//
	int nBid;
	double fPts = bidState.fPts;
	double fAdjPts = bidState.fAdjPts;
	double fCardPts = bidState.fCardPts;
	int nPrefSuit = bidState.nPrefSuit;
	int numPrefSuitCards = bidState.numPrefSuitCards;
	double numQuickTricks = bidState.numQuickTricks;

	// state expectations
	bidState.m_fPartnersMin = 16;
	bidState.m_fPartnersMax = 22;
	status << "RSTRT! Partner made a strong 2-bid, showing a very good suit or two solid suits, 9+ playing tricks, and 4+ quick tricks.  We have to respond positively if interested in slam, or negatively otherwise.\n";

	// set 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;

	// the bid is forcing to game
	bidState.m_bGameForceActive = TRUE;		

	//
	// if we have less than 1 Quick trick, respond negatively
	//
	if (numQuickTricks < 1.0) 
	{
		nBid = BID_2NT;
		status << "RSTRT10! But with only " & numQuickTricks & 
				  " QT's, we have to make the negative response of " & BTS(nBid) & 
				  " to deny slam values.\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	//
	// else we have >= 1 Quick trick, so respond positively
	//
	status << "2RSTRT20! We have " & numQuickTricks & 
			  " QT's, so we can make a positive response.\n";

	// if we have even half-decent support for partner's suit, show it
	if (nPartnersSuitSupport >= SS_WEAK_SUPPORT) 
	{

		nBid = MAKEBID(nPartnersSuit,3);
		status << "RSTRT22! And we have " & bidState.SLTS(nPartnersSuit) & 
				  " support for partner's long " & bidState.szPSS &
				  " suit (holding " & bidState.szHP & 
				  "), so raise partner's bid to " & BTS(nBid) & ".\n";
	} 
	else if ((nPrefSuit != nPartnersSuit) &&
			   (bidState.nPrefSuitStrength >= SS_OPENABLE) &&
			   (numPrefSuitCards >= 5)) 
	{

		// or show our own suit if we have a good 5+ suiter
		int nSuit = nPrefSuit;
		// jump shift if the suits is really strong
		if (bidState.nPrefSuitStrength >= SS_ABSOLUTE) 
		{
			nBid = bidState.GetJumpShiftBid(nSuit,nPartnersBid);
			status << "RSTRT24! We lack good support for partner's " & 
					  bidState.szPSS & " suit (holding " & bidState.szHP & 
					  "), but we have an excellent " & 
					  bidState.LEN(nSuit) & "-card suit of our own in " & STS(nSuit) & 
					  " (holding " & bidState.SHTS(nSuit) & "), so show it in a bid of " &
					  BTS(nBid) & ".\n";
		} 
		else 
		{
			nBid = bidState.GetCheapestShiftBid(nSuit);
			status << "RSTRT26! But we lack good support for partner's " & 
					  bidState.szPSS & " suit (holding " & bidState.szHP & 
					  "), so show our preferred " & 
					  bidState.LEN(nSuit) & "-card " & STSS(nSuit) & " suit in a bid of " &
					  BTS(nBid) & ".\n";
		}

	} 
	else if ((bidState.bBalanced) && (bidState.m_fMinTPCPoints >= 26)) 
	{
		// here, we lack good support for partner's suit, and don't have a good
		// suit of our own.  so we jump to 3NT if we have a
		// balanced hand & 26+ total HCPs
		nBid = BID_3NT;
		status << "RSTRT28! But we lack good support for partner's " & 
				  bidState.szPSS & " suit (holding " & bidState.szHP & 
				  ") with a balanced hand, so jump to " &
				  BTS(nBid) & ".\n";
	} 
	else 
	{

		// here, we don't have good support for partner's
		// suit, nor a good suit of our own, nor a balanced
		// hand.  So bid 2NT in a negative response.
		nBid = BID_2NT;
		status << "RSTRT40! But unfortunately we have poor support for partner's " & 
				  bidState.szPSS & " suit (holding " & bidState.szHP & 
				  "), no good suit of our own, and an unbalanced hand, so we have to make the negative response of " & BTS(nBid) & ".\n";
	}
	//
	bidState.SetBid(nBid);
	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;
	}
}
//
//---------------------------------------------------------------
//
// 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;
}
//
//==========================================================
//
// Rebidding as opener after partner responds to an Jacoby 2NT Bid
//
BOOL CJacoby2NTConvention::HandleConventionResponse(const CPlayer& player, 
													const CConventionSet& conventions, 
													CHandHoldings& hand, 
													CCardLocation& cardLocation, 
													CGuessedHandHoldings** ppGuessedHands,
													CBidEngine& bidState,  
													CPlayerStatusDialog& status)
{
	// check status
	if ((bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND1) &&
		(bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND2))
		return FALSE;

	// get some info
	//
	int nBid = NONE;
	int nPrevSuit = bidState.nPartnersPrevSuit;
	int nSuit = bidState.nPartnersSuit;
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int numSupportCards = bidState.numSupportCards;

	//
	// handling partner's Drury response
	//
	int nStatus = bidState.GetConventionStatus(this);

	if (nStatus == CONV_INVOKED)
	{
		//
		// here, our actions depend on partner's response
		//
		if (bidState.nPartnersBid == MAKEBID(nPrevSuit, 3))
		{
			// partner responded in the suit at the 3-level, for 18+ pts
			status << "J2N40! Partner responded to our Jacoby 2NT inquiry by rebidding his " & 
					   STSS(nPrevSuit) & " suit at the 3-level, indicating " & 
					   OPEN_PTS(18) & "+ points.\n";

			// revalue partnership totals
			bidState.AdjustPartnershipPoints(18, pCurrConvSet->GetValue(tn2ClubOpeningPoints));
		}
		else if ((nPartnersBidLevel == 3) && ISSUIT(nSuit) && (nSuit != nPrevSuit))
		{
			// partner responded in a different suit at the 3-level
			status << "J2N41! Partner responded to our Jacoby 2NT inquiry by bidding the " & 
					   STSS(nSuit) & " suit at the 3-level, indicating " & OPEN_PTS(15) & "-" & OPEN_PTS(17) & 
					   " points and a singleton or void in " & STS(nSuit) & ".\n";

			// revalue partnership totals
			bidState.AdjustPartnershipPoints(15, 17);
		}
		else if (nPartnersBid == BID_3NT)
		{
			// partner responded with 3NT
			status << "J2N42! Partner responded to our Jacoby 2NT inquiry by bidding 3NT, indicating " &
					   OPEN_PTS(15) & "-" & OPEN_PTS(17) & " points with a balanced hand.\n";

			// revalue partnership totals
			bidState.AdjustPartnershipPoints(15, 17);
		}
		else if ((nPartnersBidLevel == 4) && ISSUIT(nSuit) && (nSuit != nPrevSuit))
		{
			// partner responded in a different suit at the 4-level
			status << "J2N44! Partner responded to our Jacoby 2NT inquiry by bidding the " & 
					   STSS(nSuit) & " suit at the 4-level, indicating a strong 5-card side suit and " & 
					   OPEN_PTS(15) & "-" & OPEN_PTS(17) & " points in the hand.\n";

			// revalue partnership totals
			bidState.AdjustPartnershipPoints(15, 17);
		}
		else if ((nPartnersBidLevel == 4) && (nSuit == nPrevSuit))
		{
			// partner responded in the original suit at the 4-level
			status << "J2N44! Partner responded to our Jacoby 2NT inquiry by rebidding his " & 
					   STSS(nSuit) & " suit at the 4-level, indicating a minimum opener of approx. " & 
					   OPEN_PTS(12) & "-" & OPEN_PTS(14) & " points in the hand.\n";

			// revalue partnership totals
			bidState.AdjustPartnershipPoints(12, 14);
		}
		else if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
		{
			// the convention is cancelled!
			bidState.SetConventionStatus(this, CONV_ERROR);
			return FALSE;
		}

		// now figure out what to do
		if (bidState.m_fMinTPPoints >= PTS_SLAM)
		{
			// go to Blackwood
			status << "J2N60! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
					  " pts in the partnership, push on to slam in partner's " & STSS(nPrevSuit) & " suit.\n";
			bidState.InvokeBlackwood(nPrevSuit);
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		}
		else if (bidState.m_fMinTPPoints >= PTS_MAJOR_GAME)
		{
			// we want to bid game
			if (nPartnersBid < bidState.GetGameBid(nPrevSuit))
			{
				// raise or shift to game
				nBid = bidState.GetGameBid(nPrevSuit);
				status << "J2N62! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, go to game in " & STS(nPrevSuit) &
						  " with a bid of " & BTS(nBid) & ".\n";
			}
			else
			{
				// here partner bid game or higher -- pass unless it needs correction
				if (nSuit == nPrevSuit)
				{
					nBid = BID_PASS;
					status << "J2N64! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
							  " pts in the partnership, pass partner's " & BTS(nPartnersBid) & " bid.\n";
				}
				else
				{
					// correct to the original suit
					nBid = bidState.GetCheapestShiftBid(nPrevSuit, nPartnersBid);
					status << "J2N66! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
							  " pts in the partnership, we want to stop at game in " & STS(nPrevSuit) & 
							  "; correct partner's " & BTS(nPartnersBid) & " bid to " & BTS(nBid) & ".\n";
				}
			}
		}
		else
		{
			// oops, caught with too few points
			// either pass 3NT , or return to the suit at the cheapest level possible
			if ((nPartnersBid == BID_3NT) || ((nSuit == nPrevSuit)))
			{
				nBid = BID_PASS;
				status << "J2N70! With a total of only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, we have to stop here at " & BTS(nPartnersBid) &
						  ", so pass.\n";
			}
			else
			{
				nBid = bidState.GetCheapestShiftBid(nPrevSuit, nPartnersBid);
				status << "J2N72! With a total of only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, we have to return to the " & STSS(nPrevSuit) & 
						  " and stop at " & BTS(nBid) & ".\n";
			}
		}

		// done
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;

	}

	// oops!
	bidState.SetConventionStatus(this, CONV_ERROR);
	return FALSE;
}
//
//==========================================================
//
// Rebidding as opener after partner responds to a Michaels Cue Bid
//
BOOL CMichaelsCueBidConvention::HandleConventionResponse(const CPlayer& player, 
													     const CConventionSet& conventions, 
													     CHandHoldings& hand, 
														 CCardLocation& cardLocation, 
														 CGuessedHandHoldings** ppGuessedHands,
													     CBidEngine& bidState,  
													     CPlayerStatusDialog& status)
{
	// 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;
	int nPreviousBidLevel = bidState.nPreviousBidLevel;
	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;

	//
	// handling partner's Michaels response
	//
	int nStatus = bidState.GetConventionStatus(this);

	if (nStatus == CONV_INVOKED)
	{
		// 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 we're holding the STRONG Michaels hand indicate it by cue-bidding the
		// enemy suit again
		if (bidState.fPts >= PT_COUNT(17))
		{
			nBid = MAKEBID(nPreviousSuit, 3);
			status << "MCLRH12! with a strong Michaels hand (" & bidState.fPts & 
					  " pts), cue bid the enemy suit again at " & BTS(nBid) & 
					  " to indicate our strength.\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
			return TRUE;
		}

		// did partner bid 2NT, asking for the minor?
		if (ISMAJOR(nPreviousSuit) && (nPartnersBid == BID_2NT))
		{
			// with a weak Michaels opener, indicate the minor
			int nSuit = bidState.GetLongerSuit(CLUBS, DIAMONDS);
			nBid = MAKEBID(nSuit, 3);
			status << "MCLRH10! With the weak flavor of Michaels, respond to partner's Michaels minor inquiry with a bid of " & BTS(nBid) &
					  ", indicating " & STS(nSuit) & " as the unknown minor.\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
			return TRUE;
		}

		// did partner cue-bid the enemy suit (a slam try)?
		if ((nPartnersSuit == nPreviousSuit) && (nPartnersBidLevel == nPreviousBidLevel+1))
		{
			// determine the cheapest of the two suits
			int nCheapestSuit;
			if (ISMINOR(nPreviousSuit))
				nCheapestSuit = HEARTS;		// 5/5 in the majors, so Hearts is cheapest
			else
				nCheapestSuit = bidState.GetLongerSuit(CLUBS, DIAMONDS);

			// respond affirmatively only with a strong hand
			status << "2MCLRH20! Partner cue bid the enemy suit, which is a game or slam try.\n";
			if (bidState.fPts >= PT_COUNT(17))
			{
				// jump into Blackwood
				status << "MCLRH21! And with " & bidState.fPts & " pts in hand, proceed towards slam in the preferred "&
						  STSS(bidState.nPrefSuit) & " suit.\n";
				bidState.InvokeBlackwood(bidState.nPrefSuit);
			}
			else if ( (ISMAJOR(nCheapestSuit) && (bidState.fPts >= PT_COUNT(9))) ||
				(ISMINOR(nCheapestSuit) && (bidState.fPts >= PT_COUNT(12))) )
			{
				// stop at game in the cheapest suit
				nBid = bidState.GetGameBid(nCheapestSuit);
				status << "MCLRH22! But with only " & bidState.fPts & " pts in hand, forget about slam and stop at game in the cheapest suit ("&
						  STS(nCheapestSuit) & ") at " & BTS(nBid) & ".\n";
				bidState.SetBid(nBid);
			}
			else 
			{
				// 8 or fewer pts -- bail out in the cheapest suit
				nBid = bidState.GetCheapestShiftBid(nCheapestSuit);
				status << "MCLRH23! But with only " & bidState.fPts & " pts in hand, forget about slam and bail out in the cheapest suit (" &
						  STS(nCheapestSuit) & ") at " & BTS(nBid) & ".\n";
				bidState.SetBid(nBid);
			}
			// done
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		}

		//
		// else partner made a signoff, invitational, or game bid
		//
		if (bidState.IsGameBid(nPartnersBid))
		{
			status << "MCLRH30! Partner responded to our Michaels Cue bid with a game bid of " & 
					  bidState.szPB & ", so we should pass.\n";
			nBid = BID_PASS;	
		}
		else if (nPartnersBid != BID_PASS) 
		{
			// see if we should raise partner to game
			status << "2MCLRH40! Partner responded to our Michaels Cue bid with a bid of " & 
					  bidState.szPB & ", a possible invitation to game.\n";
			// go to game with 17+ pts (strong hand)
			if (fPts < PT_COUNT(17))
			{
				nBid = BID_PASS;	
				status << "MCLRH41! But since we opened Michaels with a weak hand (" & fPts &
						  ") pts, we likely do not have the points for game and have to pass.\n";
			}
			else
			{
				nBid = bidState.GetGameBid(nPartnersSuit);	
				status << "MCLRH42! and since we opened Michaels with a strong hand (" & fPts &
						  ") pts, we can raise to game at " & BTS(nBid) & ".\n";
			}
		}
		else
		{
			status << "2MCLRH49! Partner passed" & (bidState.bLHOInterfered? "after opponents interference" : "") &
					  ", so Michaels is off.\n";
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return FALSE;
		}

		// done
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;

	}
	else if (nStatus == CONV_INVOKED_ROUND2)
	{
		// last time, we either showed our minor suit or indicated our strength 
		// with another cue bid of the opponents' suit

		// 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);
		}

		// did we have the strong hand?
		if (bidState.fPts >= PT_COUNT(17))
		{
			// see what partner's reaction was
			if (nPartnersSuit == BID_4NT)
			{
				// parter still wants to see our minor!!!
				int nSuit = bidState.GetLongerSuit(CLUBS, DIAMONDS);
				nBid = bidState.GetCheapestShiftBid(nSuit);
				status << "MCLRH50! After our second Michaels cue bid of the enemy suit, partner still wants to see the unknown minor, so show it (" &
						  STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n";
				bidState.SetBid(nBid);
				bidState.SetConventionStatus(this, CONV_INVOKED_ROUND3);
				return TRUE;
			}

			// else partner's bid was natural
			if (bidState.IsGameBid(nPartnersBid))
			{
				if (fPts < PT_COUNT(20))
				{
					status << "MCLRH55! Partner responded to our second Michaels cue bid with a game bid of " & 
							  bidState.szPB & ", so we should pass.\n";
					nBid = BID_PASS;
				}
				else
				{
					// jump to slam
					nBid = MAKEBID(nPartnersSuit, 6);
					status << "MCLRH55! Partner responded to our second Michaels cue bid with a game bid of " & 
							  bidState.szPB & ", and with " & fPts & "+ in hand, we can go ahead and jump to slam at " & BTS(nBid) & ".\n";
				}
			}
			else if (nPartnersBid != BID_PASS)
			{
				// see if we should raise partner to game
				nBid = bidState.GetGameBid(nPartnersSuit);
				status << "MCLRH56! Partner responded to our second Michaels cue bid of the enemy suit with a bid of " & 
						  bidState.szPB & ", an invitation to game -- so go ahead and bid game at " & BTS(nBid) & ".\n";
			}
			else
			{
				if (bidState.bLHOInterfered)
					status << "MCLRH58! Partner passed our second Michaels cue bid after interference, so we have to pass also.\n";
				else
					status << "MCLRH59! Partner passed in spite of our second Michaels cue bid, so we should pass also.\n";
				nBid = BID_PASS;
			}
		}
		else
		{
			// partner responded to our minor answer
			if (bidState.IsGameBid(nPartnersBid))
			{
				status << "MCLRH60! Partner responded to our Michaels minors answer with a game bid of " & 
						  bidState.szPB & ", so we should pass.\n";
				nBid = BID_PASS;
			}
			else if (nPartnersBid != BID_PASS)
			{
				// see if we should raise partner to game
				status << "MCLRH70! Partner responded to our Michaels minor answer with a bid of " & 
						  bidState.szPB & ", a possible invitation to game.\n";

				// go to game with 17+ pts (strong hand)
				if (fPts < PT_COUNT(17))
				{
					nBid = BID_PASS;	
					status << "MCLRH72! But since we opened Michaels with a weak hand (" & fPts &
							  ") pts, we likely do not have the points for game and have to pass.\n";
				}
				else
				{
					nBid = bidState.GetGameBid(nPartnersSuit);	
					status << "MCLRH72! and since we opened Michaels with a strong hand (" & fPts &
							  ") pts, we can raise to game at " & BTS(nBid) & ".\n";
				}
			}
			else
			{
				if (bidState.bLHOInterfered)
					status << "MCLRH75! Partner passed our Michaels minor answer after interference, so we have to pass also.\n";
				else
					status << "MCLRH76! Partner passed our Michaels minor answer, so we should pass also.\n";
				nBid = BID_PASS;
			}
		}

		// done
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;

	}
	else if (nStatus == CONV_INVOKED_ROUND3)
	{
		// 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);
		}

		// we indicated our strength with another cue bid, and partner asked
		// to see our minor, _then_ bid
		if (bidState.IsGameBid(nPartnersBid))
		{
			if (fPts < PT_COUNT(20))
			{
				status << "MCLRH80! Partner responded to our Michaels minor answer with a game bid of " & 
						  bidState.szPB & ", so we should pass.\n";
				nBid = BID_PASS;
			}
			else
			{
				// jump to slam
				nBid = MAKEBID(nPartnersSuit, 6);
				status << "MCLRH81! Partner responded to our Michaels minor answer with a game bid of " & 
						  bidState.szPB & ", and with " & fPts & "+ in hand, we can go ahead and jump to slam at " & BTS(nBid) & ".\n";
			}
		}
		else if (nPartnersBid != BID_PASS)
		{
			// see if we should raise partner to game
			nBid = bidState.GetGameBid(nPartnersSuit);
			status << "MCLRH85! Partner responded to our Michaels minor answer with a bid of " & 
					  bidState.szPB & ", an invitation to game -- so go ahead and bid game at " & BTS(nBid) & ".\n";
		}
		else
		{
			if (bidState.bLHOInterfered)
				status << "MCLRH86! Partner passed our Michaels minor answer after interference, so we have to pass also.\n";
			else
				status << "MCLRH87! Partner passed in spite of our Michaels minor answer, so we should pass also.\n";
			nBid = BID_PASS;
		}

		// done (finally!)
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;
	}

	// oops!
	bidState.SetConventionStatus(this, CONV_ERROR);
	return FALSE;
}
//
//=========================================================
//
// RespondToConvention()
//
// respond to partner's preemptive shutout bid of 3, 4, or 5
//
BOOL CShutoutBidsConvention::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())
		return FALSE;

	//
	// Bidding in response to an opening preemptive shutout bid? 
	// check requirements
	//
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;

	//
	// check to see if partner did in fact make a shutout bid
	//
	if (((nPartnersBidLevel >= 3) &&  (nPartnersBidLevel <= 5)) && 
						(bidState.m_numPartnerBidsMade == 1) &&
						(nPartnersSuit != NOTRUMP) &&
						(bidState.m_bPartnerOpenedForTeam))
	{
		// okay, met requirements
	}
	else
	{
		// failed the test
		return FALSE;
	}

	//
	// in general, pass a shutout bid unless we have an exceedingly 
	// strong hand
	//
	 
	// first state expectations
	bidState.m_fPartnersMin = OPEN_PTS(6);
	bidState.m_fPartnersMax = OPEN_PTS(9);
	status << "SHUTR0! Partner made a preemptive " & bidState.szPB & 
			  " bid, showing a " & 
			  ((bidState.nPartnersBidLevel==3)? 7:(bidState.nPartnersBidLevel==4)? 8:9) &
			  "-card " & bidState.szPSS & " suit with no tricks outside the suit, and most likely " &
			  bidState.m_fPartnersMin & "-" & bidState.m_fPartnersMax & " points.\n";

	// adjust team point estimates
	double fPts = bidState.fPts;
	double fAdjPts = bidState.fAdjPts;
	double fCardPts = bidState.fCardPts;
	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;

	// raise a 3 bid to game if we have enough to make game
	// the requiremetns are:
	// 1: 4 cards in the suit,
	// 2: 5 playing tricks for a major suit, or 6 for a minor
	// 3: 2 QT's, and
	// 4: >= 26 team pts for a major game, or >= 29 pts for a minor game
	int nBid;
	int numSupportCards = bidState.numSupportCards;
	int nPartnersSuitSupport = bidState.nPartnersSuitSupport;
	double numQuickTricks = bidState.numQuickTricks;
	int numLikelyWinners = bidState.numLikelyWinners;
	double fMinTPPoints = bidState.m_fMinTPPoints;
	double fMaxTPPoints = bidState.m_fMaxTPPoints;
	
	//
	if ((nPartnersBidLevel == 3) && (ISMAJOR(nPartnersSuit)) &&
		(numSupportCards >= 4) && (numQuickTricks >= 2) && 
		(numLikelyWinners >= 5) && (fMinTPPoints >= PTS_GAME)) 
	{
		nBid = MAKEBID(nPartnersSuit,4);
		status << "SHUTR2! We have " & fCardPts & "/" & fPts & "/" & fAdjPts & 
				  " points in hand, for a total of " & fMinTPPoints & "-" & fMaxTPPoints &
				  " points in the partnership, strong support for partner's long " &
				  bidState.szPSS & " suit (holding " & bidState.szHP & 
				  "), plus " & numQuickTricks & " QTs and " & numLikelyWinners & 
				  " likely winners, so we can safely bid game at " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	// raise a minor to game as above, but with 5-card
	// support && 6+ winners && 28+ TPs
	if ((nPartnersBidLevel <= 4)  && (ISMINOR(nPartnersSuit)) &&
		(numSupportCards >= 5) && (numQuickTricks >= 2) && 
		(numLikelyWinners >= 6) && (fMinTPPoints >= PTS_MINOR_GAME)) 
	{
		nBid = MAKEBID(nPartnersSuit,5);
		status << "SHUTR4! We have " & fCardPts & "/" & fPts & "/" & fAdjPts & 
				  " points in hand, for a total of " & fMinTPPoints & "-" & fMaxTPPoints &
				  " points in the partnership, strong support for partner's long " &
				  bidState.szPSS & " suit (holding " & bidState.szHP & 
				  "), plus " & numQuickTricks & " QTs and " & numLikelyWinners & 
				  " likely winners, so we can safely bid a minor game at " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	// raise a 3 or 4 bid to slam with strong support,
	// >= 32 TPs, and 4 QTs
	if ((nPartnersBidLevel < 5) && (nPartnersSuitSupport >= SS_GOOD_SUPPORT) &&
		(numQuickTricks >= 4) && (fMinTPPoints >= PTS_SLAM)) 
	{
		nBid = MAKEBID(nPartnersSuit,6);
		status << "SHUTR6! We have " & fCardPts & "/" & fPts & "/" & fAdjPts & 
				  " points in hand, for a total of " & fMinTPPoints & "-" & fMaxTPPoints &
				  " points in the partnership, " & bidState.SLTS(nPartnersSuit) &
				  " support for partner's long " & bidState.szPSS & 
				  " suit (holding " & bidState.szHP & "), plus " & numQuickTricks & 
				  " QTs, so we can safely bid a slam at " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	// else, just pass
	nBid = BID_PASS;
	status << "SHUTR9! With " & fCardPts & "/" & fPts & "/" & fAdjPts & 
			  " points in hand, for a total of " & fMinTPPoints & "-" & fMaxTPPoints &
			  " points in the partnership, holding " & bidState.szHP & 
			  " in support of partner's " & bidState.szPSS & " suit, and with only " & 
			  numQuickTricks & " QTs and " & numLikelyWinners & 
			  " likely winners, we have no real reason to bid anything, so just pass.\n";
	bidState.SetBid(nBid);
	return TRUE;
}
//
//===============================================================================
//
// 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;
}
//
//-----------------------------------------------------
//
// 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;
} 
//
//==========================================================
//
// Rebidding as opener after partner responds to an Gambling 3NT Bid
//
BOOL CGambling3NTConvention::HandleConventionResponse(const CPlayer& player,
        const CConventionSet& conventions,
        CHandHoldings& hand,
        CCardLocation& cardLocation,
        CGuessedHandHoldings** ppGuessedHands,
        CBidEngine& bidState,
        CPlayerStatusDialog& status)
{
    // check status
    if ((bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND1) &&
            (bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND2))
        return FALSE;

    //
    // get some info
    //
    int nBid = NONE;
    int nPartnersBid = bidState.nPartnersBid;

    // 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);
    }

    //
    // handling partner's Gambling 3NT response
    //
    int nStatus = bidState.GetConventionStatus(this);

    //
    if (nStatus == CONV_INVOKED)
    {
        // if partner passed, we're done
        if (nPartnersBid == BID_PASS)
        {
            status << "G3NT60! Partner passed our Gambling 3NT bid, so we pass as well.\n";
            nBid = BID_PASS;
        }

        // else partner shold have bid 4C on a standard Gambling 3NT
        int bStandardGambling3NT = (pCurrConvSet->GetValue(tnGambling3NTVersion) == 0);
        //
        if (bStandardGambling3NT && (nPartnersBid == BID_4C))
        {
            // partner bid 4C, so correct to 4D if necesary
            status << "G3NT61! Partner responded at 4 Club to our opening Gambling 3NT bid, indicating a lack of stoppers or a void minor suit.\n";
            //
            if (bidState.nPrefSuit == DIAMONDS)
            {
                nBid = BID_4D;
                status << "G3NT62! But since our desired suit is Diamonds, correct to " &
                       BTS(nBid) & ".\n";
            }
            else
            {
                status << "G3NT63! And since Clubs is our desired suit, we can pass and accept the 4C contract.\n";
                nBid = BID_PASS;
            }
        }
        else
        {
            // oops, error
            status << "G3NT65! Oops, partner's " & BTS(nPartnersBid) &
                   " is not a proper response to our Gambling 3NT opening bid, so we have to pass.\n";
            nBid = BID_PASS;
        }

        // done
        bidState.SetBid(nBid);
        bidState.SetConventionStatus(this, CONV_FINISHED);
        return TRUE;
    }

    // oops!
    bidState.SetConventionStatus(this, CONV_ERROR);
    return FALSE;
}
//
//==================================================================
// 
//
BOOL C4thSuitForcingConvention::TryConvention(const CPlayer& player, 
											  const CConventionSet& conventions, 
											  CHandHoldings& hand, 
											  CCardLocation& cardLocation, 
											  CGuessedHandHoldings** ppGuessedHands,
											  CBidEngine& bidState, 
											  CPlayerStatusDialog& status)
{
	//
//	if (!pCurrConvSet->IsConventionEnabled(tid4thSuitForcing))
//		return FALSE;

	//
	// see if the conditions are right to apply this convention
	//
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersPrevSuit = bidState.nPartnersPrevSuit;
	int nFirstRoundSuit = bidState.nFirstRoundSuit;
	int nPreviousSuit = bidState.nPreviousSuit;
	// NCR-342 Quick test if 4 suits were bid
	if ((bidState.m_numBidsMade != 2) ||  (bidState.m_numPartnerBidsMade != 2)
		|| !ISSUIT(nPartnersSuit)  || !ISSUIT(nPartnersPrevSuit)
		|| !ISSUIT(nFirstRoundSuit) || !ISSUIT(nPreviousSuit) ) 
	{
		return FALSE;  // NCR-342 Not possible without these
	}

/*	//NCR NB- Following logic is weak???
	if ((bidState.m_numBidsMade == 2) &&   // NCR-334 changed to 2 (was 1)
		(bidState.m_numPartnerBidsMade == 2) && 
		(nPartnersSuit != nPartnersPrevSuit) && (nPartnersPrevSuit != NONE) &&
		(nFirstRoundSuit != nPreviousSuit) && (nFirstRoundSuit != NONE) &&
		(nFirstRoundSuit != NOTRUMP) && // NCR-338 NT not a suit
		(nPartnersSuit != NOTRUMP)) \
*/
	// NCR-342 Now test 4 suits bid
	bool suitBid[4] = {false, false, false, false};
	suitBid[nPartnersSuit] = true;
	suitBid[nPartnersPrevSuit] = true;
	suitBid[nFirstRoundSuit] = true;
	suitBid[nPreviousSuit] = true;

	if(suitBid[CLUBS] && suitBid[DIAMONDS] && suitBid[HEARTS] && suitBid[SPADES])
	{
		//
		// since we're playing 4th suit forcing, we can't pass 
		// partner's bid, no matter what
		//
		status << "SF0! Since we're playing fourth-suit forcing, we are required to respond to partner's bid of the 4th suit.\n";

		int nPartnersBid =  bidState.nPartnersBid;
		int nPartnersBidLevel =  bidState.nPartnersBidLevel;
		int nPrefSuit = bidState.nPrefSuit;
		int nPrefSuitStrength = bidState.nPrefSuitStrength;
		double fMinTPPoints = bidState.m_fMinTPPoints;
		double fMaxTPPoints = bidState.m_fMaxTPPoints;
		double fMinTPCPoints = bidState.m_fMinTPCPoints;
		double fMaxTPCPoints = bidState.m_fMaxTPCPoints;
		int nBid;

		//
		// choice 1: rebid a strong major, if it's our preferred suit, with 22+ pts
		//
		if ((ISMAJOR(nPrefSuit)) && (nPrefSuitStrength >= SS_STRONG) &&
												(fMinTPPoints >= 22))
		{
			nBid = bidState.GetCheapestShiftBid(nPrefSuit);
			status << "SF2! With no agreement in suits, along with " &
					  fMinTPPoints & "-" & fMaxTPPoints &
					  " partnership points, return to our preferred " & 
					  bidState.szPrefSS & " suit at " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			return TRUE;
		}

		//
		// bid 3NT with no voids and 26+ HCPs
		//
		if ((bidState.numVoids == 0) && (nPartnersBidLevel <= 3) && 
										(fMinTPCPoints >= PTS_NT_GAME))
		{
			nBid = BID_3NT;
			status << "SF4! With no agreement in suits, but with " & 
					  fMinTPCPoints & "-" & fMaxTPCPoints &
					  " high card points in the partnership and no void suits, bid " &
					  BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			return TRUE;
		}

		//
		// raise one of partner's suits with 23+ points and 2-card support
		//
		int nSuit;
		if (bidState.nPPrevSuitSupport > bidState.nPartnersSuitSupport)
			nSuit = SUIT_PREV;
		else
			nSuit = SUIT_ANY;

		// raise to game level with 26+ total pts
		if (bidState.RaisePartnersSuit(SUIT_PREV,RAISE_TO_NO_MORE_THAN_GAME,PTS_GAME,99,SUPLEN_2))
		{
			// the bid (m_nBid) is set automatically
			return TRUE;
		}

		// raise to 3-level with 23 pts
		if (bidState.RaisePartnersSuit(SUIT_PREV,RAISE_TO_3,PTS_GAME-3,99,SUPLEN_2))
		{
			return TRUE;
		}

		//
		// bid 2NT with no voids 
		//
		if ((bidState.numVoids == 0) && (nPartnersBidLevel <= 2))
		{
			nBid = BID_2NT;
			status << "SF10! With no agreement in suits, but with " &  // NCR changed from 4 to 10
					  fMinTPCPoints & "-" & fMaxTPCPoints &
					  " high card points in the partnership and no void suits, bid " &
					  BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			return TRUE;
		}

		//
		// else we've run out of other options, so 
		// raise partner's first or second suit with single-card support
		//
		if (bidState.numCardsInSuit[nPartnersPrevSuit] >= 1)
		{
			nBid = bidState.GetCheapestShiftBid(nPartnersPrevSuit);
			status << "SF20! With no better options, raise partner's first suit to " &
					  BTS(nBid) & ".\n";
		}
		else
		{
			nBid = MAKEBID(nPartnersSuit, nPartnersBidLevel+1);
			status << "SF24! With no better options, raise partner's second suit to " &
					  BTS(nBid) & ".\n";
		}
		// done
		bidState.SetBid(nBid);
		return TRUE;

	}
	else
	{

		// the 4th suit forcing convention didn't apply here
		return FALSE;

	}

}
Example #17
0
void CBidDialog::OnAutotrain() 
{
	CNNetAutotrainStatusDlg	statusDlg;
	statusDlg.Create(CNNetAutotrainStatusDlg::IDD, this);
	statusDlg.ShowWindow(SW_SHOW);
	statusDlg.UpdateWindow();
	// 
	int numHands=0, numBids=0, numNonPassBids=0, numCorrections=0, numNonPassCorrections=0, numCycles=0;
	double fError = 0;

	//
	m_nCurrMode = BD_MODE_AUTO_TRAIN;
	BOOL bBreak = FALSE;
	SetWindowText(_T("Auto Training in progress"));

	// suppress updates
	pDOC->SuppressBidHistoryUpdate(TRUE);
	pDOC->SuppressPlayHistoryUpdate(TRUE);
	pVIEW->SuppressRefresh();
	pVIEW->ClearDisplay();
	BOOL bOutputVisible = pMAINFRAME->IsDialogVisible(twNNetOutputDialog);
//	pMAINFRAME->HideDialog(twNNetOutputDialog);

	// loop 
	do
	{
		// get computer bids continuously
		int nCode = 0;
		do
		{
			// deal a new hand
			pDOC->DealHands();
			numHands++;

			// and get bids
			do 
			{
				// get the computer's bid
				CBidEngine* pBidEngine = pDOC->GetCurrentPlayer()->GetBidEngine();
				theApp.SetValue(tnBiddingEngine, 1);
				int nNetBid = pBidEngine->Bid();
				theApp.SetValue(tnBiddingEngine, 0);
				int nRuleBid = pBidEngine->Bid();
				theApp.SetValue(tnBiddingEngine, 1);
				numBids++;
				if (nNetBid != BID_PASS)
					numNonPassBids++;
				//
				if (nRuleBid != nNetBid)
				{
					pBidEngine->SetNeuralNetBid(nRuleBid);
					fError = pBidEngine->GetNeuralNetError();
					numCorrections++;
					if (nNetBid != BID_PASS)
						numNonPassCorrections++;
					numCycles = pBidEngine->GetNeuralNetTrainingCycles();
				}

				// record the bid and process
				int nCode = pDOC->EnterBid(pDOC->GetCurrentPlayerPosition(), nRuleBid);
				if ((nCode == -99) || (nCode == 1))
				{
					// passed out, or 3 passes, and bidding is complete
					break;
				}
				else if (nCode == -1) 
				{
					AfxMessageBox("Error in Bidding Dialog!");
					bBreak = TRUE;
					break;
				}

				// update display
				if (!statusDlg.Update(numHands, numBids, numCorrections, numNonPassBids, numNonPassCorrections, numCycles, fError))
				{
					bBreak = TRUE;
					break;
				}

			} while (!bBreak);
			//
			if (bBreak)
				break;

		} while (!bBreak);
		//
		if (bBreak)
			break;

	} while (!bBreak);

	// done -- reset
	statusDlg.ShowWindow(SW_SHOW);
	pDOC->SuppressBidHistoryUpdate(FALSE);
	pDOC->SuppressPlayHistoryUpdate(FALSE);
	pVIEW->EnableRefresh();
	pVIEW->Refresh(TRUE);
//	if (bOutputVisible)
//		pMAINFRAME->MakeDialogVisible(twNNetOutputDialog);
	OnBidRestart();
}
//
//---------------------------------------------------------------
//
// 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;
}
//
//---------------------------------------------------------------
//
// HandleConventionResponse()
//
// Check on Gerber response from the invoker, and act accordingly
//
//	 
BOOL CGerberConvention::HandleConventionResponse(const CPlayer& player, 
											        const CConventionSet& conventions, 
											        CHandHoldings& hand, 
											        CCardLocation& cardLocation, 
												    CGuessedHandHoldings** ppGuessedHands,
											        CBidEngine& bidState,  
											        CPlayerStatusDialog& status)
{
	int nGerberStatus = bidState.GetConventionStatus(this);
	int numAces = bidState.numAces;
	int numKings = bidState.numKings;
	double fMinTPPoints = bidState.m_fMinTPPoints;
	double fMaxTPPoints = bidState.m_fMaxTPPoints;
	double fMinTPCPoints = bidState.m_fMinTPCPoints;
	double fMaxTPCPoints = bidState.m_fMaxTPCPoints;
	int nAgreedSuit = bidState.m_nAgreedSuit;
	int nPartnersBid = bidState.nPartnersBid;
	int nBid;

	//
	// Did we ask partner for aces in our last bid?
	//
	if (nGerberStatus == 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);
		}

		//
		switch(nPartnersBid) 
		{
			//
			case BID_4D:	// 0 or 4 Aces
				if (numAces == 0)
					bidState.m_numPartnersAces = 4;
				else
					bidState.m_numPartnersAces = 0;
				break;

			case BID_4H:	// 1 Ace
				bidState.m_numPartnersAces = 1;
				break;
			
			case BID_4S:	// 2 Aces
				bidState.m_numPartnersAces = 2;
				break;

			case BID_4NT:	// 3 Aces
				bidState.m_numPartnersAces = 3;
				break;

			default:		// choke, gag, spew!
				bidState.m_numPartnersAces = 0;
				break;
		}
		if (nPartnersBid <= BID_4NT) 
		{
			status << "GRB20! Partner responded to our 4C Gerber inquiry with " & 
					  BTS(nPartnersBid) & ", indicating " & 
					  bidState.m_numPartnersAces & 
					  (((bidState.m_numPartnersAces == 0) || (bidState.m_numPartnersAces > 1))? " Aces" : " Ace") & ".\n";
		} 
		else 
		{
			status << "GRB22! Partner made an illegal " & BTS(bidState.nPartnersBid) & 
					  " response to 4C Gerber; assuming zero Aces in partner's hand.\n";
			bidState.SetConventionStatus(this, CONV_ERROR);	// Gerber complete
			return TRUE;
		}

		//
		// at this point, decide whether to pass, proceed to asking for kings,
		// or jump to a contract.
		//
		int numTotalAces = bidState.numAces + bidState.m_numPartnersAces;

		//
		if (numTotalAces == 4)
		{
			// if we're close to a grand slam, go for it
			if (fMinTPPoints >= PTS_GRAND_SLAM-1)
			{
				nBid = BID_5NT;
				status << "GRB32! Our team holds all four aces, so proceed to 5NT to ask for kings.\n";
				nGerberStatus = CONV_INVOKED_ROUND2;	// asking for kings
			}
			else
			{
				nBid = MAKEBID(nAgreedSuit, 6);
				status << "GRB32! Our team holds all four aces, but with an estimated " & 
						  fMinTPPoints & "-" & fMaxTPPoints &
					      " total partnership points, we lack the points for a grand slam, so settle for a contract of " & BTS(nBid) & ".\n";
				nGerberStatus = CONV_FINISHED;	// Gerber finished
			}
		}
		else
		{
			// oops, we don't have all 4 aces, so we gotta stop
			// if we have 3 or fewer aces and less than 32 pts. then really panic
			// NCR-246a Need 3 aces and points to continue
			if ((numTotalAces < 3) || (bidState.m_fMinTPPoints < PTS_SLAM) || (bidState.m_fMaxTPCPoints < PTS_SLAM) )
			{
				// NCR-246a See if we need to bid
				int nTestBid = BID_PASS;  // NCR-246a pass if at game in our suit
				if(( bidState.nPartnersSuit != nAgreedSuit) || !bidState.IsGameBid(bidState.nPartnersBid)) {
					nTestBid = bidState.GetCheapestShiftBid(nAgreedSuit);
                } 
				if (nTestBid <= BID_5NT)
				{
					// if we can return to the trump suit at the 5 level,
					// then do so
					nBid = nTestBid;
					status << "GRB34! Oops, we're caught with only " & numTotalAces &
							  " Aces and as few as " & bidState.m_fMinTPPoints &
							  " total points, so halt the bidding at the " & BID_LEVEL(nPartnersBid) 
							  & "-level.\n";  // NCR replaced five with BID_LEVEL()
				}		
				else
				{  
					nBid = MAKEBID(nAgreedSuit, 6);
				}
			}
			else
			{
				if( bidState.numSuitsStopped < 4) // NCR-325 don't try slam without all 4 stopped
				{
					nBid = bidState.GetCheapestShiftBid(nAgreedSuit);  //NCR-325 get cheap bid
				}else
				    nBid = MAKEBID(nAgreedSuit, 6);
			}
			status << "GRB38! Without all four aces we can't proceed to a grand slam, so stop at " & 
			BTS(nBid) & ".\n";
			nGerberStatus = CONV_FINISHED;	// Gerber finished
		}
	
		// update status and return
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, nGerberStatus);
		return TRUE;

	}


	//
	// Did we ask for kings?
	//
	if (nGerberStatus == 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);
		}

		//
		switch(nPartnersBid) 
		{
			//	
			case BID_5D:	// 0 or 4 Kings
				if (numKings == 0)
					bidState.m_numPartnersKings = 4;
				else
					bidState.m_numPartnersKings = 0;
				break;

			case BID_5H:	// 1 King
				bidState.m_numPartnersKings = 1;
				break;
			
			case BID_5S:	// 2 Kings
				bidState.m_numPartnersKings = 2;
				break;

			case BID_5NT:	// 3 Kings
				bidState.m_numPartnersKings = 3;
				break;

			default:		// choke, gag, spew!
				bidState.m_numPartnersKings = 0;
				break;
		}
		if (nPartnersBid <= BID_5NT) 
		{
			status << "GRB40! Partner responded to our 4C Gerber inquiry with " & 
					  BTS(nPartnersBid) & ", indicating " & 
					  bidState.m_numPartnersKings & 
					  ((bidState.m_numPartnersKings > 1)? " Kings" : " King") &
					  ".\n";
		} 
		else 
		{
			status << "GRB44! Partner made an illegal " & BTS(nPartnersBid) & 
					  " response to 4C Gerber inquiry; assuming zero Kings in partner's hand.\n";
			nBid = BID_PASS;
			bidState.SetConventionStatus(this, CONV_ERROR);
			return FALSE;
		}

		//
		// at this point, decide on a contract.
		//
		int numTotalAces = bidState.numAces + bidState.m_numPartnersAces;
		ASSERT(numTotalAces == 4);
		int numTotalKings = bidState.numKings + bidState.m_numPartnersKings;
		//
		if (numTotalKings == 4)
		{
			// we have all Aces & Kings, so bid a grand slam
			nBid = MAKEBID(nAgreedSuit, 7);
			status << "GRB45! We have all the aces and kings, plus a total of " &
					  fMinTPPoints & "-" & fMaxTPPoints & 
					  " points in the partnership, so go ahead and bid " & 
					  BTS(nBid) & ".\n";
		}
		else if ((numTotalKings == 3) && (fMinTPPoints >= PTS_GRAND_SLAM))
		{
			// we're missing a king but have good pts, so go for a grand
			nBid = MAKEBID(nAgreedSuit, 7);
			status << "GRB46! We're missing one King, but with a total of " & 
					  fMinTPPoints & "-" & fMaxTPPoints & 
					  " points in the partnership, we can go ahead and bid " & BTS(nBid) & ".\n";
		}
		else if ((numTotalKings >= 3) && (fMinTPPoints >= PTS_GRAND_SLAM+1))
		{
			// we're missing two kings but have good pts, so go for a grand
			nBid = MAKEBID(nAgreedSuit, 7);
			status << "GRB47! We may not have all the kings, but with a total of " & 
					  fMinTPPoints & "-" & fMaxTPPoints & 
					  " points in the partnership, go ahead and bid " & BTS(nBid) & ".\n";
		}
		else
		{
			// we're missing two or more kings, so settle for a small slam
			nBid = MAKEBID(nAgreedSuit, 6);
			if (nBid > nPartnersBid)
			{
				// bail out at 6 of the agreed suit
				status << "GRB48! Since we're missing " & (4 - numTotalKings) & 
						  " Kings and have a total of only " & fMinTPPoints & "-" & fMaxTPPoints & 
						  " pts in the partnership, we lack sufficient strength for a grand slam and have to settle for a small slam at " &
						  BTS(nBid) & ".\n";
			}
			else
			{
				// bail out at 6NT
				nBid = BID_6NT;
				status << "GRB49! Since we're missing " & (4 - numTotalKings) & 
						  " Kings and have a total of only " & fMinTPCPoints & "-" & fMaxTPCPoints & 
						  " HCPs in the partnership, we lack sufficient strength for a grand slam and have to settle for a small slam at " &
						  BTS(nBid) & ".\n";
			}
		}
		// update status and return
		bidState.SetBid(nBid);
		nGerberStatus = 3;
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;

	}

	//
	return FALSE;
}
//
//---------------------------------------------------------------
//
// RespondToConvention()
//
// Check to see if a Gerber query has been made, 
// and if so, respond as appropriate
//
//	 
BOOL CGerberConvention::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;

	//
	// first look for a Gerber _Query_ from partner -- 
	// any 4C in response to a natural NT bid is Gerber
	// NCR unless partner has bid clubs before
	//
	int nGerberStatus = bidState.GetConventionStatus(this);
	int numAces = bidState.numAces;
	int numKings = bidState.numKings;
	int nPrevioousBid = bidState.nPreviousBid;
	int nBid;

	// is partner asking for aces?
	if ( (bidState.nPartnersBid == BID_4C) 
		  // NCR-552 I didn't open 1C
		  && (bidState.nNextPrevBid != BID_1C) // Or test if CLUBs ???
		  // NCR-521 4C must be Jump to be Gerber
          && ((bidState.GetBidType(bidState.nPartnersBid) & (BT_Jump + BT_Leap)) != 0) // NCR-551 Also Leap
		  && ((nPrevioousBid == BID_1NT) || ((nPrevioousBid == BID_2NT) 
		                                     // NCR-184 was it Unusual 2NT ? use pts  ???
		                                     && (bidState.fCardPts >= OPEN_PTS(13)))  // NCR-324 use OPEN_PTS
/* NCR-466		      || ((nPrevioousBid == BID_3NT) 
			      // NCR-152 & NCR-170 Check if clubs are partner's suit
				                                                // NCR-299 Not if I bid clubs
			       && ((bidState.nPartnersPrevSuit != CLUBS) && (bidState.nNextPrevSuit != CLUBS)) ) */  // NCR-14 After 3NT ???
                 //NCR-246a Also after Stayman 2C
			  || ((bidState.nPartnersPrevBid == BID_2C) && (bidState.nNextPrevSuit == NOTRUMP)
			      // NCR-509 Pard is using Gerber only if I opened NT
			      && bidState.m_bOpenedBiddingForTeam)	 ) )
	{
		// respond
		if ((numAces == 0) || (numAces == 4))
			nBid = BID_4D;
		else if (numAces == 1)
			nBid = BID_4H;
		else if (numAces == 2)
			nBid = BID_4S;
		else if (numAces == 3)
			nBid = BID_4NT;  // NCR 4NT NOT 5
		//
		status << "GRB10! With " & numAces & " Ace" & ((numAces > 1)? "s," : ",") &
				  " respond to partner's Gerber inquiry with " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND1);	// answered Aces, ready for Kings
		return TRUE;
	}

	// is partner asking for kings?
	if ((nGerberStatus == CONV_RESPONDED_ROUND1) && 
					(bidState.nPartnersBid == BID_5C))	
	{
		// respond
		if ((numKings == 0) || (numKings == 4))
			nBid = BID_5D;
		else if (numKings == 1)
			nBid = BID_5H;
		else if (numKings == 2)
			nBid = BID_5S;
		else if (numKings == 3)
			nBid = BID_5NT;
		//
		status << "GRB12! With " & numKings & " King" & ((numKings > 1)? "s," : ",") &
				  " respond to partner's Gerber inquiry with " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND2);	// Gerber complete
		return TRUE;
	}

	// no Gerber
	return FALSE;
}
//
//-----------------------------------------------------
//
// respond to partner's Gambling 3NT Bid
//
BOOL CGambling3NTConvention::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 nOpeningBid = pDOC->GetOpeningBid();
    int nBid = NONE;

    //
    int nStatus = bidState.GetConventionStatus(this);
    if (nStatus == CONV_INACTIVE)
    {
        //
        // Bidding in response to partner's Gambling 3NT
        //

        // and test conditions
        // partner must have opened at 3NT
        if ( (nOpeningBid == nPartnersBid) && (bidState.nPartnersBid == BID_3NT) )
        {
            // passed the test
        }
        else
        {
            return FALSE;
        }

        // see which version of gambling 3NT we're playing
        int bStandardGambling3NT = (pCurrConvSet->GetValue(tnGambling3NTVersion) == 0);

        //
        if (bStandardGambling3NT)
        {
            // standard Gambling 3NT
            status << "G3NT10! Partner bid a Gambling 3NT, indicating " &
                   OPEN_PTS(10) & "-" & OPEN_PTS(12) & " HCPs, a solid 7+ card minor, "
                   " no voids or small singletons, and no outside stoppers.\n";

            // revalue partnership totals
            bidState.AdjustPartnershipPoints(10, 12);

            // if we have stoppers in at least 3 suits and no void minors, pass
            if ((bidState.numSuitsStopped >= 3) &&
                    (bidState.numCardsInSuit[CLUBS] > 0) && (bidState.numCardsInSuit[DIAMONDS] > 0))
            {
                status << "G3NT12! Since we have " & bidState.numSuitsStopped & " suits stopped and no minor suit voids, we can pass.\n";
                nBid = BID_3NT;
            }
            else
            {
                nBid = BID_4C;
                if (bidState.numSuitsStopped < 3)
                    status << "G3NT13! But since we have only " & bidState.numSuitsStopped & " suits stopped, we have to respond with " & BTS(nBid) &
                           ", which partner can correct to 4D if necessary.\n";
                else
                    status << "G3NT14! But since we are void in the " &
                           ((bidState.numCardsInSuit[CLUBS] == 0)? "Club" : "Diamond") &
                           " suit, we have to respond at " & BTS(nBid) &
                           ", which partner can correct to 4D if necessary.\n";
                //
                bidState.SetBid(nBid);
                bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND1);
                return TRUE;
            }
        }
        else
        {
            // ACOL Gambling 3NT
            // pass unless there's interest in slam
            status << "G3NT20! Partner bid an ACOL Gambling 3NT, indicating " &
                   OPEN_PTS(16) & "-" & OPEN_PTS(21) & " HCPs, a solid 7+ card minor, "
                   " no voids or small singletons, and stoppers in at least 2 outside suits.\n";

            // revalue partnership totals
            bidState.AdjustPartnershipPoints(16, 21);

            // respond positively only if there's interest in slam
            if (bidState.m_fMinTPPoints >= PTS_SLAM)
            {
                // bid slam directly
                if (bidState.m_fMinTPPoints >= PTS_GRAND_SLAM)
                {
                    nBid = BID_7NT;
                    status << "G3NT21! With a total of " &
                           bidState.m_fMinTPPoints & "-" & bidState.m_fMinTPPoints &
                           " pts in the partnership, bid a grand slam directly at " & BTS(nBid) & ".\n";
                }
                else
                {
                    nBid = BID_6NT;
                    status << "G3NT22! With a total of " &
                           bidState.m_fMinTPPoints & "-" & bidState.m_fMinTPPoints &
                           " pts in the partnership, bid slam directly at " & BTS(nBid) & ".\n";
                }
            }
            else
            {
                // gotta pass
                status << "G3NT29! But with a total of " &
                       bidState.m_fMinTPPoints & "-" & bidState.m_fMinTPPoints &
                       " pts in the partnership, we have no interest in slam and have to pass.\n";
                nBid = BID_PASS;
            }
        }
        //
        bidState.SetBid(nBid);
        bidState.SetConventionStatus(this, CONV_FINISHED);
        return TRUE;
    }
    else if (nStatus == CONV_RESPONDED_ROUND1)
    {
        // we must have responded with a 4C, so pass here
        // see if partner made sense
        if ((nPartnersBid == BID_4D) || (nPartnersBid == BID_PASS))
            status << "G3NT40! Pass partner's " & BTS(nPartnersBid) & " and conclude the Gambling 3NT convention and pass.\n";
        else
            status << "G3NT41! Partner's " & BTS(nPartnersBid) & " bid doesn't make sense, so end the Gambling 3NT convention and pas.\n";
        //
        bidState.SetBid(BID_PASS);
        bidState.SetConventionStatus(this, CONV_FINISHED);
        return TRUE;
    }

    //
    return FALSE;
}
//
//==========================================================
//
// Rebidding as opener after a strong 2-level opening
//
//
BOOL CStrongTwoBidsConvention::HandleConventionResponse(const CPlayer& player, 
												        const CConventionSet& conventions, 
												        CHandHoldings& hand, 
												        CCardLocation& cardLocation, 
													    CGuessedHandHoldings** ppGuessedHands,
												        CBidEngine& bidState,  
												        CPlayerStatusDialog& status)
{
	if (bidState.GetConventionStatus(this) != CONV_INVOKED)
		return FALSE;
	bidState.ClearConventionStatus(this);

	//
	// estimate partner's strength
	//
	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;
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersSuitSupport = bidState.nPartnersSuitSupport;
	int numSupportCards = bidState.numSupportCards;
	BOOL bBalanced = bidState.bBalanced;

	//
	// did we get a negative response from partner?
	//
	if (nPartnersBid == BID_2NT) 
	{
		status << "2S2Rb0! After our strong " & bidState.szPVB & 
			" opening bid, partner's 2NT bid is a negative response, denying slam values (less than 1 Quick Trick).\n";

		// estimate points -- 0 to 6 for now
		bidState.m_fPartnersMin = 0;
		bidState.m_fPartnersMax = 6;
		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;

		// after a negative response, bid 3NT if balanced
		// with 26+ HCPs
		if ((bBalanced) && (bidState.m_fMinTPCPoints >= PTS_NT_GAME)) 
		{
			nBid = BID_3NT;
			status << "S2RB1! With a balanced distribution and " &
					  fCardPts & " HCPs in hand, rebid " & BTS(nBid) & ".\n";
		}
		// else show a second preferred suit if available
		if (bidState.numPreferredSuits > 0) 
		{
			int nSuit = bidState.GetRebidSuit(nPreviousSuit);
			nBid = bidState.GetCheapestShiftBid(nSuit);
			status << "S2RB4! With a good second suit in " &
					  STS(nSuit) & ", show it in a rebid of " & BTS(nBid) & ".\n";
		}
		// otherwise rebid our original suit (if not 2C)
		if (bidState.nPreviousBid == BID_2C) 
		{
			nBid = bidState.GetCheapestShiftBid(nPrefSuit);
			status << "S2RB6! With no other good suits, go ahead and bid our " &
					  bidState.szPrefS & " suit at " & BTS(nBid) & ".\n";
		} 
		else 
		{
			nBid = bidState.GetCheapestShiftBid(nPreviousSuit);
			status << "B3E32! With no other good suits, go ahead and rebid our " &
					  bidState.szPVSS & " suit at " & BTS(nBid) & ".\n";
		}
		//
		bidState.SetBid(nBid);
		return TRUE;
	}
	
	//
	// otherwise, got a positive response, and partner has shown 
	// his long suit -- so either raise partner's suit, bid NT, or
	// rebid our own suit
	//
	status << "2S2Rb20! After our strong " & bidState.szPVB &
			  " opening bid, partner's " & bidState.szPB & 
			  " bid was a positive response, indicating 1+ Quick Tricks.\n";

	// estimate points -- 3+ pts for now
	bidState.m_fPartnersMin = 3;
	bidState.m_fPartnersMax = MIN(22, 40 - fCardPts);
	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;

	// bid No Trump if balanced
	if (bBalanced) 
	{
		nBid = BID_3NT;
		status << "With a balanced hand, bid game at " & BTS(nBid) & ".\n";
	} 
	// see if there's a suit agreement from a strong 2 bid
	if ((nPreviousSuit == nPartnersSuit) && (bidState.nLastBid != BID_2C)) 
	{
		// try for a slam; use Blackwood
		status << "S2RB24! Partner's encouraging raise to " & bidState.szPB & 
				  " indicates 1+ Quick Tricks and slam possibilities.\n";
		bidState.InvokeBlackwood(nPartnersSuit);
		return TRUE;
	}
	// raise partner's suit if possible
	if (nPartnersSuitSupport >= SS_GOOD_SUPPORT) 
	{
		// double raise partner if major, or go directly to Blackwood
		// if minor (double raise from 3C or 3D would exceed 4NT
		if (ISMAJOR(nPartnersSuit))
		{
			bidState.m_nAgreedSuit = nPartnersSuit;
			nBid = MAKEBID(nPartnersSuit,nPartnersBidLevel+2);
			status << "S2RB28! With " & bidState.SLTS(nPartnersSuit) & 
					  " support for partner's " & bidState.szPS & 
					  " (holding " & bidState.szHP & 
					  "), go ahead and jump raise to " & BTS(nBid) & ".\n";
		}
		else
		{
			status << "S2RB32! We have " & bidState.SLTS(nPartnersSuit) & 
					  " support for partner's " & bidState.szPS & 
					  " (holding " & bidState.szHP & 
					  ").\n";
			bidState.InvokeBlackwood(nPartnersSuit);
			return TRUE;
		}
	}

	// else show a second preferred suit if available
	if (bidState.numPreferredSuits > 1) 
	{
		int nSuit = bidState.GetRebidSuit(nPreviousSuit);
		nBid = bidState.GetCheapestShiftBid(nSuit);
		status << "S2RB36! But we don't like partner's " & bidState.szPSS & 
				  " suit (holding " & bidState.szHP & 
				  "), and we hold a good second suit in " & STS(nSuit) & 
				  ", so show it in a rebid of " & BTS(nBid) & ".\n";
	}
	// otherwise rebid our original suit (if not 2C)
	if (bidState.nPreviousBid == BID_2C) 
	{
		nBid = bidState.GetCheapestShiftBid(nPrefSuit);
		status << "S2RB44! But we don't like partner's " &
				  bidState.szPSS & " suit (holding " & bidState.szHP & 
				  "), so bid our own " & bidState.szPrefS & 
				  " suit at " & BTS(nBid) & ".\n";
	} 
	else 
	{
		nBid = bidState.GetCheapestShiftBid(nPreviousSuit);
		status << "S2RB50! But we don't like partner's " &
				  bidState.szPSS & " suit (holding " & bidState.szHP & 
				  "), so rebid our own " & bidState.szPVSS & 
				  " suit at " & BTS(nBid) & ".\n";
	}
	//
	bidState.SetBid(nBid);
	return TRUE;
}
//
//===============================================================================
//
// 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;
}
//
//===============================================================================
//
// TryConvention()
//
// check if we can open with a strong two-bid
//
BOOL CStrongTwoBidsConvention::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
	
	// To open with a strong two bid, we need either a long, very good suit 
	// or 2 string suits, with 9+ playing tricks for majors (10+ for minors)
	// plus 4 quick tricks.
	// we also need a _minimum_ of 16 HCPs, no matter what
	if ( ((bidState.numAbsoluteSuits >= 1) || (bidState.numSolidSuits >= 2)) &&
		  (bidState.numLikelyWinners >= 9) && (bidState.numQuickTricks >= 4) &&
			  								(bidState.fCardPts >= 16)) 
	{
		// bid 2 of lowest openable solid suit
		double fPts = bidState.fPts;
		double fCardPts = bidState.fCardPts;
		int nBid = bidState.GetLowestOpenableBid(SUITS_ANY, OT_STRONG, 2);
		if ((nBid == BID_2C) && (pCurrConvSet->IsConventionEnabled(tidArtificial2ClubConvention)))
		{
			// we can't open a strong 2C when playing the 2Club convention,
			// so see if we can find another strong suit
			int nextBestSuit = bidState.nPrefSuitList[1];
			if (bidState.nSuitStrength[nextBestSuit] >= SS_STRONG)
			{
				nBid = MAKEBID(nextBestSuit ,2);
				status << "STR2C1! Have a strong Club suit and " & fPts & 
						  " points, but can't open at 2 Club, so we'll have to bid " & 
						  STS(nextBestSuit) & " instead.\n";
			}
			else
			{
				// can't bid at the 1-level
				status << "STR2C2! Have a strong Club suit and no others, but can't open 2C with only " &
						   fCardPts & " HCPs, so bid " & BTS(nBid) & " instead.\n";
				return FALSE;
			}
		}
		// a biddable suit has been established
		if (bidState.numSolidSuits > 1)
		{
			status << "STR2C10! Have " & bidState.numSolidSuits & " solid " & 
					  ((bidState.numSolidSuits>1)? "suits" :  "suit") &
					  " with " & bidState.numLikelyWinners & " playing tricks and " &
					  bidState.numQuickTricks & " quick tricks, so bid a strong " &
					  BTS(nBid) & ".\n";
		}
		else
		{
			status << "STR2C12! Have a solid " & STSS(bidState.nPrefSuit) & 
					  " suit with " & bidState.numLikelyWinners & 
					  " playing tricks and " & bidState.numQuickTricks & 
					  " quick tricks, so bid a strong " & BTS(nBid) & ".\n";
		}
		bidState.SetBid(nBid);
//		bidState.SetConventionStatus(this, CONV_INVOKED);
		return TRUE;
	}
	// failed the test
	return FALSE;
}
//
//-----------------------------------------------------
//
// 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;
} 
//
//===============================================================================
//
// 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;
}
//
//==========================================================
//
// Rebidding as opener after a strong 2-level opening
//
//
BOOL CArtificial2ClubConvention::HandleConventionResponse(const CPlayer& player, 
													      const CConventionSet& conventions, 
														  CHandHoldings& hand, 
														  CCardLocation& cardLocation, 
														  CGuessedHandHoldings** ppGuessedHands,
														  CBidEngine& bidState,  
														  CPlayerStatusDialog& status)
{
	int nStatus = bidState.GetConventionStatus(this);
	if (nStatus <= 0)
		return FALSE;

	//
	// estimate partner's strength
	//
	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;
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersSuitSupport = bidState.nPartnersSuitSupport;
	int numSupportCards = bidState.numSupportCards;
	BOOL bBalanced = bidState.bBalanced;
	BOOL bSemiBalanced = bidState.bSemiBalanced;


	// see if this is our first rebid
	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);
		}

		//
		// did we get a negative response? (2D in response to the 2C)
		//
		if (nPartnersBid == BID_2D) 
		{
			status << "CRB0! After our strong 2 Club opening, partner's 2 Diamond bid is a negative response, denying slam values (less than 1 Quick Trick).\n";

			// estimate points -- 0 to 6 for now
			bidState.m_fPartnersMin = 0;
			bidState.m_fPartnersMax = 6;
			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;

			// bid game or slam with 26+ pts
			if ((bidState.m_fMinTPCPoints >= PTS_NT_GAME) && (bidState.m_fMinTPCPoints < PTS_SMALL_SLAM))
			{
				if (bBalanced || bSemiBalanced)
				{
					nBid = BID_3NT;
					status << "CRB1! With a balanced distribution and " &
							  fCardPts & " HCPs in hand, rebid " & BTS(nBid) & ".\n";
				}
				else if ( (ISMAJOR(nPrefSuit) && (bidState.m_fMinTPPoints >= PTS_MAJOR_GAME)) ||
						  (ISMINOR(nPrefSuit) && (bidState.m_fMinTPPoints >= PTS_MINOR_GAME)) )
				{
					nBid = bidState.GetGameBid(nPrefSuit);
					status << "CRB2! With no help from partner, we have to unilaterally push on to game at " & BTS(nBid) & ".\n";
				}
				bidState.SetConventionStatus(this, CONV_FINISHED);
			}
			else if ((bidState.m_fMinTPCPoints >= PTS_SMALL_SLAM) && (bidState.m_fMinTPCPoints < PTS_GRAND_SLAM))
			{
				if (bBalanced || bSemiBalanced)
				{
					nBid = BID_6NT;
					status << "CRB4! With a balanced distribution and " &
							  fCardPts & " HCPs in hand, bid a slam at " & BTS(nBid) & ".\n";
				}
				else
				{
					nBid = MAKEBID(nPrefSuit, 6);
					status << "CRB5! With no help from partner but with a total of " & bidState.m_fMinTPPoints &
							  " points in the partnership, we have to unilaterally push on to a slam at " & BTS(nBid) & ".\n";
				}
				bidState.SetConventionStatus(this, CONV_FINISHED);
			}
			else if (bidState.m_fMinTPCPoints >= PTS_GRAND_SLAM)
			{
				if (bBalanced || bSemiBalanced)
				{
					nBid = BID_7NT;
					status << "CRB6! With a balanced distribution and " &
							  fCardPts & " HCPs in hand, bid a grand slam at " & BTS(nBid) & ".\n";
				}
				else
				{
					nBid = MAKEBID(nPrefSuit, 7);
					status << "CRB5! With no help from partner but with a total of " & bidState.m_fMinTPPoints &
							  " points in the partnership, we have to unilaterally push on to a grand slam at " & BTS(nBid) & ".\n";
				}
				bidState.SetConventionStatus(this, CONV_FINISHED);
			}
			else
			{
				// else show our preferred suit and see if partner bids again
				nBid = bidState.GetCheapestShiftBid(nPrefSuit);
				status << "CRB8! Show our strongest suit (" & bidState.szPrefS &
						  ") with a bid of " & BTS(nBid) & ".\n";
				bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
			}
			//
			bidState.SetBid(nBid);
			return TRUE;
		}

		//
		// otherwise, we got a positive response, and partner has shown 
		// his long suit -- so either raise partner's suit, bid NT, or
		// rebid our own suit
		//
		status << "2CRB20! After our strong 2 Club opening, partner's " & bidState.szPB & 
				  " bid was a positive response, indicating 7+ pts and 1+ Quick Tricks.\n";

		// estimate points -- 7+ pts for now
		bidState.m_fPartnersMin = 7;
		bidState.m_fPartnersMax = MIN(22, 40 - fCardPts);
		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;

		// respond to partner's NT bid here
		// bid No Trump if reasonably balanced or have poor support
		if (nPartnersBid == BID_2NT) 
		{
			if ( bidState.bSemiBalanced ||
				 ((nPartnersSuitSupport <= SS_WEAK_SUPPORT) && (bBalanced)) )
			{
				if (bidState.m_fMinTPCPoints >= PTS_SLAM)
					nBid = BID_6NT;
				else
					nBid = BID_3NT;
				if (ISSUIT(nPartnersSuit))
					status << "CRB21! With a balanced hand and " & 
							  bidState.SLTS(nPartnersSuit) & " support for partner's " & bidState.szPS &
							  ", plus a total of " & bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints &
							  " HCPs in the partnership, move to Notrump and bid " & 
							  ((BID_LEVEL(nBid) >= 6)? "slam" : "game") & " at " & BTS(nBid) & ".\n";
				else
					status << "CRB22! With a " & (!bBalanced? "semi-" : "") &
							  "balanced hand and a total of " & 
							  bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints &
							  " HCPs in the partnership, raise partner to " & ((BID_LEVEL(nBid) >= 6)? "slam" : "game") &
							  " at " & BTS(nBid) & ".\n";
			}
			else
			{
				// we're not balanced, so show our preferred suit if possible
				nBid = bidState.GetCheapestShiftBid(nPrefSuit);
				status << "CRB25! We don't like Notrump, so so bid our " & 
						  bidState.szPrefS & " suit at " & BTS(nBid) & ".\n";
			}
			//
			bidState.SetBid(nBid);
			return TRUE;
		} 

		// raise partner's suit if possible
		if ((nPartnersSuit != NOTRUMP) && (nPartnersSuitSupport >= SS_GOOD_SUPPORT))
		{
			// double raise partner if major, or go directly to Blackwood
			// if minor (double raise from 3C or 3D would exceed 4NT
			if (ISMAJOR(nPartnersSuit))
			{
				bidState.m_nAgreedSuit = nPartnersSuit;
				nBid = bidState.GetGameBid(nPartnersSuit);
				BOOL bJumped = (nPartnersBidLevel == 2);
				status << "CRB28! With " & bidState.SLTS(nPartnersSuit) & 
						  " support for partner's " & bidState.szPS & 
						  " (holding " & bidState.szHP & 
						  "), go ahead and " & (bJumped? "jump" : "") & 
						  " raise to " & BTS(nBid) & ".\n";
				bidState.SetBid(nBid);
			}
			else
			{
				status << "CRB32! We have " & bidState.SLTS(nPartnersSuit) & 
						  " support for partner's " & bidState.szPS & 
						  " (holding " & bidState.szHP & "), so push towards slam.\n";
				bidState.InvokeBlackwood(nPartnersSuit);
				bidState.SetConventionStatus(this, CONV_FINISHED);
			}
			return TRUE;
		}

		// else show our preferred suit
		nBid = bidState.GetCheapestShiftBid(nPrefSuit);
		status << "CRB44! But we don't like partner's " & bidState.szPSS & 
				  " suit (holding " & bidState.szHP & "), so bid our own " & 
				  bidState.szPrefS & " suit at " & BTS(nBid) & ".\n";

		// done
		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);
		}

		// partner bid another suit after our rebid of our suit 
		// AFTER her negative response to our opening strong 2C
		int nPartnersSuit = bidState.nPartnersSuit;
		if ((nPartnersSuit != NOTRUMP) && (nPartnersSuit != bidState.nPreviousSuit))
		{
			status << "CRB60! Partner bid " & bidState.szPB & " after we bid our " & bidState.szPVS & 
					  " suit, indicating a strong preference for the " & bidState.szPS & " suit.\n";
			
			// support partner's suit if we have decent holdings, else bid our own suit
			if (bidState.nPartnersBid < bidState.GetGameBid(nPartnersSuit))
			{
				// see if we like partner's suit
				if (bidState.nPartnersSuitSupport >= SS_GOOD_SUPPORT)
				{
					nBid = bidState.GetGameBid(nPartnersSuit);
					status << "CRB62! So with " & bidState.SLTS(nPartnersSuitSupport) & " support for partner's " &
							   bidState.szPS & ", raise to game at " & BTS(nBid) & ".\n";
				}
				else
				{
					nBid = bidState.GetCheapestShiftBid(bidState.nPreviousSuit);
					status << "CRB62! But with only " & bidState.SLTS(nPartnersSuitSupport) & " support for partner's " &
							   bidState.szPS & ", return to our own suit at " & BTS(nBid) & ".\n";
				}
			}
			else
			{
				// partner bid game!
				if (bidState.m_fMinTPPoints < PTS_SLAM)
				{
					// we don't have points for a slam, so pass
					nBid = BID_PASS;
					if (bidState.nPartnersBidLevel < 6)
						status << "CRB68! Partner's " & bidState.szPB & " bid is at game level, so pass.\n";
					else
						status << "CRB69! Partner's " & bidState.szPB & " bid is at slam level, so pass.\n";
				}
				else
				{
					// we do have the points for a slam!
					if (bidState.nPartnersBidLevel < 6)
					{
						nBid = BID_6NT;
						status << "CRB72! While we do not have suit agreement, we have the points for a slam, so bid " & 
								  BTS(nBid) & ".\n";
					}
					else
					{
						nBid = BID_PASS;
						status << "CRB74! Partner has bid slam in his suit, so pass.\n";
					}
				}
			}
		}
		else if (nPartnersSuit == NOTRUMP)
		{
			// partner bid NT
			// bid 3NT if possible
			if ( bidState.bSemiBalanced ||
				 ((nPartnersSuitSupport <= SS_WEAK_SUPPORT) && (bBalanced)) )
			{
				if (bidState.m_fMinTPCPoints >= PTS_SLAM)
					nBid = BID_6NT;
				else
					nBid = BID_3NT;
				if (ISSUIT(nPartnersSuit))
					status << "CRB76! With a balanced hand and " & 
							  bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints &
							  " HCPs in the partnership, respond at " & 
							  ((BID_LEVEL(nBid) >= 6)? "slam" : "game") & " with a bid of " & BTS(nBid) & ".\n";
				else
					status << "CRB77! With a " & (!bBalanced? "semi-" : "") &
							  "balanced hand and a total of " & 
							  bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints &
							  " HCPs in the partnership, raise partner to " & ((BID_LEVEL(nBid) >= 6)? "slam" : "game") &
							  " at " & BTS(nBid) & ".\n";
			}
			else
			{
				// we're not balanced, so show our preferred suit if possible
				nBid = bidState.GetCheapestShiftBid(nPrefSuit);
				status << "CRB78! We don't like Notrump, so so bid our " & 
						  bidState.szPrefS & " suit at " & BTS(nBid) & ".\n";
			}
			//
			bidState.SetBid(nBid);
			return TRUE;
		}
		else
		{
			// partner raised, which is strange!
			status << "CRB80! Partner raised our " & bidState.szPVSS & " suit, which is strange, ";
			if (bidState.nPartnersBid < bidState.GetGameBid(nPartnersSuit))
			{
				nBid = bidState.GetGameBid(bidState.nPartnersSuit);
				status << "but go ahead and raise to game.";
			}
			else
			{
				nBid = BID_PASS;
				status << "but since we're at game, stop here and pass.\n";
			}
		}

		// and we're done
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;
	}
	
	// shouldn't be here!
	return FALSE;

}
//
//==========================================================
//
// 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;
	}
}
//
//-----------------------------------------------------
//
// 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
//
//===============================================================================
//
// 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;
}