vector<Equity> Evaluator::evalHoldemHands(const vector<CardSet>& hands, const CardSet& board, const CardSet& dead) { size_t numPlayers = hands.size(); vector<Equity> equities(numPlayers); vector<bool> isUsed(Card::MAX_ID + 1); bool IsValidGame = board.IsValid() && dead.IsValid(); for (auto hand : hands) { IsValidGame &= hand.IsValid(2); for (auto card : hand.ToCards()) { IsValidGame &= !isUsed[card.id()]; isUsed[card.id()] = true; } } for (auto card : board.ToCards()) { IsValidGame &= !isUsed[card.id()]; isUsed[card.id()] = true; } for (auto card : dead.ToCards()) { IsValidGame &= !isUsed[card.id()]; isUsed[card.id()] = true; } if (!IsValidGame) { return equities; } vector<int> ranks(numPlayers); vector<int> starts(5, 1); vector<int> ends(5, Card::MAX_ID); for (size_t i = 0; i < board.ToCards().size(); ++i) { starts[i] = ends[i] = board.ToCards()[i].id(); } for (int h0 = starts[0]; h0 <= ends[0]; ++h0) { if (board.ToCards().empty() && isUsed[h0]) { continue; } if (board.ToCards().empty()) { isUsed[h0] = true; starts[1] = h0 + 1; } int r0 = handRanks[h0 + Card::MAX_ID + 1]; for (int h1 = starts[1]; h1 <= ends[1]; ++h1) { if (board.ToCards().size() <= 1 && isUsed[h1]) { continue; } if (board.ToCards().size() <= 1) { isUsed[h1] = true; starts[2] = h1 + 1; } int r1 = handRanks[h1 + r0]; for (int h2 = starts[2]; h2 <= ends[2]; ++h2) { if (board.ToCards().size() <= 2 && isUsed[h2]) { continue; } if (board.ToCards().size() <= 2) { isUsed[h2] = true; starts[3] = h2 + 1; } int r2 = handRanks[h2 + r1]; for (int h3 = starts[3]; h3 <= ends[3]; ++h3) { if (board.ToCards().size() <= 3 && isUsed[h3]) { continue; } if (board.ToCards().size() <= 3) { isUsed[h3] = true; starts[4] = h3 + 1; } int r3 = handRanks[h3 + r2]; for (int h4 = starts[4]; h4 <= ends[4]; ++h4) { if (board.ToCards().size() <= 4 && isUsed[h4]) { continue; } int r4 = handRanks[h4 + r3]; int maxRank = -1; int numBestPlayers = 0; for (size_t i = 0; i < numPlayers; ++i) { ranks[i] = r4; for (auto card : hands[i].ToCards()) { ranks[i] = handRanks[ranks[i] + card.id()]; } if (maxRank == ranks[i]) { ++numBestPlayers; } else if (maxRank < ranks[i]) { maxRank = ranks[i]; numBestPlayers = 1; } } for (size_t i = 0; i < numPlayers; ++i) { if (ranks[i] == maxRank) { equities[i].addTie(numBestPlayers); } else { equities[i].addLose(); } } } if (board.ToCards().size() <= 3) { isUsed[h3] = false; } } if (board.ToCards().size() <= 2) { isUsed[h2] = false; } } if (board.ToCards().size() <= 1) { isUsed[h1] = false; } } if (board.ToCards().empty()) { isUsed[h0] = false; } } return equities; }
vector<Equity> Evaluator::evalOmahaHands(const vector<CardSet>& hands, const CardSet& board, const CardSet& dead) { size_t numPlayers = hands.size(); vector<Equity> equities(numPlayers); vector<bool> isUsed(Card::MAX_ID + 1); bool IsValidGame = board.IsValid() && dead.IsValid(); for (auto hand : hands) { IsValidGame &= hand.IsValid(2); for (auto card : hand.ToCards()) { IsValidGame &= !isUsed[card.id()]; isUsed[card.id()] = true; } } for (auto card : board.ToCards()) { IsValidGame &= !isUsed[card.id()]; isUsed[card.id()] = true; } for (auto card : dead.ToCards()) { IsValidGame &= !isUsed[card.id()]; isUsed[card.id()] = true; } if (!IsValidGame) { return equities; } vector<int> ranks(numPlayers); vector<int> starts(5, 1); vector<int> ends(5, Card::MAX_ID); for (size_t i = 0; i < board.ToCards().size(); ++i) { starts[i] = ends[i] = board.ToCards()[i].id(); } for (int h0 = starts[0]; h0 <= ends[0]; ++h0) { if (board.ToCards().size() <= 0 && isUsed[h0]) { continue; } if (board.ToCards().size() <= 0) { isUsed[h0] = true; starts[1] = h0 + 1; } for (int h1 = starts[1]; h1 <= ends[1]; ++h1) { if (board.ToCards().size() <= 1 && isUsed[h1]) { continue; } if (board.ToCards().size() <= 1) { isUsed[h1] = true; starts[2] = h1 + 1; } for (int h2 = starts[2]; h2 <= ends[2]; ++h2) { if (board.ToCards().size() <= 2 && isUsed[h2]) { continue; } if (board.ToCards().size() <= 2) { isUsed[h2] = true; starts[3] = h2 + 1; } for (int h3 = starts[3]; h3 <= ends[3]; ++h3) { if (board.ToCards().size() <= 3 && isUsed[h3]) { continue; } if (board.ToCards().size() <= 3) { isUsed[h3] = true; starts[4] = h3 + 1; } for (int h4 = starts[4]; h4 <= ends[4]; ++h4) { if (board.ToCards().size() <= 4 && isUsed[h4]) { continue; } int maxRank = -1; int numBestPlayers = 0; array<int, 5> currentBoard = {{h0, h1, h2, h3, h4}}; for (size_t i = 0; i < numPlayers; ++i) { size_t numCards = hands[i].ToCards().size(); for (size_t b0 = 0; b0 < 5; ++b0) { for (size_t b1 = b0 + 1; b1 < 5; ++b1) { for (size_t b2 = b1 + 1; b2 < 5; ++b2) { for (size_t p0 = 0; p0 < numCards; ++p0) { for (size_t p1 = p0 + 1; p1 < numCards; ++p1) { array<int, 5> currentHand = { {currentBoard[b0], currentBoard[b1], currentBoard[b2], static_cast<int>(hands[i].ToCards()[p0].id()), static_cast<int>(hands[i].ToCards()[p1].id())}}; int currentRank = Card::MAX_ID + 1; for (size_t hand : currentHand) { currentRank = handRanks[currentRank + hand]; } currentRank = handRanks[currentRank]; ranks[i] = max(ranks[i], currentRank); } } } } } if (maxRank == ranks[i]) { ++numBestPlayers; } else if (maxRank < ranks[i]) { maxRank = ranks[i]; numBestPlayers = 1; } } for (size_t i = 0; i < numPlayers; ++i) { if (ranks[i] == maxRank) { equities[i].addTie(numBestPlayers); } else { equities[i].addLose(); } } } if (board.ToCards().size() <= 3) { isUsed[h3] = false; } } if (board.ToCards().size() <= 2) { isUsed[h2] = false; } } if (board.ToCards().size() <= 1) { isUsed[h1] = false; } } if (board.ToCards().size() <= 0) { isUsed[h0] = false; } } return equities; }