Example #1
0
/*
 * Calculate the maximum opponent score
 * from the given list of opponent hands
 * opponents: an array of poker hands
 * numopponents: the number of opponents in the array
 * numcards: the size of each hand
 * return: the score of the best hand
 */
static
int BestOpponentHand(int **opponents, int numopponents, int numcards)
{
    int max = 0;
    int score;
    for (int i = 0; i < numopponents; i++)
    {
        score = GetHandValue(opponents[i], numcards);
        if (score > max)
        {
            max = score;
        }
    }

    return max;
}
Example #2
0
/*
 * Simulate a single poker game for the given AI
 * ai: the poker AI to simulate games for
 * seed_index: which seed the thread will use for rand()
 * return: AI_WIN on AI win or AI_LOSE on AI lose
 */
static
int SimulateSingleGame(PokerAI *ai, int seed_index)
{
    GameState *game = &ai->game;
    int me[NUM_HAND + NUM_COMMUNITY];
    int *opponents[MAX_OPPONENTS];
    int community[NUM_COMMUNITY];
    int myscore;
    int bestopponent;
    int rand_num;

    for (int i = 0; i < game->num_playing; i++)
    {
        opponents[i] = malloc(sizeof(*opponents[i]) * (NUM_HAND + NUM_COMMUNITY));
    }

    //Create a deck as a randomized queue data structure
    int deck[NUM_DECK] = {0};
    int decksize = 0;

    //Cards are 1 indexed
    for (int i = 1; i < NUM_DECK; i++)
    {
        if (game->deck[i])
        {
            deck[decksize] = i;
            decksize++;
        }
    }

    //Add the known community cards to the simulation community list
    for (int i = 0; i < game->communitysize; i++)
    {
        community[i] = game->community[i];
    }

    //Distribute the rest of the community cards
    for (int i = game->communitysize; i < NUM_COMMUNITY; i++)
    {
        ai->seeds[seed_index] = rand_r((unsigned int *)&ai->seeds[seed_index]);
        rand_num = ai->seeds[seed_index];
        community[i] = draw(deck, &decksize, rand_num);
    }

    //Give each opponent their cards
    for (int opp = 0; opp < game->num_playing; opp++)
    {
        //Personal cards
        for (int i = 0; i < NUM_HAND; i++)
        {
            ai->seeds[seed_index] = rand_r((unsigned int *)&ai->seeds[seed_index]);
            rand_num = ai->seeds[seed_index];
            opponents[opp][i] = draw(deck, &decksize, rand_num);
        }

        //Community cards
        for (int i = NUM_HAND; i < NUM_COMMUNITY + NUM_HAND; i++)
        {
            opponents[opp][i] = community[i - NUM_HAND];
        }
    }

    //Put my cards into a new array
    for (int i = 0; i < NUM_HAND; i++)
    {
        me[i] = game->hand[i];
    }
    for (int i = NUM_HAND; i < NUM_HAND + NUM_COMMUNITY; i++)
    {
        me[i] = community[i - NUM_HAND];
    }

    //See who won
    myscore = GetHandValue(me, NUM_HAND + NUM_COMMUNITY);
    bestopponent = BestOpponentHand(opponents, game->num_playing, NUM_HAND + NUM_COMMUNITY);

    //Free allocated memory
    for (int i = 0; i < game->num_playing; i++)
    {
        free(opponents[i]);
    }

    //Count ties as a win
    return (myscore >= bestopponent);
}
bool
OmahaWinnerCalculator::CalculateWinners(PokerTableInfo* pTableInfo, List<PokerHandWinnerInfo>* pWinners, float fRakePercent, 
										UINT& nRakeAmount, INT_CHIPS& nTotalPotAmount, bool& bOpenWinnersCards, bool& bTableCardsIsTheBestComb, int* pArrSeatsBestHandCards){
	int	nInPlaySeatCt	= pTableInfo->CountSeatsByStatus(PokerSeatStatus::InPlay) + (pTableInfo->m_bTournamentTable ? pTableInfo->CountSeatsByStatus(PokerSeatStatus::SittedOut) : 0);
	int	nAllInSeatCt	= pTableInfo->CountSeatsByStatus(PokerSeatStatus::All_In);
	nRakeAmount			= 0;
	nTotalPotAmount		= pTableInfo->GetTotalPotAmount();
	bOpenWinnersCards	= false;
	bTableCardsIsTheBestComb	= false;

	// WITHOUT CALCULATION. {{
	// Calculation is not needed becouse only one seat is active.
	if( (nInPlaySeatCt + nAllInSeatCt) == 1 ){
		PokerTableSeatInfo* pWinnerSeat = pTableInfo->GetNextSeatInfoByStatus(-1, PokerSeatStatus::All_In);
		if( pWinnerSeat == NULL )
			pWinnerSeat = pTableInfo->GetNextSeatInfoByStatus(-1, PokerSeatStatus::InPlay);
		if( pWinnerSeat == NULL ){ // Can not calculate !!
			if( pTableInfo->m_bTournamentTable )
				pWinnerSeat = pTableInfo->GetNextSeatInfoByStatus(-1, PokerSeatStatus::SittedOut);
			if( !pWinnerSeat )
				return false;
			}

		// Calculate return back amount. {{
		UINT nLoop				= 0, nCt = pTableInfo->m_cMaxPlayersCt;;
		INT_CHIPS nWinnersPot	= pWinnerSeat->GetTotalPot();
		int nWinnerSeat			= pWinnerSeat->GetSeat();
		INT_CHIPS nReturnBackAmount	= 0, nSecondPot	 = 0;

		while( nLoop < nCt ){
			if( nLoop != nWinnerSeat ){
				INT_CHIPS nPot = pTableInfo->GetSeatTotalPot(nLoop);
				if( nPot > nSecondPot )
					nSecondPot = nPot;
				}
			nLoop ++;
			}
		nReturnBackAmount = max((nWinnersPot - nSecondPot), 0);
		// }}

		nTotalPotAmount					-= nReturnBackAmount;
		nRakeAmount						= pTableInfo->CalculateRakeAmount(nTotalPotAmount);
		
		PokerHandWinnerInfo* pWinner	= new PokerHandWinnerInfo();
		pWinner->m_cSeat				= (char)pWinnerSeat->GetSeat();
		pWinner->m_nBalance				= pWinnerSeat->GetBalance();
		pWinner->m_nWonAmount			= (nTotalPotAmount - nRakeAmount);
		pWinner->m_nReturnBackAmount	= nReturnBackAmount;
		pWinner->m_cHandCardClass		= PokerHandCardsClass::CardsClass_None;
		pWinnerSeat->SetBalance			(pWinnerSeat->GetBalance() + pWinner->m_nWonAmount);
		pWinnerSeat->SetHandWonState	(true); // Set hand won state.
		pWinners->Add(pWinner);

		PokerWonAmountDetail* pDetail	= new PokerWonAmountDetail();
		pDetail->m_cPotIndex			= 0; // Main pot
		pDetail->m_nWonAmount			= pWinner->m_nWonAmount;
		pWinner->m_listWonAmountDetail.Add(pDetail);

		// Return back amount.
		pWinnerSeat->SetBalance(pWinnerSeat->GetBalance() + nReturnBackAmount);
		return true;
		}
	// }}

	AutoSortedArray arrSeatSidePots;
	List<SidePotInfoStruct> listSidePots;
	listSidePots.SetDestroyObjects(true);
	pTableInfo->CalculateSidePots(listSidePots);

	int nTableCard1		= pTableInfo->GetTableCard1();
	int nTableCard2		= pTableInfo->GetTableCard2();
	int nTableCard3		= pTableInfo->GetTableCard3();
	int nTableCard4		= pTableInfo->GetTableCard4();
	int nTableCard5		= pTableInfo->GetTableCard5();
	int	nTableVal		= GetHandValue(GetCardValue(nTableCard1), GetCardValue(nTableCard2), GetCardValue(nTableCard3),
						GetCardValue(nTableCard4), GetCardValue(nTableCard5));

	UINT nLoop			= 0, nCt = (char)pTableInfo->m_cMaxPlayersCt;
	List<PokerTableSeatInfo> *pParticipants = new List<PokerTableSeatInfo>();
	pParticipants->SetDestroyObjects(FALSE);

	while( nLoop < nCt ){
		PokerTableSeatInfo* pInfo = pTableInfo->GetSeatInfo(nLoop);
		if( pInfo && pTableInfo->IsInPlayByStatus(nLoop, pInfo->GetStatus()) /*pInfo->GetStatus() == PokerSeatStatus::All_In || pInfo->GetStatus() == PokerSeatStatus::InPlay)*/ ){
			pParticipants->Add(pInfo);
			}
		nLoop ++;
		}

	int				arrCards[]			= {	GetCardValue(nTableCard1), GetCardValue(nTableCard2), 
											GetCardValue(nTableCard3), GetCardValue(nTableCard4), 
											GetCardValue(nTableCard5)};

	int				arrCardsReplaced[]	= {	GetCardValue(nTableCard1), GetCardValue(nTableCard2), 
											GetCardValue(nTableCard3), GetCardValue(nTableCard4), 
											GetCardValue(nTableCard5)};

	int				arrWinnerCardsIdx[]	= {	4, 5, 6, 7, 8 }; // Copy best combinations card indexes.((0, 1, 2, 3) - identifies hand cards (4, 5, 6, 7, 8) = identifies table cards)

	AutoSortedArray	arrHandValByHandCombination;
	struct HandCombination{
		PokerTableSeatInfo* pSeatInfo;
		int					nHandValue;
		int					arrWinnerCardsIdx[5];
		};

	for(int i=0; i<pParticipants->GetCount(); i++){
		PokerTableSeatInfo* pInfo = pParticipants->GetAt(i);
		ASSERT(pInfo);

		int nHandCard1					= GetCardValue(pInfo->GetCard1());
		int nHandCard2					= GetCardValue(pInfo->GetCard2());
		int nHandCard3					= GetCardValue(pInfo->GetCard3());
		int nHandCard4					= GetCardValue(pInfo->GetCard4());
		int nBestHandCardsVal			= 0x7fffffff;
		int nBestHandCardsValTemp		= 0;
		HandCombination*	pHandComb	= new HandCombination;
		pHandComb->pSeatInfo			= pInfo;

		struct HandCardsCombination{
			int nHandCardVal1;
			int nHandCardVal2;
			int nHandCardIndex1;
			int nHandCardIndex2;
			};

		HandCardsCombination	comb[] = 
			{
			{nHandCard1, nHandCard2, 0, 1}, 
			{nHandCard1, nHandCard3, 0, 2}, 
			{nHandCard1, nHandCard4, 0, 3}, 
			{nHandCard2, nHandCard3, 1, 2}, 
			{nHandCard2, nHandCard4, 1, 3}, 
			{nHandCard3, nHandCard4, 2, 3}
			};

		for( int x=0; x<6; x++){
			HandCardsCombination* pComb = &comb[x];
			for( int j=0; j<5; j++ ){
				for( int k=j+1; k<5; k++ ){
					// Copy cards array.
					memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
					arrCardsReplaced[j] = pComb->nHandCardVal1;
					arrCardsReplaced[k] = pComb->nHandCardVal2;

					nBestHandCardsValTemp = GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
					if( nBestHandCardsVal > nBestHandCardsValTemp ){
						nBestHandCardsVal		= nBestHandCardsValTemp;
						arrWinnerCardsIdx[0]	= 4;						// table card 1 index
						arrWinnerCardsIdx[1]	= 5;						// table card 2 index
						arrWinnerCardsIdx[2]	= 6;						// table card 3 index
						arrWinnerCardsIdx[3]	= 7;						// table card 4 index
						arrWinnerCardsIdx[4]	= 8;						// table card 5 index
						arrWinnerCardsIdx[j]	= pComb->nHandCardIndex1;	// hand card index
						arrWinnerCardsIdx[k]	= pComb->nHandCardIndex2;	// hand card index
						}
					}
				}
			}

		// Set best hand card class.
		if( pArrSeatsBestHandCards )
			pArrSeatsBestHandCards[pHandComb->pSeatInfo->GetSeat()] =  (int)CardsHandClass(nBestHandCardsVal, NULL);

		pHandComb->nHandValue = nBestHandCardsVal;
		memcpy(pHandComb->arrWinnerCardsIdx, arrWinnerCardsIdx, sizeof(arrWinnerCardsIdx));
		// Save calculated hand value with combination info.
		arrHandValByHandCombination.Add((void*)nBestHandCardsVal, (void*)pHandComb);
		}

	if( arrHandValByHandCombination.GetCount() <= 0 ){
		delete pParticipants;
		return false;
		}

	// Determine winner seat(s). {{
	arrHandValByHandCombination.Add((void*)nTableVal, 0);
	int			nMaxHandVal			= (int)arrHandValByHandCombination.Get(0);
	_String		sHandClassName;
	INT_CHIPS	nAwardAmount		= nTotalPotAmount, nAllAwardAmount	= 0;
	bool		bTableCombIsTheBest = (nMaxHandVal == nTableVal && ((int)arrHandValByHandCombination.Get(1)) >= nTableVal);
	bTableCardsIsTheBestComb		= bTableCombIsTheBest;

	// Remove table cards combination. {{
	nLoop = 0, nCt = arrHandValByHandCombination.GetCount();
	while( nLoop < nCt ){
		if( arrHandValByHandCombination.GetData(nLoop) == 0 ){
			arrHandValByHandCombination.Delete(nLoop);
			break;
			}
		nLoop ++;
		}
	// }}

	int nPotIndex = 0;
	while( nAwardAmount > 0 ){
		if( !arrHandValByHandCombination.GetCount() ){
			//ASSERT(FALSE);
			// By some divisions of pot amounts there are some remnant amount and below we are sharing that amount to winners.
			int			nWinnersCt			= pWinners->GetCount();
			INT_CHIPS	nShareForOneWinner	= nWinnersCt > 0 ? (nAwardAmount / nWinnersCt) : 0;
			INT_CHIPS	nRemain				= nWinnersCt > 0 ? (nAwardAmount % nWinnersCt) : 0;
			if( nShareForOneWinner < 1 ){
				nShareForOneWinner	= 1;
				nWinnersCt			= (int)nAwardAmount;
				nRemain				= 0;
				}

			for(int i=0; i<nWinnersCt; i++){
				PokerHandWinnerInfo* pWinner	= pWinners->GetAt(i);
				if( !pWinner ) continue;
				if( i == (pWinners->GetCount() - 1) ){
					pWinner->m_nWonAmount	+= (nShareForOneWinner + nRemain);
					nAllAwardAmount			+= (nShareForOneWinner + nRemain);
					}
				else{
					pWinner->m_nWonAmount	+= nShareForOneWinner;
					nAllAwardAmount			+= nShareForOneWinner;
					}
				}
			break;
			}

		int nWinnersCt	= 1;
		if( !bTableCombIsTheBest ){
			nMaxHandVal	= (int)arrHandValByHandCombination.Get(0);
			for(UINT i=1; i<arrHandValByHandCombination.GetCount(); i++){
				if( ((int)arrHandValByHandCombination.Get(i)) != nMaxHandVal )
					break;
				nWinnersCt ++;
				}
			}
		else{
			nWinnersCt	= arrHandValByHandCombination.GetCount();
			nMaxHandVal	= nTableVal;
			}

		int nSidePotsUsed = 0;
		for(int i=0; i<nWinnersCt; i++){
			HandCombination*	pComb		= (HandCombination*)arrHandValByHandCombination.GetData(i);
			ASSERT(pComb);
			PokerTableSeatInfo* pSeatInfo	= pComb->pSeatInfo;
			PokerHandWinnerInfo* pWinner	= NULL;

			arrSeatSidePots.DeleteAll();
			if( pTableInfo->GetSeatSidePots(listSidePots, pSeatInfo->GetSeat(), arrSeatSidePots) > nPotIndex ){
				for(UINT j=nPotIndex; j<arrSeatSidePots.GetCount(); j++){
					if( !pWinner ){
						pWinner						= new PokerHandWinnerInfo();
						pWinner->m_cSeat			= (char)pSeatInfo->GetSeat();
						pWinner->m_cHandCardClass	= (char)CardsHandClass(nMaxHandVal, &sHandClassName);
						pWinner->m_nBalance			= pSeatInfo->GetBalance();
						pWinner->m_nWonAmount		= 0;
						pWinner->m_nReturnBackAmount= 0;
						pWinner->m_bWinner			= true;
						}

					INT_CHIPS nSeatPotAmount		= (INT_CHIPS)arrSeatSidePots.GetData(j);
					INT_CHIPS nWonAmountFromThatPot	= (nSeatPotAmount * listSidePots[j]->nSeatsCtBelongsTo) / nWinnersCt;
					pWinner->m_nWonAmount			+= nWonAmountFromThatPot;

					PokerWonAmountDetail* pDetail	= new PokerWonAmountDetail();
					pDetail->m_cPotIndex			= (char)arrSeatSidePots.Get(j);
					pDetail->m_nWonAmount			= nWonAmountFromThatPot;
					pDetail->m_wRakeAmount			= (UINT)pTableInfo->CalculateRakeAmount(nWonAmountFromThatPot);
					pWinner->m_listWonAmountDetail.Add(pDetail);
						
					nAwardAmount					-= nWonAmountFromThatPot;
					nAllAwardAmount					+= nWonAmountFromThatPot;
					}
				nSidePotsUsed = max(nSidePotsUsed, arrSeatSidePots.GetCount() - nPotIndex);
				}

			if( pWinner ){
				if( bTableCombIsTheBest ){
					pWinner->m_cWinnerCard1		= 4;	// table card 1 index
					pWinner->m_cWinnerCard2		= 5;	// table card 2 index
					pWinner->m_cWinnerCard3		= 6;	// table card 3 index
					pWinner->m_cWinnerCard4		= 7;	// table card 4 index
					pWinner->m_cWinnerCard5		= 8;	// table card 5 index
					}
				else{
					pWinner->m_cWinnerCard1		= (char)pComb->arrWinnerCardsIdx[0];
					pWinner->m_cWinnerCard2		= (char)pComb->arrWinnerCardsIdx[1];
					pWinner->m_cWinnerCard3		= (char)pComb->arrWinnerCardsIdx[2];
					pWinner->m_cWinnerCard4		= (char)pComb->arrWinnerCardsIdx[3];
					pWinner->m_cWinnerCard5		= (char)pComb->arrWinnerCardsIdx[4];
					}
				pWinners->Add(pWinner);
				}
			}

		// Delete winners combinations. {{
		nLoop = 0;
		while(nLoop < nWinnersCt ){
			HandCombination*	pComb = (HandCombination*)arrHandValByHandCombination.GetData(0);
			ASSERT(pComb);
			delete pComb; // Delete combination info class object
			arrHandValByHandCombination.Delete(0);
			nLoop ++;
			}
		// }}			
		nPotIndex	+= nSidePotsUsed;
		}

	// Delete losers combinations. {{
	while( arrHandValByHandCombination.GetCount() ){
		HandCombination*	pComb = (HandCombination*)arrHandValByHandCombination.GetData(0);
		ASSERT(pComb);
		delete pComb; // Delete combination info class object
		arrHandValByHandCombination.Delete(0);
		}
	// }}
	UNUSED(arrHandValByHandCombination);
	// }}

	AutoSortedArray arrWinnerSeats; // Winner seats ordered from dealer clockwise.
	UINT nRakeAmountSum = 0, nMaxSeatCt = (int)pTableInfo->m_cMaxPlayersCt;
	nRakeAmount = pTableInfo->CalculateRakeAmount(nAllAwardAmount);
	for(int i=0; i<pWinners->GetCount(); i++){
		PokerHandWinnerInfo* pWinner = pWinners->GetAt(i);
		if( pWinner->m_bWinner ){
			int						nSeat	= (int)pWinner->m_cSeat;
			if( nAllAwardAmount > 0 ){
				// Won percent from total pot.
				float					fWonPercent	= (float)(pWinner->m_nWonAmount / ((float)nAllAwardAmount));
				// Won amount.
				float fRakeAmount					= (float)(nRakeAmount * fWonPercent) / 100.0f;
				nRakeAmountSum						+= (UINT)Serializable::ConvertMoney(fRakeAmount);
				pWinner->m_nWonAmount				-= (UINT)Serializable::ConvertMoney(fRakeAmount);

				// Arrange info clokwise from dealler seat.
				if( nSeat <= pTableInfo->m_cDealerSeat )
					arrWinnerSeats.Add((void*)(nMaxSeatCt - (((int)pTableInfo->m_cDealerSeat) - nSeat)), (void*)pWinner);
				else
					arrWinnerSeats.Add((void*)((nSeat - 1) - ((int)pTableInfo->m_cDealerSeat)), (void*)pWinner);
				}

			// Set seat balance.
			pTableInfo->SetBalance		(nSeat, pTableInfo->GetBalance(nSeat) + pWinner->m_nWonAmount + pWinner->m_nReturnBackAmount);
			// Set seat won state.
			pTableInfo->SetHandWonState	(nSeat, true);
			}
		}

	// Award one seat after dealer(clockwise) with fraction amount remnant from total pot.
	int nRemnantFractionOfPot = (nRakeAmountSum - nRakeAmount);
	if( nRemnantFractionOfPot != 0 ){
		int nAmountAddToEach = (nRemnantFractionOfPot / (int)arrWinnerSeats.GetCount());
		int nFraction		 = abs(nRemnantFractionOfPot % (int)arrWinnerSeats.GetCount());
		int nSign			 = (nRemnantFractionOfPot > 0 ? 1 : -1);

		for(int i=0; i<arrWinnerSeats.GetCount(); i++){
			PokerHandWinnerInfo* pWinner = (PokerHandWinnerInfo*)arrWinnerSeats.GetData(i);
			if( pWinner ){
				int	nSeat				= (int)pWinner->m_cSeat;
				if( nFraction > 0 ){
					pWinner->m_nWonAmount	+= (nAmountAddToEach + 1*nSign);
					pWinner->m_nBalance		+= (nAmountAddToEach + 1*nSign);
					nFraction --;
					}
				else{
					pWinner->m_nWonAmount	+= nAmountAddToEach;
					pWinner->m_nBalance		+= nAmountAddToEach;
					}
				// Set seat balance.
				pTableInfo->SetBalance(nSeat, pWinner->m_nBalance);
				}
			}
		/* Old code.
		PokerHandWinnerInfo* pWinner = (PokerHandWinnerInfo*)arrWinnerSeats.GetData(0);
		ASSERT(pWinner);
		if( pWinner ){
			int	nSeat				= (int)pWinner->m_cSeat;
			pWinner->m_nWonAmount	+= nRemnantFractionOfPot;
			// Set seat balance.
			pTableInfo->SetBalance(nSeat, pTableInfo->GetBalance(nSeat) + nRemnantFractionOfPot);
			}*/
		}

	bOpenWinnersCards = true;
	delete pParticipants;
	return true;
	}
