public void NinjaFearLevelStringTests()
        {
            //Create our selector, indicating that we will be choosing between a set of strings.
            //This is fully generic and could be any type. 
            var Selector = new WeightedSelector<string>();

            var NinjaFearLevel = 5; //A value from 0 to 10, where 10 is the most afraid. 
                                    //As fear approaches 10, the monster is more likely to run.

            //Next we add our choices. The first parameter is the choice, the second is the weight.  
            Selector.Add("Cast Heal", NinjaFearLevel);
            Selector.Add("Flee", NinjaFearLevel - 7); //Ninjas fight to the death... Usually.
            Selector.Add("Attack", 10 - NinjaFearLevel);
               
            //So, if fear is 0, ninja will not cast heal (0) and will not flee (-7), he will always attack (10). 
            //If fear is 5, ninja might cast heal (5/50%) and will never flee (-2). He might attack (5/50%). 
            //If fear is 10, ninja will probably cast heal (10/76%) and might flee (3/23%). He's too afraid to attack (0/0%). 
            
            //This is where the magic happens. NinjaAction will be one of the choices we entered above.
            string NinjaAction = Selector.Select();
            
            //This test is mostly for documentation, however this does have to be true:
            Assert.IsTrue(NinjaAction == "Cast Heal" || 
                          NinjaAction == "Flee" || 
                          NinjaAction == "Attack");
        }
예제 #2
0
        public void NinjaFearLevelTests()
        {
            var Selector = new WeightedSelector<MonsterAction>();

            var NinjaFearLevel = 5; //A value from 0 to 10, where 10 is the most afraid. 
                                    //As fear approaches 10, the monster is more likely to run.
           
            var ActionCandidates = new List<WeightedItem<MonsterAction>>()
            {
                new WeightedItem<MonsterAction>(new MonsterAction("Cast Heal"), NinjaFearLevel), 
                new WeightedItem<MonsterAction>(new MonsterAction("Flee"), NinjaFearLevel - 7),  //Ninjas fight to the death... Usually.
                new WeightedItem<MonsterAction>(new MonsterAction("Attack"), 10 - NinjaFearLevel)     
            };

            //So, if fear is 0, ninja will not cast heal (0) and will not flee (-7), he will always attack (10). 
            //If fear is 5, ninja might cast heal (5/50%) and will never flee (-2). He might attack (5/50%). 
            //If fear is 10, ninja will probably cast heal (10/76%) and might flee (3/23%). He's too afraid to attack (0/0%). 
            
            Selector.Add(ActionCandidates);

            var SelectedAction = Selector.Select();
            
            //This test is mostly for documentation, however this does have to be true:
            Assert.IsTrue(SelectedAction.Name == "Cast Heal" || 
                          SelectedAction.Name == "Flee" || 
                          SelectedAction.Name == "Attack");
        }
예제 #3
0
        public static HashSet <int> SelectOption(
            EquipmentItemOptionSheet optionSheet,
            SkillSheet skillSheet,
            EquipmentItemSubRecipeSheet.Row subRecipe,
            IRandom random,
            Equipment equipment
            )
        {
            var optionSelector = new WeightedSelector <EquipmentItemOptionSheet.Row>(random);
            var optionIds      = new HashSet <int>();

            // Skip sort subRecipe.Options because it had been already sorted in WeightedSelector.Select();
            foreach (var optionInfo in subRecipe.Options)
            {
                if (!optionSheet.TryGetValue(optionInfo.Id, out var optionRow))
                {
                    continue;
                }

                optionSelector.Add(optionRow, optionInfo.Ratio);
            }

            IEnumerable <EquipmentItemOptionSheet.Row> optionRows =
                new EquipmentItemOptionSheet.Row[0];

            try
            {
                optionRows = optionSelector.Select(subRecipe.MaxOptionLimit);
            }
            catch (Exception e) when(
                e is InvalidCountException ||
                e is ListEmptyException
                )
            {
                return(optionIds);
            }
            finally
            {
                foreach (var optionRow in optionRows.OrderBy(r => r.Id))
                {
                    if (optionRow.StatType != StatType.NONE)
                    {
                        var statMap = GetStat(optionRow, random);
                        equipment.StatsMap.AddStatAdditionalValue(statMap.StatType, statMap.Value);
                    }
                    else
                    {
                        var skill = GetSkill(optionRow, skillSheet, random);
                        if (!(skill is null))
                        {
                            equipment.Skills.Add(skill);
                        }
                    }

                    optionIds.Add(optionRow.Id);
                }
            }

            return(optionIds);
        }
