Ejemplo n.º 1
0
//
// FlashButton()
//
// used to temporarily flash a button's border
//
void CBidDialogSmall::FlashButton(int nBid)
{
	//
	CWnd *pWnd1 = NULL, *pWnd2 = NULL;
	//
	if (ISBID(nBid))
	{
		int nLevel = BID_LEVEL(nBid);
		int nSuit = BID_SUIT(nBid);
		pWnd1 = GetDlgItem(IDC_BID_LEVEL_1 + nLevel - 1);
		pWnd2 = GetDlgItem(IDC_SUIT_CLUBS + nSuit);
	}
	else if (nBid == BID_PASS)
		pWnd1 = GetDlgItem(IDC_BID_PASS);
	else if (nBid == BID_DOUBLE)
		pWnd1 = GetDlgItem(IDC_BID_DOUBLE);
	else if (nBid == BID_REDOUBLE)
		pWnd1 = GetDlgItem(IDC_BID_REDOUBLE);
	//
	if (pWnd1 == NULL)
		return;

	//
	FlashWindow(pWnd1, pWnd2);
}
Ejemplo n.º 2
0
/**
 * @brief Set bid info for the play.
 * @param bid The contract.
 * @param bidDouble Double/redouble?
 * @param openLeader The open leader.
 */
