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"); }
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"); }
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); }
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"); }
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"); }
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); }
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); }
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()); }
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); }
//--------------------------------------------------------------------- ///<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"); } }