void CIteratorThread::InitIteratorLoop() {
	write_log(preferences.debug_prwin(), "[PrWinThread] Initializing iterator loop\n");

	// Set starting status and parameters
	InitNumberOfIterations();
	// player cards
	CardMask_RESET(_plCards);
	CardMask_RESET(_comCards);
	_nplCards = _ncomCards = 0;

	// Counters
	_win = _tie = _los = 0;

  int userchair = p_symbol_engine_userchair->userchair();
  if (userchair == k_undefined) return;

	// setup masks
  AssertRange(userchair, 0, k_max_chair_number);
	for (int i=0; i<k_number_of_cards_per_player; i++) {
    Card card = p_table_state->User()->_hole_cards[i];
    if (card.IsKnownCard()) {
      CardMask_SET(_plCards, card.GetValue());
			_nplCards++;
		}
	}
	for (int i=0; i<k_number_of_community_cards; i++) {
    Card card = p_table_state->_common_cards[i];
    if (card.IsKnownCard()) {
      CardMask_SET(_comCards, card.GetValue());
			_ncomCards++;
		}
	}

	//Weighted prwin only for nopponents <=13
	_willplay = p_function_collection->Evaluate("f$prwin_willplay");
	_wontplay = p_function_collection->Evaluate("f$prwin_wontplay");
	_mustplay = p_function_collection->Evaluate("f$prwin_mustplay");
	_topclip = p_function_collection->Evaluate("f$prwin_topclip");

	// Call prw1326 callback if needed
	if (_prw1326.useme==1326 
		  && _prw1326.usecallback==1326 
		  && (p_betround_calculator->betround()!= k_betround_preflop
			  || _prw1326.preflop==1326) ){
		_prw1326.prw_callback(); //Matrix 2008-05-09
	}
}
void CSymbolEnginePrwin::CalculateNhands() {
	CardMask		plCards = {0}, comCards = {0}, oppCards = {0}, playerEvalCards = {0}, opponentEvalCards = {0};
	HandVal			hv_player = 0, hv_opponent = 0;
	unsigned int	pl_pokval = 0, opp_pokval = 0;
	int				dummy = 0;
	int				nplCards, ncomCards;

	_nhandshi = 0;
	_nhandsti = 0;
	_nhandslo = 0;

	// player cards
	CardMask_RESET(plCards);
	nplCards = 0;
	for (int i=0; i<kNumberOfCardsPerPlayer; i++) {
    Card card = p_table_state->User()->_hole_cards[i];
    if (card.IsKnownCard()) {
      CardMask_SET(plCards, card.GetValue());
			nplCards++;
		}
	}

	// common cards
	CardMask_RESET(comCards);
	ncomCards = 0;
	for (int i=0; i<kNumberOfCommunityCards; i++) {
    Card card = p_table_state->_common_cards[i];
    if (card.IsKnownCard()) {
      CardMask_SET(comCards, card.GetValue());
			ncomCards++;
		}
	}

	// player/common cards and pokerval
	CardMask_OR(playerEvalCards, plCards, comCards);
	hv_player = Hand_EVAL_N(playerEvalCards, nplCards+ncomCards);
	pl_pokval = p_symbol_engine_pokerval->CalculatePokerval(hv_player, 
		nplCards+ncomCards, &dummy, CARD_NOCARD, CARD_NOCARD);

	for (int i=0; i<(kNumberOfCardsPerDeck-1); i++)
	{
		for (int j=(i+1); j<kNumberOfCardsPerDeck; j++)
		{
			if (!CardMask_CARD_IS_SET(plCards, i) 
				&& !CardMask_CARD_IS_SET(plCards, j) 
				&& !CardMask_CARD_IS_SET(comCards, i) 
				&& !CardMask_CARD_IS_SET(comCards, j))
			{
				// opponent cards
				CardMask_RESET(oppCards);
				CardMask_SET(oppCards, i);
				CardMask_SET(oppCards, j);

				CardMask_OR(opponentEvalCards, oppCards, comCards);
				hv_opponent = Hand_EVAL_N(opponentEvalCards, 2+ncomCards);
				opp_pokval = p_symbol_engine_pokerval->CalculatePokerval(hv_opponent,
					(kNumberOfCardsPerPlayer + ncomCards), 
					&dummy, CARD_NOCARD, CARD_NOCARD);

				if (pl_pokval > opp_pokval)
				{
					_nhandslo++;
				}
				else if (pl_pokval < opp_pokval)
				{
					_nhandshi++;
				}
				else
				{
					_nhandsti++;
				}
			}
		}
	}

	AssertRange(_nhandshi, 0, nhands());
	AssertRange(_nhandsti, 0, nhands());
	AssertRange(_nhandslo, 0, nhands());
	assert((_nhandshi + _nhandsti + _nhandslo) == nhands());


	_prwinnow = pow(((double)_nhandslo/nhands()), _nopponents_for_prwin);
	_prlosnow = 1 - pow((((double)_nhandslo + _nhandsti)/nhands()), _nopponents_for_prwin);

	AssertRange(_prwinnow, 0, 1);
	AssertRange(_prlosnow, 0, 1);
}
void COpenHoldemStatusbar::ComputeCurrentStatus() {
	CardMask	Cards;
	CString		temp; 
	int userchair = p_symbol_engine_userchair->userchair();
	// Player cards
	CardMask_RESET(Cards);
	int nCards = 0;
	_status_plcards = "";
	if (p_table_state->User()->HasKnownCards()) {
		for (int i=0; i<k_number_of_cards_per_player; i++) {	
			// This condition got already checked: "playing"
      Card card = p_table_state->User()->_hole_cards[i];
      // Assertion removeed, because the scraper runs in a different thread.
			// assert(card.IsKnownCard()); 
		  _status_plcards.Append(card.ToString());
      CardMask_SET(Cards, card.GetValue());
			nCards++;
		}
		_status_nopp.Format("%d", p_symbol_engine_prwin->nopponents_for_prwin());
	}	else 	{
		for (int i=0; i<k_number_of_cards_per_player; i++) {
			if (p_table_state->User()->HasKnownCards())	{
				Card card = p_table_state->User()->_hole_cards[i];
				_status_plcards.Append(card.ToString());
        CardMask_SET(Cards, card.GetValue());
				nCards++;
			}
		}
		// Not playing, therefore no opponents to be considered for prwin.
		_status_nopp = "";
	}

	// Common cards
	_status_comcards = "";
	for (int i=0; i<k_number_of_community_cards; i++) {
    Card card = p_table_state->_common_cards[i];
		if (card.IsKnownCard())	{
			_status_comcards.Append(card.ToString());
			CardMask_SET(Cards, card.GetValue());
			nCards++;
		}
	}

	// poker hand
	HandVal hv = Hand_EVAL_N(Cards, nCards);
	char hvstring[100] = {0};
	HandVal_toString(hv, hvstring);
	_status_pokerhand = hvstring;
	_status_pokerhand = _status_pokerhand.Mid(0, _status_pokerhand.Find(" "));

	// Always use handrank169 here
	_status_handrank.Format("%.0f/169", p_symbol_engine_handrank->handrank169());

	// Always update prwin/nit
	if (p_symbol_engine_userchair->userchair_confirmed() 
		  && p_table_state->User()->HasKnownCards()) {
		_status_prwin.Format("%d/%d/%d", 
			(int) (p_iterator_thread->prwin()*1000), 
			(int) (p_iterator_thread->prtie()*1000),
			(int) (p_iterator_thread->prlos()*1000));
		double iterations;
		p_engine_container->EvaluateSymbol("f$prwin_number_of_iterations", &iterations);
		_status_nit.Format("%d/%s", 
			p_iterator_thread->IteratorThreadProgress(),
			Number2CString(iterations));
	}	else {
		_status_prwin = "0/0/0";
		// No iteratrions without userchair or cards
		_status_nit.Format("0");
	}
}