コード例 #1
0
        public void loseCoins(Player player, int nCoins)
        {
            int nDebtTokens = 0;

            int c = player.coin - nCoins;

            if (c < 3)
            {
                nDebtTokens = player.coin - c;
            }

            player.takeDebtTokens(nDebtTokens);
        }
コード例 #2
0
        public void makeMove(Player p, GameManager gm)
        {
            // Build the first card in the hand that we can build.  If there
            // are no buildable cards, discard the first one.
            foreach (Card c in p.hand)
            {
                if (p.isCardBuildable(c) == Buildable.True)
                {
                    gm.playCard(p, c, BuildAction.BuildStructure, true);
                    return;
                }
            }

            gm.playCard(p, p.hand[0], BuildAction.Discard, true);
        }
コード例 #3
0
        public void makeMove(Player player, GameManager gm)
        {
            //go for blue cards whenever you can
            //if not, go for resources
            //otherwise, discard first card

            //look for buildable blue cards
            Card c = player.hand.Find(x => x.structureType == StructureType.Civilian && player.isCardBuildable(x) == Buildable.True);

            if (c != null)
            {
                gm.playCard(player, c, BuildAction.BuildStructure, true);
                return;
            }

            //look for buildable yellow cards that gives some resources
            c = player.hand.Find(x => x.structureType == StructureType.Commerce &&
                player.isCardBuildable(x) == Buildable.True &&
                x.effect is ResourceEffect);

            if (c != null)
            {
                gm.playCard(player, c, BuildAction.BuildStructure, true);
                return;
            }

            //look for buildable resource cards
            foreach(Card card in player.hand)
            {
                if ((card.structureType == StructureType.RawMaterial || card.structureType == StructureType.Goods) && player.isCardBuildable(card) == Buildable.True && card.effect is ResourceEffect)
                {
                    ResourceEffect e = card.effect as ResourceEffect;
                    char resource = e.resourceTypes[0];
                    int numOfResource = e.IsDoubleResource() ? 2 : 1;

                    if (resource == 'B' && numOfResource + player.brick < maxResourcesRequired ) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                    else if (resource == 'O' && numOfResource + player.ore < maxResourcesRequired) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                    else if (resource == 'T' && numOfResource + player.stone < maxResourcesRequired) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                    else if (resource == 'W' && numOfResource + player.wood < maxResourcesRequired) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                    else if (resource == 'G' && numOfResource + player.glass < maxResourcesRequired) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                    else if (resource == 'L' && numOfResource + player.loom < maxResourcesRequired) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                    else if (resource == 'P' && numOfResource + player.papyrus < maxResourcesRequired) { gm.playCard(player, card, BuildAction.BuildStructure, true); return; }
                }
            }

            //discard card[0]
            gm.playCard(player, player.hand[0], BuildAction.Discard, true);
        }
コード例 #4
0
 /// <summary>
 /// Set the neighbouring Players
 /// Used by GameManager.beginningOfSessionActions()
 /// </summary>
 /// <param name="left"></param>
 /// <param name="right"></param>
 public void setNeighbours(Player left, Player right)
 {
     leftNeighbour = left;
     rightNeighbour = right;
 }
