public bool FlushDraw(PokerHand hand, int rIdx, int aIdx)
 {
     return Hand.IsFlushDraw(hand.HeroHoleCards(), hand.BoardMask((Rounds)rIdx), 0UL);
 }
 public double WinProb(PokerHand hand, int rIdx, int aIdx)
 {
     ulong hc = hand.HeroHoleCards();
     ulong board = hand.BoardMask((Rounds)rIdx);
     int opponents = NumOpponents(hand, rIdx, aIdx);
     return Hand.WinOdds(hc, board, 0UL, opponents, 1000);
 }
Example #3
0
        public void TestRiver1()
        {
            hand = fromString(riverHand1);
            var history = server.Resume(hand, cache);
            var next = server.ValidNextActions;
            Assert.AreEqual(2, next.Count());

            var check = next.FirstOrDefault(a => a.ActionType == Action.ActionTypes.Check);
            Assert.NotNull(check);
            Assert.AreEqual("TAP_OR_SNAP", check.Name);
            Assert.AreEqual(0, check.Amount);
            Assert.AreEqual(false, check.AllIn);

            var bet = next.FirstOrDefault(a => a.ActionType == Action.ActionTypes.Bet);
            Assert.NotNull(bet);
            Assert.AreEqual("TAP_OR_SNAP", bet.Name);
            Assert.AreEqual(20, bet.Amount);
            Assert.AreEqual(false, bet.AllIn);
        }
 public bool Suited(PokerHand hand, int rIdx, int aIdx)
 {
     return Hand.IsSuited(hand.HeroHoleCards());
 }
        public bool TopPair(PokerHand hand, int rIdx, int aIdx)
        {
            if(Hand.EvaluateType(hand.HeroHoleCards() | hand.BoardMask((Rounds)rIdx)) != Hand.HandTypes.Pair)
                return false;

            var board = hand.Board((Rounds)rIdx);
            var top = board.Max(c => c.Rank);
            return top == hand.HoleCards[0].Rank || top == hand.HoleCards[1].Rank;
        }
        public int SecondaryBoardSuit(PokerHand hand, int rIdx, int aIdx)
        {
            var board = hand.Board((Rounds)rIdx);
            var suits = board.GroupBy(c => c.Suit).OrderByDescending(g => g.Count());

            var secondary = suits.Skip(1).FirstOrDefault();
            if (secondary == null)
                return 0;
            return secondary.Count();
        }
 public int StraightDrawCount(PokerHand hand, int rIdx, int aIdx)
 {
     return Hand.StraightDrawCount(hand.HeroHoleCards(), hand.BoardMask((Rounds)rIdx), 0UL);
 }
 public bool GutshotStraightDraw(PokerHand hand, int rIdx, int aIdx)
 {
     return Hand.IsGutShotStraightDraw(hand.HeroHoleCards(), hand.BoardMask((Rounds)rIdx), 0UL);
 }
 public double HandStrength(PokerHand hand, int rIdx, int aIdx)
 {
     return Hand.HandStrength(hand.HeroHoleCards(), hand.BoardMask((Rounds)rIdx), NumOpponents(hand, rIdx, aIdx), 1000);
 }
        public Tuple<string,string>[] GenerateFeatures(PokerHand hand, int rIdx, int aIdx)
        {
            // Check that we are using limit betting.
            Debug.Assert(hand.Context.BettingType == BettingType.FixedLimit);

            var results = new List<Tuple<string,string>>();
            foreach (var method in typeof(LimitFeatureGenerator).GetMethods())
            {
                // Get all the features of this class.
                var attributes = method.GetCustomAttributes(typeof(Feature), true);
                if (attributes.Length == 0)
                    continue;

                // Get the feature attribute on this method.
                var attr = ((Feature)attributes[0]);

                // Get the name for this column in the CSV file.
                string name = attr.Name;

                // Get the feature only if it's applicable to this situation.
                string feature = "?";
                if(rIdx >= (int)attr.MinRound && rIdx <= (int)attr.MaxRound)
                    feature = method.Invoke(this, new object[] { hand, rIdx, aIdx }).ToString();

                if (SkipMissingFeatures && feature == "?")
                    continue;

                if(ConvertFeaturesToNumeric)
                {
                    switch (attr.FType) {
                    case FeatureType.Continuous:
                    case FeatureType.Discrete: break;
                    case FeatureType.Nominal:
                        string oldFeature = feature;
                        feature = attr.NominalValues.IndexOf(s => s == feature).ToString();
                        if(feature == "-1")
                            throw new Exception(string.Format("Unknown nominal value {0} for feature {1}", oldFeature, method.Name));
                        break;
                    case FeatureType.Boolean:
                        if(feature == Boolean.FalseString)
                            feature = "0";
                        else
                            feature = "1";
                        break;
                    case FeatureType.Enum:
                        feature = ((int)Enum.Parse(attr.EnumType, feature)).ToString();
                        break;
                    case FeatureType.String:
                        Dictionary<string, int> indexes;
                        if(!stringIndexes.TryGetValue(attr.Name, out indexes))
                        {
                            indexes = new Dictionary<string, int>();
                            stringIndexes.Add(attr.Name, indexes);
                        }
                        int stringIdx;
                        if(!indexes.TryGetValue(feature, out stringIdx))
                        {
                            stringIdx = 1;
                            indexes.Add(feature, stringIdx);
                        }
                        feature = stringIdx.ToString();
                        break;
                    default: throw new Exception("Unspecified feature type for feature: " + method.Name);
                    }
                }

                // Add it to the list of features for this hand.
                results.Add(new Tuple<string, string>(name, feature));
            }

            string actionStr = hand.Rounds[rIdx].Actions[aIdx].Type.ToString();

            switch (hand.Rounds[rIdx].Actions[aIdx].Type)
            {
            case ActionType.Bet:
            case ActionType.Raise: actionStr = ConvertFeaturesToNumeric ? "2" : "Raise";
            break;
            case ActionType.Call:
            case ActionType.Check: actionStr = ConvertFeaturesToNumeric ? "1" : "Call";
            break;
            case ActionType.Fold: actionStr = ConvertFeaturesToNumeric ? "0" : "Fold";
            break;
            default:
                break;
            }

            results.Add(new Tuple<string, string>("Action", actionStr));
            return results.ToArray();
        }
        public Position AbsolutePosition(PokerHand hand, int rIdx, int aIdx)
        {
            // Check if hero is on one of the blinds.
            var blind = hand.Blinds.FirstOrDefault(b => b.Player == hand.Hero && (b.Type == BlindType.BigBlind || b.Type == BlindType.SmallBlind));
            if (blind != null)
                return blind.Type == BlindType.SmallBlind ? Position.SmallBlind : Position.BigBlind;

            int heroIdx = hand.Players.First(p => p.Name == hand.Hero).Seat;

            // Immediately check for being the button
            if (hand.Context.Button == heroIdx)
                return Position.Button;

            // Get the seat to wrap on
            int maxSeat = hand.Players.Max(p => p.Seat);
            int minSeat = hand.Players.Min(p => p.Seat);

            string bbPlayer = hand.Blinds.FirstOrDefault(b => b.Type == BlindType.BigBlind).Player;
            int bbSeat = hand.Players.FirstOrDefault(p => p.Name == bbPlayer).Seat;

            int playersBefore = 0;
            for (int i = bbSeat == maxSeat ? minSeat : bbSeat + 1; i != heroIdx; )
            {
                var player = hand.Players.FirstOrDefault(p => p.Seat == i);

                if (player != null)
                    playersBefore++;

                i++;
                if (i > maxSeat)
                    i = minSeat;
            }

            switch (hand.Players.Length)
            {
                case 4: return Position.Early;// only UTG is not a blind or the button
                case 5: return playersBefore > 0 ? Position.Middle : Position.Early; //UTG and UTG+1 to consider
                case 6:
                    {
                        switch (playersBefore)
                        {
                            case 0: return Position.Early;
                            case 1: return Position.Middle;
                            case 2: return Position.Late;
                            default: throw new Exception(string.Format("Impossible players before. Players: {0} Before: {1}", hand.Players.Length, playersBefore));
                        }
                    }
                case 7:
                    {
                        switch (playersBefore)
                        {
                            case 0:
                            case 1: return Position.Early;
                            case 2: return Position.Middle;
                            case 3: return Position.Late;
                            default: throw new Exception(string.Format("Impossible players before. Players: {0} Before: {1}", hand.Players.Length, playersBefore));
                        }
                    }
                case 8:
                    {
                        switch (playersBefore)
                        {
                            case 0:
                            case 1: return Position.Early;
                            case 2:
                            case 3: return Position.Middle;
                            case 4: return Position.Late;
                            default: throw new Exception(string.Format("Impossible players before. Players: {0} Before: {1}", hand.Players.Length, playersBefore));
                        }
                    }
                case 9:
                    {
                        switch (playersBefore)
                        {
                            case 0:
                            case 1:
                            case 2: return Position.Early;
                            case 3:
                            case 4: return Position.Middle;
                            case 5: return Position.Late;
                            default: throw new Exception(string.Format("Impossible players before. Players: {0} Before: {1}", hand.Players.Length, playersBefore));
                        }
                    }
                case 10:
                    {
                        switch (playersBefore)
                        {
                            case 0:
                            case 1:
                            case 2: return Position.Early;
                            case 3:
                            case 4: return Position.Middle;
                            case 5:
                            case 6: return Position.Late;
                            default: throw new Exception(string.Format("Impossible players before. Players: {0} Before: {1}", hand.Players.Length, playersBefore));
                        }
                    }
                default: throw new Exception("Unsupported player count: " + hand.Players.Length);
            }
        }
        public weka.core.Instance GenerateFeatures(PokerHand hand, int rIdx, int aIdx, weka.core.Instances data, bool generateClass = true)
        {
            // Check that we are using limit betting.
            Debug.Assert(hand.Context.BettingType == BettingType.FixedLimit);

            var results = new weka.core.Instance(data.numAttributes());
            results.setDataset(data);
            int attIdx = 0;
            foreach (var method in typeof(LimitFeatureGenerator).GetMethods())
            {
                // Get all the features of this class.
                var attributes = method.GetCustomAttributes(typeof(Feature), true);
                if (attributes.Length == 0)
                    continue;

                // Get the feature attribute on this method.
                var attr = ((Feature)attributes[0]);

                // Get the name for this attribute
                string name = attr.Name;
                //Console.WriteLine("Hand: {0} Feature: {1}", hand.Context.ID, name);

                // Get the feature only if it's applicable to this situation.
                object feature = null;
                if(rIdx >= (int)attr.MinRound && rIdx <= (int)attr.MaxRound)
                    feature = method.Invoke(this, new object[] { hand, rIdx, aIdx });

                if (SkipMissingFeatures && (feature == null || feature.ToString() == "?"))
                    continue;

                switch (attr.FType) {
                case FeatureType.Continuous:
                    results.setValue(attIdx, (double)feature);
                    break;
                case FeatureType.Discrete:
                    results.setValue(attIdx, (int)feature);
                    break;
                case FeatureType.Boolean:
                case FeatureType.Nominal:
                case FeatureType.Enum:
                {
                    var attribute = data.attribute(attIdx);
                    var attVal = attribute.indexOfValue(feature.ToString());
                    if(attVal < 0 || attVal > attribute.numValues())
                        throw new Exception(string.Format ("Invalid attribute value: {0} for attribute {1} (idx: {2} total values: {3}", feature.ToString(), name, attVal, attribute.numValues()));
                    results.setValue(attribute, attVal);
                }
                    break;
                case FeatureType.String:
                {
                    var attribute = data.attribute(attIdx);
                    results.setValue(attribute, feature.ToString());
                }
                    break;
                default: throw new Exception("Unspecified feature type for feature: " + method.Name);
                }

                attIdx++;
            }

            if(generateClass)
            {
                var classAttr = data.classAttribute();
                switch (hand.Rounds[rIdx].Actions[aIdx].Type)
                {
                case ActionType.Bet:
                case ActionType.Raise: results.setClassValue(classAttr.indexOfValue("Raise"));
                    break;
                case ActionType.Call:
                case ActionType.Check: results.setClassValue(classAttr.indexOfValue("Call"));
                    break;
                case ActionType.Fold: results.setClassValue(classAttr.indexOfValue("Fold"));;
                    break;
                default:
                    break;
                }
            }

            return results;
        }
 public bool FourCardStraightHit(PokerHand hand, int rIdx, int aIdx)
 {
     var prev = hand.Board((Rounds)(rIdx - 1)).ToMask();
     int prevCount = Hand.CountContiguous(prev);
     if (prevCount != 3)
         return false;
     return Hand.CountContiguous(hand.BoardMask((Rounds)rIdx)) == 4;
 }
        public bool FlushDrawHit(PokerHand hand, int rIdx, int aIdx)
        {
            var prev = hand.Board((Rounds)(rIdx-1));
            var prevSuits = prev.GroupBy(c => c.Suit).OrderByDescending(g => g.Count());

            if (prevSuits.First().Count() != 2)
                return false;

            var board = hand.Board((Rounds)rIdx);
            var suits = board.GroupBy(c => c.Suit).OrderByDescending(g => g.Count());

            return suits.First().Count() == 3;
        }
        public double RelativePosition(PokerHand hand, int rIdx, int aIdx)
        {
            // Get the seat to wrap on
            int maxSeat = hand.Players.Max(p => p.Seat);

            // Figure out who is in first position
            var firstBlind = hand.Blinds.FirstOrDefault(b => b.Type == BlindType.SmallBlind);
            if (firstBlind == null)
                firstBlind = hand.Blinds.FirstOrDefault(b => b.Type == BlindType.BigBlind);

            Debug.Assert(firstBlind != null);

            int firstSeat = hand.Players.First(p => p.Name == firstBlind.Player).Seat;
            int heroIdx = hand.HeroSeat();

            var actions = hand.AllPreviousActions(rIdx, aIdx);

            // Find all players that are acting before this player
            int playersBefore = 0;
            for (int i = firstSeat; i != heroIdx;)
            {
                var player = hand.Players.FirstOrDefault(p => p.Seat == i);

                if(player!= null && !actions.Folded(player.Name))
                    playersBefore++;

                i++;
                if (i > maxSeat)
                    i = 1;
            }

            // Find all players that are acting after this player
            int playersAfter = 0;
            for (int i = heroIdx + 1; i != firstSeat; )
            {
                var player = hand.Players.FirstOrDefault(p => p.Seat == i);

                if (player != null && !actions.Folded(player.Name))
                    playersAfter++;

                i++;
                if (i > maxSeat)
                    i = 1;
            }

            // Return the percentage of players acting before (position relative to players still in)
            return playersBefore / ((double)playersAfter + (double)playersBefore);
        }
 public int HandType(PokerHand hand, int rIdx, int aIdx)
 {
     return (int)Hand.EvaluateType(hand.HeroHoleCards() | hand.BoardMask((Rounds)rIdx));
 }
 public int RiverBetLevel(PokerHand hand, int rIdx, int aIdx)
 {
     var actions = hand.River.Actions;
     return getBetLevel(actions, rIdx > (int)Rounds.RIVER ? actions.Length : aIdx);
 }
 public int Holecard2Rank(PokerHand hand, int rIdx, int aIdx)
 {
     return Math.Min((int)hand.HoleCards[0].Rank, (int)hand.HoleCards[1].Rank);
 }
 public int SklanskyGroup(PokerHand hand, int rIdx, int aIdx)
 {
     return (int)PocketHands.GroupType(hand.HeroHoleCards());
 }
        public int NumOpponents(PokerHand hand, int rIdx, int aIdx)
        {
            int folds = 0;
            for (int i = 0; i <= rIdx; i++)
            {
                int stopIdx = i == rIdx ? aIdx : hand.Rounds[i].Actions.Length;
                for (int j = 0; j < stopIdx; j++)
                    if (hand.Rounds[i].Actions[j].Type == ActionType.Fold)
                        folds++;
            }

            return hand.Players.Length - folds - 1;
        }
        public bool StraightDrawHit(PokerHand hand, int rIdx, int aIdx)
        {
            var prev = hand.Board((Rounds)(rIdx - 1)).ToMask();
            var prevCount = Hand.CountContiguous(prev);
            if (prevCount != 2)
                return false;

            var board = hand.BoardMask((Rounds)rIdx);
            var hole = hand.HeroHoleCards();

            foreach(var opp in Hand.Hands(0UL, hole | board, 2))
                if (Hand.EvaluateType(board | opp) == Hand.HandTypes.Straight
                    && Hand.EvaluateType(prev | opp) != Hand.HandTypes.Straight
                    && Hand.IsOpenEndedStraightDraw(prev | opp, hole))
                    return true;
            return false;
        }
 public bool OpenEndedStraightDraw(PokerHand hand, int rIdx, int aIdx)
 {
     return Hand.IsOpenEndedStraightDraw(hand.HeroHoleCards(), hand.BoardMask((Rounds)rIdx), 0UL);
 }
 public int TableSize(PokerHand hand, int rIdx, int aIdx)
 {
     return hand.Players.Length;
 }
 public bool PocketPair(PokerHand hand, int rIdx, int aIdx)
 {
     return hand.HoleCards[0].Rank == hand.HoleCards[1].Rank;
 }
 public int TurnBetLevel(PokerHand hand, int rIdx, int aIdx)
 {
     var actions = hand.Turn.Actions;
     return getBetLevel(actions, rIdx > (int)Rounds.TURN ? actions.Length : aIdx);
 }
 public double PositivePotential(PokerHand hand, int rIdx, int aIdx)
 {
     double ppot, npot;
     Hand.HandPotential(hand.HeroHoleCards(), hand.BoardMask((Rounds)rIdx), out ppot, out npot, NumOpponents(hand, rIdx, aIdx), 1000);
     return ppot;
 }
