//
// 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 open with a preemptive 3 or 4 bid
//
BOOL CShutoutBidsConvention::TryConvention(const CPlayer& player, 
										   const CConventionSet& conventions, 
										   CHandHoldings& hand, 
										   CCardLocation& cardLocation, 
										   CGuessedHandHoldings** ppGuessedHands,
										   CBidEngine& bidState,  
										   CPlayerStatusDialog& status)
{
	// basic requirements: no non-pass bid must have been entered yet
	if (bidState.nLastValidRecordedBid != BID_PASS)
		return FALSE;	// someone else has opened already

	//
	//--------------------------------------------------------
	//
	// Now check for a shutout bid of 3 or 4
	//
	// at the very minimum, should have a 6-card suit
	//
	if (hand.GetNumSuitsOfAtLeast(6) < 1)
		return FALSE;

	//
	// first find (a) long suit
	//
/*
	for(i=0;i<4;i++) 
	{
		if (hand.numCardsInSuit[i] >= 6) 
		{
			// a 7-card suit needs 2 honors, and a a 6-card suit needs 3
			if ( ((hand.GetNumCardsInSuit(i) >= 7) && (hand.GetNumhonorsInSuit(i) >= 2)) ||
			     ((hand.GetNumCardsInSuit(i) == 6) && (hand.GetNumhonorsInSuit(i) >= 3)) )
			break;
		}
	}
*/

	// assume the long suit is the preferred one
	int nSuit = hand.GetPreferredSuit();
	CSuitHoldings& suit = hand.GetSuit(nSuit);
	int numCards = suit.GetNumCards();
	int numHonors = suit.GetNumHonors();
	// a 6-card suit needs 3 honors, and a 7+ card suit needs 2
	if ( ((numCards == 6) && (numHonors < 3)) ||
					 ((numCards >= 7) && (numHonors < 2)) )
		 return FALSE;

	//
	// then check for Aces, Kings, or Queens in outside suits
	int nBid;
	BOOL bViolation = FALSE;
	for(int i=0;i<4;i++) 
	{
		if (i == nSuit)
			continue;
		// a solitary Q is okay for a Shutout bid, but any higher honors
		// are not
		CSuitHoldings& suit = hand.GetSuit(i);
		if (suit.HasAce() || suit.HasKing())
			return FALSE;
	}

	//
	if (bidState.numCardsInSuit[nSuit] >= 8) 
	{
		nBid = MAKEBID(nSuit,4);
		status << "D00! Have a " & bidState.numCardsInSuit[nSuit] & 
				  "-card " & STSS(nSuit) & 
				  " suit with no tricks outside the suit, so make a shutout bid of " & 
				  BTS(nBid) & ".\n";
	} 
	else if (bidState.numCardsInSuit[nSuit] >= 7) 
	{
		nBid = MAKEBID(nSuit,3);
		status << "D04! Have a " & bidState.numCardsInSuit[nSuit] & 
				  "-card " & STSS(nSuit) & 
				  " suit with no tricks outside the suit, so make a shutout bid of " & 
				  BTS(nBid) & ".\n";
	}
	bidState.SetBid(nBid);
	bidState.SetConventionStatus(this, CONV_INVOKED);
	return TRUE;
}
//
//===============================================================================
//
// TryConvention()
//
// check if we can use an Gambling 3NT Bid here
//
BOOL CGambling3NTConvention::TryConvention(const CPlayer& player,
        const CConventionSet& conventions,
        CHandHoldings& hand,
        CCardLocation& cardLocation,
        CGuessedHandHoldings** ppGuessedHands,
        CBidEngine& bidState,
        CPlayerStatusDialog& status)
{
    //
    // the requirements for opening a STANDARD Gambling 3NT Bid are:
    // 1: a solid 7+ card minor suit,
    // 2: 10-12 HCPs,
    // 3: no voids or small singletons, and
    // 4: no outside stoppers
    //
    // the requirements for opening an ACOL Gambling 3NT Bid are:
    // 1: a solid 7+ card minor suit,
    // 2: 16-21 HCPs,
    // 3: no voids or small singletons, and
    // 4: stoppers in at least 2 of the remaining 3 suits

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

    // see if we have any small singletons
    bool bSmallSingletons = false;
    if (bidState.numSingletons > 0)
    {
        for(int i=0; i<4; i++)
        {
            CSuitHoldings& suit = hand.GetSuit(i);
            if ((suit.GetNumCards() == 1) && (suit[0]->GetFaceValue() < TEN))
            {
                bSmallSingletons = true;
                break;
            }
        }
    }

    // see if we have a solid suit
    int nSuit = NONE;
    if (hand.GetSuit(CLUBS).IsSolid() && (bidState.numCardsInSuit[CLUBS] >= 7))
        nSuit = CLUBS;
    else if (hand.GetSuit(DIAMONDS).IsSolid() && (bidState.numCardsInSuit[DIAMONDS] >= 7))
        nSuit = DIAMONDS;

    // test for std and ACOL Gambling 3NT conditions
    int numValidBidsMade = pDOC->GetNumValidBidsMade();
    if ( bStandardGambling3NT && (numValidBidsMade  == 0) && (ISSUIT(nSuit)) &&
            (bidState.fCardPts >= OPEN_PTS(10)) && (bidState.fCardPts <= OPEN_PTS(12)) &&
            (bidState.numVoids == 0) && !bSmallSingletons &&
            (bidState.numSuitsStopped == 1) )
    {
        // passed the test for standard gambling 3NT
        status << "G3NT1! With a solid " & bidState.numCardsInSuit[nSuit] &
               "-card " & STSS(nSuit) & " suit, " & bidState.fCardPts &
               " HCPs, no voids, no small singletons, and no outside stoppers, "
               " go ahead and bid a Gambling 3NT.\n";
    }
    else if ( !bStandardGambling3NT && (numValidBidsMade == 0) && (ISSUIT(nSuit)) &&
              (bidState.fCardPts >= OPEN_PTS(16)) && (bidState.fCardPts <= OPEN_PTS(21)) &&
              (bidState.numVoids == 0) && !bSmallSingletons &&
              (bidState.numSuitsStopped >= 3) )
    {
        // passed the test for ACOL gambling 3NT
        status << "G3NT2! With a solid " & bidState.numCardsInSuit[nSuit] &
               "-card " & STSS(nSuit) & " suit, " & bidState.fCardPts &
               " HCPs, no voids, no small singletons, and stoppers in " &
               ((bidState.numSuitsStopped == 4)? "all four suits" : "two outside suits") &
               ", go ahead and bid an ACOL Gambling 3NT.\n";
    }
    else
    {
        return FALSE;
    }

    // OK, go ahead and bid 3NT
    bidState.SetBid(BID_3NT);
    bidState.SetConventionStatus(this, CONV_INVOKED);
    return TRUE;
}