//
// PickFinalDiscardSuit()
//
int CPlayEngine::PickFinalDiscardSuit(CHandHoldings& hand)
{
	// this routine is called by the declarer & defender engined when
	// they absolutely can't find a card to discard
	int nDiscardSuit = NONE;

	// this means generally tha twe have no suits with losers, 
	// or that the only one with losers in the current hand is the priority suit
	// so look through suits by preference for one that has losers
	for(int i=3;i>=0;i--)
	{
		int nSuit = hand.GetSuitsByPreference(i);
		CSuitHoldings& testSuit = hand.GetSuit(nSuit);
		// avoid letting go of winners!
		if ((testSuit.GetNumCards() > 0) && (testSuit.GetNumCards() > testSuit.GetNumWinners()))
		{
			nDiscardSuit = nSuit;
			break;
		}
	}			
	
	// if we failed above, we aboslutely have no losers anywhere 
	// so search for a suit that has winners but no outstanding cards
	// i.e., suits that we may not be able to cash
	if (!ISSUIT(nDiscardSuit))
	{
		for(i=3;i>=0;i--)
		{
			int nSuit = hand.GetSuitsByPreference(i);
			// see if we have cards in this suit, and no outstanding cards in the suit
			if ((hand.GetNumCardsInSuit(nSuit) > 0) && (GetNumOutstandingCards(nSuit) == 0))
			{
				nDiscardSuit = nSuit;
				break;
			}
				
		}
	}
	
	// finally, give up and get any old suit that has cards
	if (!ISSUIT(nDiscardSuit))
 	{
		for(i=3;i>=0;i--)
		{
			int nSuit = hand.GetSuitsByPreference(i);
			if (hand.GetNumCardsInSuit(nSuit) > 0)
			{
				nDiscardSuit = nSuit;
				break;
			}
		}
	}

	//
	ASSERT(ISSUIT(nDiscardSuit));
	return nDiscardSuit;

}
//
//===============================================================================
//
// TryConvention()
//
// check if we can 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;
}
//
//===============================================================================
//
// 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;
}
//
//-----------------------------------------------------
//
// 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;
} 
//
//-----------------------------------------------------
//
// 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;
}