Пример #1
0
        public override CharacterAbilityBase MakeCopy()
        {
            CharacterAbility retVal = new CharacterAbility(this.Ability);

            retVal.Experience = this.Experience;
            retVal.IsAffinity = this.IsAffinity;
            retVal.IsPuissant = this.IsPuissant;
            return(retVal);
        }
Пример #2
0
        public Character(Ability writingLanguage, Ability writingAbility, Ability areaAbility, uint baseSeasonableAge = 20)
        {
            Die die = new Die();

            _attributes[(short)AttributeType.Strength]      = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Stamina]       = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Dexterity]     = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Quickness]     = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Intelligence]  = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Communication] = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Perception]    = new Attribute(die.RollNormal());
            _attributes[(short)AttributeType.Presence]      = new Attribute(die.RollNormal());

            Decrepitude     = 0;
            CurrentSeason   = Season.Spring;
            KnownAuras      = new List <Aura>();
            IsCollaborating = false;
            WantsToFollow   = true;

            _noAgingSeasons  = 0;
            _baseAge         = baseSeasonableAge;
            _mandatoryAction = null;

            _abilityList  = new Dictionary <int, CharacterAbilityBase>();
            _seasonList   = new List <IAction>();
            _booksRead    = new List <IBook>();
            _booksWritten = new List <IBook>();
            _booksOwned   = new List <IBook>();

            _areaAbility      = areaAbility;
            _writingAbility   = writingAbility;
            _writingLanguage  = writingLanguage;
            _writingAbilities = new List <Ability>();
            _writingAbilities.Add(_writingAbility);
            _writingAbilities.Add(_writingLanguage);

            _incompleteBooks = new List <Summa>();
            _goals           = new List <IGoal>();
            Log     = new List <string>();
            Warping = new CharacterAbility(Abilities.Warping);
        }
Пример #3
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);
        }