Example #1
0
        public FireworkPile Clone()
        {
            var newFirework = new FireworkPile(this.Provider);

            foreach (var card in Cards)
            {
                if (!newFirework.AddCard(card))
                {
                    throw new InvalidOperationException();
                }
            }

            return(newFirework);
        }
Example #2
0
        /// <summary>
        /// Возвращает карты, которые уже вне игры: то есть карты из сброса и фейерверка.
        /// </summary>
        /// <param name="fireworkPile"></param>
        /// <param name="discardPile"></param>
        /// <returns></returns>
        public IReadOnlyList <Card> GetThrownCards(FireworkPile fireworkPile, DiscardPile discardPile)
        {
            if (fireworkPile == null)
            {
                throw new ArgumentNullException(nameof(fireworkPile));
            }
            if (discardPile == null)
            {
                throw new ArgumentNullException(nameof(discardPile));
            }

            return(fireworkPile.Cards.Concat(discardPile.Cards)
                   .ToList()
                   .AsReadOnly());
        }
Example #3
0
        public void ListenClue(Clue clue)
        {
            if (clue == null)
            {
                throw new ArgumentNullException(nameof(clue));
            }
            if (!clue.Type.IsStraightClue)
            {
                throw new IncorrectClueException("You can give clues only about Rank IS or Nominal IS type");
            }

            // эвристика
            if (clue.IsSubtleClue(FireworkPile.GetExpectedCards()))
            {
                Logger.Log.Info("It's a subtle clue");
                _specialCards.Add(clue.Cards.First());
            }

            _memory.Update(clue);
        }
Example #4
0
 public Builder WithFireworkPile(FireworkPile fireworkPile)
 {
     _boardContext._fireworkPile = fireworkPile ?? throw new ArgumentNullException(nameof(fireworkPile));
     return(this);
 }
Example #5
0
        // карты, которые нельзя сбрасывать, для которых верно:
        // их нет в фейерверке;
        // они должны быть в фейерверке;
        // на руках или в колоде осталась всего одна такая карта.
        public IReadOnlyList <Card> GetUniqueCards(FireworkPile fireworkPile, DiscardPile discardPile)
        {
            if (fireworkPile == null)
            {
                throw new ArgumentNullException(nameof(fireworkPile));
            }
            if (discardPile == null)
            {
                throw new ArgumentNullException(nameof(discardPile));
            }

            Matrix resultMatrix = _provider.CreateFullDeckMatrix();

            // вычитаем сброшенные карты
            Matrix thrown = _converter.Encode(discardPile.Cards);

            foreach (var number in _provider.Ranks)
            {
                foreach (var color in _provider.Colors)
                {
                    if (resultMatrix[number, color] > 0 && thrown[number, color] > 0)
                    {
                        resultMatrix[number, color] -= thrown[number, color];
                    }
                }
            }

            // уберём недостижимые карты
            foreach (var color in _provider.Colors)
            {
                bool wasZero = false;
                foreach (var number in _provider.Ranks)
                {
                    if (!wasZero)
                    {
                        if (resultMatrix[number, color] == 0)
                        {
                            wasZero = true;
                        }
                    }
                    else
                    {
                        resultMatrix[number, color] = 0;
                    }
                }
            }

            // учтём сыгранные карты
            Matrix played = _converter.Encode(fireworkPile.Cards);

            foreach (var number in _provider.Ranks)
            {
                foreach (var color in _provider.Colors)
                {
                    if (played[number, color] == 1)
                    {
                        resultMatrix[number, color] = 0;
                    }
                }
            }

            // интересуют только те ячейки, в которых значение 1
            // остальные зануляем
            foreach (var number in _provider.Ranks)
            {
                foreach (var color in _provider.Colors)
                {
                    if (resultMatrix[number, color] != 1)
                    {
                        resultMatrix[number, color] = 0;
                    }
                }
            }

            // в итоге получили матрицу, в которой
            // 0 стоит у неуникальных карт,
            // 1 стоит у уникальных карт
            return(_converter.Decode(resultMatrix));
        }
