public Decision GetDecision(Round round, RoundSetup roundSetup) { UpdatePlayerProfiles(round, roundSetup); switch (round.StageEnum) { case StageEnum.Preflop: return(ChartPreflopStrategy.MakeDecision(Utils.GeneratePreflopStatusSummary(round, roundSetup.HeroIndex), new HoldingHoles(roundSetup.Hole1, roundSetup.Hole2))); //return PreflopExpert.GetPreflopDecision(Utils.GeneratePreflopStatusSummary(round), new HoldingHoles(round.Hole1, round.Hole2)); case StageEnum.Flop: return(FlopStrategy.MakeDecision(Utils.GenerateFlopDecisionContext(round, PlayerProfiles.Values.ToList(), roundSetup))); case StageEnum.Turn: return (TurnStrategy.MakeDecision(Utils.GenerateTurnDecisionContext(round, PlayerProfiles.Values.ToList(), roundSetup))); case StageEnum.River: return (RiverStrategy.MakeDecision(Utils.GenerateRiverDecisionContext(round, PlayerProfiles.Values.ToList(), roundSetup))); default: throw new InvalidOperationException(); } }
// Start is called before the first frame update void Start() { deathClip = (AudioClip)Resources.Load("Sounds/Death"); currentSetup = FindObjectOfType <RoundSetup>(); loader = FindObjectOfType <Loader>(); rounds = GameOptions.rounds; if (instance == null) { instance = this; } else { Destroy(this.gameObject); } DontDestroyOnLoad(this); scoreboard = new int[4]; //Expandir allPlayers = Player.GetList(); alivePlayers = new List <Player>(allPlayers); }
public void DealHoles(int index, Card hole1, Card hole2) { _roundSetup = new RoundSetup(); _roundSetup.HeroIndex = index; _roundSetup.Hole1 = hole1; _roundSetup.Hole2 = hole2; }
private void StartRound() { loader.Game(); currentSetup = FindObjectOfType <RoundSetup>(); alivePlayers = new List <Player>(Player.GetList()); Debug.Log("Alive Players: " + alivePlayers.Count + "All players: " + allPlayers.Count); }
private Player PollPlayers(Round round, RoundSetup roundSetup) { Logger.Instance.Log($"{round.RoundId}|Polling players for {round.StageEnum}"); foreach (var player in round.Players.Where(p => p.IsAlive)) { Logger.Instance.Log($"{round.RoundId}|{player.Position}:{player.Name} still alive."); player.ResetPolled(); } round.Index = 0; round.IsRaised = false; if (round.StageEnum == StageEnum.Preflop) { round.Index = 2; round.RecordMove(new Move(round.Players[0], new Decision(DecisionType.Ante, round.SmallBlindSize), round.StageEnum)); round.RecordMove(new Move(round.Players[1], new Decision(DecisionType.Ante, round.BigBlindSize), round.StageEnum)); round.IsRaised = true; } while (true) { var player = round.GetNextPlayer(); var candidateDecisionTypes = Utils.GetCandidateDecisionTypes(round.IsRaised); int chipsToCall = round.MostChipsBetByRound[round.StageEnum] - player.ChipsBetByStage[round.StageEnum]; var decision = player.Index == roundSetup.HeroIndex ? _input.GetMyDecision(round, candidateDecisionTypes, roundSetup) : _input.GetDecision(player, round.CurrentRaiser, candidateDecisionTypes, chipsToCall); if (!candidateDecisionTypes.Contains(decision.DecisionType)) { throw new InvalidOperationException($"{decision.DecisionType} is out of the candidates {string.Join("/", candidateDecisionTypes)}"); } var move = new Move(player, decision, round.StageEnum); round.RecordMove(move); if (round.IsSettled) { break; } } if (round.Players.Count(p => p.IsAlive) == 1) { //Winner return(round.Players.First(p => p.IsAlive)); } //Still more than one alive players, game continues return(null); }
private void UpdatePlayerProfiles(Round round, RoundSetup roundSetup) { var playersInOrder = IterateOpponentsInOrder(round, roundSetup.HeroIndex).ToList(); foreach (var player in playersInOrder) { if (!PlayerProfiles.ContainsKey(player.Name)) { PlayerProfiles.Add(player.Name, GenerateNewProfile(player, round.Players.First(p => p.Index == roundSetup.HeroIndex).Position)); } } Parallel.ForEach(playersInOrder, player => { UpdateProfile(PlayerProfiles[player.Name], player, round, roundSetup); }); }
public void Drive(Round round, RoundSetup roundSetup) { Player winner = null; round.StageEnum = StageEnum.Preflop; roundSetup.Hole1 = _input.GetHole1(); roundSetup.Hole2 = _input.GetHole2(); winner = PollPlayers(round, roundSetup); if (winner != null) { Logger.Instance.Log($"{round.RoundId}|Game ended on preflop, and the winner is {winner.Position}-{winner.Name}, potSize={round.CurrentPotSize}"); return; } round.StageEnum = StageEnum.Flop; round.Flop1 = _input.GetFlop1(); round.Flop2 = _input.GetFlop2(); round.Flop3 = _input.GetFlop3(); winner = PollPlayers(round, roundSetup); if (winner != null) { Logger.Instance.Log($"{round.RoundId}|Game ended on flop, and the winner is {winner.Position}-{winner.Name}, potSize={round.CurrentPotSize}"); return; } round.StageEnum = StageEnum.Turn; round.Turn = _input.GetTurn(); winner = PollPlayers(round, roundSetup); if (winner != null) { Logger.Instance.Log($"{round.RoundId}|Game ended on turn, and the winner is {winner.Position}-{winner.Name}, potSize={round.CurrentPotSize}"); return; } round.StageEnum = StageEnum.River; round.River = _input.GetRiver(); winner = PollPlayers(round, roundSetup); if (winner != null) { Logger.Instance.Log($"{round.RoundId}|Game ended on river, and the winner is {winner.Position}-{winner.Name}, potSize={round.CurrentPotSize}"); return; } //todo Showdown, implement the comparison of hands }
private void SqueezeRiverRange(Round round, PlayerRoundProfile profile, Move lastMove, RoundSetup roundSetup) { var newRange = RiverRangeSqueezer.Squeeze(profile.PlayerRange, lastMove, round.BigBlindSize, new RiverBoard(new TurnBoard(new FlopBoard(round.Flop1, round.Flop2, round.Flop3), round.Turn), round.River), new HoldingHoles(roundSetup.Hole1, roundSetup.Hole2)); switch (round.StageEnum) { case StageEnum.Turn: profile.TurnRange = newRange; break; case StageEnum.River: profile.RiverRange = newRange; break; default: throw new InvalidOperationException($"Should not happen with {round.StageEnum}"); } profile.PlayerRange = newRange; }
private void UpdateProfile(PlayerRoundProfile profile, Player player, Round round, RoundSetup roundSetup) { Logger.Instance.Log($"Updating profile: name={player.Name}, position={player.Position}, stage={round.StageEnum}."); if (profile.PlayerStatus == PlayerStatusEnum.Folded || profile.PlayerStatus == PlayerStatusEnum.AllIned) { //Unnecessary to update Logger.Instance.Log($"Unnecessary to update profile: name={player.Name}, PlayerStatus={profile.PlayerStatus}, " + $"position={player.Position}, stage={round.StageEnum}."); return; } Logger.Instance.Log($"Before updating profile: isAlive={profile.IsAlive}, PlayerStatus={profile.PlayerStatus}, stackSize={profile.StackSize}"); profile.StackSize = player.StackSize; Logger.Instance.Log($"After updating profile: isAlive={profile.IsAlive}, PlayerStatus={profile.PlayerStatus}, stackSize={profile.StackSize}"); switch (round.StageEnum) { case StageEnum.Preflop: profile.PreflopDecisions = new List <Decision>(round.PreflopMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision)); profile.PreflopBet = player.ChipsBetByStage[StageEnum.Preflop]; profile.PreflopPlayerStatus = GetPlayerStreetStatus(profile.PreflopDecisions); var preflopLastRaiserName = round.PreflopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name; profile.IsPreflopRaiser = string.Equals(preflopLastRaiserName, profile.Name); break; case StageEnum.Flop: profile.FlopDecisions = new List <Decision>(round.FlopMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision)); profile.FlopBet = player.ChipsBetByStage[StageEnum.Flop]; profile.FlopPlayerStatus = GetPlayerStreetStatus(profile.FlopDecisions); var flopLastRaiserName = round.FlopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name; profile.IsFlopRaiser = string.Equals(flopLastRaiserName, profile.Name); break; case StageEnum.Turn: profile.TurnDecisions = new List <Decision>(round.TurnMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision)); profile.TurnBet = player.ChipsBetByStage[StageEnum.Turn]; profile.TurnPlayerStatus = GetPlayerStreetStatus(profile.TurnDecisions); var turnLastRaiserName = round.TurnMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name; profile.IsTurnRaiser = string.Equals(turnLastRaiserName, profile.Name); break; case StageEnum.River: profile.RiverDecisions = new List <Decision>(round.RiverMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision)); profile.RiverBet = player.ChipsBetByStage[StageEnum.River]; profile.RiverPlayerStatus = GetPlayerStreetStatus(profile.RiverDecisions); var riverLastRaiserName = round.RiverMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name; profile.IsRiverRaiser = string.Equals(riverLastRaiserName, profile.Name); break; } if (profile.IsHero) { //unnecessary to squeeze hero's range Logger.Instance.Log($"Unnecessary to update hero's profile. name={profile.Name}."); return; } if (round.AllMoves.Any(m => string.Equals(m.Player.Name, player.Name))) { Move lastMove = round.AllMoves.LastOrDefault(m => string.Equals(m.Player.Name, player.Name)); if (lastMove != null && lastMove.Decision.DecisionType != DecisionType.Ante && lastMove.Decision.DecisionType != DecisionType.Fold) { //squeeze player's range according to his last move switch (lastMove.Stage) { case StageEnum.Preflop: SqueezePreflopRange(round, profile, lastMove); break; case StageEnum.Flop: SqueezeFlopRange(round, profile, lastMove, roundSetup); break; case StageEnum.Turn: SqueezeTurnRange(round, profile, lastMove, roundSetup); break; case StageEnum.River: SqueezeRiverRange(round, profile, lastMove, roundSetup); break; } } } }
public static RiverDecisionContext GenerateRiverDecisionContext(Round round, List <PlayerRoundProfile> playerProfiles, RoundSetup roundSetup) { var hero = round.Players.First(p => p.Index == roundSetup.HeroIndex); var context = new RiverDecisionContext() { BigBlindSize = round.BigBlindSize, CurrentPotSize = round.CurrentPotSize, RiverBoard = new RiverBoard(new TurnBoard(new FlopBoard(round.Flop1, round.Flop2, round.Flop3), round.Turn), round.River), Players = playerProfiles, HeroName = hero.Name, IsHeadsUp = round.Players.Count(p => p.IsAlive) == 2, HeroHoles = new HoldingHoles(roundSetup.Hole1, roundSetup.Hole2), PreflopRaiserName = round.PreflopRaiser.Name, FlopRaiserName = round.FlopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name, TurnRaiserName = round.TurnMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name, RiverRaiserName = round.RiverMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name, IsRaised = round.RiverMoves.Any(m => m.Decision.DecisionType.IsRaiseMove()), }; if (context.IsHeadsUp) { context.HeadsUpVillainName = round.Players.First(p => p.IsAlive && p.Index != roundSetup.HeroIndex).Name; } return(context); }
public Decision GetMyDecision(Round round, ISet <DecisionType> candidateDecisionTypes, RoundSetup roundSetup) { var decision = _brain.GetDecision(round, roundSetup); System.Console.WriteLine($"My decision is {decision.DecisionType} - {decision.ChipsAdded}"); return(decision); }