void CIteratorThread::ResetGlobalVariables() { CardMask_RESET(usedCards); CardMask_RESET(temp_usedCards); CardMask_RESET(addlcomCards); CardMask_RESET(evalCards); CardMask_RESET(opp_evalCards); for (int i=0; i<k_number_of_cards_per_deck; i++) { deck[i] = 0; } for (int i=0; i<MAX_OPPONENTS; i++) { ocard[2*i] = 0; ocard[2*i + 1] = 0; } }
// Evaluate the best 7 card hand given our hole cards and 5 common_cards // TODO: Change this to evalute best 5+ card hand // TODO: Change this to store common cards (so we can print it out later) unsigned int Hand::Evaluate(const CommonCards& common_cards) { CardMask eval_cards; // char buf[256]; // Debug::log(LDEBUG) << "Hand: " << (*this) << std::endl; // Debug::log(LDEBUG) << "Common cards: " << common_cards << std::endl; // Set a poker-eval card mask with the values of all the cards CardMask_RESET(eval_cards); CardMask_SET(eval_cards, pokereval_cards[0]); CardMask_SET(eval_cards, pokereval_cards[1]); CardMask_SET(eval_cards, ConvertCardToPokerEvalCard(common_cards.flop1)); CardMask_SET(eval_cards, ConvertCardToPokerEvalCard(common_cards.flop2)); CardMask_SET(eval_cards, ConvertCardToPokerEvalCard(common_cards.flop3)); CardMask_SET(eval_cards, ConvertCardToPokerEvalCard(common_cards.turn)); CardMask_SET(eval_cards, ConvertCardToPokerEvalCard(common_cards.river)); // StdDeck_maskToString(eval_cards, buf); // Debug::log(LDEBUG) << "Mask: " << buf << std::endl; // Get my handval/pokerval hand_value = Hand_EVAL_N(eval_cards, 7); // StdRules_HandVal_toString(hand_value, buf); // Debug::log(LDEBUG) << "Hand_EVAL_N: " << buf << std::endl << std::endl; return hand_value; }
int main(int argc, char **argv) { HandVal handval; LowHandVal low; gNCards = 0; CardMask_RESET(gCards); parseArgs(argc, argv); if (!gLow) { handval = Hand_EVAL_N(gCards, gNCards); printf("%s: ", Deck_maskString(gCards)); HandVal_print(handval); printf("\n"); }; if (gLow || gHighLow) { #if defined(Hand_EVAL_LOW) if (gNCards < 5) printf("Not enough cards to evaluate low hand\n"); else { low = Hand_EVAL_LOW(gCards, gNCards); printf("%s (low): ", Deck_maskString(gCards)); LowHandVal_print(low); printf("\n"); }; #else printf("Low evaluator not available \n"); #endif }; return 0; }
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 } }
static CardMask Strings2CardMask(int strings_count, char* strings[]) { CardMask cards; CardMask dead; CardMask_RESET(cards); CardMask_RESET(dead); int card; int i; for(i = 0; i < strings_count; i++) { card = -1; assert(Deck_stringToCard(strings[i], &card) != 0); assert(StdDeck_CardMask_CARD_IS_SET(dead, card) == 0); StdDeck_CardMask_SET(cards, card); } return cards; }
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); } }
static int PyList2CardMask(PyObject* object, CardMask* cardsp) { CardMask cards; int cards_size = 0; int valid_cards_size = 0; if(!PyList_Check(object)) { PyErr_SetString(PyExc_TypeError, "expected a list of cards"); return -1; } valid_cards_size = cards_size = PyList_Size(object); CardMask_RESET(cards); int card; int i; for(i = 0; i < cards_size; i++) { card = -1; PyObject* pycard = PyList_GetItem(object, i); if(PyErr_Occurred()) return -1; if(PyString_Check(pycard)) { char* card_string = PyString_AsString(pycard); if(!strcmp(card_string, "__")) { card = 255; } else { if(Deck_stringToCard(card_string, &card) == 0) { PyErr_Format(PyExc_RuntimeError, "card %s is not a valid card name", card_string); return -1; } } } else if(PyInt_Check(pycard)) { card = PyInt_AsLong(pycard); if(card != NOCARD && (card < 0 || card > StdDeck_N_CARDS)) { PyErr_Format(PyExc_TypeError, "card value (%d) must be in the range [0-%d]", card, StdDeck_N_CARDS); return -1; } } else { PyErr_SetString(PyExc_TypeError, "card must be a string or an int"); return -1; } if(card == NOCARD) valid_cards_size--; else CardMask_SET(cards, card); } *cardsp = cards; return valid_cards_size; }
void CIteratorThread::SwapDealingAlgorithmForMoreThan13Opponents(int nopponents) { write_log(preferences.debug_prwin(), "[PrWinThread] Useing swap-algorithm, as f$prwin_number_of_opponents > 13\n"); // swap alogorithm // weighted prwin not implemented for this case int numberOfCards = k_number_of_cards_per_deck; for (int i=0; i<numberOfCards; i++) { deck[i] = i; } while (numberOfCards >= 1) { int selected_card = rand() % numberOfCards; numberOfCards--; if (selected_card != numberOfCards) { SwapInts(&deck[selected_card], &deck[numberOfCards]); } } // opponent cards int x = 0; for (int i=0; i<nopponents*k_number_of_cards_per_player; i++) { while (CardMask_CARD_IS_SET(usedCards, deck[x]) && (x < k_number_of_cards_per_deck)) { x++; } ocard[i] = deck[x++]; } // additional common cards CardMask_RESET(addlcomCards); for (int i=0; i<(k_number_of_community_cards - _ncomCards); i++) { while (CardMask_CARD_IS_SET(usedCards, deck[x]) && (x < k_number_of_cards_per_deck)) { x++; } CardMask_SET(addlcomCards, deck[x++]); } }
static int rbList2CardMask(VALUE object, CardMask* cardsp) { CardMask cards; int cards_size = 0; int valid_cards_size = 0; if (TYPE(object) != T_ARRAY) { rb_fatal("expected a list of cards"); } valid_cards_size = cards_size = RARRAY_LENINT(object); CardMask_RESET(cards); int card; int i; for(i = 0; i < cards_size; i++) { card = -1; char* card_string = RSTRING_PTR(rb_ary_entry(object, i)); if(!strcmp(card_string, "__")) card = 255; else if(Deck_stringToCard(card_string, &card) == 0) rb_fatal("card %s is not a valid card name", card_string); if(card == NOCARD) valid_cards_size--; else CardMask_SET(cards, card); } *cardsp = cards; return valid_cards_size; }
UINT CIteratorThread::IteratorThreadFunction(LPVOID pParam) { CIteratorThread *pParent = static_cast<CIteratorThread*>(pParam); // Loop-variables j, k get used inside and outside loops. // It is a bit messy, nearly impossible to fix it. // At least the outer loops ("f$prwin_number_of_iterations" and "i") could be improved. unsigned int pl_pokval = 0, opp_pokval = 0, opp_pokvalmax = 0; HandVal pl_hv = 0, opp_hv = 0; int dummy = 0; int sym_nopponents = p_symbol_engine_prwin->nopponents_for_prwin(); bool hand_lost; ResetGlobalVariables(); // Seed the RNG srand((unsigned)GetTickCount()); // // Main iterator loop // write_log(preferences.debug_prwin(), "[PrWinThread] Start of main loop.\n"); // "f$prwin_number_of_iterations" has to be declared outside of the loop, // as we check afterwards, if the loop terminated successfully. AdjustPrwinVariablesIfNecessary(pParent); unsigned int nit; for (nit=0; nit < iter_vars.nit(); nit++) { // Check event for thread stop signal if(::WaitForSingleObject(pParent->_m_stop_thread, 0) == WAIT_OBJECT_0) { // Set event ::SetEvent(pParent->_m_wait_thread); AfxEndThread(0); } CardMask_OR(usedCards, pParent->_plCards, pParent->_comCards); if (UseEnhancedPrWin()) { EnhancedDealingAlgorithm(); } else { StandardDealingAlgorithm(sym_nopponents); } // Get my handval/pokerval CardMask_OR(evalCards, pParent->_plCards, pParent->_comCards); CardMask_OR(evalCards, evalCards, addlcomCards); pl_hv = Hand_EVAL_N(evalCards, 7); pl_pokval = p_symbol_engine_pokerval->CalculatePokerval(pl_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD); // Scan through opponents' handvals/pokervals // - if we find one better than ours, then we are done, increment los // - for win/tie, we need to wait until we scan them all opp_pokvalmax = 0; hand_lost = false; for (int i=0; i<sym_nopponents; i++) { CardMask_RESET(opp_evalCards); CardMask_OR(opp_evalCards, pParent->_comCards, addlcomCards); CardMask_SET(opp_evalCards, ocard[i*2]); CardMask_SET(opp_evalCards, ocard[(i*2)+1]); opp_hv = Hand_EVAL_N(opp_evalCards, 7); opp_pokval = p_symbol_engine_pokerval->CalculatePokerval(opp_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD); if (opp_pokval>pl_pokval) { _los++; hand_lost = true; break; } else { if (opp_pokval > opp_pokvalmax) { opp_pokvalmax = opp_pokval; } } } if (!hand_lost) { if (pl_pokval > opp_pokvalmax) { _win++; } else { _tie++; } } UpdateIteratorVarsForDisplay(nit); } write_log(preferences.debug_prwin(), "[PrWinThread] End of main loop.\n"); if (SimulationFinished(nit)) { iter_vars.set_iterator_thread_running(false); iter_vars.set_iterator_thread_complete(true); UpdateIteratorVarsForDisplay(nit); } else { iter_vars.set_iterator_thread_running(false); iter_vars.set_iterator_thread_complete(false); iter_vars.set_iterator_thread_progress(0); //??? iter_vars.set_nit(0); for (int i=0; i<k_number_of_cards_per_player; i++) iter_vars.set_pcard(i, CARD_NOCARD); for (int i=0; i<k_number_of_community_cards; i++) { iter_vars.set_ccard(i, CARD_NOCARD); } ResetIteratorVars(); } ::SetEvent(pParent->_m_wait_thread); StopIteratorThread(); return 0; }
UINT CIteratorThread::IteratorThreadFunction(LPVOID pParam) { CIteratorThread *pParent = static_cast<CIteratorThread*>(pParam); // Loop-variables j, k get used inside and outside loops. // It is a bit messy, nearly impossible to fix it. // At least the outer loops ("f$prwin_number_of_iterations" and "i") could be improved. unsigned int pl_pokval = 0, opp_pokval = 0, opp_pokvalmax = 0; HandVal pl_hv = 0, opp_hv = 0; int dummy = 0; bool hand_lost; ResetGlobalVariables(); // Seed the RNG srand((unsigned)GetTickCount()); while (true) { // Check event for thread stop signal once per main iterator loop // (and additionally once every 1000 iterations later) if(::WaitForSingleObject(pParent->_m_stop_thread, 0) == WAIT_OBJECT_0) { // Set event ::SetEvent(pParent->_m_wait_thread); AfxEndThread(0); } Sleep(500); if (!p_symbol_engine_autoplayer->ismyturn()) { // Not my turn; // Nothing to simulate continue; } if (IteratorThreadComplete()) { // No longer anything to do continue; } // // Main iterator loop // write_log(preferences.debug_prwin(), "[PrWinThread] Start of main loop.\n"); // "f$prwin_number_of_iterations" has to be declared outside of the loop, // as we check afterwards, if the loop terminated successfully. _nopponents = p_symbol_engine_prwin->nopponents_for_prwin(); AdjustPrwinVariablesIfNecessary(); for (_iterations_calculated=0; _iterations_calculated < _iterations_required; ++_iterations_calculated) { // Check event for thread stop signal once every 1000 iterations if ((_iterations_calculated % 1000 == 0) && (_iterations_calculated > 0) && (::WaitForSingleObject(pParent->_m_stop_thread, 0) == WAIT_OBJECT_0)) { // Set event ::SetEvent(pParent->_m_wait_thread); AfxEndThread(0); } CardMask_OR(usedCards, pParent->_plCards, pParent->_comCards); if (UseEnhancedPrWin()) { EnhancedDealingAlgorithm(); } else { StandardDealingAlgorithm(_nopponents); } // Get my handval/pokerval CardMask_OR(evalCards, pParent->_plCards, pParent->_comCards); CardMask_OR(evalCards, evalCards, addlcomCards); pl_hv = Hand_EVAL_N(evalCards, 7); pl_pokval = p_symbol_engine_pokerval->CalculatePokerval(pl_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD);//?? // Scan through opponents' handvals/pokervals // - if we find one better than ours, then we are done, increment los // - for win/tie, we need to wait until we scan them all opp_pokvalmax = 0; hand_lost = false; for (int i=0; i<_nopponents; i++) { CardMask_RESET(opp_evalCards); CardMask_OR(opp_evalCards, pParent->_comCards, addlcomCards); CardMask_SET(opp_evalCards, ocard[i*2]); CardMask_SET(opp_evalCards, ocard[(i*2)+1]); opp_hv = Hand_EVAL_N(opp_evalCards, 7); opp_pokval = p_symbol_engine_pokerval->CalculatePokerval(opp_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD); write_log(preferences.debug_prwin(), "[PrWinThread] PlayerPV: %i OppPV: %i\n", pl_pokval, opp_pokval); if (opp_pokval > pl_pokval) { write_log(preferences.debug_prwin(), "[PrWinThread] Lost\n"); _los++; hand_lost = true; break; } else { if (opp_pokval > opp_pokvalmax) { opp_pokvalmax = opp_pokval; } } } if (!hand_lost) { if (pl_pokval > opp_pokvalmax) { write_log(preferences.debug_prwin(), "[PrWinThread] Won\n"); _win++; } else { write_log(preferences.debug_prwin(), "[PrWinThread] Tie\n"); _tie++; } } UpdateIteratorVarsForDisplay(); } write_log(preferences.debug_prwin(), "[PrWinThread] End of main loop.\n"); if (!IteratorThreadComplete()) { // Computation stopped with some kind of error. // Reset vars to avoid bogus data ResetIteratorVars(); } UpdateIteratorVarsForDisplay(); ::SetEvent(pParent->_m_wait_thread); } return 0; }
void write_logautoplay(const char * action) { char nowtime[26]; CString pcards, comcards, temp, rank, pokerhand, bestaction, fcra_seen; char *card; CardMask Cards; int nCards; CString fcra_formula_status; int sym_userchair = (int) p_symbol_engine_userchair->userchair(); int betround = (int) p_betround_calculator->betround(); if (!prefs.trace_enabled()) return; if (log_fp != NULL) { CSLock lock(log_critsec); // log$ writing if (prefs.log_symbol_enabled()) { int max_log = p_symbols->logsymbols_collection()->GetCount(); if (max_log > 0) { if (max_log > prefs.log_symbol_max_log()) { max_log = prefs.log_symbol_max_log(); } write_log(k_always_log_basic_information, "*** log$ (Total: %d | Showing: %d)\n", p_symbols->logsymbols_collection()->GetCount(), max_log); for (int i=0; i<max_log; i++) { write_log(k_always_log_basic_information, "*** %s\n", p_symbols->logsymbols_collection()->GetAt(i)); } } } CardMask_RESET(Cards); nCards=0; // player cards if (p_symbol_engine_userchair->userchair_confirmed()) { for (int i=0; i<=1; i++) { card = StdDeck_cardString(p_scraper->card_player(sym_userchair, i)); temp.Format("%s", card); pcards.Append(temp); CardMask_SET(Cards, p_scraper->card_player(sym_userchair, i)); nCards++; } } else { pcards = "...."; } // common cards comcards = ""; if (betround >= k_betround_flop) { for (int i=0; i<=2; i++) { if (p_scraper->card_common(i) != CARD_BACK && p_scraper->card_common(i) != CARD_NOCARD) { card = StdDeck_cardString(p_scraper->card_common(i)); temp.Format("%s", card); comcards.Append(temp); CardMask_SET(Cards, p_scraper->card_common(i)); nCards++; } } } if (betround >= k_betround_turn) { card = StdDeck_cardString(p_scraper->card_common(3)); temp.Format("%s", card); comcards.Append(temp); CardMask_SET(Cards, p_scraper->card_common(3)); nCards++; } if (betround >= k_betround_river) { card = StdDeck_cardString(p_scraper->card_common(4)); temp.Format("%s", card); comcards.Append(temp); CardMask_SET(Cards, p_scraper->card_common(4)); nCards++; } comcards.Append(".........."); comcards = comcards.Left(10); // Always use handrank169 here rank.Format("%.0f", p_symbol_engine_handrank->handrank169()); // poker hand pokerhand = p_symbol_engine_pokerval->HandType(); // best action if (strcmp(action, "SWAG")==0) { bestaction.Format("$%.2f", p_autoplayer_functions->f$betsize()); } else { if (p_autoplayer_functions->f$alli()) bestaction = "Allin"; else if (p_autoplayer_functions->f$betsize()) bestaction = "SWAG"; else if (p_autoplayer_functions->f$rais()) bestaction = "Bet/Raise"; else if (p_autoplayer_functions->f$call()) bestaction = "Call/Check"; else if (p_autoplayer_functions->f$prefold()) bestaction = "Pre-fold"; else bestaction = "Fold/Check"; } // fcra_seen int sym_myturnbits = p_symbol_engine_autoplayer->myturnbits(); fcra_seen.Format("%s%s%s%s%s", sym_myturnbits&0x01 ? "F" : ".", sym_myturnbits&0x02 ? "C" : ".", // Check button out of order to stay consistent // with button order in manual mode. sym_myturnbits&0x10 ? "K" : ".", sym_myturnbits&0x04 ? "R" : ".", sym_myturnbits&0x08 ? "A" : "."); // fcra formula status fcra_formula_status.Format("%s%s%s%s", !p_autoplayer_functions->f$alli() && !p_autoplayer_functions->f$rais() && !p_autoplayer_functions->f$call() && !p_autoplayer_functions->f$betsize() ? "F" : ".", p_autoplayer_functions->f$call() ? "C" : ".", p_autoplayer_functions->f$rais() ? "R" : ".", p_autoplayer_functions->f$alli() ? "A" : "."); fprintf(log_fp, "%s - %1d ", get_time(nowtime), p_tablemap->nchairs()); fprintf(log_fp, "%4s %10s %4s %5s ", pcards.GetString(), comcards.GetString(), rank.GetString(), pokerhand.GetString()); fprintf(log_fp, "%4d %4d %4d ", (iter_vars.prwin() * 1000), (iter_vars.prlos() * 1000), (iter_vars.prtie() * 1000)); fprintf(log_fp, "%2d %8d %-10s - ", p_symbol_engine_prwin->nopponents_for_prwin(), iter_vars.nit(), bestaction.GetString()); fprintf(log_fp, "%-5s %9.2f %9.2f %9.2f ", action, p_symbol_engine_chip_amounts->call(), p_tablelimits->bet(), p_symbol_engine_chip_amounts->pot()); int userchair = p_symbol_engine_userchair->userchair(); fprintf(log_fp, "%9.2f - %s %s %.2f\n", p_symbol_engine_chip_amounts->balance(userchair), fcra_seen.GetString(), fcra_formula_status.GetString(), p_autoplayer_functions->f$betsize() ); if (prefs.trace_enabled() && p_symbols->symboltrace_collection()->GetSize() > 0) { write_log_nostamp(1, "***** Autoplayer Trace ****\n"); for (int i=0; i<p_symbols->symboltrace_collection()->GetSize(); i++) { write_log_nostamp(1, "%s\n", p_symbols->symboltrace_collection()->GetAt(i)); } write_log_nostamp(1, "***********************\n"); } fflush(log_fp); } }
bool CVersus::GetCounts(void) { if (_versus_fh == k_undefined) return false; int i = 0, j = 0; CardMask plCards, oppCards, deadCards, comCardsScrape, comCardsEnum, comCardsAll, usedCards; unsigned int wintemp = 0, tietemp = 0, lostemp = 0, offset = 0; unsigned int nhiwin = 0, nhitie = 0, nhilos = 0, ntiwin = 0, ntitie = 0, ntilos = 0, nlowin = 0, nlotie = 0, nlolos = 0; unsigned int nhinowwin = 0, nhinowtie = 0, nhinowlos = 0, ntinowwin = 0, ntinowtie = 0, ntinowlos = 0, nlonowwin = 0, nlonowtie = 0, nlonowlos = 0; unsigned int c0rank = 0, c1rank = 0, temprank = 0; BYTE byte[8] = {0}; long pos = 0; int listnum = 0; int card0_offset[52] = { 0, 62475, 123725, 183750, 242550, 300125, 356475, 411600, 465500, 518175, 569625, 619850, 668850, 716625, 763175, 808500, 852600, 895475, 937125, 977550, 1016750, 1054725, 1091475, 1127000, 1161300, 1194375, 1226225, 1256850, 1286250, 1314425, 1341375, 1367100, 1391600, 1414875, 1436925, 1457750, 1477350, 1495725, 1512875, 1528800, 1543500, 1556975, 1569225, 1580250, 1590050, 1598625, 1605975, 1612100, 1617000, 1620675, 1623125, 1624350 }; int betround = p_betround_calculator->betround(); int sym_userchair = (int) p_symbol_engine_userchair->userchair(); unsigned int pcard[2] = {0}; for (i=0; i<=1; i++) pcard[i] = CARD_NOCARD; unsigned int card_player[2] = {0}, card_common[5] = {0}; for (i=0; i<=1; i++) card_player[i] = p_scraper->card_player(sym_userchair, i); for (i=0; i<=4; i++) card_common[i] = p_scraper->card_common(i); // Get the lock CSLock lock(m_critsec); if (!p_symbol_engine_userchair->userchair_confirmed()) return false; if (card_player[0] == CARD_NOCARD || card_player[0] == CARD_BACK || card_player[1] == CARD_NOCARD || card_player[1] == CARD_BACK) { return false; } _nwin = _ntie = _nlos = _nhands = 0; _nhandshi = _nhandsti = _nhandslo = 0; _nhandshinow = _nhandstinow = _nhandslonow = 0; _vsprwinhi = _vsprtiehi = _vsprloshi = 0; _vsprwinti = _vsprtieti = _vsprlosti = 0; _vsprwinlo = _vsprtielo = _vsprloslo = 0; _vsprwinhinow = _vsprtiehinow = _vsprloshinow = 0; _vsprwintinow = _vsprtietinow = _vsprlostinow = 0; _vsprwinlonow = _vsprtielonow = _vsprloslonow = 0; nhiwin = nhitie = nhilos = ntiwin = ntitie = ntilos = nlowin = nlotie = nlolos = 0; // Clear counters for (listnum=0; listnum<MAX_HAND_LISTS; listnum++) _nlistwin[listnum] = _nlisttie[listnum] = _nlistlos[listnum] = 0; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PREFLOP if (betround == k_betround_preflop) { // order cards properly if (card_player[0] < card_player[1]) { pcard[0] = card_player[0]; pcard[1] = card_player[1]; } else { pcard[0] = card_player[1]; pcard[1] = card_player[0]; } // figure out offset into file offset = 0; //for (i=1; i<pcard[0]; i++) offset += (52-i)*1225; offset += card0_offset[pcard[0]]; offset += (pcard[1]-pcard[0]-1)*1225; offset *= sizeof(byte); // seek to right position in file if ((pos = _lseek(_versus_fh, offset, SEEK_SET)) == long(k_undefined)) { return false; } wintemp = lostemp = 0; for (i=0; i<(k_number_of_cards_per_deck - 1); i++) { for (j=i+1; j<k_number_of_cards_per_deck; j++) { if (i!=pcard[0] && i!=pcard[1] && j!=pcard[0] && j!=pcard[1]) { _read(_versus_fh, &byte, sizeof(byte)); memcpy(&wintemp, &byte[0], sizeof(unsigned int)); memcpy(&lostemp, &byte[4], sizeof(unsigned int)); _nwin += wintemp; _ntie += 1712304 - wintemp - lostemp; _nlos += lostemp; _nhands = _nhands + 1; if (wintemp<lostemp) { _nhandshi = _nhandshi + 1; nhiwin += wintemp; nhitie += 1712304 - wintemp - lostemp; nhilos += lostemp; } else if (wintemp>lostemp) { _nhandslo = _nhandslo + 1; nlowin += wintemp; nlotie += 1712304 - wintemp - lostemp; nlolos += lostemp; } else { _nhandsti = _nhandsti + 1; ntiwin += wintemp; ntitie += 1712304 - wintemp - lostemp; ntilos += lostemp; } // Calculations for vs$xx$prwin, vs$xx$prtie, vs$xx$prlos c0rank = StdDeck_RANK(i); c1rank = StdDeck_RANK(j); if (c0rank < c1rank) { temprank = c0rank; c0rank = c1rank; c1rank = temprank; } for (listnum=0; listnum<MAX_HAND_LISTS; listnum++) { if ((StdDeck_SUIT(i)==StdDeck_SUIT(j) && p_formula->formula()->inlist[listnum][c0rank][c1rank]) || (StdDeck_SUIT(i)!=StdDeck_SUIT(j) && p_formula->formula()->inlist[listnum][c1rank][c0rank])) { _nlistwin[listnum] += wintemp; _nlisttie[listnum] += 1712304 - wintemp - lostemp; _nlistlos[listnum] += lostemp; } } } } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FLOP, TURN, RIVER else if (betround >= k_betround_flop) { CardMask playerEvalCardsNow, oppEvalCardsNow; HandVal player_hv_now = 0, opp_hv_now = 0; // Common cards CardMask_RESET(comCardsScrape); if (betround >= k_betround_flop) CardMask_SET(comCardsScrape, card_common[0]); if (betround >= k_betround_flop) CardMask_SET(comCardsScrape, card_common[1]); if (betround >= k_betround_flop) CardMask_SET(comCardsScrape, card_common[2]); if (betround >= k_betround_turn) CardMask_SET(comCardsScrape, card_common[3]); if (betround >= k_betround_river) CardMask_SET(comCardsScrape, card_common[4]); // player cards CardMask_RESET(plCards); CardMask_SET(plCards, card_player[0]); CardMask_SET(plCards, card_player[1]); // all used cards CardMask_OR(usedCards, comCardsScrape, plCards); // eval player hand now CardMask_OR(playerEvalCardsNow, plCards, comCardsScrape); player_hv_now = Hand_EVAL_N(playerEvalCardsNow, betround+3); // Enumerate through all possible opponent hands (excludes already used cards) for (i=0; i<=50; i++) { for (j=i+1; j<=51; j++) { if (!CardMask_CARD_IS_SET(usedCards, i) && !CardMask_CARD_IS_SET(usedCards, j)) { CardMask_RESET(oppCards); CardMask_SET(oppCards, i); CardMask_SET(oppCards, j); // Enumerate through all possible river situations (exclude player cards and opponent cards) CardMask_OR(deadCards, usedCards, oppCards); wintemp = tietemp = lostemp = 0; if (betround==k_betround_flop || betround==k_betround_turn) { ENUMERATE_N_CARDS_D(comCardsEnum, betround==k_betround_flop ? 2 : betround==k_betround_turn ? 1 : 0, deadCards, { CardMask_OR(comCardsAll, comCardsScrape, comCardsEnum); DoCalc(plCards, oppCards, comCardsAll, &wintemp, &tietemp, &lostemp); }); }
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"); } }
int main(int argc, char* argv[]) { enum_game_t game = game_razz; { enum_result_t result; StdDeck_CardMask board; StdDeck_CardMask dead; StdDeck_CardMask pockets[2]; char* hand0[] = { "Ad", "2d", "3d", "4d", "5d", "Tc", "Th" }; //char* hand1[] = { "Ac", "2c", "3c", "4c", "5c", "Tc", "Th" }; char* hand1[] = { "4d", "4c", "8d", "8c", "9d", "9c", "9h" }; enumResultClear(&result); CardMask_RESET(board); CardMask_RESET(dead); pockets[0] = Strings2CardMask(7, hand0); pockets[1] = Strings2CardMask(7, hand1); assert(enumExhaustive(game, pockets, board, dead, 2, 0 /* nboard */, 0 /* orderflag */, &result) == 0); if(verbose) enumResultPrint(&result, pockets, board); assert(result.ev[0] == 1.0); assert(result.ev[1] == 0.0); } { /* http://shipitfish.livejournal.com/59671.html If after removing straights and flushes, if hand X beats hand Y under normal poker rules, the hand Y beats hand X under razz. There should *never* be a case where one hand wins over another in both normal poker rules and razz (after removing straights and flushes). Therefore, 6s full of 5s loses 4s full of 8s in razz and likewise by the same logic 6s and 5s beat 4s and 8s in razz. 4s and 8s should definately *NOT* beat 6s and 5s in both 7-card stud and razz. If one hand wins in 7-card stud, the other hand wins in razz. It is that simple. */ enum_result_t result; StdDeck_CardMask board; StdDeck_CardMask dead; StdDeck_CardMask pockets[2]; char* hand0[] = { "5d", "5c", "6d", "6c", "7d", "7c", "7h" }; char* hand1[] = { "4d", "4c", "8d", "8c", "9d", "9c", "9h" }; enumResultClear(&result); CardMask_RESET(board); CardMask_RESET(dead); pockets[0] = Strings2CardMask(7, hand0); pockets[1] = Strings2CardMask(7, hand1); assert(enumExhaustive(game, pockets, board, dead, 2, 0 /* nboard */, 0 /* orderflag */, &result) == 0); if(verbose) enumResultPrint(&result, pockets, board); assert(result.ev[0] == 1.0); assert(result.ev[1] == 0.0); } return 0; }
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
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 }
UINT CIteratorThread::IteratorThreadFunction(LPVOID pParam) { CIteratorThread *pParent = static_cast<CIteratorThread*>(pParam); // Loop-variables j, k get used inside and outside loops. // It is a bit messy, nearly impossible to fix it. // At least the outer loops ("f$prwin_number_of_iterations" and "i") could be improved. unsigned int pl_pokval = 0, opp_pokval = 0, opp_pokvalmax = 0; HandVal pl_hv = 0, opp_hv = 0; int dummy = 0, enhanced_dealing_return=0; bool hand_lost; ResetGlobalVariables(); // Seed the RNG srand((unsigned)GetTickCount()); while (true) { // Check event for thread stop signal once per main iterator loop // (and additionally once every 1000 iterations later) if(::WaitForSingleObject(pParent->_m_stop_thread, 0) == WAIT_OBJECT_0) { // Set event ::SetEvent(pParent->_m_wait_thread); AfxEndThread(0); } Sleep(500); if (!p_symbol_engine_autoplayer->ismyturn()) { // Not my turn; // Nothing to simulate continue; } if (IteratorThreadComplete()) { // No longer anything to do continue; } write_log(preferences.debug_prwin(), "[PrWinThread] Start of main loop.\n"); // "f$prwin_number_of_iterations" has to be declared outside of the loop, // as we check afterwards, if the loop terminated successfully. _nopponents = p_symbol_engine_prwin->nopponents_for_prwin(); AdjustPrwinVariablesIfNecessary(); LARGE_INTEGER frequency; // ticks per second LARGE_INTEGER t1, t2; // ticks double elapsedTime = 0; QueryPerformanceFrequency(&frequency); // get ticks per second CalculateTotalWeights(); // // Main iterator loop // for (_iterations_calculated=0; _iterations_calculated < _iterations_required; ++_iterations_calculated) { // Check event for thread stop signal once every 1000 iterations if ((_iterations_calculated % 1000 == 0) && (_iterations_calculated > 0) && (::WaitForSingleObject(pParent->_m_stop_thread, 0) == WAIT_OBJECT_0)) { // Set event ::SetEvent(pParent->_m_wait_thread); AfxEndThread(0); } CardMask_OR(usedCards, pParent->_plCards, pParent->_comCards); if (UseEnhancedPrWin()) { QueryPerformanceCounter(&t1); // start timer enhanced_dealing_return = EnhancedDealingAlgorithm(); if (enhanced_dealing_return < 0) { _prwin = enhanced_dealing_return; _prtie = enhanced_dealing_return; _prlos = enhanced_dealing_return; _iterations_calculated = _iterations_required; write_log(preferences.debug_prwin(), "[PrWinThread] Chair's %i range consists of dead cards only.\n",enhanced_dealing_return); break; } QueryPerformanceCounter(&t2); // stop timer elapsedTime = elapsedTime + (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; // compute the elapsed time in millisec } else { QueryPerformanceCounter(&t1); // start timer StandardDealingAlgorithm(_nopponents); QueryPerformanceCounter(&t2); // stop timer elapsedTime = elapsedTime + (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart; // compute the elapsed time in millisec } // Get my handval/pokerval CardMask_OR(evalCards, pParent->_plCards, pParent->_comCards); CardMask_OR(evalCards, evalCards, addlcomCards); pl_hv = Hand_EVAL_N(evalCards, 7); pl_pokval = p_symbol_engine_pokerval->CalculatePokerval(pl_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD);//?? // Scan through opponents' handvals/pokervals // - if we find one better than ours, then we are done, increment los // - for win/tie, we need to wait until we scan them all opp_pokvalmax = 0; hand_lost = false; for (int i=0; i<_nopponents; i++) { CardMask_RESET(opp_evalCards); CardMask_OR(opp_evalCards, pParent->_comCards, addlcomCards); CardMask_SET(opp_evalCards, ocard[i*2]); CardMask_SET(opp_evalCards, ocard[(i*2)+1]); opp_hv = Hand_EVAL_N(opp_evalCards, 7); opp_pokval = p_symbol_engine_pokerval->CalculatePokerval(opp_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD); write_log(preferences.debug_prwin(), "[PrWinThread] PlayerPV: %i OppPV: %i\n", pl_pokval, opp_pokval); if (opp_pokval > pl_pokval) { write_log(preferences.debug_prwin(), "[PrWinThread] Lost\n"); _los++; hand_lost = true; break; } else { if (opp_pokval > opp_pokvalmax) { opp_pokvalmax = opp_pokval; } } } if (!hand_lost) { if (pl_pokval > opp_pokvalmax) { write_log(preferences.debug_prwin(), "[PrWinThread] Won\n"); _win++; } else { write_log(preferences.debug_prwin(), "[PrWinThread] Tie\n"); _tie++; } } UpdateIteratorVarsForDisplay(); } write_log(preferences.debug_prwin(), "[PrWinThread] End of main loop.\n"); if (!IteratorThreadComplete()) { // Computation stopped with some kind of error. // Reset vars to avoid bogus data ResetIteratorVars(); } if(enhanced_dealing_return == 0) { UpdateIteratorVarsForDisplay(); //calculates _prwin, _prtie, _prlos } if(UseEnhancedPrWin()) { write_log(preferences.debug_prwin(), "EnhancedDealingAlgorithm elapsed time in millisec: %.3f Iterations: %d prwin: %.3f prtie: %.3f prlos: %.3f vanilla.limit: %i \n", elapsedTime,_iterations_calculated, _prwin, _prtie, _prlos, _prw1326.vanilla_chair.limit ); } else { write_log(preferences.debug_prwin(), "StandardDealingAlgorithm elapsed time in millisec: %.3f Iterations: %d prwin: %.3f prtie: %.3f prlos: %.3f\n", elapsedTime,_iterations_calculated, _prwin, _prtie, _prlos); } ::SetEvent(pParent->_m_wait_thread); } return 0; }
UINT CIteratorThread::IteratorThreadFunction(LPVOID pParam) { CIteratorThread *pParent = static_cast<CIteratorThread*>(pParam); // Loop-variables j, k get used inside and outside loops. // It is a bit messy, nearly impossible to fix it. // At least the outer loops ("f$prwin_number_of_iterations" and "i") could be improved. int j = 0, k = 0; int randfix = 0; CardMask addlcomCards = {0}, evalCards = {0}, opp_evalCards = {0}, usedCards = {0}, temp_usedCards = {0}; unsigned int ocard[MAX_OPPONENTS*2] = {0}, card = 0, pl_pokval = 0, opp_pokval = 0, opp_pokvalmax = 0; HandVal pl_hv = 0, opp_hv = 0; int dummy = 0; int deck[k_number_of_cards_per_deck] = {0}, x = 0; int numberOfCards = 0; int betround = p_betround_calculator->betround(); int sym_playersplayingbits = p_symbol_engine_active_dealt_playing->playersplayingbits(); double sym_nbetsround = p_symbol_engine_history->nbetsround(betround); int sym_bblindbits = p_symbol_engine_blinds->bblindbits(); bool sym_didcall = p_symbol_engine_history->didcall(betround); int sym_nopponents = p_symbol_engine_prwin->nopponents_for_prwin(); int nopp = sym_nopponents <= MAX_OPPONENTS ? sym_nopponents : MAX_OPPONENTS; bool hand_lost; // Seed the RNG srand((unsigned)GetTickCount()); // // Main iterator loop // write_log(prefs.debug_prwin(), "[PrWinThread] Start of main loop.\n"); // "f$prwin_number_of_iterations" has to be declared outside of the loop, // as we check afterwards, if the loop terminated successfully. unsigned int nit; for (nit=0; nit < iter_vars.nit(); nit++) { // Check event for thread stop signal if(::WaitForSingleObject(pParent->_m_stop_thread, 0) == WAIT_OBJECT_0) { // Set event ::SetEvent(pParent->_m_wait_thread); AfxEndThread(0); } CardMask_OR(usedCards, pParent->_plCards, pParent->_comCards); //Correct the protection aganst low f$willplay/f$wontplay - Matrix 2008-12-22 if (pParent->_willplay && (pParent->_willplay<nopp*2+1) ) { write_log(prefs.debug_prwin(), "[PrWinThread] Adjusting willplay (too low)\n"); pParent->_willplay=nopp*2+1; //too low a value can give lockup } if (pParent->_wontplay<pParent->_willplay) { write_log(prefs.debug_prwin(), "[PrWinThread] Adjusting wontplay (too low)\n"); pParent->_wontplay=pParent->_willplay; //wontplay cannot safely be less than willplay } if (_prw1326.useme==1326 && (betround>=k_betround_flop || _prw1326.preflop==1326)) { write_log(prefs.debug_prwin(), "[PrWinThread] Using Matrix's enhanced prwin.\n"); //prw1326 active Matrix 2008-05-08 k = nopp = 0; //k is used as an index into ocard[] // loop through active opponents for(int i=0; i<k_max_number_of_players; i++) { if (i==(int) p_symbol_engine_userchair->userchair()) continue; //skip our own chair! if (!((sym_playersplayingbits) & (1<<i))) continue; //skip inactive chairs nopp++; //we have to use actual opponents for prw1326 calculations // 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 && sym_nbetsround<1.1 && (sym_bblindbits&(1<<i))) ) { do { card = rand() & 63; } while (card>51 || CardMask_CARD_IS_SET(usedCards, card)); CardMask_SET(usedCards, card); ocard[k++] = card; do { card = rand() & 63; } while (card>51 || CardMask_CARD_IS_SET(usedCards, card)); CardMask_SET(usedCards, card); ocard[k++] = card; continue; } // end of special non-weighted cases randfix=(RAND_MAX/_prw1326.chair[i].limit) * _prw1326.chair[i].limit; 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 - pParent->_ncomCards); i++) { do { card = rand() & 63; } while (card>51 ||CardMask_CARD_IS_SET(usedCards, card)); CardMask_SET(usedCards, card); CardMask_SET(addlcomCards, card); } } //end of prw1326 code else { // normal prwin opponent card selection write_log(prefs.debug_prwin(), "[PrWinThread] Using standard prwin.\n"); // if f$prwin_number_of_opponents<=13 then deal with random replacement algorithm, otherwise deal with swap algorithm if (nopp <= 13) { write_log(prefs.debug_prwin(), "[PrWinThread] Using random algorithm, as f$prwin_number_of_opponents <= 13\n"); // random replacement algorithm // opponent cards if (nopp < 1) { write_log(prefs.debug_prwin(), "[PrWinThread] No opponents.\n"); } for (int i=0; i<nopp*2; i+=2) { temp_usedCards=usedCards; do { usedCards=temp_usedCards; //reset the card mask to clear settings from failed card assignments do { card = rand() & 63; } while (card>51 || CardMask_CARD_IS_SET(usedCards, card)); CardMask_SET(usedCards, card); ocard[i] = card; do { card = rand() & 63; } while (card>51 || CardMask_CARD_IS_SET(usedCards, card)); CardMask_SET(usedCards, card); ocard[i+1] = card; if (!pParent->_willplay) { write_log(prefs.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 if (sym_nbetsround<1.1 && sym_didcall && (sym_playersplayingbits&sym_bblindbits) ) { break; } } } while (!pParent->InRange(ocard[i], ocard[i+1], pParent->_willplay, pParent->_wontplay, pParent->_topclip, pParent->_mustplay)); } // additional common cards CardMask_RESET(addlcomCards); for (int i=0; i<(k_number_of_community_cards - pParent->_ncomCards); i++) { do { card = rand() & 63; } while (card>51 ||CardMask_CARD_IS_SET(usedCards, card)); CardMask_SET(usedCards, card); CardMask_SET(addlcomCards, card); } } else { write_log(prefs.debug_prwin(), "[PrWinThread] Useing swap-algorithm, as f$prwin_number_of_opponents > 13\n"); // swap alogorithm //weighted prwin not implemented for this case numberOfCards=52; for (int i=0; i<numberOfCards; i++) deck[i] = i; while (numberOfCards>=1) { x = rand() % numberOfCards; numberOfCards--; if (x != numberOfCards) { SwapInts(&deck[x], &deck[numberOfCards]); } } // opponent cards x = 0; for (int i=0; i<nopp*2; i++) { while (CardMask_CARD_IS_SET(usedCards, deck[x]) && x<=51) { x++; } ocard[i] = deck[x++]; } // additional common cards CardMask_RESET(addlcomCards); for (int i=0; i<(k_number_of_community_cards - pParent->_ncomCards); i++) { while (CardMask_CARD_IS_SET(usedCards, deck[x]) && x<=51) { x++; } CardMask_SET(addlcomCards, deck[x++]); } } } // Get my handval/pokerval CardMask_OR(evalCards, pParent->_plCards, pParent->_comCards); CardMask_OR(evalCards, evalCards, addlcomCards); pl_hv = Hand_EVAL_N(evalCards, 7); pl_pokval = p_symbol_engine_pokerval->CalculatePokerval(pl_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD); // Scan through opponents' handvals/pokervals // - if we find one better than ours, then we are done, increment los // - for win/tie, we need to wait until we scan them all opp_pokvalmax = 0; hand_lost = false; for (int i=0; i<nopp; i++) { CardMask_RESET(opp_evalCards); CardMask_OR(opp_evalCards, pParent->_comCards, addlcomCards); CardMask_SET(opp_evalCards, ocard[i*2]); CardMask_SET(opp_evalCards, ocard[(i*2)+1]); opp_hv = Hand_EVAL_N(opp_evalCards, 7); opp_pokval = p_symbol_engine_pokerval->CalculatePokerval(opp_hv, 7, &dummy, CARD_NOCARD, CARD_NOCARD); if (opp_pokval>pl_pokval) { pParent->_los++; hand_lost = true; break; } else { if (opp_pokval > opp_pokvalmax) opp_pokvalmax = opp_pokval; } } if (!hand_lost) { if (pl_pokval > opp_pokvalmax) pParent->_win++; else pParent->_tie++; } // Update display once every 1000 iterations if ((nit % 1000 == 0) && nit >= 1000) { write_log(prefs.debug_prwin(), "[PrWinThread] Progress: %d %.3f %.3f %.3f\n", nit, pParent->_win / (double) nit, pParent->_tie / (double) nit, pParent->_los / (double) nit); iter_vars.set_iterator_thread_progress(nit); iter_vars.set_prwin(pParent->_win / (double) nit); iter_vars.set_prtie(pParent->_tie / (double) nit); iter_vars.set_prlos(pParent->_los / (double) nit); } } write_log(prefs.debug_prwin(), "[PrWinThread] End of main loop.\n"); if (nit >= iter_vars.nit()) { iter_vars.set_iterator_thread_running(false); iter_vars.set_iterator_thread_complete(true); iter_vars.set_iterator_thread_progress(nit); iter_vars.set_prwin(pParent->_win / (double) iter_vars.nit()); iter_vars.set_prtie(pParent->_tie / (double) iter_vars.nit()); iter_vars.set_prlos(pParent->_los / (double) iter_vars.nit()); } else { iter_vars.set_iterator_thread_running(false); iter_vars.set_iterator_thread_complete(false); iter_vars.set_iterator_thread_progress(0); iter_vars.set_nit(0); iter_vars.set_f$p(0); iter_vars.set_br(0); for (int i=0; i<k_number_of_cards_per_player; i++) iter_vars.set_pcard(i, CARD_NOCARD); for (int i=0; i<k_number_of_community_cards; i++) iter_vars.set_ccard(i, CARD_NOCARD); iter_vars.set_prwin(0); iter_vars.set_prtie(0); iter_vars.set_prlos(0); } ::SetEvent(pParent->_m_wait_thread); delete p_iterator_thread; p_iterator_thread = NULL; return 0; }
void write_logautoplay(int level, const char * action) { char nowtime[26]; CString pcards, comcards, temp, rank, pokerhand, bestaction, fcra_seen; char *card; CardMask Cards; int i, nCards; HandVal hv; CString fcra_formula_status; int sym_userchair = (int) p_symbols->sym()->userchair; int sym_br = (int) p_symbols->sym()->br; if (level>prefs.log_level()) return; if (log_fp != NULL) { CSLock lock(log_critsec); // log$ writing if (prefs.log_symbol_enabled()) { int max_log = p_symbols->logsymbols_collection()->GetCount(); if (max_log > 0) { if (max_log > prefs.log_symbol_max_log()) { max_log = prefs.log_symbol_max_log(); } write_log(1, "*** log$ (Total: %d | Showing: %d)\n", p_symbols->logsymbols_collection()->GetCount(), max_log); for (int i=0; i<max_log; i++) { write_log(1, "*** %s\n", p_symbols->logsymbols_collection()->GetAt(i)); } } } CardMask_RESET(Cards); nCards=0; // player cards if (p_symbols->user_chair_confirmed()) { for (i=0; i<=1; i++) { card = StdDeck_cardString(p_scraper->card_player(sym_userchair, i)); temp.Format("%s", card); pcards.Append(temp); CardMask_SET(Cards, p_scraper->card_player(sym_userchair, i)); nCards++; } } else { pcards = "...."; } // common cards comcards = ""; if (sym_br >= 2) { for (i=0; i<=2; i++) { if (p_scraper->card_common(i) != CARD_BACK && p_scraper->card_common(i) != CARD_NOCARD) { card = StdDeck_cardString(p_scraper->card_common(i)); temp.Format("%s", card); comcards.Append(temp); CardMask_SET(Cards, p_scraper->card_common(i)); nCards++; } } } if (sym_br >= 3) { card = StdDeck_cardString(p_scraper->card_common(3)); temp.Format("%s", card); comcards.Append(temp); CardMask_SET(Cards, p_scraper->card_common(3)); nCards++; } if (sym_br >= 4) { card = StdDeck_cardString(p_scraper->card_common(4)); temp.Format("%s", card); comcards.Append(temp); CardMask_SET(Cards, p_scraper->card_common(4)); nCards++; } comcards.Append(".........."); comcards = comcards.Left(10); // handrank if (prefs.sym_handrank_value() == "169") rank.Format("%.0f", p_symbols->sym()->handrank169); else if (prefs.sym_handrank_value() == "1000") rank.Format("%.0f", p_symbols->sym()->handrank1000); else if (prefs.sym_handrank_value() == "1326") rank.Format("%.0f", p_symbols->sym()->handrank1326); else if (prefs.sym_handrank_value() == "2652") rank.Format("%.0f", p_symbols->sym()->handrank2652); else if (prefs.sym_handrank_value() == "p") rank.Format("%.2f", p_symbols->sym()->handrankp); // poker hand hv = Hand_EVAL_N(Cards, nCards); if (HandVal_HANDTYPE(hv)==HandType_STFLUSH && StdDeck_RANK(HandVal_TOP_CARD(hv))==Rank_ACE) pokerhand="royfl"; else if (HandVal_HANDTYPE(hv)==HandType_STFLUSH) pokerhand="strfl"; else if (HandVal_HANDTYPE(hv)==HandType_QUADS) pokerhand="4kind"; else if (HandVal_HANDTYPE(hv)==HandType_FULLHOUSE) pokerhand="fullh"; else if (HandVal_HANDTYPE(hv)==HandType_FLUSH) pokerhand="flush"; else if (HandVal_HANDTYPE(hv)==HandType_STRAIGHT) pokerhand="strai"; else if (HandVal_HANDTYPE(hv)==HandType_TRIPS) pokerhand="3kind"; else if (HandVal_HANDTYPE(hv)==HandType_TWOPAIR) pokerhand="2pair"; else if (HandVal_HANDTYPE(hv)==HandType_ONEPAIR) pokerhand="1pair"; else if (HandVal_HANDTYPE(hv)==HandType_NOPAIR) pokerhand="hcard"; // best action if (strcmp(action, "SWAG")==0) { bestaction.Format("$%.2f", p_symbols->f$betsize()); } else { if (p_symbols->f$alli()) bestaction = "Allin"; else if (p_symbols->f$betsize()) bestaction = "SWAG"; else if (p_symbols->f$rais()) bestaction = "Bet/Raise"; else if (p_symbols->f$call()) bestaction = "Call/Check"; else if (p_symbols->f$prefold()) bestaction = "Pre-fold"; else bestaction = "Fold/Check"; } // fcra_seen int sym_myturnbits = (int) p_symbols->sym()->myturnbits; fcra_seen.Format("%s%s%s%s%s", sym_myturnbits&0x01 ? "F" : ".", sym_myturnbits&0x02 ? "C" : ".", // Check button out of order to stay consistent // with button order in manual mode. sym_myturnbits&0x10 ? "K" : ".", sym_myturnbits&0x04 ? "R" : ".", sym_myturnbits&0x08 ? "A" : "."); // fcra formula status fcra_formula_status.Format("%s%s%s%s", !p_symbols->f$alli() && !p_symbols->f$rais() && !p_symbols->f$call() && !p_symbols->f$betsize() ? "F" : ".", p_symbols->f$call() ? "C" : ".", p_symbols->f$rais() ? "R" : ".", p_symbols->f$alli() ? "A" : "."); fprintf(log_fp, "%s - %1d ", get_time(nowtime), p_tablemap->nchairs()); fprintf(log_fp, "%4s %10s %4s %5s ", pcards.GetString(), comcards.GetString(), rank.GetString(), pokerhand.GetString()); fprintf(log_fp, "%4d %4d %4d ", (int) (p_symbols->sym()->prwin*1000), (int) (p_symbols->sym()->prlos*1000), (int) (p_symbols->sym()->prtie*1000)); fprintf(log_fp, "%2d %8d %-10s - ", (int) p_symbols->sym()->nopponents, (int) p_symbols->sym()->nit, bestaction.GetString()); fprintf(log_fp, "%-5s %9.2f %9.2f %9.2f ", action, p_symbols->sym()->call, p_tablelimits->bet(), p_symbols->sym()->pot); fprintf(log_fp, "%9.2f - %s %s %.2f\n", p_symbols->sym()->balance[10], fcra_seen.GetString(), fcra_formula_status.GetString(), p_symbols->f$betsize() ); if (prefs.trace_enabled() && p_symbols->symboltrace_collection()->GetSize() > 0) { write_log_nostamp(1, "***** Autoplayer Trace ****\n"); for (int i=0; i<p_symbols->symboltrace_collection()->GetSize(); i++) { write_log_nostamp(1, "%s\n", p_symbols->symboltrace_collection()->GetAt(i)); } write_log_nostamp(1, "***********************\n"); } fflush(log_fp); } }
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); } }
void CIteratorThread::InitIteratorLoop() { int e = SUCCESS; CGrammar gram; write_log(preferences.debug_prwin(), "[PrWinThread] Initializing iterator loop\n"); // Set starting status and parameters iter_vars.set_iterator_thread_running(true); iter_vars.set_iterator_thread_complete(false); iter_vars.set_iterator_thread_progress(0); iter_vars.set_nit(10000); //!! f$prwin_number_of_iterations") // Users cards for (int i=0; i<k_number_of_cards_per_player; i++) { iter_vars.set_pcard(i, p_scraper->card_player(p_symbol_engine_userchair->userchair(), i)); } // Community cards for (int i=0; i<k_number_of_community_cards; i++) { iter_vars.set_ccard(i, p_scraper->card_common(i)); } iter_vars.set_prwin(0); iter_vars.set_prtie(0); iter_vars.set_prlos(0); // player cards CardMask_RESET(_plCards); CardMask_RESET(_comCards); _nplCards = _ncomCards = 0; // Counters _win = _tie = _los = 0; // setup masks for (int i=0; i<k_number_of_cards_per_player; i++) { if (iter_vars.pcard(i) != CARD_BACK && iter_vars.pcard(i) != CARD_NOCARD) { CardMask_SET(_plCards, iter_vars.pcard(i)); _nplCards++; } } for (int i=0; i<k_number_of_community_cards; i++) { if (iter_vars.ccard(i) != CARD_BACK && iter_vars.ccard(i) != CARD_NOCARD) { CardMask_SET(_comCards, iter_vars.ccard(i)); _ncomCards++; } } //Weighted prwin only for nopponents <=13 e = SUCCESS; _willplay = (int) gram.CalcF$symbol(p_formula, "f$prwin_willplay", &e); e = SUCCESS; _wontplay = (int) gram.CalcF$symbol(p_formula, "f$prwin_wontplay", &e); e = SUCCESS; _mustplay = (int) gram.CalcF$symbol(p_formula, "f$prwin_mustplay", &e); e = SUCCESS; _topclip = (int) gram.CalcF$symbol(p_formula, "f$prwin_topclip", &e); // 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 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<k_number_of_cards_per_player; i++) { if (p_scraper_access->IsKnownCard(p_scraper->card_player(USER_CHAIR, i))) { CardMask_SET(plCards, p_scraper->card_player(USER_CHAIR, i)); nplCards++; } } // common cards CardMask_RESET(comCards); ncomCards = 0; for (int i=0; i<k_number_of_community_cards; i++) { if (p_scraper_access->IsKnownCard(p_scraper->card_common(i))) { CardMask_SET(comCards, p_scraper->card_common(i)); 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<(k_number_of_cards_per_deck-1); i++) { for (int j=(i+1); j<k_number_of_cards_per_deck; 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, (k_number_of_cards_per_player + 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); }