コード例 #1
0
        public double UseVis(Ability visType, double amount)
        {
            if (!MagicArts.IsArt(visType))
            {
                throw new ArgumentException("Only magic arts have vis!");
            }
            if (_visStock[visType] + (Covenant == null ? 0 : Covenant.GetVis(visType)) < amount)
            {
                throw new ArgumentException("Insufficient vis available!");
            }
            double covVis = Covenant == null ? 0 : Covenant.GetVis(visType);

            if (covVis >= amount)
            {
                Covenant.RemoveVis(visType, amount);
            }
            else
            {
                if (Covenant != null)
                {
                    amount -= covVis;
                    Covenant.RemoveVis(visType, covVis);
                }
                _visStock[visType] -= amount;
            }
            return(_visStock[visType]);
        }
コード例 #2
0
 public ApprenticeGoal(Character character, uint?dueDate, double desire) : base(character, dueDate, desire)
 {
     foreach (Ability ability in MagicArts.GetEnumerator())
     {
         Conditions.Add(new AbilityScoreCondition(character, dueDate == null ? 200 : (uint)(dueDate - 1), desire, ability, 5));
     }
 }
コード例 #3
0
        public override void AddActionPreferencesToList(ConsideredActions alreadyConsidered, IList <string> log)
        {
            _currentTotal = GetTotal();
            if (!ConditionFulfilled)
            {
                // the basic structure is (portion of necessary gain action provides) * (desire / time left until needed)
                foreach (Ability ability in Abilities)
                {
                    if (!MagicArts.IsArt(ability))
                    {
                        AddPracticeToActionList(ability, alreadyConsidered, log);
                    }
                    else if (Character.GetType() == typeof(Magus))
                    {
                        AddVisUseToActionList(ability, alreadyConsidered, log);
                    }

                    var topicalBooks = Character.ReadableBooks.Where(b => b.Topic == ability);
                    if (topicalBooks.Any())
                    {
                        AddReadingToActionList(topicalBooks, ability, alreadyConsidered, log);
                    }
                }
            }
        }
コード例 #4
0
ファイル: GoalHelpers.cs プロジェクト: ndilday/wizard-monks
        public virtual void ModifyActionList(Character character, ConsideredActions alreadyConsidered, IList <string> log)
        {
            if (BaseDueDate != null && BaseDueDate == 0)
            {
                return;
            }
            IEnumerable <IBook> readableBooks = character.ReadableBooks;

            foreach (Ability ability in _abilities)
            {
                // Handle Reading
                CharacterAbilityBase charAbility = character.GetAbility(ability);
                var topicalBooks = readableBooks.Where(b => b.Topic == ability);
                HandleReading(character, alreadyConsidered, topicalBooks);

                // Handle Practice
                if (!MagicArts.IsArt(ability))
                {
                    HandlePractice(character, alreadyConsidered, log, ability);
                }
                else if (character.GetType() == typeof(Magus))
                {
                    Magus mage = (Magus)character;
                    HandleVisUse(mage, charAbility, alreadyConsidered, log);
                }

                // TODO: Learning By Training
                // TODO: Learning by Teaching
            }
        }
コード例 #5
0
ファイル: Covenant.cs プロジェクト: ndilday/wizard-monks
 public double GetVis(Ability visType)
 {
     if (!MagicArts.IsArt(visType))
     {
         throw new ArgumentException("Only magic arts have vis!");
     }
     return(_visStock.ContainsKey(visType) ? _visStock[visType] : 0);
 }
コード例 #6
0
ファイル: Character.cs プロジェクト: ndilday/wizard-monks
 /// <summary>
 /// Determines the value of an experience gain in terms of practice seasons
 /// </summary>
 /// <param name="ability"></param>
 /// <param name="gain"></param>
 /// <returns>the season equivalence of this gain</returns>
 public virtual double RateSeasonalExperienceGain(Ability ability, double gain)
 {
     if (MagicArts.IsArt(ability))
     {
         return(0);
     }
     return(gain / 4);
 }
コード例 #7
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;
 }
コード例 #8
0
 public VisStudying(Ability art, double desire)
 {
     if (!MagicArts.IsArt(art))
     {
         throw new ArgumentException("Only magic arts have vis associated with them!");
     }
     Art    = art;
     Desire = desire;
     Action = Activity.StudyVis;
 }
コード例 #9
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);
        }
コード例 #10
0
 public override CharacterAbilityBase GetAbility(Ability ability)
 {
     if (MagicArts.IsArt(ability))
     {
         return(Arts.GetAbility(ability));
     }
     else
     {
         return(base.GetAbility(ability));
     }
 }
コード例 #11
0
ファイル: Covenant.cs プロジェクト: ndilday/wizard-monks
 public double AddVis(Ability visType, double amount)
 {
     if (MagicArts.IsArt(visType))
     {
         if (_visStock.ContainsKey(visType))
         {
             _visStock[visType] += amount;
         }
         else
         {
             _visStock[visType] = amount;
         }
         return(_visStock[visType]);
     }
     return(0);
 }
コード例 #12
0
 public double GainVis(Ability visType, double amount)
 {
     if (!MagicArts.IsArt(visType))
     {
         throw new ArgumentException("Only magic arts have vis!");
     }
     if (_visStock.ContainsKey(visType))
     {
         _visStock[visType] += amount;
     }
     else
     {
         _visStock[visType] = amount;
     }
     return(_visStock[visType]);
 }