int
OmahaWinnerCalculator::GetBestHandCardValue(int nCard1, int nCard2, int nCard3, int nCard4, 
											int nTableCard1, int nTableCard2, int nTableCard3, int nTableCard4, int nTableCard5, 
											PokerHandCardsClass& cardsClass, CDWordArray& arrCardsIdx){
	if( nTableCard1 <= -1 || nTableCard2 <= -1 || nTableCard3 <= -1 ){
		cardsClass = PokerHandCardsClass::CardsClass_None;
		return PokerHandCardsClass::CardsClass_None;
		}

	int				arrCards[]			= {	GetCardValue(nTableCard1), GetCardValue(nTableCard2), 
											GetCardValue(nTableCard3), GetCardValue(nTableCard4), 
											GetCardValue(nTableCard5)};
	int				arrCardsReplaced[]	= {	arrCards[0], arrCards[1], arrCards[2], arrCards[3], arrCards[4]}; 
	int				arrWinnerCardsIdx[]	= {	4, 5, 6, 7, 8 }; // Copy best combinations card indexes.((0, 1, 2, 3) - identifies hand cards (4, 5, 6, 7, 8) = identifies table cards)

	struct HandCardsCombination{
		int nHandCardVal1;
		int nHandCardVal2;
		int nHandCardIndex1;
		int nHandCardIndex2;
		};

	int nHandCardVal1			= GetCardValue(nCard1);
	int nHandCardVal2			= GetCardValue(nCard2);
	int nHandCardVal3			= GetCardValue(nCard3);
	int nHandCardVal4			= GetCardValue(nCard4);
	int nBestHandCardsVal		= 0x7fffffff;
	int nBestHandCardsValTemp	= 0;

	HandCardsCombination	comb[] = 
		{
		{nHandCardVal1, nHandCardVal2, 0, 1}, 
		{nHandCardVal1, nHandCardVal3, 0, 2}, 
		{nHandCardVal1, nHandCardVal4, 0, 3}, 
		{nHandCardVal2, nHandCardVal3, 1, 2}, 
		{nHandCardVal2, nHandCardVal4, 1, 3}, 
		{nHandCardVal3, nHandCardVal4, 2, 3}
		};

	// 3 table cards
	if( nTableCard4 <= -1 ){
		for( int x=0; x<6; x++){
			HandCardsCombination* pComb = &comb[x];
			// Copy cards array.
			memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
			arrCardsReplaced[3]			= pComb->nHandCardVal1;
			arrCardsReplaced[4]			= pComb->nHandCardVal2;

			nBestHandCardsValTemp = GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
			if( nBestHandCardsVal > nBestHandCardsValTemp ){
				nBestHandCardsVal		= nBestHandCardsValTemp;
				arrWinnerCardsIdx[0]	= 4;						// table card 1 index
				arrWinnerCardsIdx[1]	= 5;						// table card 2 index
				arrWinnerCardsIdx[2]	= 6;						// table card 3 index
				arrWinnerCardsIdx[3]	= pComb->nHandCardIndex1;	// hand card index
				arrWinnerCardsIdx[4]	= pComb->nHandCardIndex2;	// hand card index
				}
			}

		}
	else
	// 4 table cards.
	if( nTableCard5 <= -1 ){
		for( int x=0; x<6; x++){
			HandCardsCombination* pComb = &comb[x];
			for( int j=0; j<4; j++ ){
				// Copy cards array.
				memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
				arrCardsReplaced[j]			= pComb->nHandCardVal1;
				arrCardsReplaced[4]			= pComb->nHandCardVal2;

				nBestHandCardsValTemp = GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
				if( nBestHandCardsVal > nBestHandCardsValTemp ){
					nBestHandCardsVal		= nBestHandCardsValTemp;
					arrWinnerCardsIdx[0]	= 4;						// table card 1 index
					arrWinnerCardsIdx[1]	= 5;						// table card 2 index
					arrWinnerCardsIdx[2]	= 6;						// table card 3 index
					arrWinnerCardsIdx[3]	= 7;						// table card 4 index
					arrWinnerCardsIdx[4]	= pComb->nHandCardIndex2;	// hand card index
					arrWinnerCardsIdx[j]	= pComb->nHandCardIndex1;	// hand card index
					}
				}
			}
		}
	// 5 table cards.
	else{
		for( int x=0; x<6; x++){
			HandCardsCombination* pComb = &comb[x];
			for( int j=0; j<5; j++ ){
				for( int k=j+1; k<5; k++ ){
					// Copy cards array.
					memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
					arrCardsReplaced[j] = pComb->nHandCardVal1;
					arrCardsReplaced[k] = pComb->nHandCardVal2;

					nBestHandCardsValTemp = GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
					if( nBestHandCardsVal > nBestHandCardsValTemp ){
						nBestHandCardsVal		= nBestHandCardsValTemp;
						arrWinnerCardsIdx[0]	= 4;						// table card 1 index
						arrWinnerCardsIdx[1]	= 5;						// table card 2 index
						arrWinnerCardsIdx[2]	= 6;						// table card 3 index
						arrWinnerCardsIdx[3]	= 7;						// table card 4 index
						arrWinnerCardsIdx[4]	= 8;						// table card 5 index
						arrWinnerCardsIdx[j]	= pComb->nHandCardIndex1;	// hand card index
						arrWinnerCardsIdx[k]	= pComb->nHandCardIndex2;	// hand card index
						}
					}
				}
			}
		}

	_String sClassName;
	cardsClass = CardsHandClass(nBestHandCardsVal, &sClassName);
	if( cardsClass != PokerHandCardsClass::CardsClass_None ){
		arrCardsIdx.Add(arrWinnerCardsIdx[0]);
		arrCardsIdx.Add(arrWinnerCardsIdx[1]);
		arrCardsIdx.Add(arrWinnerCardsIdx[2]);
		arrCardsIdx.Add(arrWinnerCardsIdx[3]);
		arrCardsIdx.Add(arrWinnerCardsIdx[4]);
		}
	return nBestHandCardsVal;
	}
