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); } } } }
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)); } } }
public abstract void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList<string> log);
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)); } }
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); } }
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 } } }
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)); }
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); } }
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 } } }
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)); } } } }
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 } } }
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)); } }
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); }
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); } } }
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); } }
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 }