void CPlayHistory::setBidInfo(Bids bid, Bids bidDouble, Seat openLeader)
{
    this->openLeader = openLeader;

    resetPlayHistory();

    this->bid = bid;
    trumpSuit = BID_SUIT(bid);
    level = BID_LEVEL(bid);
    this->bidDouble = bidDouble;

}
Ejemplo n.º 3
0
int CGameRecord::DetermineRoundWinner(const int nRound) const
{
	ASSERT((nRound >= 0) && (nRound < 13));
	// can't determine winner if < 4 cards played in round)
	if (m_numCardsPlayed < ((nRound+1) * 4))
		return -1;
	int nStart = nRound * 4;
	int nEnd = nStart + 4;
	int nTop = NONE;
	int nTopTrump = NONE;
	int nTopPos = NONE;
	BOOL bTrumpPlayed = FALSE;
	int nContractSuit = BID_SUIT(m_nContract);
	//
	int nPos = m_nRoundLead[nRound];
	int nCardLed = m_nGameTrick[nRound][nPos];
	int nSuitLed = CARDSUIT(nCardLed);
	//
	for(int i=nStart;i<nEnd;i++)
	{
		int nCard = m_nGameTrick[nRound][nPos];
		int nSuit = CARDSUIT(nCard);
		int nFaceVal = FACEVAL(nCard);
		//
		if (nSuit == nContractSuit)
		{
			// a trump card was played -- see if it's high
			if (nFaceVal > nTopTrump)
			{
				nTopTrump = nFaceVal;
				nTopPos = nPos;
				bTrumpPlayed = TRUE;
			}
		}
		else if (!bTrumpPlayed)
		{
			// else if no trump was played so far, check if this card is high
			if ((nSuit == nSuitLed) && (nFaceVal > nTop))
			{
				nTop = nFaceVal;
				nTopPos = nPos;
			}
		}
		//
		nPos = ::GetNextPlayer(nPos);
	}

	//
	ASSERT(nTopPos != NONE);
	return nTopPos;
}
Ejemplo n.º 4
0
//
// PressBidButton()
//
// used to make a button it appear pressed
//
void CBidDialogSmall::PressBidButton(int nBid)
{
	//
	CButton *pButton1 = NULL, *pButton2 = NULL;
	//
	if (ISBID(nBid))
	{
		int nLevel = BID_LEVEL(nBid);
		int nSuit = BID_SUIT(nBid);
		pButton1 = (CButton*) GetDlgItem(IDC_BID_LEVEL_1 + nLevel - 1);
		pButton2 = (CButton*) GetDlgItem(IDC_SUIT_CLUBS + nSuit);
	}
	else if (nBid == BID_PASS)
		pButton1 = (CButton*) GetDlgItem(IDC_BID_PASS);
	else if (nBid == BID_DOUBLE)
		pButton1 = (CButton*) GetDlgItem(IDC_BID_DOUBLE);
	else if (nBid == BID_REDOUBLE)
		pButton1 = (CButton*) GetDlgItem(IDC_BID_REDOUBLE);
	//
	if (pButton1 == NULL)
		return;

	//
	BOOL bWindow2Enabled = pButton2? pButton2->IsWindowEnabled() : FALSE;
	//
	pButton1->SetState(TRUE);
	if (pButton2)
	{
		pButton2->EnableWindow(TRUE);
		pButton2->SetState(TRUE);
	}
	//
	Sleep(300);
	//
	pButton1->SetState(FALSE);
	if (pButton2)
	{
		pButton2->SetState(FALSE);
		pButton2->EnableWindow(bWindow2Enabled);
	}

	// done
	return;
}
//
//===============================================================================
//
// TryConvention()
//
// check if we can use an Jacoby 2NT Bid here
//
BOOL CJacoby2NTConvention::TryConvention(const CPlayer& player, 
										 const CConventionSet& conventions, 
										 CHandHoldings& hand, 
										 CCardLocation& cardLocation, 
										 CGuessedHandHoldings** ppGuessedHands,
										 CBidEngine& bidState,  
										 CPlayerStatusDialog& status)
{
	//
	// the requirements for an Jacoby 2NT Bid are:
	// 1: Partner must have opened with 1 of a major
	// 2: we must not have bid yet
	// 3: we have 13+ points and 4+ card trump support

	int nOpeningBid = pDOC->GetOpeningBid();
	int nPartnersBid = bidState.nPartnersBid;

	// test conditions 1 - 4
	if ( ISBID(nOpeningBid) && (nOpeningBid == nPartnersBid) && 
		 (ISMAJOR(BID_SUIT(bidState.nPartnersBid))) && (bidState.nPartnersBidLevel == 1) &&
		 (bidState.m_numBidTurns == 0) && (bidState.fPts >= OPEN_PTS(13)) &&
		 (bidState.numSupportCards >= 4) )
	{
		 // passed the test
	}
	else
	{
		return FALSE;
	}
	
	// calc adjusted pts
	int nSuit = bidState.nPartnersSuit;
	bidState.SetAgreedSuit(nSuit);
	bidState.fAdjPts = hand.RevalueHand(REVALUE_DUMMY, nSuit, TRUE);

	//
	status << "J2N1! Partner opened " & BTS(nPartnersBid) & ", and with " &
			  bidState.fAdjPts & " pts in hand and " & bidState.numSupportCards & 
			  "-card trump support, we can bid Jacoby 2NT to ask for partner's strength.\n";
	bidState.SetBid(BID_2NT);
	bidState.SetConventionStatus(this, CONV_INVOKED);
	return TRUE;
}
Ejemplo n.º 6
0
//
// SetGameIndex()
//
void CGameReviewDialog::SetGameIndex(int nGame, BOOL bRefresh)
{
	if ((nGame < 0) || (nGame >= m_numGamesAvailable))
		return;

	// init
	m_nGameIndex = nGame;
	m_nBidIndex = 0;
	m_nPlayIndex = 0;
	m_nPlayRound = 0;

	// fill tags list
	// first clear existing items
	m_listTags.DeleteAllItems();
	// then add entries
	CGameRecord* pGameRecord = pDOC->GetGameRecord(m_nGameIndex);
	if (!pGameRecord)
		return;

	// fill the tags list
	int nIndex = 0;
	int nMaxWidth = 0;
	const int tnColSpacer = 14;
	CString strTag, strValue;
	std::map<CString,CString>::const_iterator iter;
	for(iter=pGameRecord->m_mapTagValues.begin();iter!=pGameRecord->m_mapTagValues.end();iter++)
	{
		// get the next tag & value
		strTag = (*iter).first;
		strValue = (*iter).second;

		// skip certain tags
		if ((strTag.CompareNoCase("Auction") == 0) ||
						(strTag.CompareNoCase("Play") == 0))
			continue;

		// set tag column
		m_listTags.InsertItem(nIndex, strTag);

		// set value column
		m_listTags.SetItem(nIndex, 1, LVIF_TEXT, strValue, 0, 0, 0, 0L);
		int nWidth = m_listTags.GetStringWidth(strValue) + tnColSpacer;
		if (nWidth > nMaxWidth)
			nMaxWidth = nWidth;
		nIndex++;
	}

	// set value column width 
	m_listTags.SetColumnWidth(1, nMaxWidth);

	//
	m_nGameIndex = nGame;
	m_nPlayerPosition = pGameRecord->m_nRoundLead[0];
	UpdateData(FALSE);

	// now update the display
	iter = pGameRecord->m_mapTagValues.find(_T("DEAL"));
	if (iter != pGameRecord->m_mapTagValues.end())
		strValue = (*iter).second;
	pDOC->LoadGameRecord(*pGameRecord);
	if (bRefresh)
		pDOC->ResetDisplay();
	pDOC->UpdateBiddingHistory();
	pDOC->UpdatePlayHistory();
	pMAINFRAME->SetAllIndicators();

	// NCR-759 Check if this hand has data to show
	if(pDOC->GetDeclarerPosition() == NONE) {
		return;   // No plays to make
	}  // end NCR-759

	// set prompt
	pMAINFRAME->SetMessageText(FormString("Contract is %s.  Declarer is %s; %s leads.",
										   pDOC->GetFullContractString(),
										   PositionToString(pDOC->GetDeclarerPosition()),
										   PositionToString(pDOC->GetRoundLead())));
	// set game info
	m_numPlaysAvailable = pGameRecord->m_numCardsPlayed;
	if (m_numPlaysAvailable > 0)
		m_numTricksAvailable = ((m_numPlaysAvailable-1) / 4) + 1;
	else
		m_numTricksAvailable = 0;

	// reset suit sequence
	theApp.InitDummySuitSequence(BID_SUIT(pGameRecord->m_nContract), GetPartner(pGameRecord->m_nDeclarer));

	// enable/disable play controls
	GetDlgItem(IDC_PREV)->EnableWindow(FALSE);
	GetDlgItem(IDC_FIRST)->EnableWindow(FALSE);
	if (m_numPlaysAvailable <= 1)
	{
		GetDlgItem(IDC_NEXT)->EnableWindow(FALSE);
		GetDlgItem(IDC_LAST)->EnableWindow(FALSE);
	}
	else
	{
		GetDlgItem(IDC_NEXT)->EnableWindow(TRUE);
		GetDlgItem(IDC_LAST)->EnableWindow(TRUE);
	}

	// and enable/disable game nav controls
	if (m_nGameIndex == 0)
	{
		GetDlgItem(IDC_PREV_GAME)->EnableWindow(FALSE);
		GetDlgItem(IDC_FIRST_GAME)->EnableWindow(FALSE);
	}
	else
	{
		GetDlgItem(IDC_PREV_GAME)->EnableWindow(TRUE);
		GetDlgItem(IDC_FIRST_GAME)->EnableWindow(TRUE);
	}
	//
	if (m_nGameIndex >= m_numGamesAvailable-1)
	{
		GetDlgItem(IDC_NEXT_GAME)->EnableWindow(FALSE);
		GetDlgItem(IDC_LAST_GAME)->EnableWindow(FALSE);
	}
	else
	{
		GetDlgItem(IDC_NEXT_GAME)->EnableWindow(TRUE);
		GetDlgItem(IDC_LAST_GAME)->EnableWindow(TRUE);
	}
}
Ejemplo n.º 7
0
//
//---------------------------------------------------------------
//
// TryCueBid()
//
BOOL CCueBidConvention::TryCueBid(CHandHoldings& hand, CBidEngine& bidState,  CPlayerStatusDialog& status)
{
	// check basic requirements
	if (bidState.m_nAgreedSuit == NONE)
		return FALSE;

	// don't make a cue bid if we're already done with it 
	int nStatus = bidState.GetConventionStatus(this);
	if (nStatus != CONV_INACTIVE)
		return FALSE;

	// get adjusted point count as declarer
	// NCR BIG PROBLEM HERE - This changes a global variable. The changes are now always wanted ???
	bidState.fAdjPts = hand.RevalueHand(REVALUE_DECLARER, bidState.m_nAgreedSuit, TRUE);
	bidState.m_fMinTPPoints = bidState.fAdjPts + bidState.m_fPartnersMin;
	bidState.m_fMaxTPPoints = bidState.fAdjPts + bidState.m_fPartnersMax;
	bidState.m_fMinTPCPoints = bidState.fCardPts + bidState.m_fPartnersMin;
	bidState.m_fMaxTPCPoints = bidState.fCardPts + bidState.m_fPartnersMax;

	//
	// try a cue bid only if we have an interest in slam 
	// 
	if (bidState.m_fMinTPPoints < 30)
		return FALSE;

	// also, we shouldn't use cue bid if we have all four aces
	if (bidState.numAces == 4)
		return FALSE;

	// or if we're already at a slam level
	if (bidState.nPartnersBidLevel >= 6)
		return FALSE;
	int nLastBid = pDOC->GetLastValidBid();
	if (nLastBid >= bidState.GetGameBid(BID_SUIT(nLastBid)))
		return FALSE;

	// special test -- dont' cue bid if partner just raised a suit that we
	// shifted to artificially
	if ((bidState.nPartnersSuit == bidState.nPreviousSuit) && 
				( (ISSUIT(bidState.m_nAgreedSuit) && (bidState.nPreviousSuit != bidState.m_nAgreedSuit)) ||
				  (ISSUIT(bidState.m_nIntendedSuit) && (bidState.nPreviousSuit != bidState.m_nIntendedSuit)) ) )
		return FALSE;


	//
	// see what stage we're at
	//
	if (nStatus == CONV_INACTIVE)
	{
		//
		// showing first round controls 
		//
//		bidState.SetConventionStatus(this, CONV_INVOKED_ROUND1);
		// find cheapest ace
		int nBid;
		int nAgreedSuit = bidState.m_nAgreedSuit;
		int nSuit = GetCheapestAce(hand, nAgreedSuit);

		// 
		if ((nSuit != bidState.m_nAgreedSuit) && (nSuit != bidState.nPartnersSuit))
		{
			// found a suit to cue bid
			// the bid must be at a level that commits the partnership to game
			// i.e., for a major, it must be > 3 of the suit; for a minor, > 4
			nBid = bidState.GetCheapestShiftBid(nSuit);
			int nBidLevel = BID_LEVEL(nBid);
			// see if the bid is too high to qualify as a cue bid
		    if ( (ISMAJOR(nAgreedSuit) && (nBidLevel >= 5)) ||
			     (ISMINOR(nAgreedSuit) && (nBidLevel >= 6)) )
				return FALSE;
			// else if it's too low, adjust it upwards
		    if ( (ISMAJOR(nAgreedSuit) && (nBid < MAKEBID(nAgreedSuit,3))) ||
			     (ISMINOR(nAgreedSuit) && (nBid < MAKEBID(nAgreedSuit,4))) )
				nBid += 5;
			// alternatively, see if the bid is too high
			if (nBid > bidState.GetGameBid(nAgreedSuit))
				return FALSE;
			status << "CUET10! With " & bidState.m_fMinTPPoints & 
					  "+ pts and possible slam aspirations, make a cue bid, showing the cheapest ace (" & 
					  STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_INVOKED_ROUND1);
			return TRUE;
		}
		else
		{
			// either we don't have any aces, or the ace is in the trump suit
			// either way, we can't make a cue bid with this holding
			return FALSE;
		}
	}
	else if (nStatus == CONV_INVOKED_ROUND1)
	{
		//
		// showing second round controls, necesary if we want to proceed to a grand slam
		//
		bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
		// find cheapest king or void suit
		int nSuit = GetCheapestKingOrVoid(hand, bidState.m_nAgreedSuit);
		int nPartnersBid = bidState.nPartnersBid;
		// 
		if (nSuit != bidState.m_nAgreedSuit) 
		{
			// found a suit to cue bid
			int nBid = bidState.GetCheapestShiftBid(nSuit);
			status << "CUET20! Make a second-round cue bid, showing the cheapest " &
					  ((hand.GetSuitLength(nSuit) == 0)? "void suit" : "king") &
					  " (in " & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
			return TRUE;
		}
		else
		{
			// either we don't have any second-round control to show,
			// so stop cue bidding and return to the trump suit
			int nBid = bidState.GetCheapestShiftBid(bidState.m_nAgreedSuit);
			status << "CUET24! With no second-round controls to cue bid, we have to return to the trump suit at a bid of " &
					  BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
			return TRUE;
		}
	}
	else if (nStatus == CONV_INVOKED_ROUND2)
	{
		// both we and partner have shown first and second-round controls, so
		// it;s time to put up or shut up
	}
	else
	{	
		// error!
		AfxMessageBox("Error while attempting cue bid!");
		bidState.SetConventionStatus(this, CONV_ERROR);
	}
	//
	return TRUE;
}
Ejemplo n.º 8
0
//
//---------------------------------------------------------------
//
// RespondToConvention()
//
BOOL CCueBidConvention::RespondToConvention(const CPlayer& player, 
											const CConventionSet& conventions, 
											CHandHoldings& hand, 
											CCardLocation& cardLocation, 
											CGuessedHandHoldings** ppGuessedHands,
											CBidEngine& bidState,  
											CPlayerStatusDialog& status)
{
	// first see if another convention is active
	if (bidState.GetActiveConvention() &&
							(bidState.GetActiveConvention() != this))
		return FALSE;

	// basic test -- see if we had agreed on a suit last time
	if (bidState.m_nAgreedSuit == NONE)
		return FALSE;

	// get status
	int nStatus = bidState.GetConventionStatus(this);

	//
	int nPartnersBid = bidState.nPartnersBid;
	int nPartnersBidLevel = bidState.nPartnersBidLevel;
	int nPartnersSuit = bidState.nPartnersSuit;
	int nPartnersPrevSuit = bidState.nPartnersPrevSuit;
	int nAgreedSuit = bidState.m_nAgreedSuit;
	int nSupportLevel = bidState.nPartnersSuitSupport;
	int nBid;

	// see if partner made a cue bid
	// it needs to be a bid that commits the partnership to game, 
	// after a suit has been agreed upon
	if ((nAgreedSuit != NONE) && (nPartnersSuit != NOTRUMP) && (nPartnersSuit != nAgreedSuit) &&
		((nPartnersBid > MAKEBID(nAgreedSuit,3)) && (nPartnersBid < bidState.GetGameBid(nAgreedSuit))))
	{
		//NCR what if suit was previously bid by this player???
		// EG: N->1H, S->2C, N->3C, S->3H  3H is NOT a cue bid, it's a response to this player's  previous bid
		// NCR how to test if partner's current bid was in suit previously bid ???
		// NCR what about a game bid???
		int nSuit =  BID_SUIT(nPartnersBid);
		for(int i=0; i < player.GetNumBidsMade(); i++) { // NCR had to add const to this function def
			int nSuitBid = pDOC->GetBidByPlayer(player.GetPosition(), i);
			if(BID_SUIT(nSuitBid) == nSuit)
				return FALSE;  // NCR not cue if partner bid before ???
		}
                                            // NCR-295 game bid in agreed suit???
		if(bidState.IsGameBid(nPartnersBid) && (nSuit == nAgreedSuit) ) // || CheckIfSuitBid(player, BID_SUIT(nPartnersBid))) 
		{
			return FALSE;  //NCR don't treat Game bid as cue bid
		}
		// met the requirements
		status << "CUR0! Partner made a cue bid of " & BTS(nPartnersBid) &
				  ", hinting at slam prospects.\n";
	}
	else
	{
		// this is not a cue bid
		return FALSE;
	}

	//
	// respond to a cue bid only if we have an interest in slam 
	// 
	// only qualify if we have 30+ team points, _OR_
	// strong trump support and 28+ poitns
	//
	if (bidState.m_fMinTPPoints >= 30)
	{
		// 30+ team points
		status << "2CUR1! And since we have " & 
				  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
				  "+ points in the partnership, we want to respond favorably.\n";
	}
	else if ((nSupportLevel >= SS_GOOD_SUPPORT) && 
								(bidState.m_fMinTPPoints >= 28))
	{
		// good support (4 good or 5 moderate cards)
		status << "2CUR2! And since we have " & bidState.SLTS(nPartnersSuit) &
				   " trump support, " & 
				   ((bidState.m_fMinTPPoints >= 30)? " as well as " : " albeit only with ") &
				   bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
				   " points in the partnership, we want to respond favorably.\n";
	}
	else
	{
		// insufficient strength for slam -- correct back to the agreed suit
		nBid = bidState.GetCheapestShiftBid(nAgreedSuit);
		status << "CUR4! But we don't have the points (only " & 
				  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
				  " pts in the partnership) or the excellent trump support needed for a marginal slam, so we decline by returning to the agreed suit at a bid of " &
				  BTS(nBid) & ".\n";
		bidState.SetBid(nBid);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;
	}

	//
	// else we're playing along -- find the cheapest response
	//
	if (nStatus == CONV_INACTIVE)
	{
		// first invocation -- find the cheapest Ace
		int nSuit = GetCheapestAce(hand, nPartnersSuit, bidState.m_nAgreedSuit);
		// found a suit with an ace?
		if ((nSuit != nPartnersSuit) && (nSuit != nAgreedSuit)) 
		{
			// found a suit to cue bid
			nBid = bidState.GetCheapestShiftBid(nSuit);
			status << "CUR20! Respond to partner's cue bid, showing our cheapest ace (" &
					  STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND1);
			return TRUE;
		} 
		else 
		{
			// found no ace, or else it's in the trump suit, so either way
			// just sign off at the agreed suit
			nBid = bidState.GetCheapestShiftBid(nAgreedSuit);
			if (hand.SuitHasCard(nSuit, ACE))
				status << "CUR22! But our only Ace is in the trump suit of " &
						  STSS(nAgreedSuit) & ", so sign off at a bid of " & BTS(nBid) & ".\n";
			else
				status << "CUR24! We have no other Aces to offer, so sign off with the agreed " &
						  STSS(nAgreedSuit) & " suit at a bid of " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		}
	}
	else if (nStatus == CONV_RESPONDED_ROUND1)
	{
		// second invocation -- find cheapest King or void
		// first invocation -- find teh cheapest Ace
		int nSuit = GetCheapestKingOrVoid(hand, nPartnersSuit, bidState.m_nAgreedSuit);
		// found an appropriate suit?
		if ((nSuit != nPartnersSuit) && (nSuit != nAgreedSuit)) 
		{
			// found a suit to cue bid
			nBid = bidState.GetCheapestShiftBid(nSuit);
			status << "CUR30! Respond to partner's cue bid, showing our cheapest " &
					  ((hand.GetSuitLength(nSuit) > 0)? "King" : "void suit") &
					  " (in " & STS(nSuit) & ") with a bid of " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
//			bidState.SetConventionStatus(this, CONV_RESPONDED_ROUND2);
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		} 
		else 
		{
			// found no king or void, or else found a king in the trump suit, 
			// so either way, just sign off at the agreed suit
			nBid = bidState.GetCheapestShiftBid(nAgreedSuit);
			if (hand.SuitHasCard(nSuit, KING))
				status << "CUR32! But our only Ace is in the trump suit of " &
						  STSS(nAgreedSuit) & ", so sign off at a bid of " & BTS(nBid) & ".\n";
			else
				status << "CUR34 We have no other Kings or void suits to offer, so sign off with the agreed " &
						  STSS(nAgreedSuit) & " suit at a bid of " & BTS(nBid) & ".\n";
			bidState.SetBid(nBid);
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		}
	}
	else
	{
		// error!
		bidState.SetConventionStatus(this, CONV_ERROR);
		return FALSE;
	}
}
Ejemplo n.º 9
0
//
//---------------------------------------------------------------
//
// MakeOpeningBid()
//
// make initial bid
//
int CBidEngine::MakeOpeningBid()
{
	CPlayerStatusDialog& status = *m_pStatusDlg;

	//
	status << "2Opening bid for team.\n";



	//
	//--------------------------------------------------------
	//
	// First check to see if we can open using a convention
	// e.g., weak 2, stong 2, preemptive 3/4, etc.
	//
	if (pCurrConvSet->ApplyConventionTests(*m_pPlayer, *m_pHand, *m_pCardLocation, m_ppGuessedHands, *this, *m_pStatusDlg))
	{
		return ValidateBid(m_nBid);
	}




	//
	//--------------------------------------------------------
	//
	// see if we can open No Trumps
	//

	int	NTMin[3], NTMax[3];
	//
	NTMin[0] = pCurrConvSet->GetValue(tn1NTRangeMinPts);
	NTMax[0] = pCurrConvSet->GetValue(tn1NTRangeMaxPts);
	NTMin[1] = pCurrConvSet->GetValue(tn2NTRangeMinPts);
	NTMax[1] = pCurrConvSet->GetValue(tn2NTRangeMaxPts);
	NTMin[2] = pCurrConvSet->GetValue(tn3NTRangeMinPts);
	NTMax[2] = pCurrConvSet->GetValue(tn3NTRangeMaxPts);

	//
	if ((bBalanced) && (fCardPts >= OPEN_PTS(NTMin[0]))) 
	{
		//
		status << "A00! Have " & fCardPts & " HCP's with a balanced hand.\n";

		// but if we have a good 5-card major, open it in a suit
		// but not if we have to overcall to do so
		BOOL bNeedToOvercall = FALSE;
		if ( ((nLHOBid > BID_PASS) || (nRHOBid > BID_PASS)) && (nPartnersBid <= BID_PASS))
			bNeedToOvercall = TRUE;
		//
		if (IsSuitOpenable(HEARTS) && !bNeedToOvercall)
		{
			status << "A02! But with an openable " & numCardsInSuit[HEARTS] &
					  "-card Heart suit, prefer to open in the major instead of in No Trump.\n";
			goto escape1;
		}
		if (IsSuitOpenable(SPADES) && !bNeedToOvercall) 
		{
			status << "A04! But with an openable " & numCardsInSuit[SPADES] &
					  "-card Spade suit, prefer to open in the major instead of in No Trump.\n";
			goto escape1;
		}

		// check range for 1NT
		// NCR-285 Need stopper if opponents have bid!!!
		BOOL bHaveOppsStopped = TRUE;
		if ((nRHOBid != BID_PASS) && ISSUIT(nRHOSuit))
			bHaveOppsStopped = m_pHand->IsSuitStopped(nRHOSuit);  // NCR-285 consider if their suit is stopped
		else if ((nLHOBid != BID_PASS) && ISSUIT(nLHOSuit))
			bHaveOppsStopped = m_pHand->IsSuitStopped(nLHOSuit);  // NCR-285 ditto

		if ((fCardPts >= OPEN_PTS(NTMin[0])) && (fCardPts <= NTMax[0]) && bHaveOppsStopped) // NCR-285 added test
		{
			// NCR-18 Check if RHO bid NT and double 
			if(nRHOBid == BID_1NT){
				m_nBid = BID_DOUBLE;	// NCR-337 Problem here. This is not a Takeout double???
				status << "A07! This meet the rqmts for the 1NT opening range (" & NTMin[0] & "-" & NTMax[0] 
						& "), but RHO has bid 1NT, so Double.\n";
			}else {
				// open 1NT
				m_nBid = BID_1NT;
				status << "A08! This meet the rqmts for the 1NT opening range (" & NTMin[0] & "-" & NTMax[0] & "), so bid 1NT.\n";
			}
			return ValidateBid(m_nBid);
			
		} 
		else if ((fCardPts > OPEN_PTS(NTMax[0])) && (fCardPts < NTMin[1])) 
		{
			// in-between 1 & 2 situation; bid interim suit
			m_nNextIntendedBid = NIB_JUMP_NT;
			if (numOpenableSuits > 0) 
			{
				// bid 1 of lowest openable suit
				m_nBid = GetLowestOpenableBid(SUITS_ANY,OT_OPENER,1);
				// NCR-335 Don't bid 4 card major with 5CardMajor convention
				if (ISMAJOR(BID_SUIT(m_nBid)) && pCurrConvSet->IsConventionEnabled(tid5CardMajors)
					&& (numCardsInSuit[BID_SUIT(m_nBid)] < 5) ) 
				{
					// Use Diamonds if 4, else clubs (have balanced hand here)
					Suit bidThis = numCardsInSuit[DIAMONDS] >= 4 ? DIAMONDS : CLUBS;
					m_nBid = MAKEBID(bidThis, 1);  // NCR-335 use minor
                }
				status << "A10! This exceeds the max pts for a 1NT opening (" & NTMax[0] & 
								 "), but is less than min pts for 2NT (" & NTMin[1] & 
								 ").  So bid the lowest openable suit of " & BTS(m_nBid) & 
								 " for now, then try for a jump shift to 2NT later.\n";
			} 
			else 
			{
				// go ahead and bid the preferred suit
				if (!pCurrConvSet->IsConventionEnabled(tid5CardMajors) )
				{
					m_nBid = MAKEBID(nPrefSuit,1);
				} 
				else 
				{
					m_nBid = BID_1C;
				}
				status << "A14! This exceeds the max pts for a 1NT opening (" & NTMax[0] &
					      "), but is less than min pts for 2NT (" & NTMin[1] &
						  " and we have no good openable suit, so just bid " & BTS(m_nBid) &
						  " for now.\n";
			}
			return ValidateBid(m_nBid);

		} 
		// NCR can't use 2NT if using unusual NT convention
		else if ((fCardPts >= OPEN_PTS(NTMin[1])) && (fCardPts <= NTMax[1]) 
//			     && !pCurrConvSet->IsConventionEnabled(tidUnusualNT)  // NCR not relevant for Opening???
				 // NCR test that hand does NOT have a worthless doubleton
				 && ((m_pHand->GetNumDoubletons() == 0)  // OK if no doubletons
				     || (m_pHand->GetNumDoubletons() >= 1) 
				         && !m_pHand->HasWorthlessDoubleton()) //or if its not worthless
				) 
		{
			// open 2NT
			m_nBid = BID_2NT;
			status << "A20! This meets the rqmts for a 2NT opening (" & 
					  NTMin[1] & "-" & NTMax[1] & "), so bid 2NT.\n";
			return ValidateBid(m_nBid);

		} 
		else if ((fCardPts >= OPEN_PTS(NTMax[1])) && (NTMin[2] < 0))  // NCR ??? see next else if
		{

			// > pts for 2NT, but 3NT opening not allowed  NCR what does not allowed mean???
			// so bid 2C
			m_nBid = BID_2C;
			status << "A30! This exceeds the max pts for a 2NT opening (" & NTMax[1] & 
					   "), but a 3NT opening has been disallowed, so open with " & BTS(m_nBid) & ".\n";
			return ValidateBid(m_nBid);

		} 
		else if ((fCardPts > OPEN_PTS(NTMax[1])) && (fCardPts < NTMin[2])) 
		{

			// in-between 2 & 3 situation; bid 2 of interim suit
			// and bid NT later
			m_nNextIntendedBid = NIB_NT;
			if (numOpenableSuits > 0) 
			{
				// bid 1 of lowest openable suit
				m_nBid = GetLowestOpenableBid(SUITS_ANY,OT_OPENER,1);
				status << "A40! This exceeds the max pts for a 2NT opening (" &
						  NTMax[1] & "), but is less than min pts for 3NT (" &
						  NTMin[2] & ").  So bid the lowest openable suit of " &
						  BTS(m_nBid) & " for now, then jump shift to NT later.\n";
			} 
			else 
			{
				// no good openable suits; just bid preferred suit
				m_nBid = MAKEBID(nPrefSuit,1);;
				status << "A42! This exceeds the max pts for a 2NT opening (" &
						  NTMax[1] & "), but is less than min pts for 3NT (" &
						  NTMin[2] & "), and have no good openable suit, so bid " &
						  BTS(m_nBid) & " for now.\n";
			}
			return ValidateBid(m_nBid);

		} 
		else if ((fCardPts >= OPEN_PTS(NTMin[2])) && (fCardPts <= NTMax[2])
				 // NCR test that hand does NOT have a worthless doubleton
				 && ((m_pHand->GetNumDoubletons() == 0)  // OK if no doubletons
				     || (m_pHand->GetNumDoubletons() >= 1) 
				         && !m_pHand->HasWorthlessDoubleton()) //or if its not worthless

			     ) 
		{
			// open 3NT
			m_nBid = BID_3NT;
			status << "A50! Bid 3NT.\n";
			return ValidateBid(m_nBid);
		} 
/*  NCR remove falling into a 3NT bid
		else // if(!pCurrConvSet->IsConventionEnabled(tidUnusualNT)) // NCR added Unusual test??? 
		{
			// > 3NT point range? unusual, but open 3NT for now
			m_nBid = BID_3NT;
			status << "A60! bid 3NT with balanced hand and " & fCardPts & " points.\n"; // NCR
			return ValidateBid(m_nBid);
		}
*/
	}  // end balanced hand with > min pts

escape1:


		



	//
	//-------------------------------------------------------------------
	//
	// See if we can open at the 1-level
	//
	// open at the 1-level if we have:
	//  1:  14+ points in high cards
	//  2:  13+ HCPs with 2 Quick Tricks
	//  3:  12+ HCPs with 2 QTs and a rebiddable suit
	//  4:  12+ HCPs with 2 QTs and a 5-card suit
	//  5:  12+ HCPs with balanced dist (weak NT mode only)
	//  6:  10+ HCPs opening in 3rd or 4th seat and a good suit  NCR ???
	//  7:  15+ Total points with 2 QTs
	//  8:  14+ Total points with 2 QTs and a rebiddable suit
	//  9:  13+ Total points with 2 QTs and a rebiddable suit of 6+ cards
	//
	
	// we can only open if the opponents haven't opened yet
	// if they have, the COvercallsCovention object should have looked into
	// a posssible overcall.
	if ((nLHOBid > BID_PASS) || (nRHOBid > BID_PASS))
	{
		status << "B00! We cannot overcall and the hand is not appropriate for any other bid, so pass.\n";
		m_nBid = BID_PASS;
		return ValidateBid(m_nBid);
	}

	// the suit to open us usually the best suit
	nSuit = GetBestOpeningSuit();

	// case 1:  14+ points in high cards
	if (fCardPts >= OPEN_PTS(14)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E01! Have " & fCardPts & " points in high cards, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}
	// case 2:  13+ HCP's && 2 QT's
	if ((fCardPts >= OPEN_PTS(13)) && (numQuickTricks >= 2)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E02! Have " & fCardPts & " points in high cards and " & numQuickTricks & 
				  " quick tricks, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	}
	// case 3:  12+ HCP's, 2 QT's, & a rebiddable suit
	// NCR-680  reduce QTs
	if ((fCardPts >= OPEN_PTS(12)) && (numQuickTricks >= PT_COUNT(2)) && 
								(numRebiddableSuits > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E03! Have " & fCardPts & " points in high cards, " & numQuickTricks &
				  " quick tricks, and a rebiddable suit in " & STS(nSuit) & 
				  ", so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	}
	// case 4:  12+ HCP's, 2 QT's, & a 5-card suit
	if ((fCardPts >= OPEN_PTS(12)) && (numQuickTricks >= 2) && 
							(m_pHand->GetNumSuitsOfAtLeast(5) > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E04! Have " & fCardPts & " points in high cards, " & numQuickTricks & 
				  " quick tricks, and a " & numCardsInSuit[nSuit] & 
				  "-card suit, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}
	// case 5:  12+ HCP's & a balanced dist in Weak NTs
	if ((fCardPts >= OPEN_PTS(12)) && (bBalanced) && 
				(pCurrConvSet->GetValue(tn1NTRange) == 0)) 
	{
		m_nBid = BID_1NT;
		status << "E05! Have " & fCardPts & " points in high cards, a balanced hand, " &
				  "and playing Weak No Trumps, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}
	// case 6:  10+ HCPs opening in 3rd or 4th seat & a good suit
//	if ((fCardPts >= OPEN_PTS(10)) 
	if ((fCardPts >= 10)  // NCR-206 Hard 10  and > 4 cards  
		 && (((nBiddingOrder == 2) && (numCardsInSuit[nSuit] > 4)) 
		                              // NCR require Having spades to open light in 4th
		     || ((nBiddingOrder == 3) & (numCardsInSuit[SPADES] > 3))
		                              && (nSuit == SPADES))
		 &&	(numOpenableSuits > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E07! Have " & fCardPts & " points in high cards in " 
				  & ((nBiddingOrder == 2)? "3rd" :  "4th") &
				  " position and a " & SSTS(nSuit) & " " & STSS(nSuit) & 
				  " suit, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}
	// case 7:  15+ Total points and 10 HCPs, with 2 QTs
	if ((fPts >= OPEN_PTS(15)) && (fCardPts >= OPEN_PTS(10)) && (numQuickTricks >= 2)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E08! Have " & fCardPts & "/" & fPts & " total points with " 
				  & numQuickTricks & " QT's, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}
	//
	// case 8:  14+ Total points with 10+ HCPs, 2 QTs 
	// and a rebiddable suit
	if ((fPts >= OPEN_PTS(14)) && (fCardPts >= OPEN_PTS(10)) && 
		(numQuickTricks >= 2) && (numRebiddableSuits > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E09! Have " & fCardPts & "/" & fPts & " total points with "
				  & numQuickTricks & " QT's and a rebiddable suit, so bid "
				  & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	}
	//
	// case 9:  13+ Total points with 10+ HCPs, 2 QTs and a 
	// rebiddable suit of 6+ cards
	if ((fPts >= OPEN_PTS(13)) && (fCardPts >= OPEN_PTS(10)) && 
		(numQuickTricks >= 2) && (numRebiddableSuits > 0) && 
		(numPrefSuitCards >= 6) &&
		(nSuitStrength[nPrefSuit] > SS_OPENABLE)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E10! Have " & fCardPts & "/" & fPts & " total points with "
				  & numQuickTricks & " QT's and a " & numCardsInSuit[nSuit] & 
				  "-card rebiddable suit, so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}



	//
	//---------------------------------------------------------
	//
	// now test for optional 1-level openings
	//
	int nAllowed1Opens = pCurrConvSet->GetValue(tnAllowable1Openings);

	//
	// option 1:  11+ HCPs with 2 QTs, a rebiddable suit, &
	// length in both majors
	//
	if ((nAllowed1Opens & OB_11_HCPS_RBS_LM) && (fCardPts >= OPEN_PTS(11)) && 
		(numQuickTricks >= 2) && (numRebiddableSuits > 0) &&
		(numCardsInSuit[HEARTS] >= 4) && (numCardsInSuit[SPADES] >= 4)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E21! Have " & fCardPts & " points in high cards, " & numQuickTricks & 
				   " quick tricks, a rebiddable suit, and length in both majors " &
				   "(optional opening condition #1), so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}
	//
	// option 2:  11+ HCPs with 2 QTs and a 6-card suit
	//
	if ((nAllowed1Opens & OB_11_HCPS_6CS) && (fCardPts >= OPEN_PTS(11)) && 
				(numQuickTricks >= 2) && 
				(m_pHand->GetNumSuitsOfAtLeast(6) > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E22! Have " & fCardPts & " points in high cards with " & numQuickTricks & 
			      " QT's and a " & numCardsInSuit[nSuit] & 
				  "-card suit (optional opening condition #2), so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	}
	//
	// option 3:  14+ Total points with 10 HCPs, 2 QTs, and a 
	// good suit
	//
	if ((nAllowed1Opens & OB_14_TCPS_GS) && 
				(fPts >= OPEN_PTS(14)) && (fCardPts >= OPEN_PTS(10)) && 
				(numQuickTricks >= 2) && (numSolidSuits > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E23! Have " & fCardPts & "/" & fPts & "total points with " & numQuickTricks &
				  " QT's and a " & SSTS(nSuit) & " " & STSS(nSuit) & 
				  " suit (optional opening condition #3), so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	}
	//
	// option 4:  14+ Total points with 10 HCPs, 2 QTs, and a 
	// long suit (6+ cards)
	//
	if ((nAllowed1Opens & OB_14_TCPS_LS) && 
		(fPts >= OPEN_PTS(14)) && (fCardPts >= OPEN_PTS(10)) && 
		(numQuickTricks >= 2) && 
		(m_pHand->GetNumSuitsOfAtLeast(6) > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E24! Have " & fCardPts & "/" & fPts & " total points with " & numQuickTricks &
				  " QT's and a " & numCardsInSuit[nSuit] &"-card " & STSS(nSuit) & 
				  " suit (optional opening condition #4), so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	}
	//
	// option 5:  13+ Total points with 2 QTs, 10 HCPs,
	// and a 6-card suit
	//
	if ((nAllowed1Opens & OB_13_TCPS_LS) && 
		      // NCR-390 Add in distribution points here and below in status msg
		((fPts + fDistPts) >= OPEN_PTS(13)) && (fCardPts >= OPEN_PTS(10)) && 
		(numQuickTricks >= 2) && 
		(m_pHand->GetNumSuitsOfAtLeast(6) > 0)) 
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E25! Have " & fCardPts & "/" & (fPts+fDistPts) &" total points with " & numQuickTricks &
				  " QT's and a " & numCardsInSuit[nSuit] & "-card " & STSS(nSuit) & 
				  " suit (optional opening condition #5), so bid " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}

/*
	//
	// special case:  13 pts + 1 for every 0.5 QTs missing
	if ((fPts > OPEN_PTS(13)) && (numQuickTricks < 2)) 
	{
		int nRqmt = 13 + (int)(((2.0 - numQuickTricks)*2));
		if (fPts >= nRqmt) 
		{
			m_nBid = MAKEBID(nSuit,1);
			status << "E27! Have " & fCardPts & "/" & fPts & 
					  " total points; shade opening requirement of 2 QT's and make do with " & numQuickTricks &
					  " QT's in light of the high total point count; open " & BTS(m_nBid) & ".\n";
			return ValidateBid(m_nBid);;
		}
	}
*/
	// NCR-356 Loosen up a bit here - bid 5 card major if ...
	if((fCardPts >= OPEN_PTS(13)) &&  ISMAJOR(nSuit) && (numCardsInSuit[nSuit] >= 5)
		&& pCurrConvSet->IsConventionEnabled(tid5CardMajors) )
	{
		m_nBid = MAKEBID(nSuit,1);
		status << "E28! Have " & fCardPts & "/" & fPts & 
				  " total points; shade opening requirement of 2 QT's and make do with " & numQuickTricks &
				  " QT's; open " & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);;
	} // end NCR-356


	// NCR Is Convenient minor (goes with 5card Majors) appropriate - 13 HCPs and 3 clubs
	if((fCardPts >= OPEN_PTS(13)) && pCurrConvSet->IsConventionEnabled(tid5CardMajors)
		&& (numCardsInSuit[CLUBS] >= 3)) 
	{
		m_nBid = BID_1C;
		if(numCardsInSuit[DIAMONDS] > numCardsInSuit[CLUBS]) // NCR-507 Bid Diamonds if more of them
			m_nBid = BID_1D;
		status << "E31! Have " & fCardPts & " points in high cards , so bid a Convenient minor "
			        & BTS(m_nBid) & ".\n";
		return ValidateBid(m_nBid);
	}

	//
	//--------------------------------------------------------
	//
	// All attempts at opening failed, so return a PASS
	//
	status << "Z00! Hand is insufficient for any opening, so pass.\n";
	m_nBid = BID_PASS;
	return ValidateBid(m_nBid);;				

}
//
//==========================================================
//
// Rebidding as opener after partner responds to a takeout double
//
BOOL CNegativeDoublesConvention::HandleConventionResponse(const CPlayer& player, 
														  const CConventionSet& conventions, 
														  CHandHoldings& hand, 
														  CCardLocation& cardLocation, 
														  CGuessedHandHoldings** ppGuessedHands,
														  CBidEngine& bidState,  
														  CPlayerStatusDialog& status)
{
	// there's no code here for now
	return FALSE;

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

	// 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 (bidState.GetConventionStatus(this) == CONV_INVOKED_ROUND1) 
	{
		//
		//--------------------------------------------------------
		// responding to partner's forced bid
		// - estimate partner's strength
		//

		//
		// did partner pass? (horror of horrors!)
		//
		if (nPartnersBid == BID_PASS) 
		{
			if (bidState.nLHOBid >= BID_PASS)
				status << "NGDRb10! After interference from the left-hand opponent, partner passed our takeout.\n";
			else
				status << "NGDRb12! Partner unexpectedly passed our takeout double, which is supposed to be forcing.  Bidding will proceed as if the takeout was not made\n";
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return FALSE;
		}

		// set team point estimates -- be conservative
		BOOL bPartnerJumped = FALSE;
		BOOL bPartnerJumpedToGame = FALSE;
		int nEnemyBid = pDOC->GetValidBidRecord(0);
		int nEnemyBidLevel = BID_LEVEL(nEnemyBid);
		int nEnemySuit = BID_SUIT(nEnemyBid);
		if (nPartnersBidLevel > (nEnemyBidLevel + 1))
			bPartnerJumped = TRUE;
		if (nPartnersBid == bidState.GetGameBid(nPartnersSuit))
			bPartnerJumpedToGame = TRUE;
		// flag to see if we doubled in preference to an overcall
		BOOL bWantedToOvercall = FALSE;

		//
		if (nPartnersSuit == NOTRUMP)
		{
			//
			if (nPartnersBid == BID_1NT)
			{
				// partner has 6-9 HCPs
				bidState.m_fPartnersMin = 6;
				bidState.m_fPartnersMax = 9;
			}
			else if (nPartnersBid == BID_2NT)
			{
				// partner has 10-12 HCPs, maybe more
				bidState.m_fPartnersMin = 10;
				bidState.m_fPartnersMax = 12;
			}
			else if (nPartnersBid == BID_3NT)
			{
				// partner has 13+ HCPs
				bidState.m_fPartnersMin = 13;
				bidState.m_fPartnersMax = 40 - fCardPts;
				status << "NGDRb20! Partner's response of 3NT to our takeout double indicates that the opponent's suit is well stopped.\n";
			}
			else
			{
				// partner has 13+ HCPs???
				status << "NGDRb21! Partner's response of " & BTS(nPartnersBid) & 
						  " to our takeout double is unorthodox; treating it like a 3NT response.\n";
				bidState.m_fPartnersMin = 13;
				bidState.m_fPartnersMax = MIN(22, 40 - fCardPts);
			}
			// accept NT if we hold at least a semi-balanced 
			// and we don't have a 6-card major
			if ( !(ISMAJOR(bidState.nPrefSuit) && (bidState.numPrefSuitCards >= 6)) &&
				 (bidState.bSemiBalanced) )
				bidState.m_nAgreedSuit = NOTRUMP;
			//
			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;
			status << "NGDRb29! Partner's response of " & BTS(nPartnersBid) & 
					  " to our takeout double indicates " & 
					  bidState.m_fPartnersMin & "-" & bidState.m_fPartnersMax & 
					  " HCPs, for a total of " &
					  bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints & " / " &
					  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & 
					  " pts in the partnership.\n";

		}
		else
		{
			// partner bid a suit
			// see if we really intended to overcall last time
			if (bidState.GetConventionStatus(&overcallsConvention) == CONV_SUBSUMED)
				bWantedToOvercall = TRUE;
			//
			if (nPartnersSuit == nEnemySuit)
			{
				// partner bid the enemy suit, showing 13+ pts.
				status << "NEGDRb40! Partner has responded in the enemy suit, indicating 13+ pts but no long suits.\n";
				bidState.m_fPartnersMin = 13;
				bidState.m_fPartnersMax = MIN(22, 40 - bidState.fCardPts);
				bidState.m_bGameForceActive = TRUE;
			}
			else if (bPartnerJumpedToGame)
			{
				// partner had 13+ pts & a 5-card major
				status << "NEGDRb41! Partner has jumped to game in " & STS(nPartnersSuit) &
						  ", indicating 13+ pts and a 5+ card suit.\n";
				bidState.m_fPartnersMin = 30;
				bidState.m_fPartnersMax = MIN(22, 40 - bidState.fCardPts);
				if (!bWantedToOvercall)
					bidState.m_nAgreedSuit = nPartnersSuit;
			}
			else if (bPartnerJumped)
			{
				// partner had 10-12 pts
				status << "NEGDRb42! Partner has made a jump response of " & BTS(nPartnersBid) &
						  ", indicating 10-12 pts and a 4-5 card suit.\n";
				bidState.m_fPartnersMin = 10;
				bidState.m_fPartnersMax = 12;
				if (!bWantedToOvercall)
					bidState.m_nAgreedSuit = nPartnersSuit;
			}
			else
			{
				// partner had <= 9 pts
				status << "NEGDRb43! Partner has made a minimum response of " & BTS(nPartnersBid) &
						  ", indicating no more than 9 points.\n";
				bidState.m_fPartnersMin = 0;
				bidState.m_fPartnersMax = 9;
				if (!bWantedToOvercall)
					bidState.m_nAgreedSuit = nPartnersSuit;
			}
			//
			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;
			status << "NGDRb49! The total point count in the partnership is therefore " &
					  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints & 
					  " pts.\n";
		}

			
		//
		// see if RHO bid after partner's response -- that mitigates our responsibility
		// to bid again, unless partner's bid was game forcing
		//
	//	if (bidState.nRHOBid > BID_PASS)
		if ((bidState.nRHOBid > BID_PASS) && 
			(bidState.nRHOBid != BID_DOUBLE) && (bidState.nRHOBid != BID_REDOUBLE))
		{
			status << "2NGDRb51! The right-hand opponent has " &
					  ((bidState.nRHOBid == BID_DOUBLE)? "doubled" : "bid") &
					  " after partner's response, interfering with our communication.\n";
		}


		//
		//---------------------------------------------------------------------
		// see if we have an agreed suit
		//
		int nBid;
		if (bidState.m_nAgreedSuit > NONE)
		{
			if (bidState.m_nAgreedSuit == NOTRUMP)
			{
				// we've agreed to play in NoTrump
				// see if we can raise partner to a higher NT contract
				if (bidState.BidNoTrumpAsAppropriate(FALSE,STOPPED_DONTCARE))
				{
					bidState.SetConventionStatus(this, CONV_FINISHED);
					return TRUE;
				}
				// else pass
				nBid = BID_PASS;
				status << "NGDRb69! With a total of " &
						  bidState.m_fMinTPCPoints & "-" & bidState.m_fMaxTPCPoints &
						  " HCPs in the partnership, we have insufficient strength to raise partner's " &
						  BTS(nPartnersBid) & " bid, so we have to pass.\n";
				bidState.SetBid(nBid);
				bidState.SetConventionStatus(this, CONV_FINISHED);
				return TRUE;
			}
			else
			{
				// we've agreed on a suit, so raise if possible
				// if partner didn't jump, we may have credited him with
				// zero pts, so adjust rqmts accordingly

				// if partner jumped to game && we have < 32 pts, pass
				if ((bPartnerJumpedToGame) && (bidState.m_fMinTPPoints < 32))
				{
					status << "NGDRb70! Partner jumped to game in his " & bidState.szPSS & 
							  " suit, so with a team total of " &
							  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
							  " points, we pass.\n";
					bidState.SetBid(BID_PASS);
					bidState.SetConventionStatus(this, CONV_FINISHED);
					return TRUE;
				}
				// raise partner if possible -- bearing in mind that 
				// partner may have a wide range of points

				// raise a major to game with 23-31 pts and 4 trumps
				//					  or with 26-31 pts and 3 trumps
				// or raise to the 3-level with 20-24 pts and 3 trumps
				if ( (bidState.RaisePartnersSuit(SUIT_MAJOR,RAISE_TO_4,PTS_MAJOR_GAME-3,31,SUPLEN_4)) ||
				     (bidState.RaisePartnersSuit(SUIT_MAJOR,RAISE_TO_4,PTS_MAJOR_GAME,31,SUPLEN_3)) ||
					 (bidState.RaisePartnersSuit(SUIT_MAJOR,RAISE_TO_3,PTS_MAJOR_GAME-6,24,SUPLEN_3)))
				{
					if (!bPartnerJumped)
						status << "NGDRb71a! (we can assume partner has some strength in the " & bidState.szPSS & 
								  " suit, so we are shading the requirements slightly.\n";
					bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
					return TRUE;
				}
				// raise a minor to game with 28-32 pts and 4 trumps
				//                    or with 29-32 pts and 3 trumps
				// or raise to the 4-level with 26-28 pts and 3 trumps
				// or raise to the 3-level with 23-25 pts and 3 trumps
				if ( (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_5,PTS_MINOR_GAME-1,PTS_SLAM-1,SUPLEN_4)) ||
					 (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_5,PTS_MINOR_GAME,PTS_SLAM-1,SUPLEN_3)) ||
					 (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_4,PTS_MINOR_GAME-3,PTS_MINOR_GAME-1,SUPLEN_3)) ||
					 (bidState.RaisePartnersSuit(SUIT_MINOR,RAISE_TO_3,PTS_MINOR_GAME-6,PTS_MINOR_GAME-4,SUPLEN_3)) )
				{
					if (!bPartnerJumped)
						status << "NGDRb71b! We can assume partner has some strength in the " & bidState.szPSS & 
								  " suit, so we can shade the requirements slightly.\n";
					bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
					return TRUE;
				}
				// with 32+ pts, invoke Blackwood
				if (bidState.m_fMinTPCPoints >= 32)
				{
					bidState.InvokeBlackwood(bidState.m_nAgreedSuit);
					bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
					return TRUE;
				}
				// else pass
				nBid = BID_PASS;
				status << "NGDRb90! With a total of " &
						  bidState.m_fMinTPPoints & "-" & bidState.m_fMaxTPPoints &
						  " points in the partnership, we have insufficient strength to raise partner's " &
						  BTS(nPartnersBid) & " bid, so we have to pass.\n";
				bidState.SetBid(nBid);
				bidState.SetConventionStatus(this, CONV_FINISHED);
				return TRUE;
			}
		}


		//
		//--------------------------------------------------------------------------
		// here, we have no suit agreement (e.g., partner bid the opponents' suit)
		//
		int nLastBid = pDOC->GetLastValidBid();
		if (bBalanced)
		{
			// try notrumps
			if (hand.IsSuitProbablyStopped(nEnemySuit))
			{
				status << "NGDRb80! Without clear suit agreement, and holding a blanaced hand, we want to steer towards a contract in No Trump.\n";
				if (bidState.BidNoTrumpAsAppropriate(FALSE,STOPPED_DONTCARE))
				{
					bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
					return TRUE;
				}
			}
			// else pass
			status << "NGDRb81! But as we do not have a proper hand to bid No Trump at the appropriate level, we have to pass.\n";
			bidState.SetBid(BID_PASS);
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return TRUE;
		}
		else if (bidState.numPrefSuitCards >= 5)
		{
			// bid the suit
			nBid = bidState.GetCheapestShiftBid(nPrefSuit, nLastBid);
			if (bidState.IsBidSafe(nBid, 4))
			{
				if (bWantedToOvercall)
					status << "NGDRb90! Partner's forced response of " & bidState.szPB & 
							 " not withstanding, we can now show the " & 
							  STSS(nPrefSuit) & " suit that we wanted to overcall with last round by bidding " &
							  BTS(nBid) & ".\n";
				else
					status << "NGDRb91! Without clear suit agreement, we bid our " &
							  bidState.numPrefSuitCards & "-card " & STSS(bidState.nPrefSuit) &
							  " suit at " & BTS(nBid) & ".\n";
				bidState.SetBid(nBid);
				bidState.SetConventionStatus(this, CONV_INVOKED_ROUND2);
				return TRUE;
			}
		}


		//
		//--------------------------------------------------------------------------
		// else we have no other options, so pass
		status << "NEGDRb99! We see no good fit with partner and no other options, so pass.\n";
		bidState.SetBid(BID_PASS);
		bidState.SetConventionStatus(this, CONV_FINISHED);
		return TRUE;

	}
	else
	{
		//
		// responding after partner's second response to our takeout
		//

		// did partner pass?
		if (nPartnersBid == BID_PASS) 
		{
			bidState.SetConventionStatus(this, CONV_FINISHED);
			return FALSE;
		}

		//
		// otherwise, consider the choices:
		//
		// - with suit agreement, raise if possible
		//         S    N     S     N     S
		//   e.g., X -> 1C -> 1S -> 2S -> ???
		// - without suit agreement,
		//   e.g., X -> 1C -> 1S -> 2H -? ???
		//   bid the 4th suit if we have the pts (26+)
		// - without suit agreement, but if partner bids NT,
		//   or if we have a balanaced hand, bid NT
		//
		double fMinTPPoints = bidState.m_fMinTPPoints;
		double fMaxTPPoints = bidState.m_fMaxTPPoints;
		double fMinTPCPoints = bidState.m_fMinTPCPoints;
		double fMaxTPCPoints = bidState.m_fMaxTPCPoints;
		int nBid;
		
		//
		// see if we have suit agreement
		//
		if (nPartnersSuit == nPreviousSuit)
		{
			// partner raised our suit -- re-raise if possible
			bidState.m_nAgreedSuit = nPreviousSuit;
			if (nPartnersBid >= bidState.GetGameBid(nPreviousSuit))
			{
				// partner bid game or beyond
				if ((nPartnersBidLevel == 7) ||
					((nPartnersBidLevel == 6) && (fMinTPPoints <= 36)) )
				{
					nBid = BID_PASS;
					status << "NGDRc10! Partner raised our " & bidState.szPVSS & 
							  " suit to a slam, so pass.\n";
				}
				else if ((nPartnersBidLevel <= 6) && (fMinTPPoints >= 37))
				{
					nBid = MAKEBID(nPreviousSuit, 7);
					status << "NGDRc11! Partner raised our " & bidState.szPVSS & 
							  " suit to " & 
							  ((nPartnersBidLevel == 6)? "slam" : "game") &
							  ", but we have the poitns to push to a grand slam, so bid " & 
							  BTS(nBid) & ".\n";
				}
				else if ((nPartnersBidLevel < 6) && (fMinTPPoints >= 33))
				{
					nBid = MAKEBID(nPreviousSuit, 6);
					status << "NGDRc12! Partner raised our " & bidState.szPVSS & 
							  " suit to game, but we have the poitns for a slam, so bid " & 
							  BTS(nBid) & ".\n";
				}
				else
				{
					nBid = BID_PASS;
					status << "NGDRc13! Partner raised our " & bidState.szPVSS & 
							  " suit to game, which is acceptable with " & 
							  fMinTPPoints & "-" & fMaxTPPoints & 
							  " pts in the partnership, so pass.\n";
				}
			}
			else
			{
				// partner raised below game
				// re-raise if possible
				if ( (ISMAJOR(nPreviousSuit) && (fMinTPPoints >= PTS_MAJOR_GAME)) ||
					 (ISMINOR(nPreviousSuit) && (fMinTPPoints >= PTS_MINOR_GAME)) )
				{
					nBid = bidState.GetGameBid(nPreviousSuit);
					status << "NGDRc20! With a total of " & 
							  fMinTPPoints & "-" & fMaxTPPoints & 
							  " pts in the partnership, raise to game in the " &
							  bidState.szPVSS & " suit at " & BTS(nBid) & ".\n";
				}
				else
				{
					// else try to raise cheaply
					nBid = bidState.GetCheapestShiftBid(nPreviousSuit);
					if (bidState.IsBidSafe(nBid))
					{
						status << "NGDRc22! With a total of " & 
								  fMinTPPoints & "-" & fMaxTPPoints & 
								  " pts in the partnership, we can raise again to " &
								  BTS(nBid) & ".\n";
					}
					else
					{
						nBid = BID_PASS;
						status << "NGDRc29! With a total of " & 
								  fMinTPPoints & "-" & fMaxTPPoints & 
								  " pts in the partnership, we cannot safely raise any partner further, so pass.\n";
					}
				}
			}
		}
		else if ((nPartnersSuit == NOTRUMP) || (bidState.bBalanced))
		{
			//
			// partner bid NT, or else we have a balanced hand
			//
			if (bidState.BidNoTrumpAsAppropriate(FALSE, STOPPED_DONTCARE))
			{
				nBid = bidState.m_nBid;
				status << "NGDRc30! With a total of " & 
						  fMinTPCPoints & "-" & fMaxTPCPoints & 
						  " HCPs in the partnership, we can bid " & BTS(nBid) & ".\n";
			}
			else
			{
				nBid = BID_PASS;
				if (nPartnersSuit == NOTRUMP)
					status << "NGDRc35! We're willing to accept a contract in NoTrumps, but don't have the points to raise further, so pass.\n";
				else
					status << "NGDRc36! We'd like to play in NoTrumps, but don't have the points to bid agian, so pass.\n";
			}
		}
		else
		{
			//
			// else we have no suit agreement, and can't play NT
			//

			//
			// bid the 4th suit if we have enough pts
			//
			int nSuit = bidState.GetFourthSuit(nPreviousSuit, nPartnersSuit, nPartnersPrevSuit);
			nBid = bidState.GetCheapestShiftBid(nSuit);

			if ((fMinTPPoints >= PTS_GAME) && (nBid < bidState.GetGameBid(nSuit)))
			{
				status << "NGDRc40! With a total of " & 
						  fMinTPPoints & "-" & fMaxTPPoints & 
						  " pts in the partnership and no suit agreement, bid another suit (" &
						  STS(nSuit) & ") at " & BTS(nBid) & ".\n";
			}
			else
			{
				// gotta pass
				nBid = BID_PASS;
				if (nPartnersBid >= bidState.GetGameBid(nPartnersSuit))
					status << "NGDRc45! With a total of " & 
							  fMinTPPoints & "-" & fMaxTPPoints & 
							  " pts in the partnership, partner has gone to game in his suit at " &
							  bidState.szPB & ", so pass.\n";
				else if (fMinTPPoints >= PTS_GAME)
					status << "NGDRc46! With a total of " & 
							  fMinTPPoints & "-" & fMaxTPPoints & 
							  " pts in the partnership, but having run out of bidding room, we have to bail out and pass.\n";
				else 
					status << "NGDRc47! With a total of only " & 
							  fMinTPPoints & "-" & fMaxTPPoints & 
							  " pts in the partnership, and no agreement in suits, we have to pass.\n";
			}
		}
		// done with the second rebid 
		bidState.SetBid(nBid);
		bidState.ClearConventionStatus(this);
		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;
} 
Ejemplo n.º 12
0
//
//---------------------------------------------------------
//
// PBN File output routine
//
BOOL CEasyBDoc::WriteFilePBN(CArchive& ar) 
{
	pFile = ar.GetFile();
	ASSERT(pFile != NULL);

	// write header
	WriteComment("");
	WriteComment("EXPORT");
	WriteComment("PBN Format 1.0");
	WriteComment(FormString("File generated by Easy Bridge version %s", theApp.GetProgramVersionString()));
	WriteComment("");

	//
	// write the data
	//

	// Event tag
	WriteLine(TAG_EVENT, FormString("%s Game", theApp.GetValue(tstrProgramTitle)));

	// Site Tag
	WriteLine(TAG_SITE, "At Home"); // NCR added At Home

	// Date Tag
	CTime time = CTime::GetCurrentTime();
	WriteLine(TAG_DATE, time.Format("%Y.%m.%d"));

/*
 * skip the round tag -- no longer mandatory in PBN 0.91+
 *
	// Round Tag
	WriteLine(TAG_ROUND, "");
 */

	// Board Tag
	WriteLine(TAG_BOARD, "1"); // NCR added 1

	// West/North/East/South Tags
	WriteLine(TAG_WEST, "Computer");
	WriteLine(TAG_NORTH, "Computer");
	WriteLine(TAG_EAST, "Computer");
	WriteLine(TAG_SOUTH, "Human Player");

	// Dealer Tag
	WriteLine(TAG_DEALER, FormString("%c", PositionToChar(m_nDealer)));

	// Vulnerable Tag
	CString strVulnerable;
	if ((m_bVulnerable[NORTH_SOUTH]) && (m_bVulnerable[EAST_WEST]))
		strVulnerable = "Both";
	else if (m_bVulnerable[NORTH_SOUTH])
		strVulnerable = "NS";
	else if (m_bVulnerable[EAST_WEST])
		strVulnerable = "EW";
	else
		strVulnerable = "None";
	WriteLine(TAG_VULNERABLE, strVulnerable);

	// deal tag
	CString strDeal = "W:";
	int nPos = WEST;
	int i; // NCR-FFS added here, removed below
	for(/*int*/ i=0;i<4;i++)
	{
		CCardHoldings& cards = m_pPlayer[nPos]->GetHand().GetInitialHand();
		strDeal += cards.GetGIBFormatHoldingsString();
		nPos = GetNextPlayer(nPos);
		if (i < 3)
			strDeal += ' ';
	}
	WriteLine(TAG_DEAL, strDeal);

	// Scoring tag
	if (theApp.IsRubberInProgress())
		WriteLine(TAG_SCORING, _T("Rubber"));
	else
		WriteLine(TAG_SCORING, _T("None"));

	// Declarer Tag
	if (ISPOSITION(m_nDeclarer))
		WriteLine(TAG_DECLARER, FormString("%c", PositionToChar(m_nDeclarer)));
	else
		WriteLine(TAG_DECLARER, "?");

	// Contract Tag
	if (ISBID(m_nContract)) 
	{
		// NCR Include ContractToString() here as PBN file does NOT have space before X
		CString strBid;
		strBid.Format("%d%s", 
					  BID_LEVEL(m_nContract), 
					  szSuitNameShort[BID_SUIT(m_nContract)]);
		int nModifier = pDOC->GetContractModifier();
		if (nModifier > 0)
			strBid += FormString("%s", ((nModifier == 1)? "X" : "XX")); // w/o space

		WriteLine(TAG_CONTRACT, strBid);  // NCR replaced ContractToString(m_nContract)
	}
	else
		WriteLine(TAG_CONTRACT, "?");

	// Result tag
	if (m_numTricksPlayed == 13)
		WriteLine(TAG_RESULT, FormString("%d", m_numTricksWon[m_nContractTeam])); // NCR removed extra "s
	else
		WriteLine(TAG_RESULT, "?");

	//
	// write out the hands in comment form
	//
	CString strHands = "{\r\n" + pDOC->FormatOriginalHands() + "}";
	WriteLine(strHands);

	//
	// write out auction
	//
	CString strBids = FormString("[Auction \"%c\"]", PositionToChar(m_nDealer)); // NCR Lowercased
	if (m_numBidsMade > 0)
		strBids += "\r\n";
	nPos = m_nDealer;
	for(i=0;i<m_numBidsMade;i++)
	{
		strBids += FormString("%s ", ::BidToPBNString(m_nBiddingHistory[i]));
		nPos = ::GetNextPlayer(nPos);
		if ( (((i+1) % 4) == 0) && (i < m_numBidsMade-1) )
			strBids += "\r\n";
	}
	// add marker if needed
	if (!ISBID(m_nContract))
		strBids += "\r\n*";
	// and write out
	WriteLine(strBids);


	//
	// write out plays
	//
	CString strPlays = FormString("[Play \"%c\"]", PositionToChar(m_nGameLead));  // NCR Lowercased
	if (m_numTricksPlayed> 0)
		strPlays += "\r\n";
	bool bLastRowFnd = false;  // NCR added - only output single row with -s
	for(i=0;i<m_numTricksPlayed;i++)
	{
		int nPos = m_nGameLead;
		for(int j=0;j<4;j++)
		{
			CCard* pCard = m_pGameTrick[i][nPos];
			if (pCard == NULL) {
				strPlays += "-  ";
				bLastRowFnd = true;  // NCR this row will end the output
			}
			else
				strPlays += FormString("%s ", pCard->GetName());
			nPos = ::GetNextPlayer(nPos);
		} // end for(j) thru poisitions
		if (i < m_numTricksPlayed-1)
			strPlays += "\r\n";
		if(bLastRowFnd)
			break;  // NCR finished output plays on line with -s
	} // end for(i) thru tricks
	// add marker if needed
	if (m_numTricksPlayed < 13)
		strPlays += "\r\n*";
	// and write out
	WriteLine(strPlays);


	// Generator Tag
	WriteLine(TAG_GENERATOR, FormString("Easy Bridge version %s", theApp.GetProgramVersionString()));

	// Description Tag
	WriteLine(TAG_DESCRIPTION, m_strFileDescription);

	// blank line
//	SkipLine();

	//
	// write out the auction
	//

	//	
	// All done
	//
	ar.Flush();
	return TRUE;
}
Ejemplo n.º 13
0
void CBidDialogSmall::DisableControls()
{
	int nLastBid = pDOC->GetLastValidBid();
	int nLastBidLevel = BID_LEVEL(nLastBid);
	int nLastBidSuit = BID_SUIT(nLastBid);

	// check if a bid level has been specified
	if (m_nSelectedLevel == 0)
	{
		// if no bid level has been selected yet, disable the suits
		for(int i=IDC_SUIT_CLUBS;i<=IDC_SUIT_NOTRUMP;i++)
			GetDlgItem(i)->EnableWindow(FALSE);

		// and disable all lower bid levels
		if (nLastBidSuit == NOTRUMP)
		{
			// disble up to & including current level
			for(int i=IDC_BID_LEVEL_1;i<IDC_BID_LEVEL_1+nLastBidLevel;i++)
				GetDlgItem(i)->EnableWindow(FALSE);
		}
		else
		{
			// disble up to prev level
			for(int i=IDC_BID_LEVEL_1;i<IDC_BID_LEVEL_1+nLastBidLevel-1;i++)
				GetDlgItem(i)->EnableWindow(FALSE);
		}
	}
	else
	{
		// a bid level has been specified, so disable certain suits
		if ((m_nSelectedLevel == nLastBidLevel) && (nLastBidSuit != NOTRUMP))
		{
			for(int i=IDC_SUIT_CLUBS;i<=IDC_SUIT_CLUBS+nLastBidSuit;i++)
				GetDlgItem(i)->EnableWindow(FALSE);
		}
	}

	// set defaults for double/redouble buttons
	BOOL bEnableDouble = TRUE;
	BOOL bEnableReDouble = FALSE;

	// can't double if no valid bids yet
	if (nLastBid <= BID_PASS)
		bEnableDouble = FALSE;

	// or if already doubled or redoubled
	if (pDOC->IsContractDoubled() || pDOC->IsContractRedoubled())
		bEnableDouble = FALSE;

	// can't double own team's bid
	int nBidTeam = pDOC->GetLastValidBidTeam();
	if ((nBidTeam == pDOC->GetCurrentPlayer()->GetTeam()) && !m_bTrainingMode)
		bEnableDouble = FALSE;

	// can redouble only if already doubled && is team contract (or is training)
	if (pDOC->IsContractDoubled() && ((nBidTeam == NORTH_SOUTH) || m_bTrainingMode))
		bEnableReDouble = TRUE;

	// and set
	GetDlgItem(IDC_BID_DOUBLE)->EnableWindow(bEnableDouble);
	GetDlgItem(IDC_BID_REDOUBLE)->EnableWindow(bEnableReDouble);
}
//
//-----------------------------------------------------
//
// 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;
}