int
HoldemWinnerCalculator::GetBestHandCardValue(int nCard1, int nCard2, int nCard3, int nCard4, 
											int nTableCard1, int nTableCard2, int nTableCard3, int nTableCard4, int nTableCard5, 
											PokerHandCardsClass& cardsClass, CDWordArray& arrCardsIdx){

	UNUSED(nCard3);
	UNUSED(nCard4);

	if( nTableCard1 <= -1 || nTableCard2 <= -1 || nTableCard3 <= -1 ){
		cardsClass = PokerHandCardsClass::CardsClass_None;
		return PokerHandCardsClass::CardsClass_None;
		}

	int				arrCards[]			= {	GetCardValue(nTableCard1), GetCardValue(nTableCard2), 
											GetCardValue(nTableCard3), GetCardValue(nTableCard4), 
											GetCardValue(nTableCard5)};
	int				arrCardsReplaced[]	= {	arrCards[0], arrCards[1], arrCards[2], arrCards[3], arrCards[4]}; 
	int				arrWinnerCardsIdx[]	= {	4, 5, 6, 7, 8 }; // Copy best combinations card indexes.((0, 1, 2, 3) - identifies hand cards (4, 5, 6, 7, 8) = identifies table cards)


	int nHandCardVal1			= GetCardValue(nCard1);
	int nHandCardVal2			= GetCardValue(nCard2);
	int nBestHandCardsVal		= 0x7fffffff;
	int nBestHandCardsValTemp	= 0;

	// 3 table cards
	if( nTableCard4 <= -1 ){
		arrCardsReplaced[3]		= nHandCardVal1;
		arrCardsReplaced[4]		= nHandCardVal2;
		nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
		if( nBestHandCardsVal > nBestHandCardsValTemp ){
			nBestHandCardsVal = nBestHandCardsValTemp;

			arrWinnerCardsIdx[0] = 4; // table card 1 index
			arrWinnerCardsIdx[1] = 5; // table card 2 index
			arrWinnerCardsIdx[2] = 6; // table card 3 index
			arrWinnerCardsIdx[3] = 0; // hand card 1
			arrWinnerCardsIdx[4] = 1; // hand card 2
			}
		}
	else
	// 4 table cards.
	if( nTableCard5 <= -1 ){
		arrCardsReplaced[4]		= nHandCardVal1;
		nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
		if( nBestHandCardsVal > nBestHandCardsValTemp ){
			nBestHandCardsVal = nBestHandCardsValTemp;

			arrWinnerCardsIdx[0] = 4; // table card 1 index
			arrWinnerCardsIdx[1] = 5; // table card 2 index
			arrWinnerCardsIdx[2] = 6; // table card 3 index
			arrWinnerCardsIdx[3] = 7; // table card 4 index
			arrWinnerCardsIdx[4] = 0; // hand card 1
			}

		for( int j=0; j<4; j++ ){
			// Copy cards array.
			memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));

			arrCardsReplaced[j] = nHandCardVal2;
			arrCardsReplaced[4] = nHandCardVal1;

			nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
			if( nBestHandCardsVal > nBestHandCardsValTemp ){
				nBestHandCardsVal = nBestHandCardsValTemp;

				arrWinnerCardsIdx[0] = 4; // table card 1 index
				arrWinnerCardsIdx[1] = 5; // table card 2 index
				arrWinnerCardsIdx[2] = 6; // table card 3 index
				arrWinnerCardsIdx[3] = 7; // table card 4 index
				arrWinnerCardsIdx[4] = 8; // table card 5 index

				arrWinnerCardsIdx[j] = 1; // hand card 2 index
				arrWinnerCardsIdx[4] = 0; // hand card 1 index
				}
			}

		memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
		arrCardsReplaced[4] = nHandCardVal2;

		nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
		if( nBestHandCardsVal > nBestHandCardsValTemp ){
			nBestHandCardsVal = nBestHandCardsValTemp;

			arrWinnerCardsIdx[0] = 4; // table card 1 index
			arrWinnerCardsIdx[1] = 5; // table card 2 index
			arrWinnerCardsIdx[2] = 6; // table card 3 index
			arrWinnerCardsIdx[3] = 7; // table card 4 index
			arrWinnerCardsIdx[4] = 1; // hand card 2 index
			}

		for( int j=0; j<4; j++ ){
			// Copy cards array.
			memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));

			arrCardsReplaced[j] = nHandCardVal1;
			arrCardsReplaced[4] = nHandCardVal2;

			nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
			if( nBestHandCardsVal > nBestHandCardsValTemp ){
				nBestHandCardsVal = nBestHandCardsValTemp;

				arrWinnerCardsIdx[0] = 4; // table card 1 index
				arrWinnerCardsIdx[1] = 5; // table card 2 index
				arrWinnerCardsIdx[2] = 6; // table card 3 index
				arrWinnerCardsIdx[3] = 7; // table card 4 index
				arrWinnerCardsIdx[4] = 1; // hand card 2 index
				arrWinnerCardsIdx[j] = 0; // hand card 1 index
				}
			}
		}
	// 5 table cards.
	else{
		for( int j=0; j<5; j++ ){
			// Copy cards array.
			memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
			arrCardsReplaced[j] = nHandCardVal1;

			nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
			if( nBestHandCardsVal > nBestHandCardsValTemp ){
				nBestHandCardsVal = nBestHandCardsValTemp;

				arrWinnerCardsIdx[0] = 4; // table card 1 index
				arrWinnerCardsIdx[1] = 5; // table card 2 index
				arrWinnerCardsIdx[2] = 6; // table card 3 index
				arrWinnerCardsIdx[3] = 7; // table card 4 index
				arrWinnerCardsIdx[4] = 8; // table card 5 index

				arrWinnerCardsIdx[j] = 0; // hand card 1 index
				}
			}

		for( int j=0; j<5; j++ ){
			// Copy cards array.
			memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));
			arrCardsReplaced[j] = nHandCardVal2;

			nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
			if( nBestHandCardsVal > nBestHandCardsValTemp ){
				nBestHandCardsVal = nBestHandCardsValTemp;

				arrWinnerCardsIdx[0] = 4; // table card 1 index
				arrWinnerCardsIdx[1] = 5; // table card 2 index
				arrWinnerCardsIdx[2] = 6; // table card 3 index
				arrWinnerCardsIdx[3] = 7; // table card 4 index
				arrWinnerCardsIdx[4] = 8; // table card 5 index
				arrWinnerCardsIdx[j] = 1; // hand card 2 index
				}
			}

		for( int j=0; j<5; j++ ){
			for( int k=j+1; k<5; k++ ){
				// Copy cards array.
				memcpy(arrCardsReplaced, arrCards, sizeof(arrCards));

				arrCardsReplaced[j] = nHandCardVal1;
				arrCardsReplaced[k] = nHandCardVal2;

				nBestHandCardsValTemp	= GetHandValue(arrCardsReplaced[0], arrCardsReplaced[1], arrCardsReplaced[2], arrCardsReplaced[3], arrCardsReplaced[4]);
				if( nBestHandCardsVal > nBestHandCardsValTemp ){
					nBestHandCardsVal = nBestHandCardsValTemp;

					arrWinnerCardsIdx[0] = 4; // table card 1 index
					arrWinnerCardsIdx[1] = 5; // table card 2 index
					arrWinnerCardsIdx[2] = 6; // table card 3 index
					arrWinnerCardsIdx[3] = 7; // table card 4 index
					arrWinnerCardsIdx[4] = 8; // table card 5 index

					arrWinnerCardsIdx[j] = 0; // hand card 1 index
					arrWinnerCardsIdx[k] = 1; // hand card 2 index
					}
				}
			}
		}

	_String sClassName;
	cardsClass = CardsHandClass(nBestHandCardsVal, &sClassName);
	if( cardsClass != PokerHandCardsClass::CardsClass_None ){
		arrCardsIdx.Add(arrWinnerCardsIdx[0]);
		arrCardsIdx.Add(arrWinnerCardsIdx[1]);
		arrCardsIdx.Add(arrWinnerCardsIdx[2]);
		arrCardsIdx.Add(arrWinnerCardsIdx[3]);
		arrCardsIdx.Add(arrWinnerCardsIdx[4]);
		}
	return nBestHandCardsVal;
	}