コード例 #5
0
        public void makeMove(Player player, GameManager gm)
        {
            //go for blue cards only on the third age
            //if not, Discard Red Cards
            //otherwise, discard first card

            /*
            string strOutput = string.Format("{0} hand: [ ", player.nickname);

            if (gm.phase == GamePhase.LeaderRecruitment)
            {
                foreach (Card card in player.draftedLeaders)
                {
                    strOutput += card.Id;
                    strOutput += " ";
                }
            }
            else
            {
                foreach (Card card in player.hand)
                {
                    strOutput += card.Id;
                    strOutput += " ";
                }
            }

            strOutput += "]";

            logger.Info(strOutput);
            */

            if (gm.phase == GamePhase.LeaderDraft || gm.phase == GamePhase.LeaderRecruitment)
            {
                // int[] favouredLeaders = { 216, 220, 222, 232, 200, 208, 205, 221, 214, 236, 213 };
                CardId [] favouredLeaders = { CardId.Nero, CardId.Tomyris, CardId.Alexander, CardId.Hannibal, CardId.Caesar, CardId.Nefertiti, CardId.Cleopatra, CardId.Zenobia, CardId.Justinian };

                Card bestLeader = null;

                //try to find the highest rated card in hand
                //start looking for the highest rated card, then go down to the next highest, etc.
                foreach (CardId leaderName in favouredLeaders)
                {
                    if (gm.phase == GamePhase.LeaderDraft)
                    {
                        bestLeader = player.hand.Find(x => x.Id == leaderName);
                    }
                    else if (gm.phase == GamePhase.LeaderRecruitment)
                    {
                        bestLeader = player.draftedLeaders.Find(x => x.Id == leaderName);
                    }

                    if (bestLeader != null && player.isCardBuildable(bestLeader).buildable == CommerceOptions.Buildable.True)
                    {
                        break;
                    }
                }

                if (bestLeader == null && gm.phase == GamePhase.LeaderDraft)
                {
                    // this hand didn't contain a favoured leader, so draft the first one in the list.  We cannot
                    // discard during the draft.  Leaders may only be discarded for 3 coins during recruitment.
                    bestLeader = player.hand[0];
                }

                if (bestLeader != null)
                {
                    logger.Info(player.nickname + "Drafted leader: {0}", bestLeader.Id);
                    gm.playCard(player, bestLeader, BuildAction.BuildStructure, true, false, 0, 0, false);
                }
                else
                {
                    logger.Info(player.nickname + " Action: Discard {0}", player.draftedLeaders[0].Id);
                    gm.playCard(player, player.draftedLeaders[0], BuildAction.Discard, true, false, 0, 0, false);
                }

                return;
            }

            // Dictionary<Card, CardCost> cardValues = new Dictionary<Card, CardCost>(player.hand.Count);

            // Card cost:

            // NotBuildable
            // Free (the city has sufficient resources)
            // Coin cost to the bank only (flex brown, double, some City cards)
            // Commerce Required (can be constructed by paying neighbors for their resources)
            // If Commerce is required, how many coins to each neighbor and/or the bank

            CommerceOptions[] co = new CommerceOptions[player.hand.Count];
            int [] cardValues = new int[player.hand.Count];

            for (int i = 0; i < player.hand.Count; ++i)
            {
                co[i] = player.isCardBuildable(player.hand[i]);
            }

            CommerceOptions nextStageCost = player.isStageBuildable();

            for (int i = 0; i < player.hand.Count; ++i)
            {
                Card card = player.hand[i];

                if (co[i].buildable == CommerceOptions.Buildable.True || co[i].buildable == CommerceOptions.Buildable.CommerceRequired)
                {
                    switch (card.structureType)
                    {
                        case StructureType.RawMaterial:
                            {
                                ResourceEffect re = card.effect as ResourceEffect;
                                if (re.resourceTypes.Length == 2)
                                {
                                    if (re.resourceTypes[0] == re.resourceTypes[1])
                                    {
                                        // doubles can be useful, but we need to examine whether we
                                        // already have enough of them.
                                        cardValues[i] = 50;
                                    }
                                    else
                                    {
                                        // Flex resources should almost always be taken
                                        cardValues[i] = 80;
                                    }
                                }
                                else
                                {
                                    // single-resource browns are fairly useless.
                                    cardValues[i] = 25;
                                }
                            }
                            break;

                        case StructureType.Goods:
                            {
                                ResourceEffect res = card.effect as ResourceEffect;

                                cardValues[i] = 45;

                                if (player.leftNeighbour.resourceMgr.getResourceList(false).Contains(res) ||
                                    player.rightNeighbour.resourceMgr.getResourceList(false).Contains(res))
                                {
                                    // Yes: drop its value significantly and even more if we have a Marketplace too.
                                    cardValues[i] = player.resourceMgr.GetCommerceEffect().HasFlag(ResourceManager.CommerceEffects.Marketplace) ? 6 : 24;
                                }
                                else
                                {
                                    if (gm.currentAge == 2)
                                    {
                                        if (gm.currentTurn > 5)
                                            cardValues[i] = 90;
                                        else if (gm.currentTurn > 2)
                                            cardValues[i] = 65;
                                    }
                                    else
                                    {
                                        if (gm.currentTurn > 4)
                                        {
                                            cardValues[i] = 55;
                                        }
                                    }

                                    if (player.resourceMgr.GetCommerceEffect().HasFlag(ResourceManager.CommerceEffects.Marketplace) && gm.currentTurn < 5)
                                    {
                                        cardValues[i] /= 2;
                                    }
                                }
                            }
                            break;

                        case StructureType.Civilian:
                            cardValues[i] = ((card.effect as CoinsAndPointsEffect).victoryPointsAtEndOfGameMultiplier - (2 - gm.currentAge)) * 10;
                            break;

                        case StructureType.Commerce:
                            switch (card.Id)
                            {
                                case CardId.Tavern:
                                    cardValues[i] = 30 - (player.coin * 10);
                                    break;

                                case CardId.West_Trading_Post:
                                    {
                                        List<ResourceEffect> leftResources = player.leftNeighbour.resourceMgr.getResourceList(false);
                                        int nLeftResources = 0;
                                        foreach (ResourceEffect re in leftResources)
                                        {
                                            if (!re.IsManufacturedGood())
                                                nLeftResources += re.resourceTypes.Length;
                                        }

                                        cardValues[i] = (nLeftResources - gm.currentTurn + 6) * 10;
                                    }
                                    break;

                                case CardId.East_Trading_Post:
                                    {
                                        List<ResourceEffect> rightResources = player.rightNeighbour.resourceMgr.getResourceList(false);
                                        int nRightResources = 0;
                                        foreach (ResourceEffect re in rightResources)
                                        {
                                            if (!(re.IsManufacturedGood()))
                                                nRightResources += re.resourceTypes.Length;
                                        }

                                        cardValues[i] = (nRightResources - gm.currentTurn + 6) * 10;
                                    }
                                    break;

                                case CardId.Marketplace:
                                    {
                                        string strGoodsNeighbors = "PCG";

                                        List<ResourceEffect> leftResources = player.leftNeighbour.resourceMgr.getResourceList(false);
                                        foreach (ResourceEffect re in leftResources)
                                        {
                                            int resIndex = strGoodsNeighbors.IndexOf(re.resourceTypes[0]);

                                            if (resIndex != -1) strGoodsNeighbors = strGoodsNeighbors.Substring(resIndex, 1);
                                        }

                                        List<ResourceEffect> rightResources = player.rightNeighbour.resourceMgr.getResourceList(false);
                                        foreach (ResourceEffect re in rightResources)
                                        {
                                            int resIndex = strGoodsNeighbors.IndexOf(re.resourceTypes[0]);

                                            if (resIndex != -1) strGoodsNeighbors = strGoodsNeighbors.Substring(resIndex, 1);
                                        }

                                        int nMyCityGoods = player.resourceMgr.getResourceList(true).FindAll(x => x.IsManufacturedGood()).Count;

                                        // for each available grey card in neighboring cities, add 20 points,
                                        // and subtract 30 points for each grey card in our city.
                                        cardValues[i] = 40 + ((3 - strGoodsNeighbors.Length) * 20) - nMyCityGoods * 30;
                                    }

                                    break;

                                case CardId.Caravansery:
                                    // This one is pretty much automatic: if it's there, take it.
                                    cardValues[i] = 90;
                                    break;

                                case CardId.Forum:
                                    cardValues[i] = 35;
                                    break;
                            }

                            break;

                        case StructureType.Military:
                            {
                                int nShieldsLeft = player.leftNeighbour.shield;
                                int nShieldsRight = player.leftNeighbour.shield;
                                int myShields = player.shield;
                                int nShields = (card.effect as MilitaryEffect).nShields;

                                if (myShields > (nShieldsRight + nShields) && myShields > (nShieldsLeft + nShields))
                                {
                                    // our city has more military strength than our neighbors and adding more won't gain us any more points
                                    cardValues[i] = 10;
                                }
                                else if (myShields > nShieldsRight && myShields > nShieldsLeft)
                                {
                                    // Our city's military strength is stronger than both of our neighbors but if one of them plays military and
                                    // we don't, we'll be tied or losing against them.
                                    cardValues[i] = 20;
                                }
                                else if (((myShields + nShields) <= nShieldsRight) && ((myShields + nShields) <= nShieldsLeft))
                                {
                                    // Even if we played this card, we would still have fewer shields than our neighbors.  We are so far behind
                                    // in military it's probably not worth playing any military.
                                    cardValues[i] = 5;
                                }
                                else if (((myShields + nShields) > nShieldsRight) && ((myShields + nShields) > nShieldsLeft))
                                {
                                    // If we play this card, we'll go from losing against both neighbors to winning.
                                    cardValues[i] = 75;
                                }
                                else if (((myShields + nShields) > nShieldsRight) || ((myShields + nShields) > nShieldsLeft))
                                {
                                    // If we play this card, we'll go from losing against one neighbor to winning
                                    cardValues[i] = 60;
                                }
                                else
                                {
                                    // can we logically ever get here?
                                    throw new NotImplementedException();
                                }
                            }
                            break;

                        case StructureType.Science:
                            cardValues[i] = 65;
                            // calculate the value of this card, and consider whether we are going for sets (1, 2, 3) or symbols
                            break;

                        case StructureType.Guild:
                            // calculate the value of this card.
                            if (card.effect is CoinsAndPointsEffect)
                            {
                                // most guilds fall into this category: they count points based on something the neighboring cities.
                                cardValues[i] = player.CountVictoryPoints(card.effect as CoinsAndPointsEffect) * 10;

                                CoinsAndPointsEffect cpe = card.effect as CoinsAndPointsEffect;

                                // account for the possibility that the neighboring cities will play more of these structures
                                // during the 3rd age and thus increase the value of these guild cards.
                                switch (cpe.classConsidered)
                                {
                                    case StructureType.RawMaterial:
                                        // there are no Raw Materials cards available in the 3rd age.
                                        break;

                                    case StructureType.Goods:
                                        // there are no Goods cards available in the 3rd age.
                                        break;

                                    case StructureType.Civilian:
                                    case StructureType.Commerce:
                                        cardValues[i] += (gm.nTurnsInEachAge - gm.currentTurn) * 2;
                                        break;

                                    case StructureType.Military:
                                    case StructureType.Science:
                                        cardValues[i] += ((gm.nTurnsInEachAge - gm.currentTurn) * (cardValues[i] / 20));
                                        break;

                                    case StructureType.Guild:
                                        cardValues[i] += (gm.nTurnsInEachAge - gm.currentTurn);
                                        break;

                                    case StructureType.WonderStage:
                                        // for the Builder's Guild, we'll assume a high probability of all wonder stages getting built.
                                        cardValues[i] += (((player.playerBoard.numOfStages + player.leftNeighbour.playerBoard.numOfStages + player.rightNeighbour.playerBoard.numOfStages) * 10) - cardValues[i])/2;
                                        break;

                                    case StructureType.MilitaryLosses:
                                    case StructureType.ConflictToken:
                                        // Not sure what to do here.  I guess look at their shield strength.
                                        break;

                                    case StructureType.ThreeCoins:
                                        // would be better to consider other factors too, such as ours and our neighbors' resource availability
                                        // (i.e. how much we'll pay out and how much they are likely to pay us for the rest of the age).
                                        cardValues[i] += (gm.nTurnsInEachAge - gm.currentTurn) * 3;
                                        break;
                                }
                            }
                            else if (card.Id == CardId.Shipowners_Guild)
                            {
                                // Shipowners guild counts 1 point for each RawMaterial, Goods, and Guild structure in the players' city.
                                cardValues[i] = player.playedStructure.Where(x => x.structureType == StructureType.RawMaterial || x.structureType == StructureType.Goods || x.structureType == StructureType.Guild).Count() * 10;
                            }
                            else if (card.Id == CardId.Counterfeiters_Guild)
                            {
                                // Add 1 because all other players has to lose 3 coins which is the same as 1 VP.
                                // Possible TODO: adjust the value based on whether players who are close in VP to this player
                                // have many or few coins in their treasury.  Loss of coins cards hurt players with few
                                // coins more than players with many.  This card could cause an opponent to lose up to 3 VP
                                // if they have to take 3 debt tokens, which makes it more valuable to us.  Also, we could
                                // consider the effect of another player playing this card on our own treasury.
                                cardValues[i] = ((card.effect as LossOfCoinsEffect).victoryPoints + 1) * 10;
                            }
                            else if (card.Id == CardId.Scientists_Guild)
                            {
                                throw new NotImplementedException();
                            }
                            else
                            {
                                throw new NotImplementedException();
                            }
                            break;

                        case StructureType.City:
                            break;
                    }
                }
            }

            int bestCardValue = 0;
            int bestCardIndex = -1;

            for (int i = 0; i < player.hand.Count; ++i)
            {
                if (cardValues[i] > bestCardValue)
                {
                    bestCardValue = cardValues[i];
                    bestCardIndex = i;
                }
                else if (cardValues[i] == bestCardValue)
                {
                    // two cards are of equal value.  We need to consider secondary factors
                }
            }

            Card c = null;

            if (bestCardIndex != -1)
                c = player.hand[bestCardIndex];

            // go through the total value of this hand and select the best card

            #if FALSE
            /*
            foreach (Card crd in player.hand)
            {
                player.GetCost(crd);
            }
            */
            // Build Guild cards in the 3rd age (except for the Courtesan's Guild, which requires entering a special Game Phase
            // that the AI has not been programmed to think about.
            Card c = player.hand.Find(x => x.structureType == StructureType.Guild && x.Id != CardId.Courtesans_Guild && player.isCardBuildable(x).buildable == CommerceOptions.Buildable.True);

            if (c == null)
            {
                //look for buildable blue cards at the third age ..
                c = player.hand.Find(x => x.structureType == StructureType.Civilian && player.isCardBuildable(x).buildable == CommerceOptions.Buildable.True && x.age == 3);
            }

            if (c == null)
            {
                //look for buildable green cards
                c = player.hand.Find(x => x.structureType == StructureType.Science && player.isCardBuildable(x).buildable == CommerceOptions.Buildable.True);
            }

            if (c == null)
            {
                //look for buildable resource cards that give more than one manufactory resources ...
                foreach (Card card in player.hand)
                {
                    if ((card.structureType == StructureType.Commerce && player.isCardBuildable(card).buildable == CommerceOptions.Buildable.True) && card.effect is ResourceEffect)
                    {
                        // char resource = player.hand[i].effect[2];        // hunh?
                        string resource = ((ResourceEffect)card.effect).resourceTypes;

                        if (resource.Length < 3)
                            continue;

                        if (resource.Contains("C") && player.loom < maxLPG * 2) { c = card; }
                        else if (resource.Contains("P") && player.papyrus < maxLPG * 2) { c = card; }
                        else if (resource.Contains("G") && player.glass < maxLPG * 2) { c = card; }

                        // not sure what's going on here.  I think there may have been a bug in the original implementation.
                    }
                }
            }

            if (c == null)
            {
                //look for buildable resource cards that give more than one resource ...
                foreach (Card card in player.hand)
                {
                    if ((card.structureType == StructureType.RawMaterial && player.isCardBuildable(card).buildable == CommerceOptions.Buildable.True) && card.effect is ResourceEffect)
                    {
                        string resource = ((ResourceEffect)card.effect).resourceTypes;

                        if (player.brick < maxOBW && resource.Contains('B') ) { c = card; }
                        else if (player.ore < maxOBW && resource.Contains('O') ) { c = card; }
                        else if (player.stone < maxStone && resource.Contains('S') ) { c = card; }
                        else if (player.wood < maxOBW && resource.Contains('W') ) { c = card; }
                    }
                }
            }

            if (c == null)
            {
                //look for buildable resource cards that only give one and the manufactory resources ..
                foreach (Card card in player.hand)
                {
                    if ((card.structureType == StructureType.RawMaterial || card.structureType == StructureType.Goods) && player.isCardBuildable(card).buildable == CommerceOptions.Buildable.True && card.effect is ResourceEffect)
                    {
                        ResourceEffect e = card.effect as ResourceEffect;

                        char resource = e.resourceTypes[0];
                        int numOfResource = e.IsDoubleResource() ? 2 : 1;

                        if (resource == 'C' && player.loom < maxLPG) { c = card; }
                        else if (resource == 'G' && player.glass < maxLPG) { c = card; }
                        else if (resource == 'P' && player.papyrus < maxLPG) { c = card; }
                        else if (resource == 'B' && numOfResource + player.brick < maxOBW) { c = card; }
                        else if (resource == 'O' && numOfResource + player.ore < maxOBW) { c = card; }
                        else if (resource == 'S' && numOfResource + player.stone < maxStone) { c = card; }
                        else if (resource == 'W' && numOfResource + player.wood < maxOBW) { c = card; }
                    }
                }
            }

            if (c == null)
            {
                //look for buildable Red cards
                c = player.hand.Find(x => x.structureType == StructureType.Military && player.isCardBuildable(x).buildable == CommerceOptions.Buildable.True);
            }

            if (c == null)
            {
                // play a city card, if there is one
                List<Card> cityCardList = player.hand.FindAll(x => x.structureType == StructureType.City && player.isCardBuildable(x).buildable == CommerceOptions.Buildable.True);

                if (cityCardList.Count > 0)
                {
                    // Try to find a card that causes other players to lose cards
                    c = cityCardList.Find(x => x.effect is LossOfCoinsEffect);

                    if (c == null)
                    {
                        c = cityCardList.Find(x => x.effect is CopyScienceSymbolFromNeighborEffect);
                    }

                    if (c == null)
                    {
                        c = cityCardList.Find(x => x.effect is MilitaryEffect);
                    }

                    if (c == null)
                    {
                        c = cityCardList.Find(x => x.effect is DiplomacyEffect);
                    }

                    if (c == null)
                    {
                        // play a point-scoring card.
                        c = cityCardList.Find(x => x.effect is CoinsAndPointsEffect);
                    }

                    // if none of the above criteria match, it means this card is has a commerce special effect,
                    // such as the Secret Warehouse, Black Market, Clandestine Dock, or Architect Cabinet, which
                    // this AI has not been programmed to think about.  So in that case, just play the first
                    // card in the list of playable city cards.
                    c = cityCardList[0];
                }
            }

            #endif

            if (c == null)
            {
                //Discard the non-buildable Red cards
                foreach (Card card in player.hand)
                {
                    if (card.structureType == StructureType.Military && player.isCardBuildable(card).buildable != CommerceOptions.Buildable.True)
                    {
                        logger.Info(player.nickname + " Action: Discard {0}", card.Id);
                        gm.playCard(player, card, BuildAction.Discard, true, false, 0, 0, false);
                        return;
                    }
                }
            }

            if (c != null)
            {
                logger.Info(player.nickname + " Action: Construct {0}", c.Id);
                gm.playCard(player, c, BuildAction.BuildStructure, true, false, co[bestCardIndex].leftCoins, co[bestCardIndex].rightCoins, false);
            }
            else
            {
                // If a card is not found that matches any of the above criteria, discard the first card listed.
                c = player.hand[0];
                logger.Info(player.nickname + " Action: Discard {0}", c.Id);
                gm.playCard(player, c, BuildAction.Discard, true, false, 0, 0, false);
            }
        }