Example #27
0
 public void TestBigBlindNext()
 {
     //Next: <Blinds Player=""OsoWhisper"" Type=""BigBlind"" Amount=""10"" />
     hand = fromString(bbHand);
     var history = server.Resume(hand, cache);
     var next = server.ValidNextActions;
     Assert.AreEqual(next.Count(), 1);
     var action = next.ElementAt(0);
     Assert.AreEqual(action.Name, "OsoWhisper");
     Assert.AreEqual(action.ActionType, Action.ActionTypes.PostBigBlind);
     Assert.AreEqual(action.Amount, 10);
 }
 public int PreflopBetLevel(PokerHand hand, int rIdx, int aIdx)
 {
     var actions = hand.Preflop.Actions;
     return getBetLevel(actions, rIdx > (int)Rounds.PREFLOP ? actions.Length : aIdx);
 }
Example #29
0
        public void TestRiver2()
        {
            hand = fromString(riverHand2);
            var history = server.Resume(hand, cache);
            var next = server.ValidNextActions;
            Assert.AreEqual(3, next.Count());

            var fold = next.FirstOrDefault(a => a.ActionType == Action.ActionTypes.Fold);
            Assert.NotNull(fold);
            Assert.AreEqual("TAP_OR_SNAP", fold.Name);
            Assert.AreEqual(0, fold.Amount);
            Assert.AreEqual(false, fold.AllIn);

            var call = next.FirstOrDefault(a => a.ActionType == Action.ActionTypes.Call);
            Assert.NotNull(call);
            Assert.AreEqual("TAP_OR_SNAP", call.Name);
            Assert.AreEqual(20, call.Amount);
            Assert.AreEqual(false, call.AllIn);

            var raise = next.FirstOrDefault(a => a.ActionType == Action.ActionTypes.Raise);
            Assert.NotNull(raise);
            Assert.AreEqual("TAP_OR_SNAP", raise.Name);
            Assert.AreEqual(40, raise.Amount);
            Assert.AreEqual(false, raise.AllIn);
        }
        public int DominantBoardSuit(PokerHand hand, int rIdx, int aIdx)
        {
            var board = hand.Board((Rounds)rIdx);
            var suits = board.GroupBy(c => c.Suit).OrderByDescending(g => g.Count());

            return suits.First().Count();
        }