Beispiel #1
0
        public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            double dueDateDesire = Desire / (Tier + 1);
            if (DueDate != null)
            {
                if (DueDate == 0)
                {
                    log.Add("Not enough time to invent spell");
                    return;
                }
                dueDateDesire /= (double)DueDate;
            }
            if (dueDateDesire > 0.01)
            {
                if (!_labScoreGoal.IsComplete(character))
                {
                    _labScoreGoal.ModifyActionList(character, alreadyConsidered, log);
                }
                else
                {
                    double level = _spell.Level;
                    // Now we need to consider both the value of starting to invent the spell now
                    // and the value of instead learning more before doing so.
                    // As a first pass, value the portion of the spell inventable this season
                    Magus mage = (Magus)character;
                    double extraTotal = mage.GetLabTotal(_spell.BaseArts, Activity.InventSpells) - level;
                    if (extraTotal <= 0)
                    {
                        // This should not happen
                        _labScoreGoal.ModifyActionList(character, alreadyConsidered, log);
                    }
                    if (extraTotal >= level)
                    {
                        // there's no reason to consider adding to abilities for this spell
                        // TODO: eventually, we should consider the fact that the extra learning
                        // could allow one to learn more spells in a season
                        log.Add("Inventing this spell worth " + dueDateDesire.ToString("0.00"));
                        alreadyConsidered.Add(new InventSpell(_spell, Abilities.MagicTheory, dueDateDesire));
                    }
                    else
                    {
                        // we are in the multi-season-to-invent scenario
                        dueDateDesire = extraTotal * dueDateDesire / level;
                        alreadyConsidered.Add(new InventSpell(_spell, Abilities.MagicTheory, dueDateDesire));

                        // the difference between the desire of starting now
                        // and the desire of starting after practice
                        // is the effective value of practicing here
                        IncreaseLabTotalVersusEffectLevelHelper helper = new IncreaseLabTotalVersusEffectLevelHelper(_spell.BaseArts, dueDateDesire, extraTotal, level, (byte)(Tier + 1));
                        helper.ModifyActionList(character, alreadyConsidered, log);
                    }
                }
            }
        }
Beispiel #2
0
 public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
 {
     double dueDateDesire = Desire / (Tier + 1);
     if (DueDate != null)
     {
         if (DueDate == 0)
         {
             log.Add("Not enough time to build lab");
             return;
         }
         dueDateDesire /= (double)DueDate;
     }
     if (dueDateDesire > 0.01)
     {
         bool hasCovenant = _hasCovenant.IsComplete(character);
         bool hasMT = _mtCondition.IsComplete(character);
         if (!hasCovenant)
         {
             _hasCovenant.ModifyActionList(character, alreadyConsidered, log);
         }
         if (!hasMT)
         {
             _mtCondition.ModifyActionList(character, alreadyConsidered, log);
         }
         if (hasCovenant && hasMT)
         {
             log.Add("Setting up a lab worth " + (dueDateDesire).ToString("0.00"));
             alreadyConsidered.Add(new BuildLaboratory(Abilities.MagicTheory, dueDateDesire));
         }
     }
 }
Beispiel #3
0
 public abstract void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log);
Beispiel #4
0
        public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            bool isReady = true;
            foreach (AbilityScoreCondition condition in _artRequirements)
            {
                if (!condition.IsComplete(character))
                {
                    isReady = false;
                    condition.ModifyActionList(character, alreadyConsidered, log);
                }
            }
            if (isReady)
            {
                double desire = Desire / (Tier + 1);
                if(DueDate != null)
                {
                    if (DueDate == 0)
                    {
                        log.Add("Not enough time to find an apprentice");
                        return;
                    }
                    desire /= (double)DueDate;
                }

                alreadyConsidered.Add(new FindApprentice(MagicArts.Intellego, desire));
            }
        }
Beispiel #5
0
        public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            double dueDateDesire = Desire / (Tier + 1);
            if (DueDate != null)
            {
                if (DueDate == 0)
                {
                    log.Add("Has Covenant Condition failed");
                    return;
                }
                dueDateDesire /= (double)DueDate;
            }

            if (!_minScore.IsComplete(character) && dueDateDesire > 0.01)
            {
                _minScore.ModifyActionList(character, alreadyConsidered, log);
            }
        }
