public IAmTheGameOver Play() { Players = _distributor.Distribute(); Player winner = null; int iterations = 0; int iterationsAfterReShuffle = 0; bool reShuffled = false; while (!GameOver(ref winner)) { if (ShouldContinue(ref iterations, ref iterationsAfterReShuffle, ref reShuffled, out IAmTheGameOver draw)) { continue; } if (draw is Draw) { return(draw); } var takes = Players.TakeOneCardEach(Visibility.FaceUp); TableViewsHistory.Add(takes.BuildView()); var playerOfStrongestTake = takes.UniqueStrongestPlayerIfExit(); if (playerOfStrongestTake != null) { playerOfStrongestTake.Gather(takes); continue; } RunBattleIfNecessary(takes); BuildDroppedCards(takes); } if (winner == null) { return(Draw.Instance); } System.Diagnostics.Debug.Assert(winner.CardStack.Size + DroppedCards.Count == _distributor.DistributedCardsSize, "We have leaking cards here"); return(new HasWinner(winner)); }
private void RunBattleIfNecessary(List <Take> takes) { var numberOfPlayersInTheGame = takes.Count; var competitors = new List <Player>(); while (NeedBattle(takes.KeepTheLast(numberOfPlayersInTheGame), ref competitors)) { numberOfPlayersInTheGame = competitors.Count; var competitorsStillHavingCards = competitors.WhoHaveCards(); if (competitorsStillHavingCards.Length <= 1) { takes.Drop(); } if (competitorsStillHavingCards.Length == 1) { break; } // face down cards var faceDownTakes = competitors.TakeOneCardEach(Visibility.FaceDown); if (!faceDownTakes.Any()) { break; } TableViewsHistory.Add(faceDownTakes.BuildView()); takes.AddRange(faceDownTakes); // face up cards var faceUpTakes = competitors.TakeOneCardEach(Visibility.FaceUp); if (!faceUpTakes.Any()) { takes.Drop(); break; } if (faceUpTakes.Count == 1) { takes.Drop(); faceUpTakes[0].Player.Gather(faceUpTakes); break; } TableViewsHistory.Add(faceUpTakes.BuildView()); takes.AddRange(faceUpTakes); if (faceUpTakes.AllEqual()) { continue; } // Find the competitor having the strongest card, and only he has that card var strongestPlayer = faceUpTakes.UniqueStrongestPlayerIfExit(); if (strongestPlayer != null) { strongestPlayer.Gather(takes.Where(x => !x.Dropped)); break; } } }