/// <summary>
        /// Determines if a given card is buildable.
        /// Returns "T" if it is, returns "F" if it is not
        /// </summary>
        /// <param name="card"></param>
        /// <returns></returns>
        public CommerceOptions isCardBuildable(Card card)
        {
            CommerceOptions ret = new CommerceOptions();

            //retrieve the cost
            Cost cost = card.cost;

            //if the player already owns a copy of the card, Return F immediatley
            // Note cannot use playedStructure.Contains(card) because Age 1 Loom != Age 2 Loom, so it's possible to build more than one of them.
            if (playedStructure.Exists(x => x.Id == card.Id))
            {
                ret.bAreResourceRequirementsMet = false;
                ret.buildable = CommerceOptions.Buildable.StructureAlreadyBuilt;
                return ret;
            }

            //if the cost is !, that means its free. Return T immediately
            if (cost.coin == 0 && cost.resources == string.Empty)
            {
                ret.bAreResourceRequirementsMet = true;
                ret.buildable = CommerceOptions.Buildable.True;
                return ret;
            }

            //if the player owns the prerequiste, Return T immediately
            if (playedStructure.Exists(x => (x.chain[0] == card.strName) || (x.chain[1] == card.strName)))
            {
                ret.bAreResourceRequirementsMet = true;
                ret.buildable = CommerceOptions.Buildable.True;
                return ret;
            }

            if (card.structureType == StructureType.Guild && playedStructure.Exists(x => x.Id == CardId.Ramses))
            {
                // Ramses: The player can build any Guild card for free.
                ret.bAreResourceRequirementsMet = true;
                ret.buildable = CommerceOptions.Buildable.True;
                return ret;
            }

            int nWildResources = 0;
            if (playedStructure.Exists(x => x.effect is StructureDiscountEffect && ((StructureDiscountEffect)x.effect).discountedStructureType == card.structureType))
            {
                // A leader card has been played that matches the structure type being built, so we can add a wild resource
                // e.g. We're building a science structure while Archimedes is in play for this player, or a military structure
                // when Leonidas is in play.
                ++nWildResources;
            }

            int coinCost = cost.coin;

            if (card.structureType == StructureType.Leader)
            {
                if (playerBoard.name == "Roma (A)" || playedStructure.Exists(x => x.Id == CardId.Maecenas))
                {
                    coinCost = 0;
                }
                else if (playerBoard.name == "Roma (B)")
                {
                    coinCost = Math.Max(0, coinCost - 2);
                }
                else if (leftNeighbour.playerBoard.name == "Roma (B)" || rightNeighbour.playerBoard.name == "Roma (B)")
                {
                    coinCost -= 1;
                }
            }

            if (coin < coinCost)
            {
                // if the card has a coin cost and we don't have enough money, the card is not buildable.
                ret.bAreResourceRequirementsMet = false;
                ret.buildable = CommerceOptions.Buildable.InsufficientCoins;
                return ret;
            }

            ret = resourceMgr.CanAfford(cost,
                leftNeighbour.resourceMgr.getResourceList(false),
                rightNeighbour.resourceMgr.getResourceList(false),
                ResourceManager.CommercePreferences.LowestCost | ResourceManager.CommercePreferences.BuyFromLeftNeighbor);

            if (ret.bAreResourceRequirementsMet)
            {
                if ((ret.leftCoins == 0 && ret.rightCoins == 0) && (ret.bankCoins == 0 || (ret.bankCoins == cost.coin)))
                {
                    if (coin < ret.bankCoins)
                        ret.buildable = CommerceOptions.Buildable.InsufficientCoins;
                    else
                        ret.buildable = CommerceOptions.Buildable.True;
                }
                else if (coin < ret.bankCoins)
                {
                    ret.buildable = CommerceOptions.Buildable.InsufficientCoins;
                }
                else
                {
                    ret.buildable = CommerceOptions.Buildable.CommerceRequired;
                }
            }
            else
            {
                ret.buildable = CommerceOptions.Buildable.InsufficientResources;
            }

            return ret;
        }
        public void executeActionNow(Card card)
        {
            Effect effect = card.effect;

            // I think the only effects that really need to be dealt with NOW are those
            // that affect game state (e.g. Babylon B, Play a discarded card.)
            if (effect == null)
            {
                switch(card.Id)
                {
                    case CardId.Babylon_B_s2:
                        // This is a signal that the Babylon player gets to take a 7th turn in this and future ages.
                        // It only does something after the 6th turn, unlike other Powers such as Halikarnassos, Solomon,
                        // and Roma (B)
                        babylonPowerEnabled = true;
                        break;

                    case CardId.Halikarnassos_A_s2:
                    case CardId.Halikarnassos_B_s1:
                    case CardId.Halikarnassos_B_s2:
                    case CardId.Halikarnassos_B_s3:
                        phase = GamePhase.Halikarnassos;
                        break;

                    case CardId.Bilkis:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.Bilkis);
                        break;

                    case CardId.Solomon:
                        phase = GamePhase.Solomon;
                        break;

                    case CardId.Rhodos_B_s1:
                        // Add the 3 coins immediately.  The 3 victory points will be included in total for wonders
                        // The Military will also need to be included in the shield calculation.
                        addTransaction(3);
                        break;

                    case CardId.Rhodos_B_s2:
                        addTransaction(4);
                        break;

                    case CardId.Roma_B_s1:
                        // Roma (B) stage 1: draw 4 more leaders from the pile of unused leaders
                        // to add to the players list of recruitable leaders
                        {
                            for (int i = 0; i < 4; i++)
                            {
                                Card c = gm.deckList[0].GetTopCard();
                                draftedLeaders.Add(c);
                            }

                            string strMsg = "LeadrIcn";

                            foreach (Card c in draftedLeaders)
                            {
                                strMsg += string.Format("&{0}=", c.Id);
                            }

                            gm.gmCoordinator.sendMessage(this, strMsg);

                            addTransaction(5);
                        }
                        break;

                    case CardId.Roma_B_s2:
                    case CardId.Roma_B_s3:

                        // the player needs to choose another leader from his leader d
                        phase = GamePhase.RomaB;
                        break;

                    case CardId.Courtesans_Guild:
                        phase = GamePhase.Courtesan;
                        break;

                    case CardId.Gambling_Den:
                        addTransaction(6);
                        rightNeighbour.addTransaction(1);
                        leftNeighbour.addTransaction(1);
                        break;

                    case CardId.Secret_Warehouse:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.SecretWarehouse);
                        break;

                    case CardId.Gambling_House:
                        addTransaction(9);
                        rightNeighbour.addTransaction(2);
                        leftNeighbour.addTransaction(2);
                        break;

                    case CardId.Black_Market:
                        if (!resourceMgr.GetCommerceEffect().HasFlag(ResourceManager.CommerceEffects.BlackMarket1))
                            resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.BlackMarket1);
                        else
                            resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.BlackMarket2);

                        break;

                    case CardId.Architect_Cabinet:
                        hasArchitectCabinet = true;
                        break;
                }
            }
            else if (effect is CommercialDiscountEffect)
            {
                switch (card.Id)
                {
                    case CardId.Marketplace:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.Marketplace);
                        break;

                    case CardId.Clandestine_Dock_West:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.ClandestineDockWest);
                        break;

                    case CardId.Clandestine_Dock_East:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.ClandestineDockEast);
                        break;

                    case CardId.West_Trading_Post:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.WestTradingPost);
                        break;

                    case CardId.East_Trading_Post:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.EastTradingPost);
                        break;

                    case CardId.Olympia_B_s1:
                        resourceMgr.AddCommerceEffect(ResourceManager.CommerceEffects.WestTradingPost | ResourceManager.CommerceEffects.EastTradingPost);
                        break;
                }
            }
            else if (effect is PlayACardForFreeOncePerAgeEffect)
            {
                throw new Exception("This ability needs to be dealt with on the end-of-turn action queue.");
            }
            else if (effect is LossOfCoinsEffect)
            {
                LossOfCoinsEffect loce = effect as LossOfCoinsEffect;

                Player p = rightNeighbour;

                while (p != this)
                {
                    switch(loce.lc)
                    {
                        case LossOfCoinsEffect.LossCounter.Constant:
                            p.addCoinLossTransaction(loce.coinsLost);
                            break;

                        case LossOfCoinsEffect.LossCounter.ConflictToken:
                            p.addCoinLossTransaction(p.conflictTokenOne + p.conflictTokenTwo + p.conflictTokenThree);
                            break;

                        case LossOfCoinsEffect.LossCounter.WonderStage:
                            p.addCoinLossTransaction(p.currentStageOfWonder - 1);
                            break;
                    }

                    p = p.rightNeighbour;
                }
            }
            else if (effect is DiplomacyEffect)
            {
                // Aspasia, Residence, Consulate, Embassy, Wonder stage on Byzantium & China B
                diplomacyEnabled = true;
            }
            else if (
                effect is ScienceWildEffect ||
                effect is ScienceEffect ||
                effect is MilitaryEffect ||
                effect is FreeLeadersEffect ||
                effect is StructureDiscountEffect ||
                effect is CopyScienceSymbolFromNeighborEffect)
            {
                // nothing to do; this card will be included in the end of game point total, or
                // - Military cards are used at the end of each age to resolve conflicts
                // - Science cards are used at the end of the game.
                // - Free Leaders effects are captured when the cards are put into play
            }
            else
            {
                throw new Exception("Unimplemented effect type");
            }
            // any other effects do not require immediate action, they will be dealt with at the end of the turn,
            // end of the age, or the end of the game.
        }
 /// <summary>
 /// Stored actions to be executed at the end of each turn
 /// </summary>
 /// <param name="s"></param>
 public void storeCardEffect(Card c)
 {
     if (c.effect is ResourceEffect || c.effect is CoinsAndPointsEffect || c.effect is PlayACardForFreeOncePerAgeEffect)
     {
         // the effects of these cards do not come into play until the next turn.
         // put them on the actions queue to be run after all players have turned
         // in their card.  Any actions that require UI updates must go on here
         // (e.g. enabling the Olympia button)
         actions.Add(c.effect);
     }
     else
     {
         // other actions
         executeActionNow(c);
     }
 }
 /// <summary>
 /// Add a card to the Player's played structure pile
 /// </summary>
 /// <param name="card"></param>
 public void addPlayedCardStructure(Card card)
 {
     playedStructure.Add(card);
     bUIRequiresUpdating = true;
 }
        /// <summary>
        /// Set the coordinator and handle CommerceInformation, which contains all necessary UI data, from GameManager
        /// </summary>
        public NewCommerce(Coordinator coordinator, Card cardToBuild, bool isWonderStage, /* List<Card> cardList, */ /*string cardName, int wonderStage,*/ NameValueCollection qscoll)
        {
            //intialise all the UI components in the xaml file (labels, etc.) to avoid null pointer
            InitializeComponent();

            this.coordinator = coordinator;

            leftName = "Left Neighbor";
            middleName = "Player";
            rightName = "Right Neighbor";

            this.cardToBuild = cardToBuild;
            this.isStage = isWonderStage;

            if (isStage)
            {
                string strWonderName = qscoll["WonderStageCard"];

                cardToBuild = coordinator.FindCard(strWonderName);
            }

            cardCost = cardToBuild.cost;

            string strLeaderDiscounts = qscoll["LeaderDiscountCards"];

            if (strLeaderDiscounts != string.Empty)
            {
                foreach (string strCardId in strLeaderDiscounts.Split(','))
                {
                    Card leaderDiscountCard = coordinator.FindCard(strCardId);

                    if (((StructureDiscountEffect)leaderDiscountCard.effect).discountedStructureType == cardToBuild.structureType)
                    {
                        leaderDiscountCardId = leaderDiscountCard.Id.ToString();
                    }
                }
            }

            leftRawMarket = qscoll["hasWestTradingPost"] != null;
            rightRawMarket = qscoll["hasEastTradingPost"] != null;
            marketplace = qscoll["hasMarketplace"] != null;
            leftDock = qscoll["hasClandestineDockWest"] != null;
            rightDock = qscoll["hasClandestineDockEast"] != null;
            hasSecretWarehouse = qscoll["hasSecretWarehouse"] != null;

            string strBlackMarkets = qscoll["nBlackMarket"];
            if (strBlackMarkets != null)
            {
                nBlackMarkets = int.Parse(strBlackMarkets);
            }
            else
            {
                nBlackMarkets = 0;
            }

            PLAYER_COIN = int.Parse(qscoll["coin"]);

            CreateDag(middleDag, qscoll["PlayerResources"]);
            CreateDag(leftDag, qscoll["LeftResources"]);
            CreateDag(rightDag, qscoll["RightResources"]);

            //set the name labels
            leftNameLabel.Content = leftName;
            middleNameLabel.Content = middleName;
            rightNameLabel.Content = rightName;

            //set the player's total coins
            playerCoinsLabel.Content = PLAYER_COIN;

            bankCoinsLabel.Content = cardCost.coin;

            //set the market images
            leftRawImage.Source = FindResource(leftRawMarket ? "1r" : "2r") as BitmapImage;
            rightRawImage.Source = FindResource(rightRawMarket ? "1r" : "2r") as BitmapImage;
            leftManuImage.Source = rightManuImage.Source = FindResource(marketplace ? "1m" : "2m") as BitmapImage;

            if (leftDock)
                clandestineDockWestImage.Source = FindResource("Icons/Clandestine_Dock_West") as BitmapImage;

            if (rightDock)
                clandestineDockEastImage.Source = FindResource("Icons/Clandestine_Dock_East") as BitmapImage;

            if (leaderDiscountCardId != null)
            {
                middleDag.add(new ResourceEffect(false, "WSBOCGP"));
            }

            if (nBlackMarkets != 0)
            {
                string strBlackMarketResources = "WSBOCGP";

                foreach (ResourceEffect re in middleDag.getResourceList(false))
                {
                    // The Black Market only excludes resources produced by this
                    // city's brown or grey structures, which only have 1 or 2 resource types
                    // So this excludes the Caravansery, Forum, and any Wonder stages.
                    if (re.resourceTypes.Length <= 2)
                    {
                        foreach (char c in re.resourceTypes)
                        {
                            int index = strBlackMarketResources.IndexOf(c);

                            if (index >= 0)
                                strBlackMarketResources = strBlackMarketResources.Remove(index, 1);
                        }
                    }
                }

                if (strBlackMarketResources != string.Empty)
                {
                    for (int i = 0; i < nBlackMarkets; i++)
                        middleDag.add(new ResourceEffect(false, strBlackMarketResources));
                }
            }

            hasBilkis = qscoll["Bilkis"] != null;

            if (hasBilkis)
            {
                imgBilkisPower.Visibility = Visibility.Visible;

                // Add Bilkis' choice
                middleDag.add(new ResourceEffect(false, "WSBOCGP"));
            }

            if (hasSecretWarehouse)
            {
                SecretWarehouseImage.Source = FindResource("Icons/Secret_Warehouse") as BitmapImage;
            }

            //generate mutable elements (DAG buttons, Price representations, currentResources, etc.)
            reset();
        }