예제 #4
0
        public void NinjaFearLevelStringTests()
        {
            //Create our selector, indicating that we will be choosing between a set of strings.
            //This is fully generic and could be any type.
            var Selector = new WeightedSelector <string>();

            var NinjaFearLevel = 5; //A value from 0 to 10, where 10 is the most afraid.

            //As fear approaches 10, the monster is more likely to run.

            //Next we add our choices. The first parameter is the choice, the second is the weight.
            Selector.Add("Cast Heal", NinjaFearLevel);
            Selector.Add("Flee", NinjaFearLevel - 7); //Ninjas fight to the death... Usually.
            Selector.Add("Attack", 10 - NinjaFearLevel);

            //So, if fear is 0, ninja will not cast heal (0) and will not flee (-7), he will always attack (10).
            //If fear is 5, ninja might cast heal (5/50%) and will never flee (-2). He might attack (5/50%).
            //If fear is 10, ninja will probably cast heal (10/76%) and might flee (3/23%). He's too afraid to attack (0/0%).

            //This is where the magic happens. NinjaAction will be one of the choices we entered above.
            string NinjaAction = Selector.Select();

            //This test is mostly for documentation, however this does have to be true:
            Assert.IsTrue(NinjaAction == "Cast Heal" ||
                          NinjaAction == "Flee" ||
                          NinjaAction == "Attack");
        }
예제 #5
0
        public void NinjaFearLevelTests()
        {
            var Selector = new WeightedSelector <MonsterAction>();

            var NinjaFearLevel = 5; //A value from 0 to 10, where 10 is the most afraid.
                                    //As fear approaches 10, the monster is more likely to run.

            var ActionCandidates = new List <WeightedItem <MonsterAction> >()
            {
                new WeightedItem <MonsterAction>(new MonsterAction("Cast Heal"), NinjaFearLevel),
                new WeightedItem <MonsterAction>(new MonsterAction("Flee"), NinjaFearLevel - 7),  //Ninjas fight to the death... Usually.
                new WeightedItem <MonsterAction>(new MonsterAction("Attack"), 10 - NinjaFearLevel)
            };

            //So, if fear is 0, ninja will not cast heal (0) and will not flee (-7), he will always attack (10).
            //If fear is 5, ninja might cast heal (5/50%) and will never flee (-2). He might attack (5/50%).
            //If fear is 10, ninja will probably cast heal (10/76%) and might flee (3/23%). He's too afraid to attack (0/0%).

            Selector.Add(ActionCandidates);

            var SelectedAction = Selector.Select();

            //This test is mostly for documentation, however this does have to be true:
            Assert.IsTrue(SelectedAction.Name == "Cast Heal" ||
                          SelectedAction.Name == "Flee" ||
                          SelectedAction.Name == "Attack");
        }
예제 #6
0
        public void ReUseTest()
        {
            var Selector = new WeightedSelector<int>();
            Selector.Add(1, 1);
            int Result1 = Selector.Select();

            //There's only one choice - 1. It will always return.
            Assert.IsTrue(Result1 == 1);

            //Now re-use the same selector, but put an item in with so much weight that it will 
            //always "win". 
            Selector.Add(2, 5000000); //That's a heavy item.
            int Result2 = Selector.Select();

            Assert.IsTrue(Selector.ReadOnlyItems.Count == 2);
            Assert.IsTrue(Result2 == 2);
        }
예제 #7
0
        public void ReUseTest()
        {
            var Selector = new WeightedSelector <int>();

            Selector.Add(1, 1);
            int Result1 = Selector.Select();

            //There's only one choice - 1. It will always return.
            Assert.IsTrue(Result1 == 1);

            //Now re-use the same selector, but put an item in with so much weight that it will
            //always "win".
            Selector.Add(2, 5000000); //That's a heavy item.
            int Result2 = Selector.Select();

            Assert.IsTrue(Selector.ReadOnlyItems.Count == 2);
            Assert.IsTrue(Result2 == 2);
        }
