From 0f59c0ad57fae90b8b2f2714dfd8e10fa26dcd80 Mon Sep 17 00:00:00 2001 From: floty Date: Sat, 24 May 2014 15:13:49 +0200 Subject: [PATCH] implement new cards value function; circa factor 10 faster than old version --- src/engine/local_engine/cardsvalue.cpp | 226 ++++++++++++++++++++---- src/engine/local_engine/cardsvalue.h | 15 +- src/engine/local_engine/localhand.cpp | 2 +- src/engine/local_engine/localplayer.cpp | 34 ++-- src/engine/local_engine/localplayer.h | 5 +- src/engine/local_engine/tools.cpp | 10 ++ src/engine/local_engine/tools.h | 1 + 7 files changed, 231 insertions(+), 62 deletions(-) diff --git a/src/engine/local_engine/cardsvalue.cpp b/src/engine/local_engine/cardsvalue.cpp index e309d95f..21ed3b7c 100755 --- a/src/engine/local_engine/cardsvalue.cpp +++ b/src/engine/local_engine/cardsvalue.cpp @@ -221,52 +221,216 @@ int CardsValue::holeCardsClass(int one, int two) } -int CardsValue::holeCardsToIntCode(int* cards) +int CardsValue::holeCardsToIntCode(int holeCards[2]) { // Code der HoleCards ermitteln - if(cards[0]%13 == cards[1]%13) { - return ((cards[0]%13)*1000 + (cards[0]%13)*10); + if(holeCards[0]%13 == holeCards[1]%13) { + return ((holeCards[0]%13)*1000 + (holeCards[0]%13)*10); } else { - if(cards[0]%13 < cards[1]%13) { - if(cards[0]/13 == cards[1]/13) { - return ((cards[0]%13)*1000 + (cards[1]%13)*10 + 1); + if(holeCards[0]%13 < holeCards[1]%13) { + if(holeCards[0]/13 == holeCards[1]/13) { + return ((holeCards[0]%13)*1000 + (holeCards[1]%13)*10 + 1); } else { - return ((cards[0]%13)*1000 + (cards[1]%13)*10); + return ((holeCards[0]%13)*1000 + (holeCards[1]%13)*10); } } else { - if(cards[0]/13 == cards[1]/13) { - return ((cards[1]%13)*1000 + (cards[0]%13)*10 + 1); + if(holeCards[0]/13 == holeCards[1]/13) { + return ((holeCards[1]%13)*1000 + (holeCards[0]%13)*10 + 1); } else { - return ((cards[1]%13)*1000 + (cards[0]%13)*10); + return ((holeCards[1]%13)*1000 + (holeCards[0]%13)*10); } } } } -/* DO NOT USE, THIS MAY LEAK MEMORY -int* CardsValue::intCodeToHoleCards(int code) +static const int straight[10] = { 7936, 3968, 1984, 992, 496, 248, 124, 62, 31, 4111 }; + +int CardsValue::cardsValue(int cards[4], int bestHand[4]) { + int color_1_idx; + int card_idx; + KickerValue kickerValue1; - // one possibility !!! - - int* cards = new int[2]; - - cards[0] = code/1000; - cards[1] = (code-cards[0]*1000)/10; - - if(cards[0]==cards[1]) { - cards[1] +=13; - } else { - if(code%10 == 0) cards[1] +=13; + // Royal Flush, Straight Flush, Flush + for(color_1_idx=0; color_1_idx<4; color_1_idx++) { // check all colors + if(Tools::bitcount(cards[color_1_idx])>=5) { // check if at least 5 cards of one color + if((cards[color_1_idx] & straight[0]) == straight[0]) { // check for Royal Flush + if(bestHand) bestHand[color_1_idx] = straight[0]; + return 900000000; // Royal Flush + } else { + for(card_idx=1; card_idx<10; card_idx++) { + if((cards[color_1_idx] & straight[card_idx]) == straight[card_idx]) { // check for Straight Flush + if(bestHand) bestHand[color_1_idx] = straight[card_idx]; + return (800000000+(12-card_idx)*1000000); // Straight Flush + } + } + } + // Flush + kickerValue1 = determineKickerValue(cards[color_1_idx],0,4); + if(bestHand) bestHand[color_1_idx] = kickerValue1.select; + return 500000000 + kickerValue1.factorValue; + } } - return cards; + int AND = cards[0] & cards[1] & cards[2] & cards[3]; + int OR = cards[0] | cards[1] | cards[2] | cards[3]; + int temp1; + KickerValue kickerValue2; -}*/ + // Four of a Kind + if(AND) { + kickerValue1 = determineKickerValue(AND,0,0); + kickerValue2 = determineKickerValue(OR & ~AND,1,1); + if(bestHand) { + temp1 = kickerValue2.select; + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) { + bestHand[color_1_idx] = (cards[color_1_idx] & (kickerValue1.select | temp1)); + if(bestHand[color_1_idx] & temp1) temp1 = 0; + } + } + return 700000000 + kickerValue1.factorValue + kickerValue2.factorValue; + } -int CardsValue::cardsValue(int* cards, int* position) + // Straight + for(card_idx=0; card_idx<10; card_idx++) { + if((OR & straight[card_idx]) == straight[card_idx]) { + if(bestHand) { + temp1 = straight[card_idx]; + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) { + bestHand[color_1_idx] += (temp1 & cards[color_1_idx]); + temp1 &= ~bestHand[color_1_idx]; + } + } + return 400000000 + (12-card_idx)*1000000; + } + } + + int color_2_idx, color_3_idx; + int temp2; + + // Full House, Three of a Kind + temp1 = 0; + for(color_1_idx=0; color_1_idx<2; color_1_idx++) { + for(color_2_idx=color_1_idx+1; color_2_idx<3; color_2_idx++) { + for(color_3_idx=color_2_idx+1; color_3_idx<4; color_3_idx++) { + temp1 |= cards[color_1_idx] & cards[color_2_idx] & cards[color_3_idx]; + } + } + } + if(temp1) { + if(Tools::bitcount(temp1) == 2) { + // two times Three of a Kind + if(bestHand) { + kickerValue1 = determineKickerValue(temp1,0,0); + kickerValue2 = determineKickerValue(kickerValue1.remain,1,1); + temp2 = 0; + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) { + if(temp2<2) bestHand[color_1_idx] += (cards[color_1_idx] & (kickerValue1.select | kickerValue2.select)); + else bestHand[color_1_idx] += (cards[color_1_idx] & kickerValue1.select); + if(cards[color_1_idx] & kickerValue2.select) temp2++; + } + } + return 600000000 + determineKickerValue(temp1,0,1).factorValue; + } else { + // one times Three of a Kind + temp2 = temp1; + temp1 = 0; + // check for additional pair + for(color_1_idx=0; color_1_idx<3; color_1_idx++) { + for(color_2_idx=color_1_idx+1; color_2_idx<4; color_2_idx++) { + temp1 |= cards[color_1_idx] & cards[color_2_idx]; + } + } + temp1 &= ~temp2; // remove Three of a Kind from found pairs + if(temp1) { + // with additional pair + kickerValue1 = determineKickerValue(temp2,0,0); + kickerValue2 = determineKickerValue(temp1,1,1); + if(bestHand) { + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) bestHand[color_1_idx] = (cards[color_1_idx] & (kickerValue1.select | kickerValue2.select)); + } + return 600000000 + kickerValue1.factorValue + kickerValue2.factorValue; // Full House + } else { + // without addition pair + kickerValue1 = determineKickerValue(temp2,0,0); + kickerValue2 = determineKickerValue(OR & ~temp2,1,2); + if(bestHand) { + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) bestHand[color_1_idx] = (cards[color_1_idx] & (kickerValue1.select | kickerValue2.select)); + } + return 300000000 + kickerValue1.factorValue + kickerValue2.factorValue; // Three of a Kind + } + } + } + + // Two Pairs, Two of a Kind + temp1 = 0; + for(color_1_idx=0; color_1_idx<3; color_1_idx++) { + for(color_2_idx=color_1_idx+1; color_2_idx<4; color_2_idx++) { + temp1 |= (cards[color_1_idx] & cards[color_2_idx]); + } + } + if(temp1) { + if(Tools::bitcount(temp1) >= 2) { // at least two times Two of a Kind + kickerValue1 = determineKickerValue(temp1,0,1); + kickerValue2 = determineKickerValue(OR & ~kickerValue1.select,2,2); + if(bestHand) { + temp1 = (kickerValue1.select | kickerValue2.select); + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) { + bestHand[color_1_idx] += (cards[color_1_idx] & temp1); + if(bestHand[color_1_idx] & kickerValue2.select) temp1 &= ~kickerValue2.select; + } + } + return 200000000 + kickerValue1.factorValue + kickerValue2.factorValue; // Two Pairs + } else { + kickerValue1 = determineKickerValue(temp1,0,0); + kickerValue2 = determineKickerValue(OR & ~temp1,1,3); + if(bestHand) { + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) { + bestHand[color_1_idx] += (cards[color_1_idx] & (kickerValue1.select | kickerValue2.select)); + } + } + return 100000000 + kickerValue1.factorValue + kickerValue2.factorValue; // Two of a Kind + } + } + + // High Card + kickerValue1 = determineKickerValue(OR,0,4); + if(bestHand) { + for(color_1_idx=3; color_1_idx>=0; color_1_idx--) { + bestHand[color_1_idx] += (cards[color_1_idx] & kickerValue1.select); + } + } + return kickerValue1.factorValue; + +} + +static const int factor_kicker_short[4] = {1000000,10000,100,1}; +static const int factor_kicker_long[5] = {1000000,10000,100,10,1}; + +KickerValue CardsValue::determineKickerValue(int testValue, int factorPointerStart, int factorPointerEnd) +{ + KickerValue kickerValue; + kickerValue.factorValue = 0; + kickerValue.remain = testValue; + kickerValue.select = 0; + int compareValue = 4096; + int factorPointer = factorPointerStart; + for(int card_idx=0; (factorPointer<=factorPointerEnd) & (card_idx<13); card_idx++) { + if(kickerValue.remain >= compareValue) { + if(factorPointerEnd - factorPointerStart==4) kickerValue.factorValue += (12-card_idx)*factor_kicker_long[factorPointer]; + else kickerValue.factorValue += (12-card_idx)*factor_kicker_short[factorPointer]; + kickerValue.remain &= ~compareValue; + factorPointer++; + } + compareValue >>= 1; + } + kickerValue.select = testValue & ~kickerValue.remain; + return kickerValue; +} + +int CardsValue::cardsValueOld(int cards[7], int position[5]) { int array[7][3]; @@ -645,7 +809,7 @@ int CardsValue::cardsValue(int* cards, int* position) } -std::vector< std::vector > CardsValue::calcCardsChance(GameState beRoID, int* playerCards, int* boardCards) +std::vector< std::vector > CardsValue::calcCardsChance(GameState beRoID, int playerCards[2], int boardCards[5]) { int i,j; @@ -681,7 +845,7 @@ std::vector< std::vector > CardsValue::calcCardsChance(GameState beRoID, in if(j!=cards[0] && j!=cards[1] && j!=cards[2] && j!=cards[3] && j!=cards[4]) { cards[5] = i; cards[6] = j; - (chance[0][cardsValue(cards,0)/100000000])++; + (chance[0][cardsValueOld(cards,0)/100000000])++; sum++; } } @@ -699,7 +863,7 @@ std::vector< std::vector > CardsValue::calcCardsChance(GameState beRoID, in for(i=0; i<52; i++) { if(i!=cards[0] && i!=cards[1] && i!=cards[2] && i!=cards[3] && i!=cards[4] && i!=cards[5]) { cards[6] = i; - (chance[0][cardsValue(cards,0)/100000000])++; + (chance[0][cardsValueOld(cards,0)/100000000])++; sum++; } } @@ -711,8 +875,8 @@ std::vector< std::vector > CardsValue::calcCardsChance(GameState beRoID, in } break; case GAME_STATE_RIVER: { - chance[0][cardsValue(cards,0)/100000000] = 100; - chance[1][cardsValue(cards,0)/100000000] = 1; + chance[0][cardsValueOld(cards,0)/100000000] = 100; + chance[1][cardsValueOld(cards,0)/100000000] = 1; } break; default: { diff --git a/src/engine/local_engine/cardsvalue.h b/src/engine/local_engine/cardsvalue.h index ff45baf6..a056cf0a 100755 --- a/src/engine/local_engine/cardsvalue.h +++ b/src/engine/local_engine/cardsvalue.h @@ -38,18 +38,25 @@ #include #include +struct KickerValue { + int factorValue; + int select; + int remain; +}; + class CardsValue { public: static int holeCardsClass(int, int); - static int cardsValue(int*, int*); + static int cardsValue(int[4], int[4]); + static KickerValue determineKickerValue(int, int, int); + static int cardsValueOld(int[7], int[5]); static std::string determineHandName(int myCardsValueInt, PlayerList activePlayerList); static std::list translateCardsValueCode(int cardsValueCode); - static int holeCardsToIntCode(int*); - static int* intCodeToHoleCards(int); + static int holeCardsToIntCode(int[2]); - static std::vector< std::vector > calcCardsChance(GameState, int*, int*); + static std::vector< std::vector > calcCardsChance(GameState, int[2], int[5]); //static int** showdown(GameState, int**, int); }; diff --git a/src/engine/local_engine/localhand.cpp b/src/engine/local_engine/localhand.cpp index ebf669fd..213a4e0b 100755 --- a/src/engine/local_engine/localhand.cpp +++ b/src/engine/local_engine/localhand.cpp @@ -98,7 +98,7 @@ LocalHand::LocalHand(boost::shared_ptr f, GuiInterface *g, boost: for(j=0; j<2; j++) tempPlayerAndBoardArray[j] = tempPlayerArray[j]; (*it)->setMyCards(tempPlayerArray); - (*it)->setMyCardsValueInt(CardsValue::cardsValue(tempPlayerAndBoardArray, bestHandPos)); + (*it)->setMyCardsValueInt(CardsValue::cardsValueOld(tempPlayerAndBoardArray, bestHandPos)); (*it)->setMyBestHandPosition(bestHandPos); (*it)->setMyRoundStartCash((*it)->getMyCash()); diff --git a/src/engine/local_engine/localplayer.cpp b/src/engine/local_engine/localplayer.cpp index 9e1c07d0..6900271b 100755 --- a/src/engine/local_engine/localplayer.cpp +++ b/src/engine/local_engine/localplayer.cpp @@ -905,18 +905,10 @@ LocalPlayer::LocalPlayer(ConfigFile *c, int id, unsigned uniqueId, PlayerType ty } - LocalPlayer::~LocalPlayer() { } - -void LocalPlayer::setHand(HandInterface* br) -{ - currentHand = br; -} - - void LocalPlayer::action() { @@ -1269,7 +1261,6 @@ void LocalPlayer::preflopEngine() evaluation(bet, raise); } - void LocalPlayer::flopEngine() { @@ -1532,7 +1523,6 @@ void LocalPlayer::flopEngine() } - void LocalPlayer::turnEngine() { @@ -1807,7 +1797,6 @@ void LocalPlayer::turnEngine() } - void LocalPlayer::riverEngine() { @@ -2068,7 +2057,6 @@ void LocalPlayer::riverEngine() } - void LocalPlayer::evaluation(int bet, int raise) { @@ -2193,7 +2181,6 @@ void LocalPlayer::evaluation(int bet, int raise) } - int LocalPlayer::flopCardsValue(int* cards) { @@ -2827,7 +2814,6 @@ int LocalPlayer::flopCardsValue(int* cards) } - void LocalPlayer::calcMyOdds() { @@ -2941,8 +2927,8 @@ void LocalPlayer::calcMyOdds() tempOpponentCardsArray[1] = j; tempOpponentCardsArray[6] = k; tempMyCardsArray[6] = k; - tempMyCardsValue = CardsValue::cardsValue(tempMyCardsArray,0); - tempOpponentCardsValue = CardsValue::cardsValue(tempOpponentCardsArray,0); + tempMyCardsValue = CardsValue::cardsValueOld(tempMyCardsArray,0); + tempOpponentCardsValue = CardsValue::cardsValueOld(tempOpponentCardsArray,0); if(tempMyCardsValue>=tempOpponentCardsValue) countMy++; } @@ -2995,8 +2981,8 @@ void LocalPlayer::calcMyOdds() tempOpponentCardsArray[0] = i; tempOpponentCardsArray[1] = j; - tempMyCardsValue = CardsValue::cardsValue(tempMyCardsArray,0); - tempOpponentCardsValue = CardsValue::cardsValue(tempOpponentCardsArray,0); + tempMyCardsValue = CardsValue::cardsValueOld(tempMyCardsArray,0); + tempOpponentCardsValue = CardsValue::cardsValueOld(tempOpponentCardsArray,0); if(tempMyCardsValue>=tempOpponentCardsValue) countMy++; } @@ -3490,8 +3476,8 @@ void LocalPlayer::flopEngine3() tempOpponentCardsArray[6] = l; tempMyCardsArray[5] = k; tempMyCardsArray[6] = l; - tempMyCardsValue = CardsValue::cardsValue(tempMyCardsArray,0); - tempOpponentCardsValue = CardsValue::cardsValue(tempOpponentCardsArray,0); + tempMyCardsValue = CardsValue::cardsValueOld(tempMyCardsArray,0); + tempOpponentCardsValue = CardsValue::cardsValueOld(tempOpponentCardsArray,0); if(tempMyCardsValue>=tempOpponentCardsValue) countMy++; @@ -3659,8 +3645,8 @@ void LocalPlayer::turnEngine3() tempOpponentCardsArray[1] = j; tempOpponentCardsArray[6] = k; tempMyCardsArray[6] = k; - tempMyCardsValue = CardsValue::cardsValue(tempMyCardsArray,0); - tempOpponentCardsValue = CardsValue::cardsValue(tempOpponentCardsArray,0); + tempMyCardsValue = CardsValue::cardsValueOld(tempMyCardsArray,0); + tempOpponentCardsValue = CardsValue::cardsValueOld(tempOpponentCardsArray,0); if(tempMyCardsValue>=tempOpponentCardsValue) countMy++; } @@ -3823,8 +3809,8 @@ void LocalPlayer::riverEngine3() tempOpponentCardsArray[0] = i; tempOpponentCardsArray[1] = j; - tempMyCardsValue = CardsValue::cardsValue(tempMyCardsArray,0); - tempOpponentCardsValue = CardsValue::cardsValue(tempOpponentCardsArray,0); + tempMyCardsValue = CardsValue::cardsValueOld(tempMyCardsArray,0); + tempOpponentCardsValue = CardsValue::cardsValueOld(tempOpponentCardsArray,0); if(tempMyCardsValue>=tempOpponentCardsValue) countMy++; } diff --git a/src/engine/local_engine/localplayer.h b/src/engine/local_engine/localplayer.h index 58269e9b..f705c74e 100755 --- a/src/engine/local_engine/localplayer.h +++ b/src/engine/local_engine/localplayer.h @@ -48,8 +48,9 @@ public: ~LocalPlayer(); - void setHand(HandInterface *); - + void setHand(HandInterface *theValue) { + currentHand = theValue; + } int getMyID() const { return myID; } diff --git a/src/engine/local_engine/tools.cpp b/src/engine/local_engine/tools.cpp index ebc47a6c..974b0956 100755 --- a/src/engine/local_engine/tools.cpp +++ b/src/engine/local_engine/tools.cpp @@ -83,3 +83,13 @@ void Tools::GetRand(int minValue, int maxValue, unsigned count, int *out) } } +int Tools::bitcount(int in) +{ + int count=0 ; + while (in) { + count++ ; + in &= (in - 1) ; + } + return count ; +} + diff --git a/src/engine/local_engine/tools.h b/src/engine/local_engine/tools.h index 7cd599a4..36fdbdae 100755 --- a/src/engine/local_engine/tools.h +++ b/src/engine/local_engine/tools.h @@ -38,6 +38,7 @@ public: static void ShuffleArrayNonDeterministic(int *inout, unsigned count); static void GetRand(int minValue, int maxValue, unsigned count, int *out); + static int bitcount(int in); };