//
// GetMaxCardsInSuit()
//
// returns the maximum number of cards a player currently holds in a suit
//
int CPlayEngine::GetMaxCardsInSuit(int nPlayer, int nSuit) const
{
	VERIFY((nPlayer >= 0) && (nPlayer <= 3) && ISSUIT(nSuit));

	// see if the hand's cards have all been identified
	CGuessedSuitHoldings& suit = m_ppGuessedHands[nPlayer]->GetSuit(nSuit);
	if (suit.AreAllCardsIdentified())
		return suit.GetNumMaxRemainingCards();

	// else see if the player is dummy & his cards are visible
	if (nPlayer == pDOC->GetDummyPosition() && pDOC->IsDummyExposed())
	{
		CHandHoldings& hand = pDOC->GetDummyPlayer()->GetHand();
		return hand.GetNumCardsInSuit(nSuit);
	}

	// else calc
	// initial max is 13 cards in a suit
	int nMax = 13;

	// deduct the # of our original suit cards 
	nMax -= m_pHand->GetInitialHand().GetNumCardsOfSuit(nSuit);

	// deduct dummy's suit holdings, if visible
	CPlayer* pDummy = pDOC->GetDummyPlayer();
	if (pDummy->AreCardsExposed())
	{
		CCardHoldings& initialHand = pDummy->GetHand().GetInitialHand();
		nMax -= initialHand.GetNumCardsOfSuit(nSuit);
	}

	// and deduct the cards that have been played by the other two players
	int nDummyPos = pDummy->GetPosition();
	int nOurPos = m_pPlayer->GetPosition();
	for(int nPos=0;nPos<4;nPos++)
	{
		if ((nPos == nDummyPos) || (nPos == nOurPos))
			continue;
		nMax -= GetNumCardsPlayedInSuit(nPos, nSuit);
	}

	// if the max == 0, all the player's suit cards have been identified
	if (nMax == 0)
	{
		// update status
		suit.MarkAllCardsIdentified();
		// and update counts
		suit.SetNumOriginalCards(nMax + m_ppGuessedHands[nPlayer]->GetSuit(nSuit).GetNumCardsPlayed());
		suit.SetNumRemainingCards(nMax);
		suit.SetNumLikelyCards(nMax);
		suit.SetNumMinRemainingCards(nMax);
		suit.SetNumMaxRemainingCards(nMax);
	}

	// and we're done
	return nMax;
}
//
// GetOutstandingCards()
//
// determine the list of outstanding cards in this suit
// outstanding means all the cards that are not in our own hand
// (or dummy), _and_ which have not been played
//
int	CPlayEngine::GetOutstandingCards(int nSuit, CCardList& cardList, bool bCountDummy) const
{
	VERIFY(ISSUIT(nSuit));

	// first fill the list with all the cards in the suit
	for(int i=2;i<=ACE;i++)
		cardList << deck.GetSortedCard(MAKEDECKVALUE(nSuit,i));
	cardList.Sort();

	// then remove the cards remaining in our own hand
	CSuitHoldings& suit = m_pHand->GetSuit(nSuit);
	for(i=0;i<suit.GetNumCards();i++)
		cardList.Remove(suit[i]);

	// then remove the cards in dummy from the list
	// but only if indicated, _and_ dummy's cards are visible
	if (!bCountDummy)		// i.e, don't count dummy's cards as outstanding
	{
		CPlayer* pDummy = pDOC->GetDummyPlayer();
		if (pDummy->AreCardsExposed() && (GetPlayerPosition() != pDOC->GetDummyPosition()))
		{
			CSuitHoldings& dummySuit = pDummy->GetHand().GetSuit(nSuit);
			for(int i=0;i<dummySuit.GetNumCards();i++)
				cardList.Remove(dummySuit[i]);
		}
	}

	// then search the list of guessed cards for cards in this suit 
	// that have already been played, and remove them from the list
	int nOurPos = m_pPlayer->GetPosition();
	for(int nPlayer=0;nPlayer<4;nPlayer++)
	{
		CGuessedSuitHoldings& suit = m_ppGuessedHands[nPlayer]->GetSuit(nSuit);
		for(int j=0;j<suit.GetNumDefiniteCards();j++)
		{
			if (suit[j]->WasPlayed())
				cardList.Remove(deck.GetSortedCard(suit[j]->GetDeckValue()));
		}
	}

	// now we have only the outstanding cards in the suit
	cardList.Sort();
	return cardList.GetNumCards();
}
//
// AdjustCardCountFromPlay()
//
// adjust card count and analysis after a card is played
//
void CPlayEngine::AdjustCardCountFromPlay(int nPos, CCard* pCard)
{
	// default code
//	if (nPos != m_pPlayer->GetPosition())
//	{
		// note the card that was played
		CGuessedHandHoldings* pPlayerHoldings = m_ppGuessedHands[nPos];
		CGuessedCard* pGuessedCard = new CGuessedCard(pCard,	// card
													  FALSE,	// no longer outstanding
													  nPos,		// location
													  1.0);		// known with certainty
		*pPlayerHoldings << pGuessedCard;

		// see if the player showed out
		CPlayerStatusDialog& status = *m_pStatusDlg;
		CCard* pCardLed = pDOC->GetCurrentTrickCardByOrder(0);
		if (pCard)
		{
			int nSuitLed = pCardLed->GetSuit();
			ASSERT(nSuitLed != NONE);
			CGuessedSuitHoldings& suit = pPlayerHoldings->GetSuit(nSuitLed);
			if ((pCard->GetSuit() != nSuitLed) && (!suit.IsSuitShownOut()))
			{
				status << "4RCP10! " & PositionToString(nPos) & 
						  " shows out of " & STS(nSuitLed) & ".\n";
				suit.MarkSuitShownOut();
				if (pPlayerHoldings->GetNumSuitsFullyIdentified() > 1)
				{
					// multiple suits identified
					status << "4RCP1A! " & PositionToString(nPos) & 
							  " is now known to have started with ";
					int numTotalIdentifiedSuits = pPlayerHoldings->GetNumSuitsFullyIdentified();
					int numIdentifiedSuits = 0;
					int numTotalIdentifiedCards = 0;
					int numTotalOriginalCards = 0;
					int nIdentifiedSuits[4];
					for(int i=0;i<4;i++)
					{
						if (pPlayerHoldings->GetSuit(i).AreAllCardsIdentified())
						{
							CGuessedSuitHoldings& currSuit = pPlayerHoldings->GetSuit(i);
							status < ((numIdentifiedSuits > 0)? " and " : " ") &
									  currSuit.GetNumOriginalCards() & " " & 
									  ((suit.GetNumOriginalCards() > 1)? STS(i) : STSS(i));
							nIdentifiedSuits[numIdentifiedSuits] = i;
							numIdentifiedSuits++;
							numTotalIdentifiedCards += currSuit.GetNumDefiniteCards();
							numTotalOriginalCards += currSuit.GetNumOriginalCards();
						}
					}
					status < ".\n";
					// if the number of cards is known in 3 suits, the orignal 
					// and current length of the 4th suit is also known
					if (numTotalIdentifiedSuits == 3)
					{
						// first identify the fourth suit
						int nFourthSuit = NONE;
						for(int i=0;i<4;i++)
						{
							// test each suit to see if it's in the list of know suits
							for(int j=0;j<3;j++)
							{
								if (nIdentifiedSuits[j] == i)
									break;
							}
							if (j == 3)
								nFourthSuit = i;
						}
						//
						VERIFY(nFourthSuit != NONE);
						CGuessedSuitHoldings& fourthSuit = pPlayerHoldings->GetSuit(nFourthSuit);
						int numOriginalCards = 13 - numTotalOriginalCards;
						VERIFY(numOriginalCards >= 0);
						fourthSuit.SetNumOriginalCards(numOriginalCards);
						int numRemainingCards = numOriginalCards - fourthSuit.GetNumCardsPlayed();
						VERIFY(numRemainingCards >= 0);
						// mark the # of remaining cards
						// revisit this later
	//					fourthSuit.SetNumLikelyCards(numRemainingCards);
						fourthSuit.SetNumRemainingCards(numRemainingCards);
						//
						status << "4RCP1B! Therefore, " & PositionToString(nPos) &
								  " started with " & numOriginalCards & " " & STS(nFourthSuit) &
								  " and has " & numRemainingCards & " left.\n";
					}
				}
				else
				{
					status < "RCP5A! " & PositionToString(nPos) & 
							  " is now known to have started with " &
							  suit.GetNumOriginalCards() & " " & 
							  ((suit.GetNumOriginalCards() == 1)? STSS(nSuitLed) : STS(nSuitLed)) & ".\n";
				}
			}

			// also, if this is the dummy, and the dummy plays his last card 
			// in the suit, he has effectively shown out
			CPlayer* pDummy = pDOC->GetDummyPlayer();
			if ((nPos == pDummy->GetPosition()) && (pDummy->AreCardsExposed()))
			{
				if ((pCard->GetSuit() == nSuitLed) && 
					(pDummy->GetHand().GetNumCardsInSuit(nSuitLed) == 0) &&
					(!pPlayerHoldings->IsSuitShownOut(nSuitLed)))
				{
					status << "3RCP20! Dummy is now out of " & STS(nSuitLed) & ".\n";
					pPlayerHoldings->MarkSuitShownOut(nSuitLed);
				}
			}
		}
//	}

	// special code -- if dummy has just been laid down, mark a suit as shown
	// out if dummy is void in the suit
	CPlayer* pDummy = pDOC->GetDummyPlayer();
	int nRound = pDOC->GetPlayRound();
	if ((nRound == 0) && (nPos == pDummy->GetPosition()) && (pDummy->AreCardsExposed()))
	{
		CHandHoldings& dummy = pDummy->GetHand();
		for(int i=0;i<4;i++)
		{
			if (dummy.GetNumCardsInSuit(i) == 0) 
			{
				status << "3RCP25! Dummy is shown to be void in " & STS(i) & ".\n";
				pPlayerHoldings->MarkSuitShownOut(i);
			}
		}
	}
}