void CSymbolEngineRaisersCallers::CalculateRaisers()
{
	_raischair = k_undefined;
	_raisbits[_betround] = 0;

	// Raischair, nopponentsraising, raisbits
	//
	int first_possible_raiser = FirstPossibleRaiser();
	int last_possible_raiser  = LastPossibleRaiser();
	double last_bet = p_scraper->player_bet(_raischair_previous_frame);

	for (int i=first_possible_raiser; i<=last_possible_raiser; i++)
	{
		double current_players_bet = p_symbol_engine_chip_amounts->currentbet(i%p_tablemap->nchairs());

		if (current_players_bet > last_bet)
		{
			last_bet = current_players_bet;
			_raischair = i % p_tablemap->nchairs();
			int new_raisbits = _raisbits[_betround] | k_exponents[i%p_tablemap->nchairs()];
			_raisbits[_betround] = new_raisbits;
		}
	}
	AssertRange(_raischair, k_undefined, k_last_chair);
}
void CSymbolEngineRaisersCallers::CalculateRaisers() {
	_nopponentstruelyraising = 0;
	if (p_symbol_engine_chip_amounts->call() <= 0.0) 	{
		// There are no bets and raises.
		// Skip the calculations to keep the raischair of the previous round.
		// http://www.maxinmontreal.com/forums/viewtopic.php?f=156&t=16806
    write_log(preferences.debug_symbolengine(), 
      "[CSymbolEngineRaisersCallers] No bet to call, therefore no raises\n");
		return;
	}
	// Raischair, nopponentstruelyraising, raisbits
	int first_possible_raiser = FirstPossibleRaiser();
	int last_possible_raiser  = LastPossibleRaiser();
	double highest_bet = LastOrbitsLastRaisersBet();
  write_log(preferences.debug_symbolengine(), "[CSymbolEngineRaisersCallers] Searching for raisers from chair %i to %i with a bet higher than %.2f\n",
		first_possible_raiser, last_possible_raiser, highest_bet); 
	for (int i=first_possible_raiser; i<=last_possible_raiser; ++i) {
		int chair = i % p_tablemap->nchairs();
		double current_players_bet = p_symbol_engine_chip_amounts->currentbet(chair);
    write_log(preferences.debug_symbolengine(), 
      "[CSymbolEngineRaisersCallers] chair %d bet %.2f\n",
      chair, current_players_bet);
		// Raisers are people
		// * with a higher bet than players before them
		// * who are still playing, not counting people who bet/fold in later orbits
    // * either betting/raising postflop or truely raising preflop
    //   (not counting the infamous "blind raisers")
    if (!p_table_state->_players[chair].HasAnyCards()) {
      write_log(preferences.debug_symbolengine(), 
        "[CSymbolEngineRaisersCallers] chair %d has no cards.\n", chair);
      continue;
    } else if (current_players_bet <= highest_bet) {
      write_log(preferences.debug_symbolengine(), 
        "[CSymbolEngineRaisersCallers] chair %d is not raising\n", chair);
      continue;
    } else if ((p_betround_calculator->betround() == k_betround_preflop)
				&& (current_players_bet <= p_symbol_engine_tablelimits->bblind())) {
      write_log(preferences.debug_symbolengine(), 
        "[CSymbolEngineRaisersCallers] chair %d so-called \"blind raiser\". To be ignored.\n", chair);
      continue;
    }
		highest_bet = current_players_bet;
    write_log(preferences.debug_symbolengine(), "[CSymbolEngineRaisersCallers] Opponent %i raising to %s\n",
			chair, Number2CString(highest_bet));
		_raischair = chair;
		int new_raisbits = _raisbits[BETROUND] | k_exponents[chair];
		_raisbits[BETROUND] = new_raisbits;
		assert(chair != USER_CHAIR);
		++_nopponentstruelyraising;
	}
	AssertRange(_raischair, k_undefined, k_last_chair);
  _lastraised[BETROUND] = _raischair;
	write_log(preferences.debug_symbolengine(), "[CSymbolEngineRaisersCallers] nopponentstruelyraising: %i\n", _nopponentstruelyraising);
	write_log(preferences.debug_symbolengine(), "[CSymbolEngineRaisersCallers] raischair: %i\n", _raischair);
}
int CSymbolEngineRaisersCallers::LastPossibleRaiser() {
	// For technical reasons (for-loop) we handle the modulo-operation 
	// inside the loop and not here.
	return (FirstPossibleRaiser() + p_tablemap->nchairs() - 1);
}