From 151d8e336f75365bfed2af2c326f0966f86bcc04 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Oct 2019 00:15:24 +0300 Subject: SCI32: More work on Hoyle 5 poker logic --- engines/sci/engine/hoyle5poker.cpp | 147 ++++++++++++++++++++++++++++--------- 1 file changed, 114 insertions(+), 33 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/hoyle5poker.cpp b/engines/sci/engine/hoyle5poker.cpp index 90a2e2b580..944bb83af9 100644 --- a/engines/sci/engine/hoyle5poker.cpp +++ b/engines/sci/engine/hoyle5poker.cpp @@ -73,13 +73,13 @@ enum Hoyle5PokerData { // 49 - 58: next clockwise player's cards (number + suit) // 59 - 60 seem to be unused? // ---- Return values ----------------------------------- - kWhatAmIResult = 61, // bitmask, 0 - 128, checked by PokerHand::whatAmI. Determines what kind of card each player has - kResult = 62, // 1 - 15, checked by localproc_3020 - kDiscardCard0 = 63, // flag, checked by PokerHand::think - kDiscardCard1 = 64, // flag, checked by PokerHand::think - kDiscardCard2 = 65, // flag, checked by PokerHand::think - kDiscardCard3 = 66, // flag, checked by PokerHand::think - kDiscardCard4 = 67, // flag, checked by PokerHand::think + kWhatAmIResult = 61, // bitmask, 0 - 128, checked by PokerHand::whatAmI. Determines what kind of card each player has + kWinningPlayers = 62, // bitmask, winning players (0000 - 1111 binary), checked by localproc_3020 + kDiscardCard0 = 63, // flag, checked by PokerHand::think + kDiscardCard1 = 64, // flag, checked by PokerHand::think + kDiscardCard2 = 65, // flag, checked by PokerHand::think + kDiscardCard3 = 66, // flag, checked by PokerHand::think + kDiscardCard4 = 67, // flag, checked by PokerHand::think // 77 seems to be a bit array? }; @@ -123,28 +123,79 @@ void printPlayerCards(int player, SciArray *data) { } #endif -// Checks the current player's hand, and returns its type using a bitmask -int checkHand(SciArray *data) { +int getCardValue(int card) { + return card == 1 ? 14 : card; // aces are the highest valued cards +} + +int getCardTotal(SciArray *data, int player) { + int result = 0; + int cards[5] = { - data->getAsInt16(kCard0), - data->getAsInt16(kCard1), - data->getAsInt16(kCard2), - data->getAsInt16(kCard3), - data->getAsInt16(kCard4), + getCardValue(data->getAsInt16(kCard0 + 10 * player)), + getCardValue(data->getAsInt16(kCard1 + 10 * player)), + getCardValue(data->getAsInt16(kCard2 + 10 * player)), + getCardValue(data->getAsInt16(kCard3 + 10 * player)), + getCardValue(data->getAsInt16(kCard4 + 10 * player)), + }; + + Common::sort(cards, cards + 5, Common::Less()); + + int lastCard = -1; + int sameRank = 0; + int sameSuit = 0; + int orderedCards = 0; + + for (int i = 0; i < 4; i++) { + if (cards[i] == cards[i + 1]) { + if (sameRank == 0) { + result += cards[i] + cards[i + 1]; + sameRank += 2; + } else { + result += cards[i + 1]; + sameRank++; + } + } + if (cards[i] == cards[i + 1] - 1) + orderedCards == 0 ? orderedCards += 2 : orderedCards++; + + lastCard = cards[i]; + } + + bool isFullHouse = + (cards[0] == cards[1] && cards[1] == cards[2] && cards[3] == cards[4]) || + (cards[0] == cards[1] && cards[2] == cards[3] && cards[3] == cards[4]); + + if (isFullHouse || sameSuit == 5 || orderedCards == 5) { + result = 0; + + for (int i = 0; i < 5; i++) + result += cards[i]; + } + + return result; +} + +// Checks a player's hand, and returns its type using a bitmask +int checkHand(SciArray *data, int player = 0) { + int cards[5] = { + data->getAsInt16(kCard0 + 10 * player), + data->getAsInt16(kCard1 + 10 * player), + data->getAsInt16(kCard2 + 10 * player), + data->getAsInt16(kCard3 + 10 * player), + data->getAsInt16(kCard4 + 10 * player), }; int suits[5] = { - data->getAsInt16(kSuit0), - data->getAsInt16(kSuit1), - data->getAsInt16(kSuit2), - data->getAsInt16(kSuit3), - data->getAsInt16(kSuit4), + data->getAsInt16(kSuit0 + 10 * player), + data->getAsInt16(kSuit1 + 10 * player), + data->getAsInt16(kSuit2 + 10 * player), + data->getAsInt16(kSuit3 + 10 * player), + data->getAsInt16(kSuit4 + 10 * player), }; Common::sort(cards, cards + 5, Common::Less()); int lastCard = -1; - //int lastSuit = -1; int pairs = 0; int sameRank = 0; int sameSuit = 0; @@ -154,38 +205,68 @@ int checkHand(SciArray *data) { if (cards[i] == cards[i + 1] && cards[i] != lastCard) pairs++; if (cards[i] == cards[i + 1]) - sameRank++; + sameRank == 0 ? sameRank += 2 : sameRank++; if (suits[i] == suits[i + 1]) - sameSuit++; + sameSuit == 0 ? sameSuit += 2 : sameSuit++; if (cards[i] == cards[i + 1] - 1) - orderedCards++; + orderedCards == 0 ? orderedCards += 2 : orderedCards++; lastCard = cards[i]; - //lastSuit = suits[i]; } - if (pairs == 1) + bool isFullHouse = + (cards[0] == cards[1] && cards[1] == cards[2] && cards[3] == cards[4]) || + (cards[0] == cards[1] && cards[2] == cards[3] && cards[3] == cards[4]); + + if (pairs == 1 && sameRank == 2) return 1 << 0; // 1, one pair - else if (pairs == 2) + else if (pairs == 2 && !isFullHouse) return 1 << 1; // 2, two pairs - else if (sameRank == 3) + else if (sameRank == 3 && !isFullHouse) return 1 << 2; // 4, three of a kind else if (orderedCards == 5 && sameSuit < 5) - return 1 << 7; // 128, straight - else if (sameSuit == 5) + return 1 << 3; // 8, straight + else if (orderedCards < 5 && sameSuit == 5) return 1 << 4; // 16, flush - else if (cards[0] == cards[1] && cards[1] == cards[2] && cards[3] == cards[4]) + else if (isFullHouse) return 1 << 5; // 32, full house else if (sameRank == 4) return 1 << 6; // 64, four of a kind else if (orderedCards == 5 && sameSuit == 5) - return 0; // straight flush // TODO + return 1 << 7; // straight flush else if (sameRank == 5) return 1 << 8; // 256, five of a kind return 0; // high card } +struct Hand { + int player; + int handTotal; + + Hand(int p, int h) : player(p), handTotal(h) {} +}; + +struct WinningHand : public Common::BinaryFunction { + bool operator()(const Hand &x, const Hand &y) const { return x.handTotal > y.handTotal; } +}; + +int getWinner(SciArray *data) { + Hand playerHands[4] = { + Hand(0, checkHand(data, 0)), + Hand(1, checkHand(data, 1)), + Hand(2, checkHand(data, 2)), + Hand(3, checkHand(data, 3)) + }; + + Common::sort(playerHands, playerHands + 4, WinningHand()); + + if (playerHands[0].handTotal > playerHands[1].handTotal) + return playerHands[0].player; + else + return getCardTotal(data, 0) > getCardTotal(data, 1) ? playerHands[0].player : playerHands[1].player; +} + reg_t hoyle5PokerEngine(SciArray *data) { #if 0 debug("Player %d's turn", data->getAsInt16(kCurrentPlayer)); @@ -224,10 +305,10 @@ reg_t hoyle5PokerEngine(SciArray *data) { #endif data->setFromInt16(kWhatAmIResult, checkHand(data)); + data->setFromInt16(kWinningPlayers, 1 << getWinner(data)); - // Dummy logic + // Dummy logic for card discard Common::RandomSource &rng = g_sci->getRNG(); - data->setFromInt16(kResult, 1 + (int)rng.getRandomNumber(14)); data->setFromInt16(kDiscardCard0, (int)rng.getRandomBit()); data->setFromInt16(kDiscardCard1, (int)rng.getRandomBit()); data->setFromInt16(kDiscardCard2, (int)rng.getRandomBit()); -- cgit v1.2.3