コード例 #13
0
ファイル: Covenant.cs プロジェクト: ndilday/wizard-monks
 public double RemoveVis(Ability visType, double amount)
 {
     if (amount <= 0)
     {
         return(_visStock.ContainsKey(visType) ? _visStock[visType] : 0);
     }
     if (!MagicArts.IsArt(visType))
     {
         throw new ArgumentException("Only magic arts have vis!");
     }
     if (!_visStock.ContainsKey(visType) || _visStock[visType] < amount)
     {
         throw new ArgumentException("Insufficient vis available!");
     }
     _visStock[visType] -= amount;
     return(_visStock[visType]);
 }
コード例 #14
0
 public override void ModifyVisDesires(VisDesire[] desires)
 {
     foreach (Ability ability in this.Abilities)
     {
         if (MagicArts.IsArt(ability))
         {
             double visNeed = 0.5 + (this.Character.GetAbility(ability).Value / 10.0);
             foreach (VisDesire visDesire in desires)
             {
                 if (visDesire.Art == ability)
                 {
                     visDesire.Quantity += visNeed;
                     break;
                 }
             }
         }
     }
 }
コード例 #15
0
ファイル: Character.cs プロジェクト: ndilday/wizard-monks
        /// <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);
        }
コード例 #16
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);
        }
コード例 #17
0
        public WorldGenerator()
        {
            ImmutableMultiton <int, Ability> .Initialize(MagicArts.GetEnumerator());

            ImmutableMultiton <int, Ability> .Initialize(Abilities.GetEnumerator());

            // read out values in multiton
            foreach (int i in ImmutableMultiton <int, Ability> .GetKeys())
            {
                Ability ability = ImmutableMultiton <int, Ability> .GetInstance(i);

                if (ability.AbilityName == "Latin")
                {
                    _latin = ability;
                }
                else if (ability.AbilityName == "Magic Theory")
                {
                    _magicTheory = ability;
                }
                else if (ability.AbilityName == "Artes Liberales")
                {
                    _artLib = ability;
                }
                else if (ability.AbilityName == "Area Lore")
                {
                    _areaLore = ability;
                }
            }

            InitializeComponent();

            foreach (Magus founder in Founders.GetEnumerator())
            {
                _magusArray[_magusCount] = founder;
                _magusCount++;
            }
            lstMembers.DataSource = _magusArray.Take(_magusCount).ToList();
            _log = new List <string>();
            lstAdvance.DataSource = _log;
        }
コード例 #18
0
        public Magus(Ability magicAbility, Ability writingLanguage, Ability writingAbility, Ability areaAbility, uint baseAge = 20)
            : base(writingLanguage, writingAbility, areaAbility, baseAge)
        {
            _magicAbility = magicAbility;
            Arts          = new Arts();
            Covenant      = null;
            Laboratory    = null;
            _visStock     = new Dictionary <Ability, double>();
            SpellList     = new List <Spell>();
            //_tractatusGoals = new List<TractatusGoal>();
            //_summaGoals = new List<SummaGoal>();
            _partialSpell         = null;
            _partialSpellProgress = 0;
            VisStudyRate          = 6.75;
            House = Houses.Apprentice;
            foreach (Ability art in MagicArts.GetEnumerator())
            {
                _visStock[art] = 0;
            }

            InitializeGoals();
        }
コード例 #19
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);
        }
コード例 #20
0
 public override void Advance()
 {
     // harvest vis
     foreach (Aura aura in KnownAuras)
     {
         foreach (VisSource source in aura.VisSources)
         {
             if ((CurrentSeason & source.Seasons) == CurrentSeason)
             {
                 _visStock[source.Art] += source.Amount;
             }
         }
     }
     Log.Add("VIS STOCK");
     foreach (Ability art in MagicArts.GetEnumerator())
     {
         if (_visStock[art] > 0)
         {
             Log.Add(art.AbilityName + ": " + _visStock[art].ToString("0.00"));
         }
     }
     base.Advance();
 }
コード例 #21
0
        protected IEnumerable <BookForTrade> EvaluateBookValuesAsSeller(IEnumerable <IBook> books)
        {
            List <BookForTrade> list = new List <BookForTrade>();
            double distillRate       = GetVisDistillationRate();

            foreach (IBook book in books)
            {
                if (book.Level == 1000)
                {
                    list.Add(new BookForTrade(book, distillRate));
                }
                else
                {
                    double writeRate = GetAbility(_writingLanguage).Value + _attributes[(int)AttributeType.Communication].Value;
                    double seasons   = book.Level / writeRate;
                    if (!MagicArts.IsArt(book.Topic))
                    {
                        seasons *= 5;
                    }
                    list.Add(new BookForTrade(book, distillRate * seasons));
                }
            }
            return(list);
        }
コード例 #22
0
 public double GetWritingPointsNeeded()
 {
     return(MagicArts.IsArt(Topic) ? Level : Level * 5);
 }
コード例 #23
0
 private void DisplayAbilities()
 {
     dgvAbilities.AutoGenerateColumns = false;
     dgvAbilities.DataSource          = _character.GetAbilities().Where(a => !MagicArts.IsArt(a.Ability)).OrderBy(a => a.Ability.AbilityName).ToList();
 }
コード例 #24
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);
        }