/***************************************************************************** * PokerTH - The open source texas holdem engine * * Copyright (C) 2006-2011 Felix Hammer, Florian Thauer, Lothar May * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Affero General Public License as * * published by the Free Software Foundation, either version 3 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Affero General Public License for more details. * * * * You should have received a copy of the GNU Affero General Public License * * along with this program. If not, see . * *****************************************************************************/ #include "localboard.h" #include "handinterface.h" #include #include #include "localexception.h" #include "engine_msg.h" LocalBoard::LocalBoard(unsigned dp) : BoardInterface(), pot(0), sets(0), dealerPosition(dp), allInCondition(false), lastActionPlayerID(0) { myCards[0] = myCards[1] = myCards[2] = myCards[3] = myCards[4] = 0; } LocalBoard::~LocalBoard() { } void LocalBoard::setPlayerLists(PlayerList sl, PlayerList apl, PlayerList rpl) { seatsList = sl; activePlayerList = apl; runningPlayerList = rpl; } void LocalBoard::collectSets() { sets = 0; PlayerListConstIterator it_c; for(it_c=seatsList->begin(); it_c!=seatsList->end(); ++it_c) { sets += (*it_c)->getMySet(); } } void LocalBoard::collectPot() { pot += sets; sets = 0; PlayerListIterator it; for(it=seatsList->begin(); it!=seatsList->end(); ++it) { (*it)->setMySetNull(); } } void LocalBoard::distributePot() { winners.clear(); size_t i,j,k,l; PlayerListIterator it; PlayerListConstIterator it_c; // filling player sets vector std::vector playerSets; for(it=seatsList->begin(); it!=seatsList->end(); ++it) { if((*it)->getMyActiveStatus()) { playerSets.push_back( ( ((*it)->getMyRoundStartCash()) - ((*it)->getMyCash()) ) ); } else { playerSets.push_back(0); } (*it)->setLastMoneyWon(0); } // sort player sets asc std::vector playerSetsSort = playerSets; sort(playerSetsSort.begin(), playerSetsSort.end()); // potLevel[0] = amount, potLevel[1] = sum, potLevel[2..n] = winner std::vector potLevel; // temp var int highestCardsValue; size_t winnerCount; bool finalPot; int potCarryOver = 0; size_t mod; bool winnerHit; // level loop for(i=0; i 0) { // level amount potLevel.push_back(playerSetsSort[i]); // level sum potLevel.push_back((playerSetsSort.size()-i)*potLevel[0] + potCarryOver); // determine level highestCardsValue for(it_c=seatsList->begin(), j=0; it_c!=seatsList->end(); ++it_c,j++) { if((*it_c)->getMyActiveStatus() && (*it_c)->getMyCardsValueInt() > highestCardsValue && (*it_c)->getMyAction() != PLAYER_ACTION_FOLD && playerSets[j] >= potLevel[0]) { highestCardsValue = (*it_c)->getMyCardsValueInt(); } } // level winners for(it_c=seatsList->begin(), j=0; it_c!=seatsList->end(); ++it_c,j++) { if((*it_c)->getMyActiveStatus() && highestCardsValue == (*it_c)->getMyCardsValueInt() && (*it_c)->getMyAction() != PLAYER_ACTION_FOLD && playerSets[j] >= potLevel[0]) { potLevel.push_back((*it_c)->getMyUniqueID()); } } // determine the number of level winners winnerCount = potLevel.size()-2; if (!winnerCount) { throw LocalException(__FILE__, __LINE__, ERR_NO_WINNER); } // check if this is the final pot level for at least one winner finalPot = false; for(j=2; jbegin(), k=0; it!=seatsList->end(); ++it, k++) { if((*it)->getMyUniqueID() == potLevel[j] && potLevel[0] == playerSets[k]) { finalPot = true; break; } } if(finalPot) break; } if(finalPot) { // distribute the pot level sum to level winners mod = (potLevel[1])%winnerCount; // pot level sum divisible by winnerCount if(mod == 0) { for(j=2; jbegin(); it!=seatsList->end(); ++it) { if((*it)->getMyUniqueID() == potLevel[j]) { break; } } if(it == seatsList->end()) { throw LocalException(__FILE__, __LINE__, ERR_SEAT_NOT_FOUND); } (*it)->setMyCash( (*it)->getMyCash() + ((potLevel[1])/winnerCount)); // filling winners vector winners.push_back((*it)->getMyUniqueID()); (*it)->setLastMoneyWon( (*it)->getLastMoneyWon() + (potLevel[1])/winnerCount ); } } // pot level sum not divisible by winnerCount // --> distribution after smallBlind else { // find Seat with dealerPosition for(it=seatsList->begin(); it!=seatsList->end(); ++it) { if((*it)->getMyUniqueID() == dealerPosition) { break; } } if(it == seatsList->end()) { throw LocalException(__FILE__, __LINE__, ERR_SEAT_NOT_FOUND); } for(j=0; jend()) it = seatsList->begin(); for(l=2; lgetMyActiveStatus() && (*it)->getMyUniqueID() == potLevel[l]) winnerHit = true; } } if(jsetMyCash( (*it)->getMyCash() + (int)((potLevel[1])/winnerCount) + 1); // filling winners vector winners.push_back((*it)->getMyUniqueID()); (*it)->setLastMoneyWon( (*it)->getLastMoneyWon() + ((potLevel[1])/winnerCount) + 1 ); } else { (*it)->setMyCash( (*it)->getMyCash() + (int)((potLevel[1])/winnerCount)); // filling winners vector winners.push_back((*it)->getMyUniqueID()); (*it)->setLastMoneyWon( (*it)->getLastMoneyWon() + (potLevel[1])/winnerCount ); } } } potCarryOver = 0; // pot refresh pot -= potLevel[1]; } else { potCarryOver = potLevel[1]; } // reevaluate the player sets for(j=0; j0) { playerSets[j] -= potLevel[0]; } } // sort player sets asc playerSetsSort = playerSets; sort(playerSetsSort.begin(), playerSetsSort.end()); // clear potLevel potLevel.clear(); } } // winners sort and unique winners.sort(); winners.unique(); // ERROR-Outputs if(pot!=0) LOG_ERROR(__FILE__ << " (" << __LINE__ << "): distributePot-ERROR: Pot = " << pot); /*int sum = 0; for(it_c=activePlayerList->begin(); it_c!=activePlayerList->end(); ++it_c) { sum += (*it_c)->getMyCash(); }*/ } void LocalBoard::determinePlayerNeedToShowCards() { playerNeedToShowCards.clear(); // in All In Condition everybody have to show the cards if(allInCondition) { PlayerListConstIterator it_c; for(it_c = activePlayerList->begin(); it_c != activePlayerList->end(); ++it_c) { if((*it_c)->getMyAction() != PLAYER_ACTION_FOLD) { playerNeedToShowCards.push_back((*it_c)->getMyUniqueID()); } } } else { // all winners have to show their cards std::list > level; PlayerListConstIterator lastActionPlayerIt; PlayerListConstIterator it_c; // search lastActionPlayer for(it_c = activePlayerList->begin(); it_c != activePlayerList->end(); ++it_c) { if((*it_c)->getMyUniqueID() == lastActionPlayerID && (*it_c)->getMyAction() != PLAYER_ACTION_FOLD) { lastActionPlayerIt = it_c; break; } } if(it_c == activePlayerList->end()) { for(it_c = activePlayerList->begin(); it_c != activePlayerList->end(); ++it_c) { if((*it_c)->getMyAction() != PLAYER_ACTION_FOLD) { lastActionPlayerIt = it_c; break; } } } // the player who has done the last action has to show his cards first playerNeedToShowCards.push_back((*lastActionPlayerIt)->getMyUniqueID()); std::pair level_tmp; // get position und cardsValue of the player who show his cards first level_tmp.first = (*lastActionPlayerIt)->getMyCardsValueInt(); level_tmp.second = (*lastActionPlayerIt)->getMyRoundStartCash()-(*lastActionPlayerIt)->getMyCash(); level.push_back(level_tmp); std::list >::iterator level_it; std::list >::iterator next_level_it; it_c = lastActionPlayerIt; ++it_c; for(unsigned i = 0; i < activePlayerList->size(); i++) { if(it_c == activePlayerList->end()) it_c = activePlayerList->begin(); if((*it_c)->getMyAction() != PLAYER_ACTION_FOLD) { for(level_it = level.begin(); level_it != level.end(); ++level_it) { if((*it_c)->getMyCardsValueInt() > (*level_it).first) { next_level_it = level_it; ++next_level_it; if(next_level_it == level.end()) { playerNeedToShowCards.push_back((*it_c)->getMyUniqueID()); level_tmp.first = (*it_c)->getMyCardsValueInt(); level_tmp.second = (*it_c)->getMyRoundStartCash()-(*it_c)->getMyCash(); level.push_back(level_tmp); break; } } else { if((*it_c)->getMyCardsValueInt() == (*level_it).first) { next_level_it = level_it; ++next_level_it; if(next_level_it == level.end() || (*it_c)->getMyRoundStartCash()-(*it_c)->getMyCash() > (*next_level_it).second) { playerNeedToShowCards.push_back((*it_c)->getMyUniqueID()); if((*it_c)->getMyRoundStartCash()-(*it_c)->getMyCash() > (*level_it).second) { (*level_it).second = (*it_c)->getMyRoundStartCash()-(*it_c)->getMyCash(); } } break; } else { if((*it_c)->getMyRoundStartCash()-(*it_c)->getMyCash() > (*level_it).second) { playerNeedToShowCards.push_back((*it_c)->getMyUniqueID()); level_tmp.first = (*it_c)->getMyCardsValueInt(); level_tmp.second = (*it_c)->getMyRoundStartCash()-(*it_c)->getMyCash(); level.insert(level_it,level_tmp); break; } } } } } ++it_c; } level.clear(); } // sort and unique the list playerNeedToShowCards.sort(); playerNeedToShowCards.unique(); }