public IClueSituationStrategy FindClueCandidate(IReadOnlyList <Player> players) { // поищем подсказки "на ход" var expectedCards = _boardContext.GetExpectedCards(); var expectedOneRankedCards = expectedCards.Where(card => card.Rank == Rank.One); if (expectedOneRankedCards.Any()) { var situation = FindClueToPlayOneRankedCard(players, expectedOneRankedCards); if (situation != null) { return(situation); } expectedCards = expectedCards.Except(expectedOneRankedCards); } foreach (var player in players) { var playerContext = new PlayerContext(player, player.ShowCards(_clueGiver)); ClueType clue = FindClueToPlay(playerContext, expectedCards); if (clue == null) { continue; } return(new OnlyClueExistsSituation(playerContext, clue)); } var uniqueCards = _boardContext.GetUniqueCards(); // поищем подсказки из серии "как бы чего не вышло" foreach (var player in players) { var playerContext = new PlayerContext(player, player.ShowCards(_clueGiver)); ClueType clue = FindClueToDiscard(playerContext, uniqueCards); if (clue == null) { continue; } return(new OnlyClueExistsSituation(playerContext, clue)); } // поищем подсказки из серии "на будущее" var whateverToPlayCards = _boardContext.GetWhateverToPlayCards(); foreach (var player in players) { var playerContext = new PlayerContext(player, player.ShowCards(_clueGiver)); ClueType clue = FindClueToWhateverPlay(playerContext, whateverToPlayCards); if (clue == null) { continue; } return(new OnlyClueExistsSituation(playerContext, clue)); } return(new ClueNotExistsSituation()); }
public IClueSituationStrategy FindClueCandidate(IReadOnlyList <Player> players) { // player1 -> player2 -> player3 -> player4 // подсказку даёт player1. // Пока не будет сброса или не будет сыграна 5, то // прогнозируем ход следующего игрока. // игрок сбрасывает некритичную карту --> выход из цикла [если была подсказка в уме, то дать её] // игрок ходит пятёркой --> выход из цикла [если была в уме подсказка, то дать её] // // игрок ходит не пятёркой, карта ложится в фейерверк --> оценить действия следующего игрока // игрок ходит не пятёркой, что приводит к взрыву --> дать подсказку, оценить действия следующего игрока // // игрок сбрасывает критичную карту, нет подсказки --> безвыходная ситуация. Надо сбрасывать самому // игрок сбрасывает критичную карту, есть подсказка --> дать подсказку, оценить действия следующего игрока LogUniqueCards(); var boardContext = _boardContext; //IBoardContext boardContext = BoardContext.Create(_board.FireworkPile, _board.DiscardPile, _pilesAnalyzer, new Card[0]); State state = new NoCluesState(boardContext); foreach (var playerToClue in players) { IEnumerable <Card> otherPlayerCards = GetPlayersCards(playerToClue); var playerHand = playerToClue.ShowCards(_clueGiver); boardContext = boardContext.ChangeContext(otherPlayerCards); IPlayerContext playerContext = new PlayerContext(playerToClue, playerHand); // надо оценить, что будет делать другой игрок. IPlayCardStrategy playCardStrategy = PlayStrategyFabric.Create(_gameProvider, playerContext); IDiscardStrategy discardStrategy = DiscardStrategyFabric.Create(_gameProvider, playerContext); var playerActionPredictor = new PlayerActionPredictor(boardContext, playerContext); var action = playerActionPredictor.Predict(playCardStrategy, discardStrategy); action.Log(_clueGiver.Name, playerToClue.Name); state.BoardContext = boardContext; state = state.Handle(action, playerContext); boardContext = state.BoardContext; if (state.IsFinalState) { break; } } Logger.Log.Info(""); if (state.Solution != null) { return(state.Solution); } if (state.OptionalSolution != null) { // TODO проверить, что подсказка ещё актуальна. // Пример: после подсказки игрок А сходит жёлтой двойкой. // Но мы знаем, что по-любому игрок Б сходит жёлтой двойкой. return(state.OptionalSolution); } // выскочили из цикла, но не придумали подсказку... // Значит, можно расслабиться... var playersCircle = players; if (state.IgnoreUntil != null) { playersCircle = players.SkipWhile(p => p != state.IgnoreUntil) .Skip(1) .Concat(players.TakeWhile(p => p != state.IgnoreUntil)) .ToList() .AsReadOnly(); } // костыль на случай конца игры // осталось по ходу у двух игроков: А и Б. // А попытался подсказать Б. Не вышло. // Без костыля playersCircle будет пустым. if (!playersCircle.Any()) { playersCircle = players; } return (new NoCriticalSituation(_clueGiver, playersCircle, boardContext)); }