public bool Play(Card card) { if (_hand.Contains(card)) { _hand.Remove(card); _grave.Add(card); EventManager.Instance.QueueEvent(new Evt_PlayedCard() { Owner = Owner, Card = card }); return(true); } return(false); }
private void VerifyCombination(ref CardSet cs) { _combinationsCount++; Assert.IsFalse(cs.IsIntersectingWith(_dead)); Assert.IsTrue(cs.Contains(_shared)); CardSet uniqueMask = new CardSet { bits = cs.bits & (~_shared.bits) }; Assert.AreEqual(_enumCount, uniqueMask.CountCards()); // Use the fact that CardEnum generate masks in ascending order to check uniqueness if (_enumCount > 0) { Assert.Greater(uniqueMask.bits, _lastCs); } _lastCs = uniqueMask.bits; }
private void VerifyCombinationParam(int [] cards, int param) { CardSet cs = StdDeck.Descriptor.GetCardSet(cards); Assert.AreEqual(_combinationsCount, param); _combinationsCount1++; Assert.IsFalse(cs.IsIntersectingWith(_dead)); Assert.IsTrue(cs.Contains(_shared)); CardSet uniqueCs = new CardSet { bits = cs.bits & (~_shared.bits) }; Assert.AreEqual(_enumCount, uniqueCs.CountCards()); // Use the fact that CardEnum generate masks in ascending order to check uniqueness if (_enumCount > 0) { Assert.Greater(uniqueCs.bits, _lastCs1); } _lastCs1 = uniqueCs.bits; }
public void Resolve(IReactionScope scope) { var revealedTreasures = new CardSet(); 2.Times(() => { var revealedCard = scope.RevealCardFromDeck(); if (revealedCard.IsTreasure && !revealedTreasures.Contains(revealedCard)) { revealedTreasures.Add(revealedCard, scope); } }); if (revealedTreasures.Count() == 1) { scope.Publish(new TrashTreasureCardFromThief(TurnScope, scope, revealedTreasures.Single())); } else if (revealedTreasures.Count() == 2) { TurnScope.Publish(new ChooseTreasureCardToTrashFromThief(TurnScope, scope, revealedTreasures)); } }
public static void DoMonteCarlo( ActionTree tree, int ourPos, CardSet pocket, int round, string sharedCardsAsString, List <ActionTreeNode> strategyPath, int repetitionsCount) { string[] sharedCards = sharedCardsAsString.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); ActionTreeNode curStrategyNode = strategyPath[strategyPath.Count - 1]; // Here we sometimes use the knowledge about the game definition. _clearValues.Walk(tree, curStrategyNode); MonteCarloData[] mc = new MonteCarloData[tree.GameDef.RoundsCount]; for (int r = 0; r < mc.Length; ++r) { mc[r] = new MonteCarloData(); } // Fill known public data. for (int r = 1; r <= round; ++r) { int sharedCount = tree.GameDef.SharedCardsCount[r]; mc[r].boardSize = mc[r - 1].boardSize + sharedCount; mc[r].shared = StdDeck.Descriptor.GetCardSet(sharedCards, mc[r - 1].boardSize, sharedCount); mc[r].board = mc[r - 1].board | mc[r].shared; Debug.Assert(mc[r].shared.CountCards() == sharedCount); Debug.Assert(mc[r].board.CountCards() == mc[r].boardSize); } Debug.Assert(mc[round].boardSize == sharedCards.Length); MonteCarloDealer mcDealer = new MonteCarloDealer(); ApplyMonteCarloData applyMc = new ApplyMonteCarloData(); mcDealer.Initialize(pocket | mc[round].board); Debug.Assert(mcDealer.Cards.Length + pocket.CountCards() + mc[round].boardSize == 52); for (int repetition = 0; repetition < repetitionsCount * 10; ++repetition) { mcDealer.Shuffle(7); // 2 for opponent, up to 5 for the board CardSet mcPocket = StdDeck.Descriptor.GetCardSet(mcDealer.Cards, 0, 2); Debug.Assert(mc[0].board.IsEmpty()); int sharedDealt = 0; for (int r = 0; r < tree.GameDef.RoundsCount; ++r) { if (r > round) { mc[r].boardSize = mc[r - 1].boardSize + tree.GameDef.SharedCardsCount[r]; mc[r].shared = StdDeck.Descriptor.GetCardSet(mcDealer.Cards, 2 + sharedDealt, tree.GameDef.SharedCardsCount[r]); sharedDealt += tree.GameDef.SharedCardsCount[r]; Debug.Assert(!mc[r - 1].board.Contains(mc[r].shared)); Debug.Assert(!mcPocket.Contains(mc[r].shared)); mc[r].board = mc[r - 1].board | mc[r].shared; } mc[r].bucket = tree.Bucketizer.GetBucket(mcPocket, mc[r].board, r); } double strategyFactor = 1; // Go through the strategy path, skip the b-node Debug.Assert(strategyPath[0].ActionKind == Ak.b); // Start from pos. 2 to skip deals (where OppBuckets always contains 0s if ourPos == 0). for (int pathIndex = 2; pathIndex < strategyPath.Count; pathIndex++) { ActionTreeNode pathNode = strategyPath[pathIndex]; Debug.Assert(pathNode.ActionKind != Ak.b); // Take nodes where opponent acts. if (pathNode.State.CurrentActor == 1 - ourPos) { // nextNode always exists because this function is called when we act ActionTreeNode nextNode = strategyPath[pathIndex + 1]; Debug.Assert(pathNode.State.Round == nextNode.State.Round); int freq = pathNode.OppBuckets.Counts[mc[pathNode.State.Round].bucket]; int nextFreq = nextNode.OppBuckets.Counts[mc[pathNode.State.Round].bucket]; double coef = freq == 0 ? 0 : (double)nextFreq / freq; strategyFactor *= coef; } } if (strategyFactor > 0) { int showdownValue = Showdown(pocket, mcPocket, mc[tree.GameDef.RoundsCount - 1].board, mc[tree.GameDef.RoundsCount - 1].boardSize + 2); applyMc.ApplyData(curStrategyNode, mc, ourPos, showdownValue, strategyFactor); repetition += 9; } } FinalizeMonteCarloData finalizer = new FinalizeMonteCarloData(); finalizer.Finalize(tree, curStrategyNode, ourPos); }
public int Best() { Sort(Order.ASC); CardSet oneSetCards = new CardSet(); CardSet twoSetsCards = new CardSet(); ClassifyCards(ref oneSetCards, ref twoSetsCards); int bestScore = 1000; // There is at least one card which is in two sets. if (twoSetsCards.Length() > 0) { int tmpScore = 0; for (int i = 0; i < twoSetsCards.Length(); i++) { // Debug.Log ("Rank set:" + ToCardString ()); // First check same rank set. CardSet rankSet = FindRankSetCombination((PhomCard)twoSetsCards.At(i)); List <int> overlappedIndice = new List <int> (); if (rankSet.Length() == 4) { for (int j = 0; j < twoSetsCards.Length(); j++) { if (i != j && rankSet.Contains(twoSetsCards.At(j))) { overlappedIndice.Add(j); break; } } } // Two cards in the same rank set. Quad set. if (overlappedIndice.Count > 0) { for (int m = 0; m < overlappedIndice.Count; m++) { // Keep all in the rank set. if (BestSubHand(rankSet, -1, ref bestScore)) { return(0); } // Remove the overlapped out of rank set. if (BestSubHand(rankSet, overlappedIndice [m], ref bestScore)) { return(0); } } } else { if (BestSubHand(rankSet, -1, ref bestScore)) { return(0); } } // Check straight set. // Debug.Log ("Straight set:" + ToCardString ()); CardSet straightSet = FindStraightCombination((PhomCard)twoSetsCards.At(i)); // Debug.Log ("Straight set2:" + straightSet.ToCardString ()); int mainIndex = straightSet.cards.IndexOf(twoSetsCards.At(i)); overlappedIndice.Clear(); for (int j = 0; j < twoSetsCards.Length(); j++) { if (i != j && straightSet.Contains(twoSetsCards.At(j))) { overlappedIndice.Add(j); break; } } // Two cards in the same straight. if (overlappedIndice.Count > 0) { for (int m = 0; m < overlappedIndice.Count; m++) { // Keep the overlapped card in the straight hand <=> remove it from the remaining. if (BestSubHand(straightSet, -1, ref bestScore)) { return(0); } // Remove the overlapped card in the set <=> not remove it from the remaining. if ((int)Mathf.Abs(mainIndex - overlappedIndice [m]) > 2) { PhomHand straightHand = new PhomHand(SubSetList(0, numCards)); if (mainIndex < overlappedIndice [m]) { for (int k = overlappedIndice [m]; k < straightSet.Length(); k++) { straightHand.RemoveCard(straightSet.At(k)); } } else { for (int k = 0; k <= overlappedIndice [m]; k++) { straightHand.RemoveCard(straightSet.At(k)); } } if (CheckBestScore(straightHand, ref bestScore, true)) { return(0); } } } } // else { if (BestSubHand(straightSet, -1, ref bestScore)) { return(0); } } } } // No card in two sets. else if (oneSetCards.Length() > 0) { int tmpScore = 0; // Debug.Log ("++++++++:" + oneSetCards.ToCardString () + " " + oneSetCards.Length ()); for (int i = 0; i < oneSetCards.Length(); i++) { // First check same rank set. CardSet rankSet = FindRankSetCombination((PhomCard)oneSetCards.At(i)); // Debug.Log ("++++++++2:" + rankSet.ToCardString ()); if (rankSet.Length() > 0 && BestSubHandWithNoCardInTwoSet(rankSet, ref bestScore)) { return(0); } // Check straight set. CardSet straightSet = FindStraightCombination((PhomCard)oneSetCards.At(i)); // Debug.Log ("Set one: straight set:" + straightSet.ToCardString ()); if (straightSet.Length() > 0 && BestSubHandWithNoCardInTwoSet(straightSet, ref bestScore)) { return(0); } } } else { // Debug.Log ("no set found:" + ToCardString ()); singleCards.cards.AddRange(cards); if (CheckBestScore(this, ref bestScore, false)) { return(0); } } // Debug.Log ("bestScore:" + bestScore); return(bestScore); }