/// <summary> /// Find whether or not the plant is currently toxic. Toxicity can change /// and is a semi-random property. /// The plant is toxic with probability (t/100) * (a/50), where: /// t: toxicity factor of the plant, determined upon creation, /// 100: the maximum toxicity factor of a plant, /// a: the age of the plant, /// 50: the maximum age of a plant. /// </summary> /// <returns>True if the plant is toxic, false otherwise.</returns> public bool IsToxic() { // Calculate the toxicity probability according to the formula above double prob = (((double)ToxicityFactor) / TOXICITY_FACTOR_UPPER_BOUND) * (((double)Age) / Senescence); // Use the probability to determine whether the plant is toxic or not return(ProbabilityHelper.EvaluateIndependentPredicate(prob)); }
/// <summary> /// Construct a new Plant unit /// </summary> /// <param name="row"> The row of the Plant within the grid. </param> /// <param name="col"> The column of the Plant within the grid. </param> public Plant(int row = -1, int col = -1) : base(Enums.UnitType.Plant, senescence: 50, foodRequirement: 5, waterRequirement: 25, gasRequirement: 4, inputGas: Enums.GasType.CarbonDioxide, outputGas: Enums.GasType.Oxygen, idealTemperature: 35, infectionResistance: 7, decompositionValue: 10, row: row, col: col) { // Generate a unique toxicity factor for this plant -- used to calculate its toxicity ToxicityFactor = ProbabilityHelper.RandomInteger(TOXICITY_FACTOR_LOWER_BOUND, TOXICITY_FACTOR_UPPER_BOUND); // Store the minimum water requirement for a plant BaselineWaterRequirement = WaterRequirement; }
/// <summary> /// Checks if the unit should increase in age. This is probabilistic. A Unit /// cannot age past its age of senescence. /// </summary> /// <remarks> /// Author: Tiffanie Truong /// </remarks> /// <param name="gameEnv"></param> /// <returns>True if the Unit should age, false otherwise.</returns> private bool ShouldAge(Environment gameEnv) { // Calculate the probability that the Unit should age double ageProbability = AgeProbability(gameEnv); // If the Unit's age is at its max, do not age if (Age == Senescence) { return(false); } // Otherwise, probabilistically determine if it should age based on its conditions return(ProbabilityHelper.EvaluateIndependentPredicate(ageProbability)); }
/// <summary> /// Determines if the unique environmental event begins in the environment /// </summary> /// <returns> True if the environmental event begins and false otherwise </returns> public bool EventStarts() { // Probabilistically evaluate whether the event should occur in order to initiate it if (ProbabilityHelper.EvaluateIndependentPredicate(PROBABILITY_OF_ENV_EVENT / 100.0)) { // Indicate that the environmental event will begin occurring for the next 5 generations EnvEventOccurring = true; EventGenerationsLeft = 5; return(true); } // If the probability fails, the event does not start return(false); }
/// <summary> /// Determines if it starts raining in the environment /// </summary> /// <returns> True if it starts raining in the environment and false otherwise </returns> public bool WillRain() { // Probabilistically evaluate whether it will rain in order to initiate raining if (ProbabilityHelper.EvaluateIndependentPredicate(probabilityOfRain / 100.0)) { // Indicate that it is raining for the next 5 generations IsRaining = true; EventGenerationsLeft = 5; return(true); } // If the probability fails, it does not start raining return(false); }
/// <summary> /// Performs photosynthesis, consuming a random amount of the carbon dioxide and water to return food to the environment /// </summary> /// <remarks> Tiffanie Truong </remarks> /// <param name="gameEnv"> The Environment of the simulation that the plants reside in </param> protected void Photosynthesize(Environment gameEnv) { // Generate how many carbon dioxide and water units are consumed to turn into food int resourceUsage = ProbabilityHelper.RandomInteger(PHOTOSYNTHESIS_RESOURCE_LOWER_BOUND, PHOTOSYNTHESIS_RESOURCE_UPPER_BOUND); // Check if there is enough carbon dioxide and water in the environment to create this given amount of food if (resourceUsage <= gameEnv.CarbonDioxideLevel && resourceUsage <= gameEnv.WaterAvailability) { // Perform photosynthesis and create more food gameEnv.IncreaseFood(resourceUsage); // Consume water and carbon dioxide in the environment gameEnv.DecreaseFood(resourceUsage); gameEnv.DecreaseWater(resourceUsage); } }
/// <summary> /// Compute which Multicellular type a Colony should merge into: Plant or Animal. /// This is probabilistically based on the atmosphere of the Environment: /// The more carbon dioxide in the atmosphere, the more likely it is for a Plant to be formed. /// </summary> /// <remarks> /// Author: Rudy Ariaz /// </remarks> /// <param name="gameEnv">The Environment of the Colony.</param> /// <returns>Enums.Animal if an Animal should be formed upon merging, Enums.Plant if a Plant /// should be formed upon merging.</returns> private Enums.UnitType GetMergeType(Environment gameEnv) { // The probability to merge into a plant is the normalized percentage // of the atmosphere that is carbon dioxide double plantProbability = gameEnv.CarbonDioxideLevel / 100.0; // Check if a Plant should be formed if (ProbabilityHelper.EvaluateIndependentPredicate(plantProbability)) { // Return Plant as the type of Multicellular organism to be formed return(Enums.UnitType.Plant); } // Otherwise, an Animal should be formed else { // Return Animal as the type of Multicellular organism to be formed return(Enums.UnitType.Animal); } }
/// <summary> /// Given probabilities for a new child Unit (a Unit occupying a previously-empty block) /// to be of each of its neighbors' species, find the neighbor with the same species as the child Unit. /// </summary> /// <param name="neighborProbabilities">A mapping between a block's neighbors, and the cumulative probabilities /// that each of them will be selected as a model neighbor.</param> /// <returns>The non-null Unit (one of the block's neighbors) whose type is the same /// as the child Unit's type.</returns> private static Unit GetModelNeighbor(Dictionary <Unit, double> neighborProbabilities) { // Convert the dictionary into an iterable list of key-value pairs, sorted in ascending order // since the probabilities are cumulative var neighbors = (from neighbor in neighborProbabilities orderby neighbor.Value ascending select neighbor).ToList(); // Get just the probabilities of each neighbor being selected as the model neighbor double[] sortedProbabilities = neighbors.Select(x => x.Value).ToArray(); // Keep, in a parallel array, the neighbors corresponding to each probability Unit[] correspondingSpecies = neighbors.Select(x => x.Key).ToArray(); // Get the index of the neighbor probabilistically selected to serve as a model neighbor int indexSelected = ProbabilityHelper.EvaluateDependentPredicate(sortedProbabilities); // Return the model neighbor return(correspondingSpecies[indexSelected]); }
/// <summary> /// Determine whether the LivingUnit is cured of infection. /// </summary> /// <remarks> /// Author: Rudy Ariaz /// </remarks> /// <returns>True if the LivingUnit is cured, false otherwise.</returns> protected bool IsCured() { // Evaluate whether the Unit is cured or not, depending on the cure probability return(ProbabilityHelper.EvaluateIndependentPredicate(CureProbabillity())); }