Example #6
0
        /// <summary>
        /// Возвращает карты, которые могут быть добавлены в фейерверк
        /// </summary>
        /// <param name="fireworkPile"></param>
        /// <param name="discardPile"></param>
        /// <returns></returns>
        public IReadOnlyList <Card> GetCardsWhateverToPlay(FireworkPile fireworkPile, DiscardPile discardPile)
        {
            if (fireworkPile == null)
            {
                throw new ArgumentNullException(nameof(fireworkPile));
            }
            if (discardPile == null)
            {
                throw new ArgumentNullException(nameof(discardPile));
            }

            Matrix possibleToPlay = _provider.CreateFullDeckMatrix();

            Matrix played = _converter.Encode(fireworkPile.Cards);

            foreach (var number in _provider.Ranks)
            {
                foreach (var color in _provider.Colors)
                {
                    if (played[number, color] == 1)
                    {
                        possibleToPlay[number, color] = 0;
                    }
                    else
                    {
                        possibleToPlay[number, color] = 1;
                    }
                }
            }

            // теперь вычитаем сброшенные карты
            Matrix thrown = _converter.Encode(discardPile.Cards);

            Matrix remain = _provider.CreateFullDeckMatrix();

            foreach (var number in _provider.Ranks)
            {
                foreach (var color in _provider.Colors)
                {
                    remain[number, color] -= thrown[number, color];
                }
            }

            // итак, в матрице result у нас карты, которые могут быть добавлены в фейерверк
            // теперь надо собрать их воедино.

            foreach (var color in _provider.Colors)
            {
                // цвет зафиксирован.
                // теперь разберёмся с номиналами.
                bool wasOne = false;
                foreach (var number in _provider.Ranks)
                {
                    if (possibleToPlay[number, color] == 0 && !wasOne)
                    {
                        continue;
                    }

                    if (remain[number, color] == 0 || wasOne)
                    {
                        wasOne = true;
                        possibleToPlay[number, color] = 0;
                    }
                }
            }

            return(_converter.Decode(possibleToPlay));
        }
Example #7
0
        private CardInHand GetCardToPlay()
        {
            // cards we need to play
            var neededCards = FireworkPile.GetExpectedCards();

            List <CardInHand> cardsToPlay = new List <CardInHand>();

            if (_specialCards.Count > 0)
            {
                Logger.Log.Info("Use a subtle clue");

                var cardToPlay = _specialCards.First();

                _specialCards.RemoveAt(0);
                if (neededCards.Any(c => cardToPlay.Card == c))
                {
                    return(cardToPlay);
                }
            }

            // получить список карт, которые уже сброшены или находятся на руках у других игроков
            var excludedCards =
                _pilesAnalyzer.GetThrownCards(FireworkPile, DiscardPile)
                .Concat(GetOtherPlayersCards().Select(cardInHand => cardInHand.Card));

            // поискать у себя карты из списка нужных
            foreach (Guess guess in Guesses)
            {
                var probability = guess.GetProbability(neededCards, excludedCards);
                if (probability > PlayProbabilityThreshold)
                {
                    cardsToPlay.Add(_memory.GetCardByGuess(guess));
                }
            }

            // эвристика:
            // если игрок знает, что у него есть единица, то пусть играет ей.
            // при условии, что ещё нужны единицы
            if (
                FireworkPile.GetExpectedCards().Any(card => card.Rank == Rank.One) &&
                cardsToPlay.Count == 0 &&
                BlowCounter > 1)
            {
                CardInHand card = GetCardWithRankOneToPlay();
                if (card != null)
                {
                    Logger.Log.Info("I know that I have One. I'll try to play it.");
                    cardsToPlay.Add(card);
                }
            }

            if (cardsToPlay.Count == 0)
            {
                return(null);
            }

            cardsToPlay = cardsToPlay
                          .OrderBy(card => (int)card.Card.Rank)
                          .ToList();

            return(cardsToPlay.Last().Card.Rank == Rank.Five ? cardsToPlay.Last() : cardsToPlay.First());
        }