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); }
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; }
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); }
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(); }