Beispiel #6
0
        public override void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            base.ModifyActionList(character, alreadyConsidered, log);
            // TODO: consider Cr Co/Me spells that increase statistics
            foreach (AttributeType attribute in _attributes)
            {
                double currentAttribute = character.GetAttribute(attribute).Value;
                if (currentAttribute < 5)
                {
                    ArtPair artPair;
                    if (attribute == AttributeType.Dexterity || attribute == AttributeType.Quickness ||
                        attribute == AttributeType.Stamina || attribute == AttributeType.Strength)
                    {
                        artPair = MagicArtPairs.CrCo;
                    }
                    else
                    {
                        artPair = MagicArtPairs.CrMe;
                    }

                    double total = 30;
                    if (currentAttribute > 0)
                    {
                        total = 35;
                    }
                    if (currentAttribute > 1)
                    {
                        total = 40;
                    }
                    if (currentAttribute > 2)
                    {
                        total = 45;
                    }
                    if (currentAttribute > 3)
                    {
                        total = 50;
                    }
                    if (currentAttribute > 4)
                    {
                        total = 55;
                    }
                    // TODO: see if the mage already knows a ritual of sufficient strength
                    // If not, consider the value of such a ritual
                }
            }
        }
Beispiel #7
0
 public override void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
 {
     double dueDateDesire = Desire / (Tier + 1);
     if (DueDate != null && DueDate > 0)
     {
         dueDateDesire /= (double)DueDate;
     }
     alreadyConsidered.Add(new GauntletApprentice(Abilities.MagicTheory, dueDateDesire));
 }
Beispiel #8
0
 private void AddReading(Character character, ConsideredActions alreadyConsidered, IEnumerable<IBook> topicalBooks, double remainingTotal, double desire)
 {
     if (topicalBooks.Any())
     {
         var bestBook =
             (from book in topicalBooks
              orderby character.GetBookLevelGain(book),
                      book.Level ascending
              select new EvaluatedBook
              {
                  Book = book,
                  PerceivedValue = character.GetBookLevelGain(book) * desire / remainingTotal
              }).First();
         // check to see if reading this book is already in the action list
         Reading readingAction = new Reading(bestBook.Book, bestBook.PerceivedValue);
         alreadyConsidered.Add(readingAction);
     }
 }
Beispiel #9
0
        private void HandleVisUse(Magus mage, CharacterAbilityBase charAbility, double remainingTotal, double desire, ConsideredActions alreadyConsidered, IList<string> log )
        {
            // see if the mage has enough vis of this type
            double stockpile = mage.GetVisCount(charAbility.Ability);
            double visNeed = 0.5 + (charAbility.Value / 10.0);
            double baseDesire = desire * charAbility.GetValueGain(mage.VisStudyRate) / remainingTotal;
            // if so, assume vis will return an average of 6XP + aura
            if (stockpile > visNeed)
            {
                log.Add("Studying vis for " + charAbility.Ability.AbilityName + " worth " + baseDesire.ToString("0.00"));
                VisStudying visStudy = new VisStudying(charAbility.Ability, baseDesire);
                alreadyConsidered.Add(visStudy);
                // TODO: how do we decrement the cost of the vis?
            }
            else if(baseDesire > 0.01 && (DueDate == null || DueDate > 1))
            {
                // only try to extract the vis now if there's sufficient time to do so
                List<Ability> visType = new List<Ability>();
                visType.Add(charAbility.Ability);
                VisCondition visCondition = new VisCondition(visType, visNeed - stockpile, baseDesire, (byte)(Tier + 1), DueDate == null ? null : DueDate - 1);
                visCondition.ModifyActionList(mage, alreadyConsidered, log);
                if(baseDesire > 0.04 && (DueDate == null || DueDate > 4))
                {
                    // we have enough time and interest to consider finding a new aura and building a new lab in it

                }
            }
        }
