void CIteratorThread::StandardDealingAlgorithmForUpTo13Opponents(int nopponents)
{
	unsigned int	card = 0;

	write_log(Preferences()->debug_prwin(), "[PrWinThread] Using random algorithm, as f$prwin_number_of_opponents <= 13\n");
	// random replacement algorithm
	// opponent cards
	if (nopponents < 1) {
		write_log(Preferences()->debug_prwin(), "[PrWinThread] No opponents. Auto-adapting to 1.\n");
    nopponents = 1;
	}
	for (int i=0; 
		i<nopponents*NumberOfCardsPerPlayer(); 
		i+=NumberOfCardsPerPlayer())
	{
		temp_usedCards=usedCards;
		do
		{
			usedCards = temp_usedCards; //reset the card mask to clear settings from failed card assignments

			for (int j=0; j<NumberOfCardsPerPlayer(); j++)
			{
				card = GetRandomCard();
				CardMask_SET(usedCards, card);
				ocard[i+j] = card;
			}

			if (!_willplay)
			{
				write_log(Preferences()->debug_prwin(), "[PrWinThread] Weighting disabled. Willplay is 0.\n");
				break; //0 disables weighting
			}

			//put break for i=0 and opponent unraised BB case (cannot assume anything about his cards)
			//In round 1 we should really do an analysis of chairs to find out how many have still to
			//place a bet. Not implemented since accuracy of prwin pre-flop is less critical.
			//
      // bblimp and special handling for checking players removed in OH 9.2.8
      // as it was broken and we consider it useless / even harmful.
      // http://www.maxinmontreal.com/forums/viewtopic.php?f=156&t=19064
		} while (!IsHandInWeightedRange(ocard[i], ocard[i+1],
			_willplay, _wontplay, 
			_topclip, _mustplay));
	}
	// additional common cards
	CardMask_RESET(addlcomCards);
	for (int i=0; i<(kNumberOfCommunityCards - _ncomCards); i++)
	{
		card = GetRandomCard();
		CardMask_SET(usedCards, card);
		CardMask_SET(addlcomCards, card);
	}
}
void CIteratorThread::EnhancedDealingAlgorithm()
{
	// Dealing algorithm for enhanced prwin
	// (user-defined weighting at DLL-level).
	write_log(preferences.debug_prwin(), "[PrWinThread] Using Matrix's enhanced prwin.\n");

	//prw1326 active  Matrix 2008-05-08
	int k = 0; //k is used as an index into ocard[] 
	unsigned int	card = 0;

	int userchair = p_symbol_engine_userchair->userchair();
	int playersplayingbits = p_symbol_engine_active_dealt_playing->playersplayingbits();
	//we have to use actual opponents for prw1326 calculations
	int nopponents = bitcount(playersplayingbits & ~(1 << userchair));
	int betround   = p_betround_calculator->betround();
	int bblindbits = p_symbol_engine_blinds->bblindbits();

	// loop through active opponents
	for(int i=0; i<k_max_number_of_players; i++) 
	{
		if (i == userchair)
			continue; //skip our own chair!

		if (!(playersplayingbits & (1<<i)))
			continue; //skip inactive chairs 

		// first deal with the special non-weighted cases
		// player who is marked 'ignore' or one who is BB and has not VPIP'd
		if (_prw1326.chair[i].ignore || 
			(_prw1326.bblimp && p_symbol_engine_history->nbetsround(betround)<1.1 
				&& (bblindbits&(1<<i))) )
		{
			card = GetRandomCard();
			CardMask_SET(usedCards, card);
			ocard[k++] = card;

			card = GetRandomCard();
			CardMask_SET(usedCards, card);
			ocard[k++] = card;

			continue;
		} // end of special non-weighted cases

		int randfix=(RAND_MAX/_prw1326.chair[i].limit) * _prw1326.chair[i].limit;

		int j;
		while (true)
		{ //find a possible hand for this chair NOTE: may want to put in loop limits to prevent hanging
			do 
			{
				j=rand();
			} while (j>=randfix);

			j = j % _prw1326.chair[i].limit; //j is now any one of the allowed hands

			if(CardMask_CARD_IS_SET(usedCards, _prw1326.chair[i].rankhi[j] ))
				continue; //hand contains dead card

			if(CardMask_CARD_IS_SET(usedCards, _prw1326.chair[i].ranklo[j] ))
				continue; //hand contains dead card

//					if(symbols.prw1326.chair[i].ignore)break; //chair marked as not to be weighted

			if(_prw1326.chair[i].level <= _prw1326.chair[i].weight[j])
				break; //hand marked as always uae

			//check if we want a player who is BB and has not VPIP'd to be analysed further
//					if(symbols.prw1326.bblimp)
//					{
//					if ((symbols.sym.nbetsround[0]<1.1) && ((int)symbols.sym.bblindbits&(1<<i)))break;
//					}

			//we should really do a 'randfix' here for the case where RAND_MAX is not an integral
			//multiple of .level, but the bias introduced is trivial compared to other uncertainties.
			if(rand() % _prw1326.chair[i].level < _prw1326.chair[i].weight[j])
				break; //allowable

			//if we reach here we will loop again to find a suitable hand
		} //end of possible hand find

		ocard[k++] = _prw1326.chair[i].rankhi[j];
		ocard[k++] = _prw1326.chair[i].ranklo[j];

		CardMask_SET(usedCards, ocard[k-2]);
		CardMask_SET(usedCards, ocard[k-1]);

	} //end of active opponent loop

	// additional common cards
	CardMask_RESET(addlcomCards);
	for (int i=0; i<(k_number_of_community_cards - _ncomCards); i++)
	{
		card = GetRandomCard();
		CardMask_SET(usedCards, card);
		CardMask_SET(addlcomCards, card);
	}
} //end of prw1326 code
void CIteratorThread::StandardDealingAlgorithmForUpTo13Opponents(int nopponents)
{
	unsigned int	card = 0;

	write_log(preferences.debug_prwin(), "[PrWinThread] Using random algorithm, as f$prwin_number_of_opponents <= 13\n");
	// random replacement algorithm
	// opponent cards
	if (nopponents < 1) {
		write_log(preferences.debug_prwin(), "[PrWinThread] No opponents. Auto-adapting to 1.\n");
    nopponents = 1;
	}
	for (int i=0; 
		i<nopponents*k_number_of_cards_per_player; 
		i+=k_number_of_cards_per_player)
	{
		temp_usedCards=usedCards;
		do
		{
			usedCards = temp_usedCards; //reset the card mask to clear settings from failed card assignments

			for (int j=0; j<k_number_of_cards_per_player; j++)
			{
				card = GetRandomCard();
				CardMask_SET(usedCards, card);
				ocard[i+j] = card;
			}

			if (!_willplay)
			{
				write_log(preferences.debug_prwin(), "[PrWinThread] Weighting disabled. Willplay is 0.\n");
				break; //0 disables weighting
			}

			//put break for i=0 and opponent unraised BB case (cannot assume anything about his cards)
			//In round 1 we should really do an analysis of chairs to find out how many have still to
			//place a bet. Not implemented since accuracy of prwin pre-flop is less critical.
			if (!i)
			{
				//if we called then we are not BB, BB limped to flop,
				//BB still playing, so do not weight his cards
				int betround = p_betround_calculator->betround();
				if (p_symbol_engine_history->nbetsround(betround) < 1.1 
					&& p_symbol_engine_history->didcall(betround) 
					&& (p_symbol_engine_active_dealt_playing->playersplayingbits() 
						& p_symbol_engine_blinds->bblindbits()))
				{
					break;
				}
			}
		} while (!IsHandInWeightedRange(ocard[i], ocard[i+1],
			_willplay, _wontplay, 
			_topclip, _mustplay));
	}
	// additional common cards
	CardMask_RESET(addlcomCards);
	for (int i=0; i<(k_number_of_community_cards - _ncomCards); i++)
	{
		card = GetRandomCard();
		CardMask_SET(usedCards, card);
		CardMask_SET(addlcomCards, card);
	}
}
int CIteratorThread::EnhancedDealingAlgorithm() {
	write_log(preferences.debug_prwin(), "[PrWinThread] Using ZeeZooLaa's enhanced prwin.\n");
	unsigned int	card = 0, deadHandsCounter = 0;
	int k = 0; //k is used as an index into ocard[]
	int userchair = p_symbol_engine_userchair->userchair();
	int playersplayingbits = p_symbol_engine_active_dealt_playing->playersplayingbits();
	int chairWeight;
	bool deadHands[k_number_of_pocketcard_combinations_without_order];

	for(int eachChair=0; eachChair < kMaxNumberOfPlayers; eachChair++) { // loop through playing opponents
		if (eachChair == userchair) continue; //skip our own chair!
		if (!(playersplayingbits & (1<<eachChair))) continue; //skip inactive chairs 
		chairWeight = _total_weight[eachChair];
		if (_prw1326.chair[eachChair].ignore || chairWeight <= 0	)	{
			card = GetRandomCard();
			CardMask_SET(usedCards, card);
			ocard[k++] = card;

			card = GetRandomCard();
			CardMask_SET(usedCards, card);
			ocard[k++] = card;

			continue;
		} // end of special non-weighted cases

		memset(deadHands,false,sizeof(deadHands));
		deadHandsCounter = 0;

		bool random_weighted_hand_was_found = false;
		while(!random_weighted_hand_was_found) {
			int random_weight = RNG::Instance()->under(chairWeight);	//find random_weight which is between [0..chairWeight)
			for (int eachPossibleHand=0; eachPossibleHand < _prw1326.chair[eachChair].limit; eachPossibleHand++) {	//find random weighted hand			
				if (!deadHands[eachPossibleHand] && random_weight < _prw1326.chair[eachChair].weight[eachPossibleHand]) { //random hand found.
					if(CardMask_CARD_IS_SET(usedCards, _prw1326.chair[eachChair].rankhi[eachPossibleHand] ) 
              || CardMask_CARD_IS_SET(usedCards, _prw1326.chair[eachChair].ranklo[eachPossibleHand] )) {
						//hand contains dead card
						deadHands[eachPossibleHand] = true;
						deadHandsCounter++;
						chairWeight -= _prw1326.chair[eachChair].weight[eachPossibleHand];
						if(deadHandsCounter == _prw1326.chair[eachChair].limit || chairWeight <= 0) {
							//all range consists only of dead cards
							//failed to satisfy the specified range, user possibly needs to expand the range of corresponding chair
							if(eachChair == 0) return -10;
							return 0-eachChair; 
						}
						break; //generate new random_weight
					}
					//hand not dead, use it
					ocard[k++] = _prw1326.chair[eachChair].rankhi[eachPossibleHand];
					ocard[k++] = _prw1326.chair[eachChair].ranklo[eachPossibleHand];

					CardMask_SET(usedCards, ocard[k-2]);
					CardMask_SET(usedCards, ocard[k-1]);
					random_weighted_hand_was_found = true;
					break;
				}
				//keep decreasing the random_weight until it becomes less then _prw1326.chair[eachPlayer].weight
				if(!deadHands[eachPossibleHand]) {
					random_weight -= _prw1326.chair[eachChair].weight[eachPossibleHand];
				}
			}//end of eachPossibleHand
		}//end of random_weighted_hand_was_found
	} //end of eachPlayer

	// additional common cards
	CardMask_RESET(addlcomCards);
	for (int i=0; i<(kNumberOfCommunityCards - _ncomCards); i++) {
		card = GetRandomCard();
		CardMask_SET(usedCards, card);
		CardMask_SET(addlcomCards, card);
	}
  return 0; //success
}