Beispiel #1
0
        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));
        }