public void CardWentToLocation(DeckPlacement deckPlacement) { for (int i = 0; i < this.gameLogs.Length; ++i) { this.gameLogs[i].CardWentToLocation(deckPlacement); } }
public void CardWentToLocation(DeckPlacement deckPlacement) { switch (deckPlacement) { case DeckPlacement.TopOfDeck: this.textWriter.WriteLine("... and placed card on top of deck"); break; case DeckPlacement.Hand: this.textWriter.WriteLine("... and placed card in hand"); break; } }
public void PlayerDiscardCard(PlayerState playerState, Card card, DeckPlacement source) { this.textWriter.WriteLine("{0} Discarded {1} from {2}.", playerState.actions.PlayerName, card.name, TextForDeckPlacement(source)); }
internal void GainCard(GameState gameState, Card card, DeckPlacement originalLocation, DeckPlacement defaultPlacement = DeckPlacement.Discard, GainReason gainReason = GainReason.Gain) { if (gainReason == GainReason.Buy) { this.gameLog.PlayerBoughtCard(this, card); this.turnCounters.cardsBoughtThisTurn.Add(card); gameState.cardContextStack.PushCardContext(this, card, CardContextReason.CardBeingBought); } else { this.gameLog.PlayerGainedCard(this, card); gameState.cardContextStack.PushCardContext(this, card, CardContextReason.CardBeingGained); } // should only include cards gained on the players turned, not cards gained as a side effect on some other players turn // important for smugglers ... if (this == gameState.players.CurrentPlayer) { this.turnCounters.cardsGainedThisTurn.Add(card); } this.gameLog.PushScope(); // technically, the hovel reaction can cause hand size to change. This is not a problem though // would only be a problem if cards were added that would subsequently needed to be enumerated. bool wasCardMoved = false; if (this.ownsCardWithSpecializedActionOnBuyWhileInHand || this.ownsCardWithSpecializedActionOnGainWhileInHand) { foreach (Card cardInHand in this.Hand) { gameState.cardContextStack.PushCardContext(this, cardInHand, CardContextReason.CardReacting); DeckPlacement preferredPlacement = (gainReason == GainReason.Buy) ? cardInHand.DoSpecializedActionOnBuyWhileInHand(this, gameState, card) : DeckPlacement.Default; if (!wasCardMoved && preferredPlacement == DeckPlacement.Default) { preferredPlacement = cardInHand.DoSpecializedActionOnGainWhileInHand(this, gameState, card); } if (!wasCardMoved && preferredPlacement != DeckPlacement.Default) { defaultPlacement = preferredPlacement; wasCardMoved = true; } gameState.cardContextStack.Pop(); } } if (this.ownsCardWithSpecializedActionOnGainWhileInPlay) { foreach (Card cardInPlay in this.CardsInPlay) { gameState.cardContextStack.PushCardContext(this, cardInPlay, CardContextReason.CardReacting); DeckPlacement preferredPlacement = cardInPlay.DoSpecializedActionOnGainWhileInPlay(this, gameState, card); if (!wasCardMoved && preferredPlacement != DeckPlacement.Default) { defaultPlacement = preferredPlacement; wasCardMoved = true; } gameState.cardContextStack.Pop(); } } // buys are also gains. { DeckPlacement preferredPlacement = card.DoSpecializedWhenGain(this, gameState); if (!wasCardMoved && preferredPlacement != DeckPlacement.Default) { defaultPlacement = preferredPlacement; wasCardMoved = true; } } if (gainReason == GainReason.Buy) { if (card.canOverpay) { gameState.CurrentContext.PushCardContext(this, card, CardContextReason.CardReacting); this.RequestPlayerOverpayForCard(card, gameState); gameState.CurrentContext.Pop(); } card.DoSpecializedWhenBuy(this, gameState); if (this.ownsCardWithSpecializedActionOnBuyWhileInPlay) { foreach (Card cardInPlay in this.CardsInPlay) { gameState.cardContextStack.PushCardContext(this, card, CardContextReason.CardReacting); gameLog.PushScope(); cardInPlay.DoSpecializedActionOnBuyWhileInPlay(this, gameState, card); gameLog.PopScope(); gameState.cardContextStack.Pop(); } } } this.PlaceCardFromPlacement(new CardPlacementPair(card, defaultPlacement), gameState, originalLocation); gameState.cardContextStack.Pop(); this.gameLog.PopScope(); gameState.hasCurrentPlayerGainedCard |= true; this.ownsCardThatMightProvideDiscountWhileInPlay |= card.MightProvideDiscountWhileInPlay; this.ownsCardThatHasSpecializedCleanupAtStartOfCleanup |= card.HasSpecializedCleanupAtStartOfCleanup; this.ownsCardWithSpecializedActionOnBuyWhileInPlay |= card.HasSpecializedActionOnBuyWhileInPlay; this.ownsCardWithSpecializedActionOnTrashWhileInHand |= card.HasSpecializedActionOnTrashWhileInHand; this.ownsCardWithSpecializedActionOnGainWhileInPlay |= card.HasSpecializedActionOnGainWhileInPlay; this.ownsCardWithSpecializedActionOnBuyWhileInHand |= card.HasSpecializedActionOnBuyWhileInHand; this.ownsCardWithSpecializedActionOnGainWhileInHand |= card.HasSpecializedActionOnGainWhileInHand; this.ownsCardWithSpecializedActionToCardWhileInPlay |= card.HasSpecializedActionToCardWhileInPlay; }
internal bool GainCardFromSupply(Card card, GameState gameState, DeckPlacement defaultLocation = DeckPlacement.Discard) { return gameState.PlayerGainCardFromSupply(card, this, defaultLocation:defaultLocation) != null; }
internal void RevealCard(Card card, DeckPlacement source) { this.gameLog.PlayerRevealedCard(this, card, DeckPlacement.TopOfDeck); }
private void PlaceCardFromPlacement(CardPlacementPair pair, GameState gameState, DeckPlacement originalSource) { gameLog.CardWentToLocation(pair.placement); switch (pair.placement) { case DeckPlacement.Discard: this.discard.AddCard(pair.card); break; case DeckPlacement.Hand: this.hand.AddCard(pair.card); break; case DeckPlacement.Trash: this.MoveCardToTrash(pair.card, gameState); break; case DeckPlacement.Play: this.PlayCard(pair.card, gameState); break; case DeckPlacement.TopOfDeck: this.deck.AddCardToTop(pair.card); break; case DeckPlacement.None: { switch (originalSource) { case DeckPlacement.Supply: this.ReturnCardToSupply(pair.card, gameState); break; case DeckPlacement.Trash: this.MoveCardToTrash(pair.card, gameState); break; default: throw new NotImplementedException(); } break; } default: throw new Exception("Invalid case"); } }
public void PlayerRevealedCard(PlayerState playerState, Card card, DeckPlacement source) { for (int i = 0; i < this.gameLogs.Length; ++i) { this.gameLogs[i].PlayerRevealedCard(playerState, card, source); } }
public void PlayerDiscardCard(PlayerState playerState, Card card, DeckPlacement source) { if (playerState.PlayPhase == PlayPhase.Cleanup) { this.discardedCards.Add(card); } else { this.textWriter.WriteLine("{0} Discards {1} from {2}.", GetPlayerName(playerState), card.name, TextForDeckPlacement(source)); } }
virtual public Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { deckPlacement = DeckPlacement.Default; return(PlayerMustMakeCardChoice()); }
public override Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { var self = gameState.Self; Card result = this.trashOrder.GetPreferredCard( gameState, card => (self.Hand.HasCard(card) || self.Discard.HasCard(card)) && acceptableCard(card)); // warning, strategy didnt' include what to, try to do a reasonable default. if (result == null && !isOptional) { result = self.Hand.OrderBy(c => c, new DefaultPlayRules.CompareCardByFirstToTrash()).FirstOrDefault(); } deckPlacement = DeckPlacement.Discard; if (result != null) { if (self.Discard.HasCard(result)) { deckPlacement = DeckPlacement.Discard; } else if (self.Hand.HasCard(result)) { deckPlacement = DeckPlacement.Hand; } else { throw new Exception("Card should have been in hand or discard"); } } return(result); }
public Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { IPlayerAction playerAction = this.GetActionForCardInPlay(gameState); return(playerAction.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement)); }
public override Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { IPlayerAction playerAction = this.GetActionForCurrentCardContext(gameState); if (playerAction != null) { return(playerAction.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement)); } else { return(base.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement)); } }
public virtual Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { return(this.playerAction.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement)); }
public Card PlayerGainCardFromSupply(Card cardType, PlayerState playerState, DeckPlacement defaultLocation = DeckPlacement.Discard, GainReason gainReason = GainReason.Gain) { PileOfCards pile = this.GetPile(cardType); if (pile == null) { return null; } if (GetPile(this.supplyPiles, cardType) != null) this.hasPileEverBeenGained[pile] = true; Card card = pile.DrawCardFromTop(); if (card == null) { return null; } playerState.GainCard(this, card, DeckPlacement.Supply, defaultLocation, gainReason); return card; }
public void PlayerRevealedCard(PlayerState playerState, Card card, DeckPlacement source) { this.textWriter.WriteLine("{0} Reveals {1}.", GetPlayerName(playerState), card.name); }
private string TextForDeckPlacement(DeckPlacement source) { switch (source) { case DeckPlacement.Discard: return "discard"; case DeckPlacement.TopOfDeck: return "top of deck"; case DeckPlacement.Default: return "default"; case DeckPlacement.Hand: return "hand"; case DeckPlacement.Play: return "play"; case DeckPlacement.Revealed: return "revealed cards"; case DeckPlacement.Supply: return "supply"; case DeckPlacement.Trash: return "trash"; default: throw new Exception(); } }
internal Card RequestPlayerGainCardFromSupply(GameState gameState, CardPredicate acceptableCard, string description, bool isOptional = false, DeckPlacement defaultLocation = DeckPlacement.Discard) { return RequestPlayerGainCardFromSupply(gameState, this, acceptableCard, description, isOptional, defaultLocation); }
public Card PlayerGainCardFromSupply(Card cardType, PlayerState playerState, DeckPlacement defaultLocation = DeckPlacement.Discard, GainReason gainReason = GainReason.Gain) { bool canGainCardFromSupply = CanGainCardFromSupply(cardType); PileOfCards pile = this.GetPile(cardType); if (pile == null) { System.Diagnostics.Debug.Assert(!canGainCardFromSupply); return null; } if (GetPile(this.supplyPiles, cardType) != null) this.hasPileEverBeenGained[pile] = true; if (!IsCardEqualOrOfType(pile.TopCard(), cardType)) { System.Diagnostics.Debug.Assert(!canGainCardFromSupply); return null; } Card card = pile.DrawCardFromTop(); if (card == null) { System.Diagnostics.Debug.Assert(!canGainCardFromSupply); return null; } System.Diagnostics.Debug.Assert(canGainCardFromSupply); playerState.GainCard(this, card, DeckPlacement.Supply, defaultLocation, gainReason); return card; }
internal Card RequestPlayerGainCardFromTrash(GameState gameState, CardPredicate acceptableCard, string description, bool isOptional = false, DeckPlacement defaultLocation = DeckPlacement.Discard) { if (!gameState.trash.HasCard(acceptableCard)) return null; Card cardType = this.actions.GetCardFromTrashToGain(gameState, acceptableCard, isOptional); if (cardType == null) { if (isOptional) { return null; } throw new Exception("Must gain a card where " + description); } if (!acceptableCard(cardType)) { throw new Exception("Card does not meet constraint: " + description); } Card cardFromTrash = gameState.trash.RemoveCard(cardType); if (cardFromTrash == null) { throw new Exception("Card requested wasnt in the trash"); } this.GainCard(gameState, cardFromTrash, DeckPlacement.Trash, defaultLocation, GainReason.Gain); return cardFromTrash; }
public virtual void CardWentToLocation(DeckPlacement deckPlacement) { }
public Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { var saved = gameState.self; gameState.self = this.self; var result = this.playerAction.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement); gameState.self = saved; return(result); }
internal Card RequestPlayerGainCardFromSupply(GameState gameState, PlayerState playerGainingCard, CardPredicate acceptableCard, string description, bool isOptional = false, DeckPlacement defaultLocation = DeckPlacement.Discard) { PileOfCards exampleCard = gameState.supplyPiles.Where(cardPile => !cardPile.IsEmpty && acceptableCard(cardPile.TopCard())).FirstOrDefault(); bool hasCardOfCost = exampleCard != null; if (!hasCardOfCost) { return null; } CardPredicate cardPredicate = card => gameState.GetSupplyPile(card) != null && acceptableCard(card); // how do you know which player you are gaining for? Card cardType = this.actions.GetCardFromSupplyToGain(gameState, cardPredicate, isOptional); if (cardType == null) { if (isOptional) { return null; } throw new Exception("Must gain a card where " + description); } Card gainedCard = gameState.PlayerGainCardFromSupply(cardType, playerGainingCard, defaultLocation); if (gainedCard == null) { throw new Exception("Card specified can not be gained"); } if (!acceptableCard(gainedCard)) { throw new Exception("Card does not meet constraint: " + description); } return gainedCard; }
public virtual void PlayerRevealedCard(PlayerState playerState, Card card, DeckPlacement source) { }
internal Card RequestPlayerTrashCardFromHandAndGainCard( GameState gameState, CardPredicate acceptableCardsToTrash, CostConstraint costConstraint, int cost, CardRelativeCost cardRelativeCost, bool isOptionalToTrash = false, bool isOptionalToGain = false, DeckPlacement defaultLocation = DeckPlacement.Discard) { Card trashedCard = this.RequestPlayerTrashCardFromHand(gameState, acceptableCardsToTrash, isOptionalToTrash); if (trashedCard != null) { int cardCost = cardRelativeCost == CardRelativeCost.RelativeCost ? trashedCard.CurrentCoinCost(this) + cost : cardRelativeCost == CardRelativeCost.AbsoluteCost ? cost : 0; CardPredicate cardPredicate; if (costConstraint == CostConstraint.Exactly) { cardPredicate = acceptableCard => acceptableCard.CurrentCoinCost(this) == cardCost; } else if (costConstraint == CostConstraint.UpTo) { cardPredicate = acceptableCard => acceptableCard.CurrentCoinCost(this) <= cardCost; } else { throw new Exception("Invalid operation"); } return this.RequestPlayerGainCardFromSupply( gameState, cardPredicate, "", isOptionalToGain, defaultLocation); } return null; }
public CardPlacementPair(Card card, DeckPlacement placement) { this.card = card; this.placement = placement; }
private void MoveAllCardsToDiscard(CollectionCards cards, GameState gameState, DeckPlacement source) { foreach (Card card in cards) { this.DiscardCard(card, gameState, source); } cards.Clear(); }
internal void GainCard(GameState gameState, Card card, DeckPlacement originalLocation, DeckPlacement defaultPlacement = DeckPlacement.Discard, GainReason gainReason = GainReason.Gain) { if (gainReason == GainReason.Buy) { this.gameLog.PlayerBoughtCard(this, card); } else { this.gameLog.PlayerGainedCard(this, card); } this.gameLog.PushScope(); // technically, the hovel reaction can cause hand size to change. This is not a problem though // would only be a problem if cards were added that would subsequently needed to be enumerated. bool wasCardMoved = false; if (this.ownsCardWithSpecializedActionOnBuyWhileInHand || this.ownsCardWithSpecializedActionOnGainWhileInHand) { foreach (Card cardInHand in this.Hand) { DeckPlacement preferredPlacement = (gainReason == GainReason.Buy) ? cardInHand.DoSpecializedActionOnBuyWhileInHand(this, gameState, card) : DeckPlacement.Default; if (!wasCardMoved && preferredPlacement == DeckPlacement.Default) { preferredPlacement = cardInHand.DoSpecializedActionOnGainWhileInHand(this, gameState, card); } if (!wasCardMoved && preferredPlacement != DeckPlacement.Default) { defaultPlacement = preferredPlacement; wasCardMoved = true; } } } if (this.ownsCardWithSpecializedActionOnGainWhileInPlay) { foreach (Card cardInPlay in this.CardsInPlay) { DeckPlacement preferredPlacement = cardInPlay.DoSpecializedActionOnGainWhileInPlay(this, gameState, card); if (!wasCardMoved && preferredPlacement != DeckPlacement.Default) { defaultPlacement = preferredPlacement; wasCardMoved = true; } } } // buys are also gains. { DeckPlacement preferredPlacement = card.DoSpecializedWhenGain(this, gameState); if (!wasCardMoved && preferredPlacement != DeckPlacement.Default) { defaultPlacement = preferredPlacement; wasCardMoved = true; } } if (gainReason == GainReason.Buy) { card.DoSpecializedWhenBuy(this, gameState); } this.PlaceCardFromPlacement(new CardPlacementPair(card, defaultPlacement), gameState, originalLocation); this.gameLog.PopScope(); gameState.hasCurrentPlayerGainedCard |= true; this.ownsCardThatMightProvideDiscountWhileInPlay |= card.MightProvideDiscountWhileInPlay; this.ownsCardThatHasSpecializedCleanupAtStartOfCleanup |= card.HasSpecializedCleanupAtStartOfCleanup; this.ownsCardWithSpecializedActionOnBuyWhileInPlay |= card.HasSpecializedActionOnBuyWhileInPlay; this.ownsCardWithSpecializedActionOnTrashWhileInHand |= card.HasSpecializedActionOnTrashWhileInHand; this.ownsCardWithSpecializedActionOnGainWhileInPlay |= card.HasSpecializedActionOnGainWhileInPlay; this.ownsCardWithSpecializedActionOnBuyWhileInHand |= card.HasSpecializedActionOnBuyWhileInHand; this.ownsCardWithSpecializedActionOnGainWhileInHand |= card.HasSpecializedActionOnGainWhileInHand; }
internal void DiscardCard(Card card, GameState gameState, DeckPlacement source) { this.cardBeingDiscarded.AddCardToTop(card); if (source != DeckPlacement.Deck) { this.gameLog.PlayerDiscardCard(this, card, source); this.gameLog.PushScope(); gameState.cardContextStack.PushCardContext(this, card, CardContextReason.CardBeingDiscarded); if (gameState.players.CurrentPlayer.PlayPhase != PlayPhase.Cleanup) { card.DoSpecializedDiscardNonCleanup(this, gameState); } if (source == DeckPlacement.Play) { card.DoSpecializedDiscardFromPlay(this, gameState); } gameState.cardContextStack.Pop(); this.gameLog.PopScope(); } Card cardBeingDiscarded = this.cardBeingDiscarded.DrawCardFromTop(); if (cardBeingDiscarded != null) { this.discard.AddCard(card); } }
public Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { var saved = gameState.self; gameState.self = this.self; var result = this.playerAction.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement); gameState.self = saved; return result; }
internal Card GainCardFromSupply(GameState gameState, Card cardType, DeckPlacement defaultLocation = DeckPlacement.Discard) { return gameState.PlayerGainCardFromSupply(cardType, this, defaultLocation); }
public override Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { IPlayerAction playerAction = this.GetActionForCurrentCardContext(gameState); if (playerAction != null) return playerAction.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement); else return base.GetCardFromHandOrDiscardToTrash(gameState, acceptableCard, isOptional, out deckPlacement); }
internal void GainCardsFromSupply(GameState gameState, Card cardType, int count, DeckPlacement defaultLocation = DeckPlacement.Discard) { for (int i = 0; i < count; ++i) gameState.PlayerGainCardFromSupply(cardType, this, defaultLocation); }
public void PlayerRevealedCard(PlayerState playerState, Card card, DeckPlacement source) { this.textWriter.WriteLine("{0} Revealed {1}.", playerState.actions.PlayerName, card.name); }
public virtual Card GetCardFromHandOrDiscardToTrash(GameState gameState, CardPredicate acceptableCard, bool isOptional, out DeckPlacement deckPlacement) { deckPlacement = DeckPlacement.Default; return PlayerMustMakeCardChoice(); }