コード例 #6
0
 public void makeMove(Player player, GameManager gm)
 {
     gm.playCard(player, player.hand[0], BuildAction.Discard, true);
 }
コード例 #7
0
        public void makeMove(Player player, GameManager gm)
        {
            //go for Red cards whenever you can
            //if not, Discard Red Cards
            //otherwise, discard first card

            string strOutput = string.Format("{0} hand: [ ", player.nickname);

            foreach (Card card in player.hand)
            {
                strOutput += card.Id;
                strOutput += " ";
            }

            strOutput += "]";

            //look for buildable Red cards
            Card c = player.hand.Find(x => x.structureType == StructureType.Military && player.isCardBuildable(x) == Buildable.True);

            if (c == null)
            {
                //look for buildable resource cards that give more than one resource ...
                foreach (Card card in player.hand)
                {
                    if ((card.structureType == StructureType.RawMaterial || card.structureType == StructureType.Goods) && player.isCardBuildable(card) == Buildable.True && card.effect is ResourceEffect)
                    {
                        string resource = ((ResourceEffect)card.effect).resourceTypes;

                        if (resource.Length < 3)
                            continue;

                        if (resource.Contains('B') && player.brick < maxOBS) { c = card; return; }
                        else if (resource.Contains('O') && player.ore < maxOBS) { c = card; return; }
                        else if (resource.Contains('S') && player.stone < maxOBS) { c = card; return; }
                        else if (resource.Contains('W') && player.wood < maxWood) { c = card; return; }
                        else if (resource.Contains('L') && player.loom < maxLoom) { c = card; return; }
                    }
                }
            }

            if (c == null)
            {
                //look for buildable resource cards that only give one ..
                foreach (Card card in player.hand)
                {
                    if ((card.structureType == StructureType.RawMaterial || card.structureType == StructureType.Goods) && player.isCardBuildable(card) == Buildable.True && card.effect is ResourceEffect)
                    {
                        ResourceEffect e = card.effect as ResourceEffect;

                        char resource = e.resourceTypes[0];
                        int numOfResource = e.IsDoubleResource() ? 2 : 1;

                        if (resource == 'B' && numOfResource + player.brick < maxOBS) { c = card; return; }
                        else if (resource == 'O' && numOfResource + player.ore < maxOBS) { c = card; return; }
                        else if (resource == 'S' && numOfResource + player.stone < maxOBS) { c = card; return; }
                        else if (resource == 'W' && numOfResource + player.wood < maxWood) { c = card; return; }
                        else if (resource == 'L' && numOfResource + player.loom < maxLoom) { c = card; return; }
                    }
                }
            }

            if (c == null)
            {
                //Discard the non-buildable Red cards
                foreach (Card card in player.hand)
                {
                    if (card.structureType == StructureType.Military && player.isCardBuildable(card) != Buildable.True)
                    {
                        Console.WriteLine(player.nickname + " Action: Discard {0}", card.Id);
                        gm.playCard(player, card, BuildAction.Discard, true);
                        return;
                    }
                }
            }

            if (c != null)
            {
                Console.WriteLine(player.nickname + " Action: Construct {0}", c.Id);
                gm.playCard(player, c, BuildAction.BuildStructure, true);
            }
            else
            {
                c = player.hand[0];
                Console.WriteLine(player.nickname + " Action: Discard {0}", c.Id);
                gm.playCard(player, c, BuildAction.Discard, true);
            }
        }