public FireworkPile Clone() { var newFirework = new FireworkPile(this.Provider); foreach (var card in Cards) { if (!newFirework.AddCard(card)) { throw new InvalidOperationException(); } } return(newFirework); }
/// <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()); }
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); }
public Builder WithFireworkPile(FireworkPile fireworkPile) { _boardContext._fireworkPile = fireworkPile ?? throw new ArgumentNullException(nameof(fireworkPile)); return(this); }
// карты, которые нельзя сбрасывать, для которых верно: // их нет в фейерверке; // они должны быть в фейерверке; // на руках или в колоде осталась всего одна такая карта. 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)); }
/// <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)); }
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()); }