private bool IsCardHigher(int card, int highestCard) { int suit = BitwiseCardHelper.GetSuitAsBits(card); int highestSuit = BitwiseCardHelper.GetSuitAsBits(highestCard); if (suit == highestSuit) { return((uint)card > (uint)highestCard); } int trumpSuit = mContext.TrumpSuit; if (trumpSuit != 0) { if ((suit == trumpSuit) && (highestSuit != trumpSuit)) { return(true); } if ((suit != trumpSuit) && (highestSuit == trumpSuit)) { return(false); } } return(false); }
internal void DoMove(Move move) { // Register the move. ActiveHand.Move = move; // Remove the played card from the player's cards. ActiveHand.Cards &= ~move.Card; // Update the leading suit. if (mLeadingSuit == 0) { mLeadingSuit = BitwiseCardHelper.GetSuitAsBits(move.Card); } ActivateNextHand(); // If the next player has already played a card, then the trick is over. if (ActiveHand.Move.Card != 0) { mActiveIndex = GetTrickWinner(); ActiveHand.Tricks++; for (int i = 0; i < HandCount; i++) { mDiscards |= mHands[i].Move.Card; mHands[i].Move = Move.Empty; } mLeadingSuit = 0; } }
private double GetFailureProbabilityForSuit(int cards, int discards, CardSuit suit) { int cardSet = BitwiseCardHelper.GetCardSet(cards, suit); int discardsCount = BitwiseCardHelper.GetSuitCount(discards, suit); int otherSuitsDistribution = CardSuitDistribution.GetDistribution(cards, discards, suit); return(MisereProbabilities.GetFailureProbability(cardSet, discardsCount, otherSuitsDistribution, IsFirstHand)); }
internal HandState(Hand source) { Cards = BitwiseCardHelper.CardCollectionToBits(source.Cards); if (source.PlayedCard.HasValue) { Move = new Move(BitwiseCardHelper.CardToBits(source.PlayedCard.Value)); } Tricks = source.Tricks; }
internal PlayingContext(Game game) { Game = game; if (game.GameType != GameType.AllPass) { mDeclarerIndex = game.Declarer.Index; } TrumpSuit = BitwiseCardHelper.SuitToBits(game.BiddingContext.TrumpSuit); InitialSuit = BitwiseCardHelper.SuitToBits(game.PlayingContext.InitialSuit); SetStateEvaluator(); }
internal PlayingState(PlayingContext context) { mContext = context; Game game = context.Game; for (int i = 0; i < HandCount; i++) { mHands[i] = new HandState(game.GetHand(i)); } mActiveIndex = game.ActiveHand.Index; mDiscards = BitwiseCardHelper.CardCollectionToBits(game.PlayingContext.Discards); mLeadingSuit = context.InitialSuit; }
private double EvaluateDiscards(int cards) { Debug.Assert(BitwiseCardHelper.GetCardCount(cards) == 12); var values = new List <double>(); var enumerator = new TwoCardsEnumerator(cards); while (enumerator.MoveNext()) { int cardsAfterDiscarding = cards & ~enumerator.Current; double value = EvaluateCards(cardsAfterDiscarding, enumerator.Current); values.Add(value); } return(values.Max()); }
internal Card PlayCard() { var context = new PlayingContext(mGame); var rootState = new PlayingState(context); var validMoves = rootState.GetValidMoves(); // Exit if only one move is possible. if (BitwiseCardHelper.GetGroupCount(validMoves) == 1) { return(GetRandomCard(validMoves)); } bool isCheater = (mGame.Options.DifficultyLevel == GameDifficultyLevel.Cheater); var bestNode = TreeSearcher.Search(rootState, 100000, !isCheater); return(GetRandomCard(bestNode.Move.Group)); }
protected override double EvaluateCards(int cards, int discards) { Debug.Assert(BitwiseCardHelper.GetCardCount(cards) == 10); int trumpCount = BitwiseCardHelper.GetSuitCount(cards, mTrumpSuit); // Don't consider trump game if the number of trumps is less than 4. // TODO Consider 3-3-3-1. if (trumpCount < 4) { return(double.MinValue); } IEnumerable <TrickProbability> totalProbabilities = Enumerable.Empty <TrickProbability>(); // Calculate sum of tricks with corresponding probabilities in all suits. for (var suit = CardSuit.Spades; suit <= CardSuit.Hearts; suit++) { int cardSet = BitwiseCardHelper.GetCardSet(cards, suit); IEnumerable <TrickProbability> probabilities = TrickPlayProbabilities.GetTrickProbabilities(cardSet); // Combine probabilities.. totalProbabilities = totalProbabilities.Combine(probabilities); } bool isEasyLevel = (Game.Options.DifficultyLevel == GameDifficultyLevel.Beginner) || (Game.Options.DifficultyLevel == GameDifficultyLevel.Amateur); // The following stuff is too complex for weak players. if (!isEasyLevel) { totalProbabilities = ConsiderTrumpAdvancing(totalProbabilities); totalProbabilities = ConsiderTrickTaking(totalProbabilities); } return(totalProbabilities.Expectation( tricks => Game.Rules.GetGameCost( GameType.TrickPlay, Game.Options.NumberOfPlayers, DeclaredTricks, tricks))); }
/// <summary> /// Calculates a mathematical expectation of the active hand for a certain game type. /// Uses the expecti-max algorithm to compute the value among all possible widow cards and further discards. /// Updates the <see cref="Expectation"/> property. /// </summary> /// <returns></returns> internal void Evaluate() { int ownCards = BitwiseCardHelper.CardCollectionToBits(mGame.ActiveHand.Cards); int unknownCards = ~ownCards; Debug.Assert(BitwiseCardHelper.GetCardCount(unknownCards) == 22); var values = new List <double>(); var enumerator = new TwoCardsEnumerator(unknownCards); while (enumerator.MoveNext()) { int ownCardsWithWidow = ownCards | enumerator.Current; double value = EvaluateDiscards(ownCardsWithWidow); values.Add(value); } Expectation = values.Average(); }
private void CalculateCardSets() { mHandsToRandomize = mState.GetHandsToRandomize(); int handCount = mHandsToRandomize.Count; mCardCounts = new int[handCount]; mCardSets = new CardSet[handCount]; // We know own cards. int knownCards = mState.ActiveHand.Cards; // We know just played cards. for (int i = 0; i < 3; i++) { if (mState.Hands[i] != mState.ActiveHand) { knownCards |= mState.Hands[i].Move.Card; } } // We know discarded cards. knownCards |= mState.Discards; for (int i = 0; i < handCount; i++) { int handIndex = mHandsToRandomize[i]; Hand hand = mState.Game.GetHand(handIndex); mCardCounts[i] = hand.Cards.Count; int cardSet = ~knownCards; // Remove suits that the hand is known to miss. foreach (var suit in hand.VoidSuits) { cardSet &= ~BitwiseCardHelper.SuitToBits(suit); } mCardSets[i] = new CardSet(cardSet); } }
internal void RemoveCards(int cards) { mCards &= ~cards; mCount = BitwiseCardHelper.GetCardCount(mCards); }
internal CardSet(int cards) { mCards = cards; mCount = BitwiseCardHelper.GetCardCount(cards); }
private static Card GetRandomCard(int cards) { var cardCollection = BitwiseCardHelper.BitsToCardCollection(cards); return(RandomHelper.Select(cardCollection)); }