Beispiel #10
0
        public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            double dueDateDesire = Desire / (Tier + 1);
            if (DueDate != null)
            {
                if (DueDate == 0)
                {
                    log.Add("Vis Goal Failed");
                    return;
                }
                dueDateDesire /= (double)DueDate;
            }
            if (dueDateDesire > 0.01)
            {
                Magus mage = (Magus)character;
                bool hasLab = _hasLab.IsComplete(character);

                if (_isVimSufficient)
                {
                    // determine value of extracting vis from aura

                    if (!hasLab)
                    {
                        // if we don't have a lab, we need a lab
                        _hasLab.ModifyActionList(character, alreadyConsidered, log);
                    }
                    else
                    {
                        // Now we need to consider both the value of starting to distill vis now
                        // and the value of instead learning more before doing so.
                        double labTotal = mage.GetLabTotal(MagicArtPairs.CrVi, Activity.DistillVis);
                        double currentRate = labTotal / 10;
                        if (currentRate >= _total)
                        {
                            // we can get what we want in one season, go ahead and do it
                            log.Add("Extracting vis worth " + (dueDateDesire).ToString("0.00"));
                            alreadyConsidered.Add(new VisExtracting(Abilities.MagicTheory, dueDateDesire));
                        }
                        else
                        {
                            // we are in the multi-season-to-fulfill scenario
                            double desire = currentRate * dueDateDesire / _total;
                            log.Add("Extracting vis worth " + (desire).ToString("0.00"));
                            alreadyConsidered.Add(new VisExtracting(Abilities.MagicTheory, desire));

                            // the difference between the desire of starting now
                            // and the desire of starting after gaining experience
                            // is the effective value of practicing here

                            // TODO: this should really be a lab total increse, yes?
                            IncreaseAbilitiesForVisHelper helper = new IncreaseAbilitiesForVisHelper(_extractAbilities, Desire, labTotal, (byte)(Tier + 1), DueDate - 1);
                            helper.ModifyActionList(character, alreadyConsidered, log);
                        }
                    }
                }
                // determine current rate of automatic accrual of vis of the desired type
                double annualGain =
                    mage.KnownAuras.SelectMany(a => a.VisSources).Where(v => _visTypes.Contains(v.Art)).Select(v => v.AnnualAmount).Sum();
                if (annualGain == 0 || (DueDate != null && (annualGain * DueDate / 4) < _total))
                {
                    List<Ability> visSearchAbilities = new List<Ability>();
                    visSearchAbilities.Add(Abilities.MagicLore);
                    visSearchAbilities.Add(MagicArts.Intellego);
                    visSearchAbilities.Add(MagicArts.Vim);
                    // we're not getting vis fast enough, so we need to find a new source
                    // consider the value of searching for new vis sites in current auras
                    // determine average vis source found
                    double magicLore = mage.GetAbility(Abilities.MagicLore).Value;
                    magicLore += mage.GetAttribute(AttributeType.Perception).Value;
                    magicLore += mage.GetCastingTotal(MagicArtPairs.InVi) / 5;
                    if (magicLore > 0)
                    {
                        foreach (Aura aura in mage.KnownAuras)
                        {
                            double averageFind = aura.GetAverageVisSourceSize(magicLore);
                            if (averageFind > 0)
                            {
                                // modify by chance vis will be of the proper type
                                double desire = (averageFind * _visTypes.Count() / 15);

                                // TODO: modify by lifelong value of source?
                                log.Add("Looking for vis source worth " + (desire * dueDateDesire).ToString("0.00"));
                                alreadyConsidered.Add(new FindVisSource(aura, Abilities.MagicLore, desire * dueDateDesire));
                            }
                            // consider the value of getting better at the vis search skills first
                            double currentVis = aura.VisSources.Select(v => v.AnnualAmount).Sum();
                            IncreaseAbilitiesForVisSearchHelper helper =
                                new IncreaseAbilitiesForVisSearchHelper(Desire, currentVis, magicLore, aura.Strength, (byte)(Tier + 1), DueDate == null ? null : DueDate - 1);
                            helper.ModifyActionList(character, alreadyConsidered, log);
                        }
                    }

                    // consider increasing skills to be able to find vis
                    List<Ability> visSourceAbilities = new List<Ability>();
                    visSourceAbilities.Add(MagicArts.Intellego);
                    visSourceAbilities.Add(MagicArts.Vim);
                    visSourceAbilities.Add(Abilities.MagicLore);
                    AbilityScoreCondition condition =
                        new AbilityScoreCondition(visSourceAbilities, 2, Desire, (byte)(Tier + 1), DueDate == null ? null : DueDate - 1);
                    condition.ModifyActionList(character, alreadyConsidered, log);

                    // consider the value of looking for a new aura
                    double areaLore = mage.GetAbility(Abilities.AreaLore).Value;
                    areaLore += mage.GetAttribute(AttributeType.Perception).Value;
                    areaLore += mage.GetCastingTotal(MagicArtPairs.InVi) / 10;
                    if (areaLore > 0 && magicLore > 0)
                    {
                        double auraFound = mage.GetAverageAuraFound();
                        double multiplier = Math.Sqrt(magicLore * auraFound) * 2 / 3;
                        double areaUnder = 11.180339887498948482045868343656 * multiplier;
                        double visFromAura = areaUnder * _visTypes.Count() / 75;
                        dueDateDesire = dueDateDesire * visFromAura * (Tier + 1) / (Tier + 2);
                        log.Add("Looking for aura (to find a vis source in) worth " + (dueDateDesire).ToString("0.00"));
                        alreadyConsidered.Add(new FindAura(Abilities.AreaLore, dueDateDesire));
                    }
                }
            }
        }
