//
//-----------------------------------------------------
//
// handle an artificial 2C opening bid (23+ pts)
//
BOOL CArtificial2ClubConvention::RespondToConvention(const CPlayer& player, 
													 const CConventionSet& conventions, 
													 CHandHoldings& hand, 
													 CCardLocation& cardLocation, 
													 CGuessedHandHoldings** ppGuessedHands,
													 CBidEngine& bidState,  
													 CPlayerStatusDialog& status)
{
	// first see if another convention is active
	if (bidState.GetActiveConvention() &&
					(bidState.GetActiveConvention() != this))
		return FALSE;

	//
	// Bidding in response to an opening 2C bid? check requirements
	//
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersSuitSupport = bidState.nPartnersSuitSupport;
	int numSupportCards = bidState.numSupportCards;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int numPartnerBidsMade = bidState.m_numPartnerBidsMade;
	int nBid;

	// see if this is our second response to partner's opening 2C bid
	if (bidState.GetConventionStatus(this) == CONV_RESPONDED)
	{
		// see if we responded 2D last time
		if (bidState.nPreviousBid == BID_2D)
		{
			status << "R2CLR2! Partner showed his best suit of " & bidState.szPS & 
					  " in response to our negative 2D response.\n";
			
			// what to do here???
			// if partner shows a suit, adjust point count as dummy
			double fAdjPts = bidState.fAdjPts = (ISSUIT(bidState.nPartnersSuit))? hand.RevalueHand(REVALUE_DUMMY, bidState.nPartnersSuit, TRUE) : bidState.fPts;
			double fCardPts = bidState.fCardPts;
		
			// adjust partnership point count minimums & maximums
			bidState.m_fMinTPPoints = fAdjPts + bidState.m_fPartnersMin;
			bidState.m_fMaxTPPoints = fAdjPts + bidState.m_fPartnersMax;
			bidState.m_fMinTPCPoints = fCardPts + bidState.m_fPartnersMin;
			bidState.m_fMaxTPCPoints = fCardPts + bidState.m_fPartnersMax;

			//
			if (bidState.m_fMinTPPoints <= PTS_GAME-2)
			{
				nBid = BID_PASS;
				status << "R2CLR10! But with only " & bidState.m_fMinTPPoints & " points in the partnership, we have to pass.\n";
			}
			else
			{
				// either shift to our own suit, raise partner to game, or bid 3NT
				if ((nPartnersSuitSupport >= SS_MODERATE_SUPPORT) && (nPartnersBid < bidState.GetGameBid(nPartnersSuit)))
				{
					nBid = bidState.GetGameBid(nPartnersSuit);
					status << "R2CLR20! Raise partner's & " & bidState.szPS &
							  " to game at "& BTS(nBid) & ".\n";
				}
				else if (bidState.IsSuitOpenable(bidState.nPrefSuit) && (nPartnersBidLevel <= 3))
				{
					nBid = bidState.GetCheapestShiftBid(bidState.nPrefSuit);
					status << "R2CLR22! Bid our own " & bidState.szPrefSS &
							  " suit in preference to partner's " & bidState.szPSS &
							  " suit .\n";
				}
				else if (nPartnersBid < BID_3NT)
				{
					nBid = BID_3NT;
					status << "R2CLR25! With only " & bidState.SLTS(nPartnersSuit) &
							  " support for partner and no good suit of our own, bid 3NT.\n";
				}
				else
				{
					nBid = BID_PASS;
					status << "R2CLR30! With only " & bidState.SLTS(nPartnersSuit) &
							  " support for partner and no good suit of our own, we have to pass.\n";
				}
			}
			// 
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		}

		// mark this convention as completed
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return FALSE;
	}

	//
	//
	// partner must've bid 2 Club at his first opportunity,
	// and partner's bid must have been the first bid made
	//
	if ((nPartnersBid == BID_2C) && (bidState.m_bPartnerOpenedForTeam) &&
					(numPartnerBidsMade == 1) &&
					(nPartnersBid == pDOC->GetValidBidRecord(0)))
	{
		// condition valid
		// record that we responded
		bidState.SetConventionStatus(this, CONV_RESPONDED);
	}
	else
	{
		return FALSE;
	}

	// state expectations
	status << "R2CLUB! Partner made an artificial bid of 2 Clubs, showing either a game suit or " &
			  pCurrConvSet->GetValue(tn2ClubOpeningPoints) &
			  "+ points.  We want to respond positively if interested in a slam.\n";

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

	//
	double fPts = bidState.fPts;
	double fAdjPts = bidState.fAdjPts;
	double fCardPts = bidState.fCardPts;
	int nPrefSuit = bidState.nPrefSuit;
	int nPrefSuitStrength = bidState.nPrefSuitStrength;

	//
	bidState.AdjustPartnershipPoints(pCurrConvSet->GetValue(tn2ClubOpeningPoints), 40 - fCardPts);

	// respond negatively (2D) with < 33 points
	if (bidState.m_fMinTPPoints < PTS_SLAM) 
	{
		nBid = BID_2D;
		status << "R2C04! With only " & fCardPts & "/" & fPts &
				  " points, we deny interest in slam by making the negative response of " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}


	//
	// else with 33+ points, state slam hopes
	//
	status << "2R2C08! With a total of " & bidState.m_fMinTPPoints & 
			  "+ points in the partnership, we want to invite slam.\n";

	// show an openable suit
	if (nPrefSuitStrength >= SS_OPENABLE) 
	{
		if (ISMAJOR(nPrefSuit))
			nBid = MAKEBID(nPrefSuit,2);
		else
			nBid = MAKEBID(nPrefSuit,3);
		status << "R2C14! With  " & fCardPts & "/" & fPts & " points in hand, and a total of " &
				  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & 
				  " points in the partnership, we express possible interest in slam by showing our best suit (" &
				  bidState.szPrefS & ") with a bid of " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	// or a SOLID suit (jump shift)
	if (bidState.bPrefSuitIsSolid) 
	{
		if (ISMAJOR(nPrefSuit))
			nBid = MAKEBID(nPrefSuit,3);
		else
			nBid = MAKEBID(nPrefSuit,4);
		status << "R2C18! With " & fCardPts & "/" & fPts & " points in hand and a total of " &
				  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & 
				  " points in the partnership, we express interest in a slam by showing our solid " &
				  bidState.szPrefSS & " suit in a jump bid of " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	// else assume a balanced hand
	// with a balanced hand & >= 26 total HCPs, bid 3NT; 
	// with < 26 total HCPs, 2NT
	if (bidState.bBalanced) 
	{
		if (bidState.m_fMinTPCPoints >= PTS_NT_GAME)
			nBid = BID_3NT;
		else
			nBid = BID_2NT;
		status << "R2C22! With " & fCardPts & 
				  " HCPs and a balanced hand, and a total of " & 
				  bidState.m_fMinTPCPoints & 
				  "+ HCPs in the partnership, we respond with " & BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		return TRUE;
	}

	// else just bid the best suit
	nBid = bidState.GetCheapestShiftBid(nPrefSuit, BID_2C);
	status << "R2C26! With " & fCardPts & "/" & fPts & 
			  " points but with no strong suit and an unbalanced hand, we have to respond with our best suit of " & 
			  bidState.szPrefS & " by bidding " & BTS(nBid) & ".\n";
	bidState.SetBid(nBid);
	return TRUE;

} // end of 2C opening section
//
//-----------------------------------------------------
//
// respond to partner's 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 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;
}
//
//-----------------------------------------------------
//
// 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;
} 
//
//-----------------------------------------------------
//
// respond to partner's Michaels Cue Bid
//
BOOL CMichaelsCueBidConvention::RespondToConvention(const CPlayer& player, 
													const CConventionSet& conventions, 
													CHandHoldings& hand, 
													CCardLocation& cardLocation, 
												    CGuessedHandHoldings** ppGuessedHands,
													CBidEngine& bidState,  
													CPlayerStatusDialog& status)
{
	// first see if another convention is active
	if ((bidState.GetActiveConvention() != NULL) &&
					(bidState.GetActiveConvention() != this))
		return FALSE;

	//
	// make a responding bid
	//
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersPrevSuit = bidState.nPartnersPrevSuit;
	//
	int nBid, nSuit;
	double fPts = bidState.fPts;
	double fCardPts = bidState.fCardPts;

	// 
	// see what round this is
	//
	int nStatus = bidState.GetConventionStatus(this);
	if (nStatus == CONV_INACTIVE)
	{
		//
		// Bidding in response to partner's Michael's bid? check requirements
		//
		// the identifying marks of a Michaels bid are:
		// 1: we must not have bid yet
		// 2: LHO must have bid a suit at the 1 level, and 
		// 3: partner overcalled LHO's suit at the 2 level
		int nLastValidBid = pDOC->GetLastValidBid();

		// apply tests #1, 2, and 3
		int nOpeningBid = pDOC->GetOpeningBid();
		int nOpeningBidder = pDOC->GetOpeningBidder();
		BOOL bLHOMajor = ISMAJOR(nOpeningBid);
		if (ISBID(nOpeningBid) && (GetPlayerTeam(nOpeningBidder) != player.GetTeam()) &&
			 ((nOpeningBid >= BID_1C) && (nOpeningBid <= BID_1S)) &&
			  (nPartnersSuit == bidState.nLHOSuit) && (nPartnersBidLevel == 2) &&
			  (bidState.m_numBidsMade == 0) )
		{
			//
			status << "MCLR10! Partner has made a Michaels Cue bid of " & BTS(nPartnersBid) &
					  ", indicating 5/5 length in " &
					  (bLHOMajor? ((bidState.nLHOSuit == HEARTS)? "Spades and a minor" : "Hearts and a minor") : "the majors") & ".\n";
		}
		else
		{
			return FALSE;
		}

		// did partner bid a minor, indicating both majors?
		if (ISMINOR(nPartnersSuit))
		{
			// Pard has both majors -- pick the preferred one
			nSuit = bidState.PickSuperiorSuit(HEARTS, SPADES);
			if (hand.GetNumCardsInSuit(nSuit) < 3)
			{
				// should have at least 3 trumps
				int nOtherSuit = (nSuit == HEARTS)? SPADES : HEARTS;
				if (hand.GetNumCardsInSuit(nOtherSuit) >= 3)
					nSuit = nOtherSuit;
			}
		}
		else if (nPartnersSuit == HEARTS)
		{
			// pard has Spades + a minor
			// see if Spades are decent (3-card support)
//			if ((hand.GetNumCardsInSuit(SPADES) >= 3) && (hand.GetSuitStrength(SPADES) >= SS_MODERATE_SUPPORT))
			if (hand.GetNumCardsInSuit(SPADES) >= 3)
			{
				// fine, go with Spades
				nSuit = SPADES;
			}
			else 
			{
				// Spades are too weak; look for a minor
				if ((hand.GetSuitStrength(CLUBS) >= SS_MODERATE_SUPPORT) || (hand.GetSuitStrength(DIAMONDS) >= SS_MODERATE_SUPPORT))
					nSuit = NOTRUMP;
				else
					nSuit = SPADES;	// minors are no good either, so go with Spades
			}
		}
		else 
		{
			// pard has Hearts + a minor
			// see if Hearts are decent (3-card support)
//			if ((hand.GetNumCardsInSuit(HEARTS) >= 3) && (hand.GetSuitStrength(HEARTS) >= SS_MODERATE_SUPPORT))
			if (hand.GetNumCardsInSuit(HEARTS) >= 3)
			{
				// fine, go with Hearts
				nSuit = HEARTS;
			}
			else 
			{
				// Spades are too weak; look for a minor
				if ((hand.GetSuitStrength(CLUBS) >= SS_MODERATE_SUPPORT) || (hand.GetSuitStrength(DIAMONDS) >= SS_MODERATE_SUPPORT))
					nSuit = NOTRUMP;
				else
					nSuit = HEARTS;	// minors are no good either, so go with Hearts
			}
		}

		// now adjust point count
		if (ISSUIT(nSuit))
		{
			bidState.SetAgreedSuit(nSuit);
			fPts = bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, nSuit, TRUE);
		}
		// partner may have 6-11 OR 17+ pts; assume it's a weak hand
		bidState.AdjustPartnershipPoints(6, 11);

		// and make a responding bid
		CString strChoices = ISMINOR(nPartnersSuit)? "the two majors" : 
					(nPartnersSuit == HEARTS)? "Spades and a minor" : "Hearts and an unknown minor";
		int numTrumps = ISSUIT(nSuit)? hand.GetNumCardsInSuit(nSuit) : 0;

		// set initial convention status to finished
		bidState.SetConventionStatus(this, CONV_FINISHED);

		// see if we need to look at the minor
		if (nSuit == NOTRUMP)
		{
			// bid 2NT to ask for the minor
			nBid = BID_2NT;
			if (nBid > nLastValidBid)
			{
				if (nPartnersSuit == HEARTS)
					status << "MCLR12! Given a choice between a " & hand.GetNumCardsInSuit(SPADES) &
							  "-card Spade suit and an unknown minor, we're forced to ask for the minor by bidding " & BTS(nBid) & ".\n";
				else
					status << "MCLR12! Given a choice between a " & hand.GetNumCardsInSuit(HEARTS) &
							  "-card Heart suit and an unknown minor, we're forced to ask for the minor by bidding " & BTS(nBid) & ".\n";
				// this convention will go another round
				bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND1);
			}
			else
			{
				nBid = BID_PASS;
				status << "MCLR13! We'd like to bid 2NT to ask for partner's minor, but we can't do so after RHO's interference, so we have to pass.\n";
			}
		}
		else if ((numTrumps >= 5) && (bidState.m_fMinTPPoints <= PT_COUNT(20)) &&
			ISMAJOR(nSuit) && (MAKEBID(nSuit, 4) > nLastValidBid))
		{
			// make a preemptive bid if possible
			nBid = MAKEBID(nSuit, 4);
			status << "MCLR15! With " & numTrumps & " " & STS(nSuit) & " and a total of " & 
					  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
					  " pts in the partnership, make a shutout bid in " & STS(nSuit) & 
					  " by jumping to " & BTS(nBid) & ".\n";
		}
		else if (bidState.m_fMinTPPoints <= PT_COUNT(21))
		{
			// respond at the 2-level
			nBid = bidState.GetCheapestShiftBid(nSuit, nLastValidBid);
			if (BID_LEVEL(nBid) == 2)
			{
				status << "MCLR20! Given a choice between " & strChoices & 
						   ", respond to partner's Michaels with the preferred " & 
						   STSS(nSuit) & " suit with a bid of " & BTS(nBid) & ".\n";
			}
			else
			{
				nBid = BID_PASS;
				status << "MCLR21! After RHO interference, we don't have the points to go to the 3-level in response to partner's Michaels, so pass.\n";
			}
		}
		else if (bidState.m_fMinTPPoints <= PT_COUNT(24))
		{
			// bid at the 3-level
			nBid = MAKEBID(nSuit, 3);
			if (nBid > nLastValidBid)
			{
				status << "MCLR24! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						   " pts in the partnership and a choice between " & strChoices &
						   ", invite game in " & STS(nSuit) & " by jumping to " & BTS(nBid) & ".\n";
			}
			else
			{
				nBid = BID_PASS;
				status << "MCLR25! After RHO interference, we don't have the points to go to the 4-level in response to partner's Michaels, so pass.\n";
			}
		}
		else if (ISMINOR(nSuit) && (bidState.m_fMinTPPoints <= PT_COUNT(27)))
		{
			// with 25+ pts, bid game
			nBid = bidState.GetGameBid(nSuit);
			if (nBid > nLastValidBid)
			{
				status << "MCLR27! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						   " pts in the partnership and a choice between " & strChoices & 
						   ", jump to the 4-level in " & STS(nSuit) & " with a bid of " & BTS(nBid) & ".\n";
			}
			else
			{
				nBid = BID_PASS;
				status << "MCLR28! After RHO interference, we don't have the points to go to the 5-level in response to partner's Michaels, so pass.\n";
			}
		}
		else
		{
			// with 25+ pts in a major, or 28+ pts in a minor, bid game
			nBid = bidState.GetGameBid(nSuit);
			if (nBid > nLastValidBid)
			{
				status << "MCLR30! With a total of " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						   " pts in the partnership and a choice between " & strChoices & 
						   ", jump to game in " & STS(nSuit) & " at " & BTS(nBid) & ".\n";
			}
			else
			{
				nBid = BID_PASS;
				status << "MCLR31! After RHO interference, we don't want to bid past game, so pass.\n";
			}
		}

		// done!
		bidState.SetBid(nBid);
		return TRUE;

	}
	else if (nStatus == CONV_RESPONDED_ROUND1)
	{
		//
		// round 2 -- we must've bid 2NT last time to ask for partner's minor
		//

		// see if partner cue bid the enemy suit again
		if (nPartnersSuit == nPartnersPrevSuit)
		{
			// partner has 17+ pts
			bidState.AdjustPartnershipPoints(OPEN_PTS(17), MIN(17,40 - bidState.fCardPts));

			// bid 4NT to ask for the minor again
			if (fPts >= PT_COUNT(15))
			{
				// else make a natural game bid
				nBid = BID_4NT;
				status << "MCLR35! Partner cue bid the enemy suit again, indicating a strong Michaels opening hand with " &
						   OPEN_PTS(17) & "+ pts; so with " & 
						   bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						   " pts in the partnership, ask for the other minor by bidding " & BTS(nBid) & ".\n";
				bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND2);
			}
			else
			{
				// else make a natural 3NT game bid
				nBid = BID_3NT;
				status << "MCLR36! Partner cue bid the enemy suit again, indicating a strong Michaels opening hand with " &
						   OPEN_PTS(17) & "+ pts; but with " & 
						   bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						   " pts in the partnership, stop at game with a natural bid of " & BTS(nBid) & ".\n";
				bidState.SetConventionStatus(this, CONV_FINISHED);
			}
			// done
			bidState.SetBid(nBid);
			return TRUE;
		}

		// see if partner's bid is valid
		if (!ISMINOR(nPartnersSuit))
		{
			status << "MCLR40! After his opening Michaels Cue Bid, partner did not respond properly to our 2NT minor suit inquiry, so michaels is off.\n";
			bidState.SetConventionStatus(this, CONV_ERROR);
			return FALSE;
		}

		// see if we can live with partner's minor
		int nAgreedSuit;
		if (hand.GetNumCardsInSuit(nPartnersSuit) >= 3)
		{
			// stick with the minor
			status << "4MCLR41! Since we have " & hand.GetNumCardsInSuit(nPartnersSuit) & 
					  " cards in the " & STSS(nPartnersSuit) & " suit, choose that suit for our response.\n";
			nAgreedSuit = nPartnersSuit;
		}
		else
		{
			// minor's not so great; select the better of the minor or the major
			nAgreedSuit = bidState.PickSuperiorSuit(nPartnersSuit, bidState.nPartnersPrevSuit);
			if (nAgreedSuit == nPartnersSuit)
				status << "4MCLR42! The " & STSS(nPartnersSuit) & " suit isn't great, but it's better than " &
						   STS(bidState.nPartnersPrevSuit) & ", so choose that suit for our response.\n";
			else
				status << "4MCLR43! The " & STSS(nPartnersSuit) & " suit is poor, so pick the major suit ("& 
						   STS(bidState.nPartnersPrevSuit) & ") for our response.\n";
			bidState.SetAgreedSuit(bidState.PickSuperiorSuit(nPartnersSuit, bidState.nPartnersPrevSuit));
		}

		// recalc points as dummy
		bidState.SetAgreedSuit(nAgreedSuit);
		fPts = bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, nAgreedSuit, TRUE);
		bidState.AdjustPartnershipPoints();

		// select the bid level
		if (ISMINOR(nAgreedSuit))
		{
			// Clubs or Diamonds
			if (bidState.m_fMinTPPoints <= PTS_MINOR_GAME-6)	// <= 22
				nBid = BID_PASS;
			else if (bidState.m_fMinTPPoints <= PTS_MINOR_GAME-4)	// <= 24
				nBid = MAKEBID(nPartnersBid, 4);
			else 
				nBid = MAKEBID(nPartnersBid, 5);	// go for game
			//
			if (nBid == BID_PASS)
				status << "MCLR45! Partner showed his minor to be " & STS(nPartnersSuit) & 
						  ", which we can support with " & hand.GetNumCardsInSuit(nPartnersSuit) &
						  " trumps, but with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, we have to pass.\n";
			else
				status << "MCLR46! Partner showed his minor to be " & STS(nPartnersSuit) & 
						  ", which we can support with " & hand.GetNumCardsInSuit(nPartnersSuit) &
						  " trumps, so with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, we bid " & BTS(nBid) & ".\n";
		}
		else
		{
			// sticking with the major (though not a very good one!)
			// sign off at the 3-level or go to game
			if (bidState.m_fMinTPPoints < PTS_MAJOR_GAME)	// < 25
				nBid = MAKEBID(nPartnersBid, 3);
			else	
				nBid = MAKEBID(nPartnersBid, 4);
			//
			if (BID_LEVEL(nBid) == 3)
				status << "MCLR47! With " & hand.GetNumCardsInSuit(nAgreedSuit) & 
						  "-card support for partner's " & STS(nAgreedSuit) & 
						  ", and with only " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, we have to pass.\n";
			else
				status << "MCLR47! With " & hand.GetNumCardsInSuit(nAgreedSuit) & 
						  "-card support for partner's " & STS(nAgreedSuit) & 
						  ", and with " & bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " pts in the partnership, we can go to game at " & BTS(nBid) & ".\n";
		}

		// done!
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;
	}
	else if (nStatus == CONV_RESPONDED_ROUND2)
	{
		//
		// round 3 -- we must've bid 4NT last time to ask for partner's minor
		//            after partner's second Michaels cue bid
		//

	}


	//
	return FALSE;
}