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

}
//
//=========================================================
//
// 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;
}
Ejemplo n.º 4
0
//
//---------------------------------------------------------------
//
// 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;
	}
}
//
//==========================================================
//
// 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;
}
//
//===============================================================================
//
// 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;
}