//http://poker.stackexchange.com/questions/1474/formula-for-making-a-single-pair-on-the-flop public ProbabilityViewModel FindChancesOfPokerHands(MyHand myHand) { //TODO: POSSIBLE BUGS SEEN ON STRAIGHT POSSIBILITY //TODO: INDICATOR OF PLAYING BOARD CARDS (IE IF 2 BOARD CARDS ARE PAIR, GETTING 3KIND ON BOARD IS //ONLY GOOD IF YOU HAVE ANOTHER HIGH CARD FOR POSSIBLE KICKER) //HAND STRENGTH INDICATOR: DEPENDS ON WHETHER YOUR CARDS COME INTO PLAY, HOW HIGH IN PLAY //(IE HIGHEST CARD IN STRAIGHT, LOW OR HIGH COMPLETION OF FLUSH, ETC) ProbabilityViewModel vm = null; if (CurrentRound == Rounds.isPreFlop) { vm = GetChancesOnFlop(myHand); } else if (CurrentRound == Rounds.isFlop || CurrentRound == Rounds.isTurn) { vm = GetChancesOnTurnAndRiver(myHand); } //river was just dealt, hide all chance texts except my hand else if (CurrentRound == Rounds.isRiver) { double rank = myHand.GetRank(); var pokerHand = MyHand.GetPokerHand(rank); bool isRoyalFlush = false; if (pokerHand == PokerHand.STRAIGHT_FLUSH && MyHand.CheckForRoyalFlush(rank)) { isRoyalFlush = true; } vm = new ProbabilityViewModel(pokerHand, isRoyalFlush); } return(vm); }
private ProbabilityViewModel GetChancesOnFlop(MyHand myHand) { //pc.roundText.text = "CHANCES ON THE FLOP"; List <int> myPocketRanks = myHand.GetPocketCardRanksHighToLow(); //just the suits of the pocket hand List <string> myPocketSuits = myHand.GetPocketSuits(); bool cardsAreSuited = myHand.PocketCardsAreSuited(); var cardsForPair = new double(); var cardsForTriple = new double(); var chanceHighCard = new double(); var chancePair = new double(); var chanceTwoPair = new double(); var chanceThreeKind = new double(); var chanceStraight = new double(); var chanceFlush = new double(); var chanceFullHouse = new double(); var chanceFourKind = new double(); var chanceStraightFlush = new double(); var chanceRoyalFlush = new double(); double rank = myHand.GetRank(); //IF I HAVE A HIGH CARD WITH MY POCKET CARDS if (MyHand.IsMyPokerHand(rank, PokerHand.HIGH_CARD)) { //3 cards could pair with first pocket card and 3 with the second cardsForPair = 6; // chanceHighCard = 1; //flop0 pairs, flop1 doesnt, flop2 doesnt //6/50 * 44/49 * (43-3)/48. The 3 represents the number of ranks left matching flop1 chancePair = cardsForPair / CardsLeft * ((CardsLeft - 1) - (cardsForPair - 1)) / (CardsLeft - 1) * ((CardsLeft - 2) - (cardsForPair - 1) - 3) / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE; //TWO PAIR SECTION -------------------------------------------------------- //chance of first card pairing with a pocket card, 2nd card not pairing, 3rd card pairing with 2nd card //6/50 * 44/49 * 3/48 double chanceTwoPairComm = 6d / CardsLeft * 44d / (CardsLeft - 1) * 3d / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE; //chance of first card pairing with a pocket card, 2nd card pairing with other pocket card, 3rd card not pairing //6/50 * 3/49 * 44/48 chanceTwoPair = cardsForPair / CardsLeft * 3d / (CardsLeft - 1) * ((CardsLeft - 2) - (cardsForPair - 2)) / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE + chanceTwoPairComm; //chance of all 3 comm cards same rank (not same as either pocket card) //(50-6)/50 * 3/49 * 2/48 double chanceThreeKindComm = (CardsLeft - cardsForPair) / CardsLeft * 3d / (CardsLeft - 1) * 2d / (CardsLeft - 2); //chance flop0 pairing, flop1 pairing with flop0, flop3 not pairing //6/50 * 2/49 * 44/48 * Constants.HOLDEM_FLOPSIZE + chanceThreeKindComm chanceThreeKind = cardsForPair / CardsLeft * 2d / (CardsLeft - 1) * ((CardsLeft - 2) - (cardsForPair - 2)) / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE + chanceThreeKindComm; //STRAIGHT AND STRAIGHT FLUSH POSSIBILITY -------------------------------------------- //for possible straight on flop, //cards must have an Ace and 2,3,4 or 5 (Ace low straight), or cards must be less than 5 ranks different bool hasAce = myPocketRanks[0] == 14; bool possAceLowStraight = hasAce && myPocketRanks[1] <= 5; bool possNormalStraight = myPocketRanks[0] - myPocketRanks[1] < 5; if (possAceLowStraight || possNormalStraight) { //STRAIGHT IS POSSIBLE ON FLOP //number of card ranks per each suit double ranksPerSuit = 4d; //IF RANKS ARE < 4 APART AND THERE IS NO ACE, the first card has 8 possibilities //(ie if pocket cards are 2 and 5, first card can be Ace or 6) if (myPocketRanks[0] - myPocketRanks[1] < 4 && !hasAce) { //8d / 50d * 4d / 49d * 4d / 48d * 3d*2d; chanceStraight = 2d * ranksPerSuit / CardsLeft * ranksPerSuit / (CardsLeft - 1) * ranksPerSuit / (CardsLeft - 2) * 3d * 2d; } else { //ranks are at the ends of the straight so there is only one possible straight //since they are all different ranks, there are 3! (3*2) different orders for them to be dealt //4d / 50d * 4d / 49d * 4d / 48d * 3d*2d; chanceStraight = ranksPerSuit / CardsLeft * ranksPerSuit / (CardsLeft - 1) * ranksPerSuit / (CardsLeft - 2) * 3d * 2d; } //if cards are suited, there's a chance of straight flush on flop if (cardsAreSuited) { //straight flush is also possible on flop //1d / 50d * 1d / 49d * 1d / 48d * 3d * 2d; chanceStraightFlush = 1d / CardsLeft * 1d / (CardsLeft - 1) * 1d / (CardsLeft - 2) * 3d * 2d; //Royal flush chance bool bothRankedAtLeastTen = myPocketRanks[0] >= 10 && myPocketRanks[1] >= 10; if (bothRankedAtLeastTen) { chanceRoyalFlush = chanceStraightFlush; } } } else { //cards are not within 5 ranks so no possibility of straight Debug.WriteLine("straight is not possible on flop"); chanceStraight = 0; chanceStraightFlush = 0; } //FLUSH POSSIBILITY-------------------------------------------- if (cardsAreSuited) { //flush is possible on flop var flushCardsLeft = 11d; //flop0 is flushcard, flop1 is flushcard, flop2 is flushcard (only one way to order this) //11d / 50d * 10d / 49d * 9d / 48d; chanceFlush = flushCardsLeft / CardsLeft * (flushCardsLeft - 1) / (CardsLeft - 1) * (flushCardsLeft - 2) / (CardsLeft - 2); } else { Debug.WriteLine("flush not possible on flop"); chanceFlush = 0; } //FULL HOUSE POSSIBILITY-------------------------------------------- //chance of pairing on flop0, triple on flop1, pairing with other pocket card on flop2 //6d / 50d * 2d / 49d * 3d / 48d * Constants.HOLDEM_FLOPSIZE; chanceFullHouse = cardsForPair / CardsLeft * 2d / (CardsLeft - 1) * 3d / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE; //FOUR OF A KIND POSSIBILITY-------------------------------------------- //first card has 6 possibilities for pairing, then only 2 for triple, then 1 for quad //6 / 50 * 2 / 49 * 1 / 48 chanceFourKind = cardsForPair / CardsLeft * 2d / (CardsLeft - 1) * 1d / (CardsLeft - 2); //starts from 1 (pair) through straight flush (count-1) because royal flush is a type of straight flush chanceHighCard = 1; } //CLOSE HIGH CARD else if (MyHand.IsMyPokerHand(rank, PokerHand.PAIR)) { //HIDE HIGH CARD CHANCE TEXT //pc.chanceTexts [0].enabled = false; //TWO PAIR SECTION -------------------------------------------------------- //chance of first card not tripling with pocket cards, 2nd card not tripling or pairing with 1st, 3rd card pairing with 2nd card //48/50 * (47-3)/49 * 3/48 * 3 chanceTwoPair = 48d / CardsLeft * 44d / (CardsLeft - 1) * 3d / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE; //THREE KIND SECTION cardsForTriple = 2; //chance flop0 tripling, flop1 no multiple, flop2 no multiple //2/50 * 48/49 * (47-3)/48 * Constants.HOLDEM_FLOPSIZE chanceThreeKind = cardsForTriple / CardsLeft * ((CardsLeft - 1) - (cardsForTriple - 1)) / (CardsLeft - 1) * ((CardsLeft - 2) - (cardsForTriple - 1) - 3d) / (CardsLeft - 2) * Constants.HOLDEM_FLOPSIZE; //STRAIGHT, FLUSH, AND STRAIGHT FLUSH NOT POSSIBLE -------------------------------------------- chanceStraight = 0; chanceFlush = 0; chanceStraightFlush = 0; //FULL HOUSE POSSIBILITY-------------------------------------------- //chance of all 3 comm cards same rank (not same as either pocket card) //(50-2)/50 * 3/49 * 2/48 double chanceThreeKindComm = (CardsLeft - cardsForTriple) / CardsLeft * 3d / (CardsLeft - 1) * 2d / (CardsLeft - 2); //TODO: RECODE //flop0 triples, flop1 other rank, flop2 pairs with flop1 //2/50 * 48/49 * 3/48 * Constants.HOLDEM_FLOPSIZE chanceFullHouse = 2d / 50d * 48d / 49d * 3d / 48d * Constants.HOLDEM_FLOPSIZE + chanceThreeKindComm; //flop0 and flop1 make quad, flop2 any card //2d / 50d * 1d / 49d * 1d * Constants.HOLDEM_FLOPSIZE chanceFourKind = 2d / 50d * 1d / 49d * 1d * Constants.HOLDEM_FLOPSIZE; chancePair = 1; } //CLOSE PAIR var vm = new ProbabilityViewModel (chanceHighCard, chancePair, chanceTwoPair, chanceThreeKind, chanceStraight, chanceFlush, chanceFullHouse, chanceFourKind, chanceStraightFlush, chanceRoyalFlush); return(vm); }
private ProbabilityViewModel GetChancesOnTurnAndRiver(MyHand myHand) { var chanceHighCard = new double(); var chancePair = new double(); var chanceTwoPair = new double(); var chanceThreeKind = new double(); var chanceStraight = new double(); var chanceFlush = new double(); var chanceFullHouse = new double(); var chanceFourKind = new double(); var chanceStraightFlush = new double(); var chanceRoyalFlush = new double(); var cardsForPair = new double(); var cardsForTriple = new double(); double rank = myHand.GetRank(); //if (CurrentRound == Rounds.isFlop) //{ // //pc.roundText.text = "ON THE TURN AND RIVER"; //} //else //{ // //pc.roundText.text = "ON THE RIVER"; //} //high card if (MyHand.IsMyPokerHand(rank, PokerHand.HIGH_CARD)) { if (CurrentRound == Rounds.isFlop) { //5 cards dealt (including my pocket hand) * 3 left of each rank cardsForPair = 15; // 15/47 * 32/46 * 2 chancePair = cardsForPair / CardsLeft * (CardsLeft - cardsForPair) / (CardsLeft - 1) * 2; // 15/47 * 12/46 chanceTwoPair = cardsForPair / CardsLeft * (cardsForPair - 3) / (CardsLeft - 1); // 15/47 * 2/46 (there are 2 cards left after pair that could make a triple) chanceThreeKind = cardsForPair / CardsLeft * 2 / (CardsLeft - 1); } else if (CurrentRound == Rounds.isTurn) { cardsForPair = 18; chancePair = cardsForPair / CardsLeft; chanceTwoPair = 0; chanceThreeKind = 0; } chanceFullHouse = 0; chanceFourKind = 0; //todo this should be 1 - all other chances chanceHighCard = 1; } else if (MyHand.IsMyPokerHand(rank, PokerHand.PAIR)) { //HIDE HIGH CARD CHANCE TEXT IF ALREADY HAVE A PAIR //pc.chanceTexts [0].enabled = false; if (CurrentRound == Rounds.isFlop) { // 9/47 * 38/46 * 2 = 31.6% chanceTwoPair = 9d / CardsLeft * (CardsLeft - 9d) / (CardsLeft - 1) * 2; // 2/47 * 45/46 * 2 = 8% chanceThreeKind = 2d / CardsLeft * (CardsLeft - 2d) / (CardsLeft - 1) * 2; //triple, then pair // 2/47 * 9/46 * 2 = 1.7% chanceFullHouse = 2d / CardsLeft * 9d / (CardsLeft - 1) * 2; //.09% chanceFourKind = 2d / CardsLeft * 1d / (CardsLeft - 1); } else //if (GameState.currentRound == GameState.Rounds.isTurn) { //6 cards dealt, 2 are a pair, so 4 * 3 possible cards to pair with chanceTwoPair = 12d / CardsLeft; //triple with pocket cards chanceThreeKind = 2d / CardsLeft; chanceFullHouse = 0; chanceFourKind = 0; } chancePair = 1; } else if (MyHand.IsMyPokerHand(rank, PokerHand.TWO_PAIR)) { Debug.WriteLine("Case: two pair on flop/turn"); //HIDE CHANCE TEXTS FOR HIGH CARD, PAIR, THREE KIND for (int i = 0; i <= 3; i++) { //don't hide 2 pair if (i != 2) { //pc.chanceTexts [i].enabled = false; } } if (CurrentRound == Rounds.isFlop) { // 4/47 * 43/46 * 2 = 16% chanceFullHouse = 4d / CardsLeft * (CardsLeft - 4) / (CardsLeft - 1) * 2; chanceFourKind = 4d / CardsLeft * 1d / (CardsLeft - 1); } else { chanceFullHouse = 4d / CardsLeft; chanceFourKind = 0; } //if 2 pair, a triple would give a full house chanceThreeKind = 0; chanceTwoPair = 1; } //3 of a kind else if (MyHand.IsMyPokerHand(rank, PokerHand.THREE_OF_A_KIND)) { for (int i = 0; i <= 2; i++) { //pc.chanceTexts [i].enabled = false; } if (CurrentRound == Rounds.isFlop) { // 6/47 * 41/46 * 2 chanceFullHouse = 6d / CardsLeft * (CardsLeft - 6d) / (CardsLeft - 1) * 2; chanceFourKind = 1d / CardsLeft * 2; } else { chanceFullHouse = 6d / CardsLeft; chanceFourKind = 1d / CardsLeft; } chanceThreeKind = 1; } //straight else if (MyHand.IsMyPokerHand(rank, PokerHand.STRAIGHT)) { chanceFullHouse = 0; chanceFourKind = 0; chanceStraight = 1; } //flush else if (MyHand.IsMyPokerHand(rank, PokerHand.FLUSH)) { chanceFullHouse = 0; chanceFourKind = 0; chanceFlush = 1; } //full house else if (MyHand.IsMyPokerHand(rank, PokerHand.FULL_HOUSE)) { if (CurrentRound == Rounds.isFlop) { chanceFourKind = 1d / CardsLeft * 2; } else { chanceFourKind = 1d / CardsLeft; } chanceFullHouse = 1; } //four of a kind else if (MyHand.IsMyPokerHand(rank, PokerHand.FOUR_OF_A_KIND)) { //already checked below //chanceStraightFlush = 0; chanceFourKind = 1; } //straight flush else if (MyHand.IsMyPokerHand(rank, PokerHand.STRAIGHT_FLUSH)) { int rankIndexStraightFlush = (int)PokerHand.STRAIGHT_FLUSH; bool isRoyalFlush = Math.Round(rank, 2) == rankIndexStraightFlush + Constants.ACE_VAL / 100d; bool isKingHighStraightFlush = Math.Round(rank, 2) == rankIndexStraightFlush + Constants.KING_VAL / 100d; bool isQueenHighStraightFlush = Math.Round(rank, 2) == rankIndexStraightFlush + Constants.QUEEN_VAL / 100d; if (isQueenHighStraightFlush) { if (CurrentRound == Rounds.isFlop) { chanceRoyalFlush = (2d / CardsLeft) * (1d / (CardsLeft - 1)); } else { chanceRoyalFlush = 0; } } else if (isKingHighStraightFlush) { if (CurrentRound == Rounds.isFlop) { //(chance getting the ace first, anything else second) + (chance getting anything else first, the ace second) chanceRoyalFlush = (1d / CardsLeft) + ((CardsLeft - 1d) / CardsLeft) * (1d / (CardsLeft - 1)); } else { chanceRoyalFlush = 1d / CardsLeft; } } //if my hand is a royal flush else if (isRoyalFlush) { chanceRoyalFlush = 1; return(new ProbabilityViewModel { RoyalFlush = chanceRoyalFlush }); } chanceStraightFlush = 1; return(new ProbabilityViewModel { StraightFlush = chanceStraightFlush, RoyalFlush = chanceRoyalFlush }); } //FLUSH, STRAIGHT, AND STRAIGHT FLUSH POSSIBILITY---------------------------- //getRank already called checkForStraight //equals null if there is no four card flush string myFourFlushSuit = myHand.FourFlushSuit; //IF THERE IS A 4 FLUSH SUIT, THERE IS A 3 FLUSH SUIT string myThreeFlushSuit = myHand.ThreeFlushSuit; Debug.WriteLine("four flush suit: " + myFourFlushSuit); Debug.WriteLine("three flush suit: " + myThreeFlushSuit); MyHand my4FlushHand = null; MyHand my3FlushHand = null; if (myThreeFlushSuit != null) { List <string> myThreeFlushCards = myHand.GetFlushCards(myThreeFlushSuit); my3FlushHand = new MyHand(myThreeFlushCards); my3FlushHand.CheckForStraight(); } if (myFourFlushSuit != null) { List <string> myFourFlushCards = myHand.GetFlushCards(myFourFlushSuit); //create new hand with just 4 flush cards, check if 4 cards present in straight my4FlushHand = new MyHand(myFourFlushCards); my4FlushHand.CheckForStraight(); } bool isLowerThanFlush = MyHand.IsMyPokerHandLower(rank, PokerHand.FLUSH); bool isLowerThanStraight = MyHand.IsMyPokerHandLower(rank, PokerHand.STRAIGHT); //chance for flush if (isLowerThanFlush) { chanceFlush = this.GetFlushChancesOnTurnAndRiver(myHand, myFourFlushSuit, myThreeFlushSuit); } //CHANCE FOR STRAIGHT if (isLowerThanStraight) { chanceStraight = this.GetStraightChancesOnTurnAndRiver(myHand); } //CHANCE FOR STRAIGHT FLUSH //works for if I have a flush already too (my4FlushHand can have 4+ cards in it) if (my4FlushHand != null && my4FlushHand.Is4AlmostStraight) { //STRAIGHT FLUSH IS POSSIBLE Debug.WriteLine("poss straight flush"); //ROYAL FLUSH POSSIBILITY if (my4FlushHand.Is4AlmostHighStraight) { Debug.WriteLine("poss royal flush"); if (CurrentRound == Rounds.isFlop) { chanceRoyalFlush = 1d / CardsLeft * 2; } else { chanceRoyalFlush = 1d / CardsLeft; } } //check if there is possible Royal Flush w 3 of the 5 poss cards else if (CurrentRound == Rounds.isFlop && my4FlushHand.Is3AlmostHighStraight) { Debug.WriteLine("is3almosthighstraight with a 4+ card flush (also is almost straight flush)"); chanceRoyalFlush = 2d / CardsLeft * 1d / (CardsLeft - 1); } //STRAIGHT FLUSH POSSIBILITY: chance with 2 possible cards to finish straight flush if (my4FlushHand.NumberOfPossStraightsWithMy4Cards == 2) { if (CurrentRound == Rounds.isFlop) { chanceStraightFlush = 2d / CardsLeft + (CardsLeft - 2d) / CardsLeft * 2d / (CardsLeft - 1); } else { chanceStraightFlush = 2d / CardsLeft; } } //chance with 1 possible card to finish straight flush else { //only 1 possible 4straight if (CurrentRound == Rounds.isFlop) { if (my4FlushHand.Is3AlmostStraight) { //chance of completing the 4 straight + chance of completing the 3 straight chanceStraightFlush = (1d / CardsLeft * 2) + 2d / CardsLeft * 1d / (CardsLeft - 1); } else { chanceStraightFlush = 1d / CardsLeft + (CardsLeft - 1d) / CardsLeft * 1d / (CardsLeft - 1); } } else { chanceStraightFlush = 1d / CardsLeft; } } } //3+ flush hand is 3almost straight during flop round else if (my3FlushHand != null && my3FlushHand.Is3AlmostStraight && CurrentRound == Rounds.isFlop) { Debug.WriteLine("is3almosthighstraight " + my3FlushHand.Is3AlmostHighStraight); if (my3FlushHand.NumberOfPossStraightsWithMy3Cards >= 3) { Debug.WriteLine("3 or more diff poss straight flushes"); //both cards must straight. //first card has 2 poss ranks to make 4 in a row, then 2 poss ranks for 2nd card + //first card has 2 poss ranks to make 4 in poss straight (with gap), then 1 poss rank (gap card) // 2/47 * 2/46 + 2/47 * 1/46 chanceStraightFlush = 2d / CardsLeft * 2d / (CardsLeft - 1) + 2d / CardsLeft * 1d / (CardsLeft - 1); } else if (my3FlushHand.NumberOfPossStraightsWithMy3Cards == 2) { Debug.WriteLine("2 diff poss straight flushes"); //1 poss rank for 4 in a row (the gap), then 2 poss ranks (2 ways this can happen) // 1/47 * 2/46 * 2 chanceStraightFlush = 1d / CardsLeft * 2d / (CardsLeft - 1) * 2; } else if (my3FlushHand.NumberOfPossStraightsWithMy3Cards == 1) { Debug.WriteLine("1 poss straight flush"); //2 poss ranks then 1 poss rank // 2/47 * 1/46 chanceStraightFlush = 2d / CardsLeft * 1d / (CardsLeft - 1); } if (my3FlushHand.Is3AlmostHighStraight) { Debug.WriteLine("is3almosthighstraight!!!!!!!!"); chanceRoyalFlush = 2d / CardsLeft * 1d / (CardsLeft - 1); } } else { //there are not 4 of 5 straight flush cards present chanceStraightFlush = 0; chanceRoyalFlush = 0; } var vm = new ProbabilityViewModel (chanceHighCard, chancePair, chanceTwoPair, chanceThreeKind, chanceStraight, chanceFlush, chanceFullHouse, chanceFourKind, chanceStraightFlush, chanceRoyalFlush); return(vm); }