Пример #1
0
        public IBook WriteBook(Ability topic, string name, Ability exposureAbility, double desiredLevel = 0)
        {
            // grant exposure experience
            List <Ability> abilityList = new List <Ability>(_writingAbilities);

            abilityList.Add(topic);
            GetAbility(exposureAbility).AddExperience(2);

            // TODO: When should books moved from the owned list to the covenant library?
            if (desiredLevel == 1000)
            {
                Tractatus t = WriteTractatus(topic, name);
                _booksOwned.Add(t);
                return(t);
            }
            else
            {
                Summa s = WriteSumma(topic, name, desiredLevel);
                if (s != null)
                {
                    _booksOwned.Add(s);
                }
                return(s);
            }
        }
Пример #2
0
        public override bool Equals(object obj)
        {
            if (obj.GetType() != typeof(Summa))
            {
                return(false);
            }
            Summa otherBook = (Summa)obj;

            return
                (this.Author == otherBook.Author &&
                 this.Level == otherBook.Level &&
                 this.Quality == otherBook.Quality &&
                 this.Title == otherBook.Title &&
                 this.Topic == otherBook.Topic);
        }
Пример #3
0
        /// <summary>
        /// Works on a summa on the given topic.
        /// If the work invested is not enough to finish a book on that topic,
        /// the incomplete work is added to the list
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="desiredLevel"></param>
        /// <returns>the summa if it is completed, null otherwise</returns>
        protected Summa WriteSumma(Ability topic, string name, double desiredLevel)
        {
            Summa s;
            CharacterAbilityBase ability = GetAbility(topic);
            Summa previousWork           = _incompleteBooks.Where(b => b.Title == name).FirstOrDefault();

            if (previousWork == null)
            {
                double difference = (ability.Value / 2) - desiredLevel;
                if (difference < 0)
                {
                    throw new ArgumentOutOfRangeException();
                }
                s = new Summa()
                {
                    Author  = this,
                    Level   = desiredLevel,
                    Topic   = topic,
                    Title   = name,
                    Quality = MagicArts.IsArt(ability.Ability) ?
                              this.GetAttribute(AttributeType.Communication).Value + difference + 6 :
                              this.GetAttribute(AttributeType.Communication).Value + (difference * 3) + 6
                };
            }
            else
            {
                s = previousWork;
            }

            s.PointsComplete += this.GetAttribute(AttributeType.Communication).Value + GetAbility(_writingLanguage).Value;
            if (s.PointsComplete >= s.GetWritingPointsNeeded())
            {
                _booksWritten.Add(s);
                if (previousWork != null)
                {
                    _incompleteBooks.Remove(previousWork);
                }
                return(s);
            }
            return(null);
        }
Пример #4
0
        /// <summary>
        /// Works on a summa on the given topic. 
        /// If the work invested is not enough to finish a book on that topic,
        /// the incomplete work is added to the list
        /// </summary>
        /// <param name="topic"></param>
        /// <param name="desiredLevel"></param>
        /// <returns>the summa if it is completed, null otherwise</returns>
        protected Summa WriteSumma(Ability topic, string name, double desiredLevel)
        {
            Summa s;
            CharacterAbilityBase ability = GetAbility(topic);
            Summa previousWork = _incompleteBooks.Where(b => b.Title == name).FirstOrDefault();
            if (previousWork == null)
            {
                double difference = (ability.Value / 2) - desiredLevel;
                if (difference < 0)
                {
                    throw new ArgumentOutOfRangeException();
                }
                s = new Summa()
                {
                    Author = this,
                    Level = desiredLevel,
                    Topic = topic,
                    Title = name,
                    Quality = MagicArts.IsArt(ability.Ability) ?
                        this.GetAttribute(AttributeType.Communication).Value + difference + 6 :
                        this.GetAttribute(AttributeType.Communication).Value + (difference * 3) + 6
                };
            }
            else
            {
                s = previousWork;
            }

            s.PointsComplete += this.GetAttribute(AttributeType.Communication).Value + GetAbility(_writingLanguage).Value;
            if (s.PointsComplete >= s.GetWritingPointsNeeded())
            {
                _booksWritten.Add(s);
                if (previousWork != null)
                {
                    _incompleteBooks.Remove(previousWork);
                }
                return s;
            }
            return null;
        }
Пример #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);
        }