Exemplo n.º 1
0
    public static CardTags GetCardTags(CardDescription cardDesc)
    {
        CardTags tags = GetCardTagsFromCardType(cardDesc.cardType);

        tags |= GetCardTagsFromManaCost(cardDesc.manaCost);
        switch (cardDesc.cardType)
        {
        case CardType.CREATURE:
            CreatureCardDescription creatureDesc = cardDesc as CreatureCardDescription;
            tags |= GetCardTagsFromCreatureType(creatureDesc.creatureType);
            foreach (KeywordAttribute keywords in creatureDesc.GetAttributes())
            {
                tags |= GetCardTagsFromKeywordAttributes(keywords);
            }

            break;

        case CardType.SPELL:
        case CardType.TRAP:
            foreach (CardEffectDescription effect in cardDesc.cardEffects)
            {
                if (effect.GetAlignment() == Alignment.POSITIVE)
                {
                    tags |= GetCardTagsFromTargetType(effect.targettingType);
                }
            }

            break;
        }
        return(tags);
    }
Exemplo n.º 2
0
    static private CardDescription GenerateCreatureCard(System.Random random, IHistogram model, ImageGlossary images, CreatureModelIndex creatureModels, NameModel nameModel, CardGenerationFlags flags)
    {
        CreatureCardDescription card = ScriptableObject.CreateInstance(typeof(CreatureCardDescription)) as CreatureCardDescription;

        card.creatureType = ProceduralUtils.GetRandomValue <CreatureType>(random, model);

        if ((flags & CardGenerationFlags.HUMAN) == CardGenerationFlags.HUMAN)
        {
            card.creatureType = CreatureType.HUMAN;
        }
        else if ((flags & CardGenerationFlags.GOBLIN) == CardGenerationFlags.GOBLIN)
        {
            card.creatureType = CreatureType.GOBLIN;
        }
        else if ((flags & CardGenerationFlags.FAERIE) == CardGenerationFlags.FAERIE)
        {
            card.creatureType = CreatureType.FAERIE;
        }

        MultiCardHistogram combinedModel = ScriptableObject.CreateInstance(typeof(MultiCardHistogram)) as MultiCardHistogram;

        combinedModel.Init(new IHistogram[] { model, creatureModels.GetModel(card.creatureType) });

        card.manaCost = (int)ProceduralUtils.GetRandomValue <ManaCost>(random, model);

        // Potentially generate a stronger body, but with a drawback
        double bodyManaCost = GetCreatureBodyBudget(creatureModels.GetBodyLambda(card.creatureType), random.Next(), card.manaCost + 1);
        int    maxStats     = PowerBudget.StatBudget(bodyManaCost);

        // Decide on stats
        card.health = GetHealth(random, creatureModels.GetStatProbability(card.creatureType, (int)Math.Round(bodyManaCost, MidpointRounding.AwayFromZero)), maxStats);
        card.attack = maxStats - card.health;

        // Decide on power budget
        double powerBudget = PowerBudget.ManaPowerBudgets[card.manaCost];
        double powerMargin = PowerBudget.ManaPowerMargin[card.manaCost];
        double powerLimit  = PowerBudget.ManaPowerLimit[card.manaCost];

        card.cardName = "A creature card";
        //card.name += "(" + powerBudget.ToString() + ")";

        // Decide on keyword attributes
        int maxKeywords = 3;

        for (int i = 0; i < maxKeywords; i++)
        {
            double keywordPowerLimit = powerLimit - card.PowerLevel();
            if (keywordPowerLimit < 0)
            {
                keywordPowerLimit = 0;
            }
            KeywordAttribute keyword = ProceduralUtils.GetRandomValue(random, combinedModel, ProceduralUtils.GetKeywordsWithinBudget(keywordPowerLimit, card.attack, card.health));
            if (keyword == KeywordAttribute.NONE)
            {
                break;
            }
            card.AddAttribute(keyword);
        }

        // Decide on effects
        GenerateCardEffects(random, combinedModel, creatureModels, card, powerBudget, powerMargin, powerLimit);

        // Revise the mana cost based on what effects we actually did generate
        int revisedMana = PowerBudget.PowerLevelToMana(card.PowerLevel());

        if (revisedMana != card.manaCost)
        {
            Debug.Log("Had to revise the mana cost from " + card.manaCost.ToString() + " to " + revisedMana.ToString());
            card.manaCost = revisedMana;
        }
        card.image = ProceduralUtils.GetRandomTexture(random, images.GetCreatureImages(card.creatureType));

        CardTags tags = CardTagging.GetCardTags(card);

        card.cardName = nameModel.GenerateName(random, tags);

        return(card);
    }
Exemplo n.º 3
0
    public static double GetTriggerModifier(TriggerCondition trigger, CardDescription card)
    {
        switch (trigger)
        {
        // Can happen repeatedly and can make decisions very difficult for opponent
        case TriggerCondition.ON_CREATURE_DIES:
            return((card is CreatureCardDescription) ? 2.5 : 1.0);

        // Should occur very frequently, and creature entering is very hard for opponent to play around
        // Entering is more threatening than dying
        case TriggerCondition.ON_CREATURE_ENTER:
            return((card is CreatureCardDescription) ? 3 : 1.0);

        // Worse than on enter, on self enter is like a spell so its the baseline for an effects strength
        case TriggerCondition.ON_SELF_DIES:
            return(0.9);

        // Very good on bodies with good offensive keywords
        case TriggerCondition.ON_SELF_DAMAGE_DEALT_TO_PLAYER:
        {
            CreatureCardDescription creatureCard = card as CreatureCardDescription;
            // Base is worse than a mostly guarenteed trigger like on dies
            // Gets better the easier it is to inflict player damage

            // Much weaker with a 0 power creature, because you require another card or effect to help
            double multiplier = (creatureCard.attack == 0) ? 0.25 : 0.5;
            if (creatureCard.HasKeywordAttribute(KeywordAttribute.EVASION))
            {
                // Evasion is the strongest offensive keyword
                multiplier += (creatureCard.attack == 0) ? 0.5 : 1;
            }
            if (creatureCard.HasKeywordAttribute(KeywordAttribute.PIERCING))
            {
                // Piercing depends on how good the body is, for now we'll say the average blocker has 4 toughness,
                // So you get the max effectiveness from piercing at 5 attack
                multiplier += 0.5 * Math.Min(5, creatureCard.attack) / 5;
            }
            if (creatureCard.HasKeywordAttribute(KeywordAttribute.FAST_STRIKE))
            {
                // Fast strike is less appealing to block with high power, like piercing but will not get damage through
                // a blocker only deter opponent from blocking so cap is smaller
                multiplier += 0.25 * Math.Min(5, creatureCard.attack) / 5;
            }
            if (creatureCard.HasKeywordAttribute(KeywordAttribute.EAGER))
            {
                // With eager the player can likely guarentee the effect at least once
                if (creatureCard.attack > 0)
                {
                    multiplier += 0.5;
                }
            }

            return(multiplier);
        }

        // Good with high health, also good with untouchable because the common way to beat it is through combat
        case TriggerCondition.ON_SELF_DAMAGE_TAKEN:
        {
            CreatureCardDescription creatureCard = card as CreatureCardDescription;
            // Assume average damage will come in 3s, but cap how strong the card effect multiplier is
            double multiplier = Math.Max(3.0, creatureCard.health / 3.0);
            if (!creatureCard.HasKeywordAttribute(KeywordAttribute.UNTOUCHABLE))
            {
                multiplier *= 0.75;
            }

            return(multiplier);
        }
        }

        return(1.0);
    }