using Poker.Cards; using Poker.Players; using Poker.Strategies; namespace Poker; internal class Table { private readonly IReadWrite _io; private readonly IRandom _random; public int Pot; public Table(IReadWrite io, IRandom random, Deck deck, Human human, Computer computer) { _io = io; _random = random; Deck = deck; Human = human; Computer = computer; human.Sit(this); computer.Sit(this); } public int Ante { get; } = 5; public Deck Deck { get; } public Human Human { get; } public Computer Computer { get; } internal void PlayHand() { while (true) { _io.WriteLine(); Computer.CheckFunds(); if (Computer.IsBroke) { return; } _io.WriteLine($"The ante is ${Ante}. I will deal:"); _io.WriteLine(); if (Human.Balance <= Ante) { Human.RaiseFunds(); if (Human.IsBroke) { return; } } Deal(_random); _io.WriteLine(); GetWagers("I'll open with ${0}", "I check.", allowRaiseAfterCheck: true); if (SomeoneIsBroke() || SomeoneHasFolded()) { return; } Draw(); GetWagers(); if (SomeoneIsBroke()) { return; } if (!Human.HasBet) { GetWagers("I'll bet ${0}", "I'll check"); } if (SomeoneIsBroke() || SomeoneHasFolded()) { return; } if (GetWinner() is { } winner) { winner.TakeWinnings(); return; } } } private void Deal(IRandom random) { Deck.Shuffle(random); Pot = Human.AnteUp() + Computer.AnteUp(); Human.NewHand(); Computer.NewHand(); _io.WriteLine("Your hand:"); _io.Write(Human.Hand); } private void Draw() { _io.WriteLine(); _io.Write("Now we draw -- "); Human.DrawCards(); Computer.DrawCards(); _io.WriteLine(); } private void GetWagers(string betFormat, string checkMessage, bool allowRaiseAfterCheck = false) { if (Computer.Strategy is Bet) { Computer.Bet = Computer.GetWager(Computer.Strategy.Value); if (Computer.IsBroke) { return; } _io.WriteLine(betFormat, Computer.Bet); } else { _io.WriteLine(checkMessage); if (!allowRaiseAfterCheck) { return; } } GetWagers(); } private void GetWagers() { while (true) { Human.HasBet = false; while (true) { if (Human.SetWager()) { break; } if (Human.IsBroke || Human.HasFolded) { return; } } if (Human.Bet == Computer.Bet) { CollectBets(); return; } if (Computer.Strategy is Fold) { if (Human.Bet > 5) { Computer.Fold(); _io.WriteLine("I fold."); return; } } if (Human.Bet > 3 * Computer.Strategy.Value) { if (Computer.Strategy is not Raise) { _io.WriteLine("I'll see you."); Computer.Bet = Human.Bet; CollectBets(); return; } } var raise = Computer.GetWager(Human.Bet - Computer.Bet); if (Computer.IsBroke) { return; } _io.WriteLine($"I'll see you, and raise you {raise}"); Computer.Bet = Human.Bet + raise; } } internal void CollectBets() { Human.Balance -= Human.Bet; Computer.Balance -= Computer.Bet; Pot += Human.Bet + Computer.Bet; } private bool SomeoneHasFolded() { if (Human.HasFolded) { _io.WriteLine(); Computer.TakeWinnings(); } else if (Computer.HasFolded) { _io.WriteLine(); Human.TakeWinnings(); } else { return false; } Pot = 0; return true; } private bool SomeoneIsBroke() => Human.IsBroke || Computer.IsBroke; private Player? GetWinner() { _io.WriteLine(); _io.WriteLine("Now we compare hands:"); _io.WriteLine("My hand:"); _io.Write(Computer.Hand); _io.WriteLine(); _io.WriteLine($"You have {Human.Hand.Name}"); _io.WriteLine($"and I have {Computer.Hand.Name}"); if (Computer.Hand > Human.Hand) { return Computer; } if (Human.Hand > Computer.Hand) { return Human; } _io.WriteLine("The hand is drawn."); _io.WriteLine($"All $ {Pot} remains in the pot."); return null; } internal bool ShouldPlayAnotherHand() { if (Computer.IsBroke) { _io.WriteLine("I'm busted. Congratulations!"); return true; } if (Human.IsBroke) { _io.WriteLine("Your wad is shot. So long, sucker!"); return true; } _io.WriteLine($"Now I have $ {Computer.Balance} and you have $ {Human.Balance}"); return _io.ReadYesNo("Do you wish to continue"); } }