//
//---------------------------------------------------------------
//
// HandleConventionResponse()
//
// Check on Gerber response from the invoker, and act accordingly
//
//	 
BOOL CGerberConvention::HandleConventionResponse(const CPlayer& player, 
											        const CConventionSet& conventions, 
											        CHandHoldings& hand, 
											        CCardLocation& cardLocation, 
												    CGuessedHandHoldings** ppGuessedHands,
											        CBidEngine& bidState,  
											        CPlayerStatusDialog& status)
{
	int nGerberStatus = bidState.GetConventionStatus(this);
	int numAces = bidState.numAces;
	int numKings = bidState.numKings;
	double fMinTPPoints = bidState.m_fMinTPPoints;
	double fMaxTPPoints = bidState.m_fMaxTPPoints;
	double fMinTPCPoints = bidState.m_fMinTPCPoints;
	double fMaxTPCPoints = bidState.m_fMaxTPCPoints;
	int nAgreedSuit = bidState.m_nAgreedSuit;
	int nPartnersBid = bidState.nPartnersBid;
	int nBid;

	//
	// Did we ask partner for aces in our last bid?
	//
	if (nGerberStatus == CONV_INVOKED_ROUND1) 
	{
		// first check for a strange response
		if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
		{
			// we don't understand partner's bid
			return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status);
		}

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

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

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

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

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

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

	}


	//
	// Did we ask for kings?
	//
	if (nGerberStatus == CONV_INVOKED_ROUND2) 
	{
		// first check for a strange response
		if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
		{
			// we don't understand partner's bid
			return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status);
		}

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

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

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

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

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

	}

	//
	return FALSE;
}
//
//---------------------------------------------------------------
//
// RespondToConvention()
//
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 partner responds to a Michaels Cue Bid
//
BOOL CMichaelsCueBidConvention::HandleConventionResponse(const CPlayer& player, 
													     const CConventionSet& conventions, 
													     CHandHoldings& hand, 
														 CCardLocation& cardLocation, 
														 CGuessedHandHoldings** ppGuessedHands,
													     CBidEngine& bidState,  
													     CPlayerStatusDialog& status)
{
	// check status
	if ((bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND1) &&
		(bidState.GetConventionStatus(this) != CONV_INVOKED_ROUND2))
		return FALSE;

	//
	// get some info
	//
	int nBid;
	double fPts = bidState.fPts;
	double fAdjPts = bidState.fAdjPts;
	double fCardPts = bidState.fCardPts;
	int nPrefSuit = bidState.nPrefSuit;
	int nPrefSuitStrength = bidState.nPrefSuitStrength;
	int nPreviousSuit = bidState.nPreviousSuit;
	int nPreviousBidLevel = bidState.nPreviousBidLevel;
	BOOL bBalanced = bidState.bBalanced;
	//
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersSuitSupport = bidState.nPartnersSuitSupport;
	int nPartnersPrevSuit = bidState.nPartnersPrevSuit;
	int numSupportCards = bidState.numSupportCards;

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

	if (nStatus == CONV_INVOKED)
	{
		// first check for a strange response
		if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
		{
			// we don't understand partner's bid
			return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status);
		}

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

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

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

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

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

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

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

		// first check for a strange response
		if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
		{
			// we don't understand partner's bid
			return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status);
		}

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

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

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

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

	}
	else if (nStatus == CONV_INVOKED_ROUND3)
	{
		// first check for a strange response
		if ((nPartnersBid == BID_DOUBLE) || (nPartnersBid == BID_REDOUBLE))
		{
			// we don't understand partner's bid
			return CConvention::HandleConventionResponse(player, conventions, hand, cardLocation, ppGuessedHands, bidState, status);
		}

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

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

	// oops!
	bidState.SetConventionStatus(this, CONV_ERROR);
	return FALSE;
}