예제 #8
0
파일: Skills.cs 프로젝트: dahlia/lib9c
        private Skill.Skill PostSelect(IRandom random, IEnumerable <Skill.Skill> skills)
        {
            var skillList     = skills.ToList();
            var defaultAttack = skillList.FirstOrDefault(x => x.SkillRow.Id == GameConfig.DefaultAttackId);

            if (defaultAttack == null)
            {
                throw new Exception("There is no default attack");
            }

            if (skillList.Count == 1) // If there's only a default attack in skills
            {
                return(defaultAttack);
            }

            var sortedSkills = skillList
                               .Where(x => x.SkillRow.Id != GameConfig.DefaultAttackId)
                               .OrderBy(x => x.SkillRow.Id)
                               .ToList();

            var sumChance = sortedSkills.Sum(x => x.Chance);

            if (sumChance < 100 &&
                sumChance <= random.Next(0, 100))
            {
                return(defaultAttack);
            }

            var itemSelector = new WeightedSelector <Skill.Skill>(random);

            foreach (var skill in sortedSkills)
            {
                itemSelector.Add(skill, skill.Chance);
            }

            var selectedSkill = itemSelector.Select(1);

            return(selectedSkill.First());
        }
예제 #9
0
        public Dictionary <string, int> RunTrialsAndCountResults()
        {
            //Do [trials] selections, and dump the number of hits for each item into a dictionary.
            var Results = new Dictionary <string, int>();

            for (var i = 0; i < Trials; i++)
            {
                string Decision = Selector.Select();

                if (!Results.ContainsKey(Decision))
                {
                    Results[Decision] = 1;
                }
                else
                {
                    Results[Decision] += 1;
                }
            }

            this.ResultCounter = Results;

            return(Results);
        }
