コード例 #1
0
 public ArtPair(Ability technique, Ability form)
 {
     if (!MagicArts.IsTechnique(technique) || !MagicArts.IsForm(form))
     {
         throw new ArgumentException("one of the arts used to initialize this pair is invalid!");
     }
     Technique = technique;
     Form      = form;
 }
コード例 #2
0
ファイル: Economy.cs プロジェクト: ndilday/wizard-monks
        /// <summary>
        /// Looks at the giver and receiver vis desires, and sees what combination of vis can meet the desires
        /// </summary>
        /// <param name="price">the agreed upon price, in Vim vis</param>
        /// <param name="giverVisDesires"></param>
        /// <param name="receiverVisDesires"></param>
        /// <returns></returns>
        private IEnumerable <VisOffer> GenerateVisOffer(double price, VisDesire[] giverVisDesires, VisDesire[] receiverVisDesires)
        {
            double          remainingPrice = price;
            List <VisOffer> offerSegments  = new List <VisOffer>();

            // order the receiver's desires from largest to smallest
            foreach (VisDesire desire in receiverVisDesires.Where(d => d.Quantity > 0).OrderByDescending(d => d.Quantity))
            {
                var giverArt = giverVisDesires.First(d => d.Art == desire.Art);
                // see if the giver can supply this type of vis
                if (giverArt.Quantity < 0)
                {
                    // they have some to trade
                    double maxNeed = remainingPrice;
                    if (MagicArts.IsTechnique(desire.Art))
                    {
                        maxNeed /= 4.0;
                        if (giverArt.Quantity * -1 >= maxNeed)
                        {
                            offerSegments.Add(new VisOffer(desire.Art, maxNeed));
                            remainingPrice = 0;
                            break;
                        }
                        else
                        {
                            // we're going to need more than this, so use all of this vis and move on
                            offerSegments.Add(new VisOffer(desire.Art, giverArt.Quantity * -1));
                            remainingPrice -= giverArt.Quantity * -4;
                        }
                    }
                    else if (desire.Art != MagicArts.Vim)
                    {
                        maxNeed /= 2.0;
                        if (giverArt.Quantity * -1 >= maxNeed)
                        {
                            offerSegments.Add(new VisOffer(desire.Art, maxNeed));
                            remainingPrice = 0;
                            break;
                        }
                        else
                        {
                            // we're going to need more than this, so use all of this vis and move on
                            offerSegments.Add(new VisOffer(desire.Art, giverArt.Quantity * -1));
                            remainingPrice -= giverArt.Quantity * -2;
                        }
                    }
                }
            }
            if (remainingPrice > 0)
            {
                return(null);
            }
            return(offerSegments);
        }
コード例 #3
0
ファイル: Economy.cs プロジェクト: ndilday/wizard-monks
        private double CalculateVisValue()
        {
            double total = 0;

            foreach (VisOffer offer in VisOffers)
            {
                if (MagicArts.IsTechnique(offer.Art))
                {
                    total += offer.Quantity * 4.0;
                }
                else if (offer.Art != MagicArts.Vim)
                {
                    total += offer.Quantity * 2.0;
                }
                else
                {
                    total += offer.Quantity;
                }
            }
            return(total);
        }