Beispiel #11
0
        public override void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            double remainingTotal = GetRemainingTotal(character);
            if(remainingTotal <= 0)
            {
                return;
            }
            double dueDateDesire = Desire / (Tier + 1);
            if (DueDate != null)
            {
                if (DueDate == 0)
                {
                    log.Add("Ability Condition failed!");
                    return;
                }
                dueDateDesire /= (double)DueDate;
            }
            if (dueDateDesire > 0.01 && Tier <= 10)
            {
                IEnumerable<IBook> readableBooks = character.ReadableBooks;
                foreach (Ability ability in _abilities)
                {
                    bool isArt = MagicArts.IsArt(ability);
                    CharacterAbilityBase charAbility = character.GetAbility(ability);

                    // Handle Reading
                    var topicalBooks = readableBooks.Where(b => b.Topic == ability);
                    AddReading(character, alreadyConsidered, topicalBooks, remainingTotal, dueDateDesire);

                    // Abilities get practice, arts get vis study
                    if (!isArt && (ability.AbilityType != AbilityType.Supernatural || charAbility.Value > 0))
                    {
                        double desire = dueDateDesire * charAbility.GetValueGain(4) / remainingTotal;
                        log.Add("Practicing " + ability.AbilityName + " worth " + desire.ToString("0.00"));
                        Practice practiceAction = new Practice(ability, desire);
                        alreadyConsidered.Add(practiceAction);
                    }
                    else if (isArt && character.GetType() == typeof(Magus))
                    {
                        Magus mage = (Magus)character;
                        HandleVisUse(mage, charAbility, remainingTotal, dueDateDesire, alreadyConsidered, log);
                    }

                    // TODO: Learning By Training
                    // TODO: Learning by Teaching
                }
            }
        }
Beispiel #12
0
 public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
 {
     double desire = CalculateDesire(character);
     bool alDone = _writingAbilityCondition.IsComplete(character);
     bool latinDone = _languageAbilityCondition.IsComplete(character);
     bool abilityDone = _abilityScoreCondition.IsComplete(character);
     if (!alDone)
     {
         _writingAbilityCondition.Desire = desire;
         _writingAbilityCondition.ModifyActionList(character, alreadyConsidered, log);
     }
     if (!latinDone)
     {
         _languageAbilityCondition.Desire = desire;
         _languageAbilityCondition.ModifyActionList(character, alreadyConsidered, log);
     }
     if (!abilityDone)
     {
         _abilityScoreCondition.Desire = desire;
         _abilityScoreCondition.ModifyActionList(character, alreadyConsidered, log);
     }
     if (abilityDone && latinDone && alDone)
     {
         alreadyConsidered.Add(new Writing(Topic, _name, Topic, 1000, desire));
     }
 }
Beispiel #13
0
 public override void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
 {
     double dueDateDesire = Desire / (double)(Tier + 1);
     if(DueDate != null)
     {
         if (DueDate > 0)
         {
             dueDateDesire /= (double)DueDate;
         }
         else
         {
             character.Log.Add("Behind schedule on teaching!");
         }
     }
     Magus mage = (Magus)character;
     // TODO: figure out what to teach
     Ability ability = Abilities.MagicTheory;
     double xpDiff = mage.GetAbility(ability).Experience - mage.Apprentice.GetAbility(ability).Experience;
     double quality = mage.GetAttributeValue(AttributeType.Communication) + mage.GetAbility(Abilities.Teaching).Value + 6.0;
     if (quality > xpDiff)
     {
         var arts = mage.GetAbilities().Where(a => MagicArts.IsArt(a.Ability)).OrderBy(a => a.Value);
         foreach (CharacterAbilityBase art in arts)
         {
             xpDiff = art.Experience - mage.Apprentice.GetAbility(art.Ability).Experience;
             if (quality <= xpDiff)
             {
                 ability = art.Ability;
                 break;
             }
         }
     }
     _teachAction = new Teach(Students.First(), ability, Abilities.Teaching, dueDateDesire);
     alreadyConsidered.Add(_teachAction);
 }