예제 #10
0
        //---------------------------------------------------------------------

        ///<summary>
        /// Run the plug-in at a particular timestep.
        ///</summary>
        public override void Run()
        {
            if (PlugIn.ModelCore.CurrentTime > 0)
            {
                SiteVars.InitializeDisturbances();
            }

            SiteVars.Disturbed.ActiveSiteValues         = false;
            SiteVars.Intensity.ActiveSiteValues         = 0;
            SiteVars.SpreadProbability.ActiveSiteValues = 0.0;
            SiteVars.DayOfFire.ActiveSiteValues         = 0;
            SiteVars.TypeOfIginition.ActiveSiteValues   = 0;
            SiteVars.SpecialDeadWood.ActiveSiteValues   = 0;
            SiteVars.EventID.ActiveSiteValues           = 0;

            foreach (IDynamicIgnitionMap dynamicRxIgnitions in dynamicRxIgns)
            {
                if (dynamicRxIgnitions.Year == PlugIn.modelCore.CurrentTime)
                {
                    PlugIn.ModelCore.UI.WriteLine("   Reading in new Ignitions Maps {0}.", dynamicRxIgnitions.MapName);
                    MapUtility.ReadMap(dynamicRxIgnitions.MapName, SiteVars.RxFireWeight);

                    double totalWeight = 0.0;
                    activeRxSites = PreShuffle(SiteVars.RxFireWeight, out totalWeight);
                    rxTotalWeight = totalWeight;
                }
            }

            foreach (IDynamicIgnitionMap dynamicLxIgns in dynamicLightningIgns)
            {
                if (dynamicLxIgns.Year == PlugIn.modelCore.CurrentTime)
                {
                    PlugIn.ModelCore.UI.WriteLine("   Reading in new Ignitions Maps {0}.", dynamicLxIgns.MapName);
                    MapUtility.ReadMap(dynamicLxIgns.MapName, SiteVars.LightningFireWeight);

                    double totalWeight = 0.0;
                    activeLightningSites = PreShuffle(SiteVars.LightningFireWeight, out totalWeight);
                    lightningTotalWeight = totalWeight;
                }
            }
            foreach (IDynamicIgnitionMap dynamicAxIgns in dynamicAccidentalIgns)
            {
                if (dynamicAxIgns.Year == PlugIn.modelCore.CurrentTime)
                {
                    PlugIn.ModelCore.UI.WriteLine("   Reading in new Ignitions Maps {0}.", dynamicAxIgns.MapName);
                    MapUtility.ReadMap(dynamicAxIgns.MapName, SiteVars.AccidentalFireWeight);

                    double totalWeight = 0.0;
                    activeAccidentalSites = PreShuffle(SiteVars.AccidentalFireWeight, out totalWeight);
                    accidentalTotalWeight = totalWeight;
                }
            }
            foreach (IDynamicSuppressionMap dynamicSuppressMaps in dynamicSuppress)
            {
                if (dynamicSuppressMaps.Year == PlugIn.modelCore.CurrentTime)
                {
                    PlugIn.ModelCore.UI.WriteLine("   Reading in new Fire Suppression Map {0}.", dynamicSuppressMaps.MapName);
                    MapUtility.ReadMap(dynamicSuppressMaps.MapName, SiteVars.AccidentalSuppressionIndex);
                }
            }

            AnnualClimate_Daily weatherData = null;

            dNBR                  = new int[3];
            totalBurnedSites      = new int[3];
            numberOfFire          = new int[3];
            totalBiomassMortality = new int[3];

            modelCore.UI.WriteLine("   Processing landscape for Fire events ...");

            ActualYear = 0;
            try
            {
                ActualYear = (PlugIn.ModelCore.CurrentTime - 1) + Climate.Future_AllData.First().Key;
            }
            catch
            {
                throw new UninitializedClimateData(string.Format("Could not initilize the actual year {0} from climate data", ActualYear));
            }

            // modelCore.UI.WriteLine("   Next, shuffle ignition sites...");
            // Get the active sites from the landscape and shuffle them
            // Sites are weighted for ignition in the Ether.WeightedSelector Shuffle method, based on the respective inputs maps.
            int numSites = 0;

            weightedRxSites = PreShuffleEther(SiteVars.RxFireWeight, out numSites);
            int numRxSites = numSites;

            //modelCore.UI.WriteLine("   Number Rx sites = {0}", numRxSites);
            weightedAccidentalSites = PreShuffleEther(SiteVars.AccidentalFireWeight, out numSites);
            int numAccidentalSites = numSites;

            weightedLightningSites = PreShuffleEther(SiteVars.LightningFireWeight, out numSites);
            int numLightningSites = numSites;

            //modelCore.UI.WriteLine("   Next, loop through each day to start fires...");

            int numAnnualRxFires = Parameters.RxNumberAnnualFires;

            for (int day = 0; day < DaysPerYear; ++day)
            {
                double landscapeAverageFireWeatherIndex = 0.0;
                double landscapeAverageTemperature      = 0.0;
                double landscapeAverageRelHumidity      = 0.0;
                // number of fires get initilized to 0 every timestep

                foreach (IEcoregion climateRegion in PlugIn.ModelCore.Ecoregions)
                {
                    if (sitesPerClimateRegion.ContainsKey(climateRegion.Index))
                    {
                        double climateRegionFractionSites = (double)fractionSitesPerClimateRegion[climateRegion.Index];

                        try
                        {
                            weatherData = Climate.Future_DailyData[ActualYear][climateRegion.Index];
                        }
                        catch
                        {
                            throw new UninitializedClimateData(string.Format("Climate data could not be found in Run(). Year: {0} in ecoregion: {1}", ActualYear, climateRegion.Name));
                        }

                        try
                        {
                            // modelCore.UI.WriteLine(" Fire Weather Check Daily={0}, Average={1}", weatherData.DailyFireWeatherIndex[day], landscapeAverageFireWeatherIndex);

                            landscapeAverageFireWeatherIndex += weatherData.DailyFireWeatherIndex[day] * climateRegionFractionSites;
                            landscapeAverageTemperature      += weatherData.DailyMaxTemp[day] * climateRegionFractionSites;
                            if (weatherData.DailyMinRH[day] == -99.0)
                            {
                                double relativeHumidity = AnnualClimate_Daily.ConvertSHtoRH(weatherData.DailySpecificHumidity[day], weatherData.DailyTemp[day]);
                                if (relativeHumidity > 100)
                                {
                                    relativeHumidity = 100.0;
                                }
                                landscapeAverageRelHumidity += relativeHumidity * climateRegionFractionSites;
                            }
                            else
                            {
                                landscapeAverageRelHumidity += weatherData.DailyMinRH[day] * climateRegionFractionSites;
                            }
                            //landscapeAverageRelHumidity += weatherData.DailyMinRH[day] * climateRegionFractionSites;
                            // modelCore.UI.WriteLine("  Fire Weather Check Daily={0}, Average={1}", weatherData.DailyFireWeatherIndex[day], landscapeAverageFireWeatherIndex);
                        }
                        catch
                        {
                            throw new UninitializedClimateData(string.Format("Fire Weather Index could not be found in Run(). Year: {0}, day: {1}, climate region: {2}, NumSites={3}", ActualYear, day, climateRegion.Name, sitesPerClimateRegion[climateRegion.Index]));
                        }

                        if (Climate.Future_DailyData[PlugIn.ActualYear][climateRegion.Index].DailyRH[day] < 0)
                        {
                            string mesg = string.Format("Relative Humidity not included in the climate data.  (RH is required to calculate FWI.) Year: {0}, day: {1}, climate region: {2}, NumSites={3}", ActualYear, day, climateRegion.Name, sitesPerClimateRegion[climateRegion.Index]);
                            throw new System.ApplicationException(mesg);
                        }
                    }
                }



                //PlugIn.ModelCore.UI.WriteLine("   Generating accidental fires...");
                if (numAccidentalSites > 0)
                {
                    bool fire = false;
                    int  maxNumAccidentalFires    = NumberOfIgnitions(IgnitionType.Accidental, landscapeAverageFireWeatherIndex);
                    int  logMaxNumAccidentalFires = maxNumAccidentalFires;
                    int  actualNumAccidentalFires = 0;
                    while (maxNumAccidentalFires > 0)
                    {
                        //Ignite(Ignition.Accidental, shuffledAccidentalFireSites, day, landscapeAverageFireWeatherIndex);
                        fire = Ignite(IgnitionType.Accidental, weightedAccidentalSites.Select(), day, landscapeAverageFireWeatherIndex);
                        if (fire)
                        {
                            maxNumAccidentalFires--;
                            actualNumAccidentalFires++;
                        }
                    }
                    if (fire)
                    {
                        LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, IgnitionType.Accidental.ToString(), logMaxNumAccidentalFires, actualNumAccidentalFires, day);
                    }
                }

                /// Removed FWI threshold ZR 11-12-20
                //PlugIn.ModelCore.UI.WriteLine("   Generating lightning fires...");
                if (numLightningSites > 0)
                {
                    bool fire = false;
                    int  maxNumLightningFires    = NumberOfIgnitions(IgnitionType.Lightning, landscapeAverageFireWeatherIndex);
                    int  logMaxNumLightningFires = maxNumLightningFires;
                    int  actualNumLightningFires = 0;
                    while (maxNumLightningFires > 0)
                    {
                        //Ignite(Ignition.Lightning, shuffledLightningFireSites, day, landscapeAverageFireWeatherIndex);
                        fire = Ignite(IgnitionType.Lightning, weightedLightningSites.Select(), day, landscapeAverageFireWeatherIndex);
                        if (fire)
                        {
                            maxNumLightningFires--;
                            actualNumLightningFires++;
                        }
                    }
                    if (fire)
                    {
                        LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, IgnitionType.Lightning.ToString(), logMaxNumLightningFires, actualNumLightningFires, day);
                    }
                }

                // Ignite a single Rx fire per day
                //PlugIn.ModelCore.UI.WriteLine("   Generating prescribed fires...");

                if (numRxSites > 0 &&
                    numAnnualRxFires > 0 &&
                    landscapeAverageFireWeatherIndex > Parameters.RxMinFireWeatherIndex &&
                    landscapeAverageFireWeatherIndex < Parameters.RxMaxFireWeatherIndex &&
                    landscapeAverageTemperature < Parameters.RxMaxTemperature &&
                    landscapeAverageRelHumidity > Parameters.RxMinRelativeHumidity &&
                    weatherData.DailyWindSpeed[day] < Parameters.RxMaxWindSpeed &&
                    day >= Parameters.RxFirstDayFire &&
                    day < Parameters.RxLastDayFire)
                {
                    int  maxNumDailyRxFires = Parameters.RxNumberDailyFires;
                    int  actualNumRxFires   = 0;
                    bool fire = false;
                    int  maxIgnitionFailures    = 20;
                    int  actualIgnitionFailures = 0;

                    while (numAnnualRxFires > 0 && maxNumDailyRxFires > 0)
                    {
                        ActiveSite site = weightedRxSites.Select();

                        if (SiteVars.Disturbed[site])
                        {
                            actualIgnitionFailures++;
                        }
                        if (actualIgnitionFailures > maxIgnitionFailures)
                        {
                            break;
                        }

                        //PlugIn.ModelCore.UI.WriteLine("   Ignite prescribed fires...");
                        fire = Ignite(IgnitionType.Rx, site, day, landscapeAverageFireWeatherIndex);
                        if (fire)
                        {
                            numAnnualRxFires--;
                            maxNumDailyRxFires--;
                            actualNumRxFires++;
                        }
                    }
                    if (fire)
                    {
                        LogIgnition(ModelCore.CurrentTime, landscapeAverageFireWeatherIndex, IgnitionType.Rx.ToString(), Parameters.RxNumberDailyFires, actualNumRxFires, day);
                    }
                }
            }

            modelCore.UI.WriteLine("  Fire for the year completed.  Next, write fire maps and summary fire files. ...");

            WriteMaps(PlugIn.ModelCore.CurrentTime);

            WriteSummaryLog(PlugIn.ModelCore.CurrentTime);

            if (isDebugEnabled)
            {
                modelCore.UI.WriteLine("Done running extension");
            }
        }