コード例 #4
0
        /// <summary>
        /// Determines the value of an experience gain in terms of the value of vis,
        /// and the amount of time it would take the character to produce and learn from
        /// that amount of vis
        /// </summary>
        /// <param name="ability"></param>
        /// <param name="gain"></param>
        /// <returns>the vis equivalence (vis savings) of this gain relative to vis study</returns>
        public override double RateSeasonalExperienceGain(Ability ability, double gain)
        {
            if (!MagicArts.IsArt(ability))
            {
                return(base.RateSeasonalExperienceGain(ability, gain));
            }
            double baseDistillVisRate = GetVisDistillationRate();
            double distillVisRate     = baseDistillVisRate;

            if (MagicArts.IsTechnique(ability))
            {
                distillVisRate /= 4.0;
            }
            else if (ability != MagicArts.Vim)
            {
                distillVisRate /= 2.0;
            }

            CharacterAbilityBase charAbility = GetAbility(ability);
            double visUsedPerStudySeason     = 0.5 + ((charAbility.Value + (charAbility.GetValueGain(gain) / 2)) / 10.0);
            // the gain per season depends on how the character views vis
            double studySeasons = gain / VisStudyRate;
            double visNeeded    = studySeasons * visUsedPerStudySeason;
            // compare to the number of seasons we would need to extract the vis
            // plus the number of seasons we would need to study the extracted vis
            double extractTime        = visNeeded / distillVisRate;
            double totalVisEquivalent = (extractTime + studySeasons) * baseDistillVisRate;

            // credit back the value of the exposure gained in the process of distilling
            double exposureGained                = 2.0 * extractTime;
            double exposureSeasonsOfVis          = exposureGained / VisStudyRate;
            CharacterAbilityBase vim             = GetAbility(MagicArts.Vim);
            CharacterAbilityBase creo            = GetAbility(MagicArts.Creo);
            CharacterAbilityBase exposureAbility = creo.Value < vim.Value ? creo : vim;
            double visValueOfExposure            = 0.5 + ((exposureAbility.Value + (exposureAbility.GetValueGain(exposureGained) / 2)) / 10.0) * exposureSeasonsOfVis;

            return(totalVisEquivalent - visValueOfExposure);
        }