Beispiel #14
0
        public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            if (character.GetType() == typeof(Magus))
            {
                Magus mage = (Magus)character;
                Desire = CalculateDesire(mage);
                double visNeed = character.SeasonalAge / 20.0;
                VisCondition visCondition = new VisCondition(_artsRequired, visNeed, Desire, Tier, DueDate == null ? null : DueDate - 1);

                bool visComplete = visCondition.IsComplete(character);
                bool labComplete = _hasLabCondition.IsComplete(character);

                if (!visComplete)
                {
                    visCondition.ModifyActionList(character, alreadyConsidered, log);
                }
                if (!labComplete)
                {
                    _hasLabCondition.Desire = Desire;
                    _hasLabCondition.ModifyActionList(character, alreadyConsidered, log);
                }
                if (visComplete && labComplete)
                {
                    //effectively, every five points of lab total is worth a decade of effectiveness
                    double dueDateDesire = Desire / (Tier + 1);
                    if (DueDate != null)
                    {
                        if (DueDate == 0)
                        {
                            log.Add("Not enough time to perform longevity ritual");
                            return;
                        }
                        dueDateDesire /= (double)DueDate;
                    }
                    if (DueDate == null || DueDate < 4)
                    {
                        log.Add("Performing longevity ritual worth " + dueDateDesire.ToString("0.00"));
                        alreadyConsidered.Add(new LongevityRitual(Abilities.MagicTheory, dueDateDesire));
                    }
                    double labTotalDesire = mage.GetLabTotal(MagicArtPairs.CrVi, Activity.DistillVis) * 8;
                    if (DueDate != null)
                    {
                        labTotalDesire /= (double)DueDate;
                    }
                    // every point of lab total is effectively two years
                    LongevityRitualAbilitiesHelper helper =
                        new LongevityRitualAbilitiesHelper(labTotalDesire, (byte)(Tier + 1), DueDate == null ? null : DueDate - 1);
                    helper.ModifyActionList(character, alreadyConsidered, log);
                }
            }
        }
Beispiel #15
0
 private void HandleAuraSearch(Magus mage, ConsideredActions alreadyConsidered, IList<string> log, double remainingTotal, double dueDateDesire)
 {
     double greatestAura = mage.KnownAuras.Select(a => a.Strength).Max();
     double currentAura = mage.Covenant.Aura.Strength;
     if (greatestAura > currentAura)
     {
         Aura bestAura = mage.KnownAuras.Where(a => a.Strength == greatestAura).First();
         if (!_hasLabCondition.IsComplete(mage))
         {
             // just move the covenant right now
             log.Add("Since no lab built, moving to better aura.");
             mage.FoundCovenant(bestAura);
         }
         else
         {
             // how do we want to rate the value of moving and having to build a new lab?
             // it seems like basically the same as any other single-month activity
             double gain = greatestAura - currentAura;
             double desire = dueDateDesire * gain / remainingTotal;
             log.Add("Moving to new aura (to boost lab total) worth " + dueDateDesire.ToString("0.00"));
             alreadyConsidered.Add(new BuildLaboratory(bestAura, Abilities.MagicTheory, desire));
         }
     }
     else
     {
         // consider finding a new aura
         IncreaseAuraHelper helper = new IncreaseAuraHelper(Desire / remainingTotal, (byte)(Tier + 1), DueDate == null ? null : DueDate - 1);
         helper.ModifyActionList(mage, alreadyConsidered, log);
     }
 }
Beispiel #16
0
        public void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log)
        {
            Magus mage = (Magus)character;
            double remainingTotal = _total - mage.GetLabTotal(_artPair, _labWorkType);
            double dueDateDesire = Desire / (Tier + 1);
            if (DueDate != null)
            {
                if (DueDate == 0)
                {
                    log.Add("Ability Condition failed!");
                    return;
                }
                dueDateDesire /= (double)DueDate;
            }

            // consider aura search
            HandleAuraSearch(mage, alreadyConsidered, log, remainingTotal, dueDateDesire);

            if (!_hasLabCondition.IsComplete(character))
            {
                _hasLabCondition.ModifyActionList(character, alreadyConsidered, log);
            }
            else if(!_attributeAbilityScore.IsComplete(character))
            {
                _attributeAbilityScore.ModifyActionList(character, alreadyConsidered, log);
            }

            // TODO: consider laboratory refinements
            // TODO: consider taking an apprentice
            // TODO: consider finding a familiar
        }