Ejemplo n.º 1
0
            /// <summary>
            /// Randomly selects from discrete options with unequal weights. The program state
            /// shall be unchanged in the event of an exception.
            /// </summary>
            ///
            /// <typeparam name="T">The type of object to be selected.</typeparam>
            /// <param name="weightedChoices">A list of (<typeparamref name="T"/>, double) tuples.
            /// The first value of each tuple represents one of the choices, the second the weight
            /// for that choice. The odds of selecting two choices equals the ratio of the weights
            /// between them. All weights must be nonnegative, and at least one must be
            /// positive.</param>
            /// <returns>The selected object.</returns>
            ///
            /// <exception cref="ArgumentException">Thrown if <c>weightedChoices</c> is
            /// empty.</exception>
            /// <exception cref="ArgumentOutOfRangeException">Thrown if any weight is
            /// negative, or if no weight is positive.</exception>
            internal static T weightedSample <T> (
                System.Collections.Generic.IList <Tuple <T, double> > weightedChoices)
            {
                if (weightedChoices.Count == 0)
                {
                    throw new ArgumentException(
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorNoSample"),
                              nameof(weightedChoices));
                }
                double norm = 0.0;

                foreach (Tuple <T, double> choice in weightedChoices)
                {
                    if (choice.Item2 < 0)
                    {
                        throw new ArgumentOutOfRangeException(
                                  nameof(weightedChoices),
                                  Localizer.Format("#autoLOC_CustomAsteroids_ErrorNegativeSample",
                                                   choice.Item2, choice.Item1));
                    }
                    norm += choice.Item2;
                }
                if (norm <= 0.0)
                {
                    throw new ArgumentOutOfRangeException(
                              nameof(weightedChoices),
                              Localizer.Format("#autoLOC_CustomAsteroids_ErrorZeroSample"));
                }

                // important: no exceptions beyond this point

                // assert: r is in [0, norm]
                double threshold = norm * rng.NextDouble();

                // If you stack up all the weights, at what level do you hit threshold?
                double level = 0.0;

                foreach (Tuple <T, double> choice in weightedChoices)
                {
                    level += choice.Item2;
                    if (level >= threshold)
                    {
                        return(choice.Item1);
                    }
                }

                // Should only get here because of rounding error when threshold = norm
                return(weightedChoices [weightedChoices.Count - 1].Item1);
            }
 /// <summary>
 /// Uses criteria similar to ScenarioDiscoverableObjects to decide whether to create an
 /// asteroid.
 /// </summary>
 protected override void checkSpawn()
 {
     if (areAsteroidsTrackable() &&
         AsteroidManager.spawnRate() > 0.0 &&
         countUntrackedAsteroids() < rng.Next(SPAWN_GROUP_MIN_LIMIT, SPAWN_GROUP_MAX_LIMIT))
     {
         if (rng.NextDouble() < 1.0 / (1.0 + SPAWN_ODDS_AGAINST))
         {
             spawnAsteroid();
         }
         else
         {
             Debug.Log("[StockalikeSpawner]: "
                       + Localizer.Format("#autoLOC_CustomAsteroids_LogSpawnStock",
                                          SPAWN_ODDS_AGAINST));
         }
     }
 }