コード例 #5
0
        public override IBook GetBestBookToWrite()
        {
            double        currentBestBookValue = 0;
            IBook         bestBook             = null;
            HashSet <int> consideredTopics     = new HashSet <int>();

            // since the value of a tractatus is independent of topic,
            // calculate the value of writing a tractatus now, so that we don't have to keep doing it
            double tractatusValue     = (6 + GetAttributeValue(AttributeType.Communication)) * GlobalEconomy.GlobalTractatusValue / 6;
            double writingRate        = GetAttributeValue(AttributeType.Communication) + GetAbility(_writingLanguage).Value;
            var    unneededBookTopics = GetUnneededBooksFromCollection().Select(b => b.Topic).Distinct();

            foreach (BookDesire bookDesire in GlobalEconomy.DesiredBooksList)
            {
                // if we already have a suitable book for this topic, let's not try to write another
                if (unneededBookTopics.Contains(bookDesire.Ability))
                {
                    continue;
                }
                // check to see if we could even write a summa of a level that would meet this desire
                if (GetAbility(bookDesire.Ability).Value > bookDesire.CurrentLevel * 2)
                {
                    CharacterAbility buyerAbility = new CharacterAbility(bookDesire.Ability);
                    buyerAbility.Experience = buyerAbility.GetExperienceUntilLevel(bookDesire.CurrentLevel);

                    // see if we have started a summa on this topic
                    var relatedIncompleteBooks = _incompleteBooks.Where(b => b.Topic == bookDesire.Ability && b.Level > bookDesire.CurrentLevel);
                    if (relatedIncompleteBooks.Any())
                    {
                        foreach (Summa incompleteBook in relatedIncompleteBooks)
                        {
                            // the effective value is based on time to finish, not time already invested
                            double experienceValue  = buyerAbility.GetExperienceUntilLevel(incompleteBook.Level);
                            double seasonsOfStudy   = Math.Ceiling(experienceValue / incompleteBook.Quality);
                            double effectiveQuality = experienceValue / seasonsOfStudy;
                            // at a minimum, the book is worth the vis it would take, on average, to gain that experience
                            double visUsedPerStudySeason = 0.5 + ((buyerAbility.Value + (buyerAbility.GetValueGain(experienceValue) / 2)) / 10.0);
                            double studySeasons          = experienceValue / VisStudyRate;
                            double visNeeded             = studySeasons * visUsedPerStudySeason;
                            // scale visNeeded according to vis type
                            if (MagicArts.IsTechnique(bookDesire.Ability))
                            {
                                visNeeded *= 4;
                            }
                            else if (MagicArts.IsArt(bookDesire.Ability) && bookDesire.Ability != MagicArts.Vim)
                            {
                                visNeeded *= 2;
                            }

                            // for now, scale vis according to quality of book vs. quality of vis study
                            visNeeded *= incompleteBook.Quality / VisStudyRate;

                            // divide this visNeed valuation by how many seasons are left for writing
                            double writingNeeded = incompleteBook.GetWritingPointsNeeded() - incompleteBook.PointsComplete;
                            double seasonsLeft   = Math.Ceiling(writingNeeded / writingRate);
                            double writingValue  = visNeeded / seasonsLeft;
                            if (writingValue > currentBestBookValue)
                            {
                                // continue writing this summa
                                bestBook = incompleteBook;
                            }
                        }
                    }
                    else
                    {
                        // NOTE: this could lead us down a strange rabbit hole of starting a bunch of
                        // summae on a subject of varying levels, but I think that's unlikely enough
                        // to not try and protect from for now
                        double maxLevel = GetAbility(bookDesire.Ability).Value / 2.0;

                        for (double l = maxLevel; l > bookDesire.CurrentLevel; l--)
                        {
                            double q = 6 + maxLevel - l;
                            // the effective value is based on time to finish, not time already invested
                            double experienceValue  = buyerAbility.GetExperienceUntilLevel(l);
                            double seasonsOfStudy   = Math.Ceiling(experienceValue / q);
                            double effectiveQuality = experienceValue / seasonsOfStudy;
                            // at a minimum, the book is worth the vis it would take, on average, to gain that experience
                            double visUsedPerStudySeason = 0.5 + ((buyerAbility.Value + (buyerAbility.GetValueGain(experienceValue) / 2)) / 10.0);
                            double studySeasons          = experienceValue / VisStudyRate;
                            double visNeeded             = studySeasons * visUsedPerStudySeason;
                            // scale visNeeded according to vis type
                            if (MagicArts.IsTechnique(bookDesire.Ability))
                            {
                                visNeeded *= 4;
                            }
                            else if (MagicArts.IsArt(bookDesire.Ability) && bookDesire.Ability != MagicArts.Vim)
                            {
                                visNeeded *= 2;
                            }

                            // for now, scale vis according to quality of book vs. quality of vis study
                            visNeeded *= q / VisStudyRate;

                            // divide this visNeed valuation by how many seasons are left for writing
                            double seasonsLeft  = Math.Ceiling(l / writingRate);
                            double writingValue = visNeeded / seasonsLeft;
                            if (writingValue > currentBestBookValue)
                            {
                                // write this summa
                                bestBook = new Summa
                                {
                                    Quality = q,
                                    Level   = l,
                                    Topic   = bookDesire.Ability,
                                    Title   = bookDesire.Ability.AbilityName + " Summa for Dummies by " + Name,
                                    Value   = writingValue
                                };
                                currentBestBookValue = writingValue;
                            }
                        }
                    }
                }

                // consider the value of writing a tractatus
                var charAbility = GetAbility(bookDesire.Ability);
                if (!consideredTopics.Contains(bookDesire.Ability.AbilityId) && tractatusValue > currentBestBookValue && CanWriteTractatus(charAbility))
                {
                    ushort previouslyWrittenCount = GetTractatiiWrittenOnTopic(bookDesire.Ability);
                    string name = Name + " " + bookDesire.Ability.AbilityName + " T" + previouslyWrittenCount.ToString();
                    bestBook = new Tractatus
                    {
                        Topic = bookDesire.Ability,
                        Title = name,
                        Value = tractatusValue
                    };
                    currentBestBookValue = tractatusValue;
                }
                consideredTopics.Add(bookDesire.Ability.AbilityId);
            }

            return(bestBook);
        }