PageRenderTime 40ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/Cas/Core/Species.cs

https://github.com/andrewanderson/Web-Critters
C# | 259 lines | 171 code | 31 blank | 57 comment | 22 complexity | e014a1a7b911423d415d1a6d201afc47 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Cas.Core.Interfaces;
  6. namespace Cas.Core
  7. {
  8. public class Species : ISpecies
  9. {
  10. /// <summary>
  11. /// Unique identifier for the species.
  12. /// </summary>
  13. public UniqueIdentifier Id {
  14. get
  15. {
  16. return this.id;
  17. }
  18. }
  19. private readonly UniqueIdentifier id;
  20. /// <summary>
  21. /// An example of the agent that this species represents
  22. /// </summary>
  23. public IAgent Exemplar {
  24. get
  25. {
  26. return this.exemplar;
  27. }
  28. }
  29. private readonly IAgent exemplar;
  30. /// <summary>
  31. /// The generation that this species first arose.
  32. /// </summary>
  33. public long FirstSeen
  34. {
  35. get
  36. {
  37. return this.firstSeen;
  38. }
  39. }
  40. private readonly long firstSeen;
  41. /// <summary>
  42. /// The species id(s) that this species arose from, if any.
  43. /// </summary>
  44. /// <remarks>
  45. /// Species that were created at the start of the simulation
  46. /// will have an empty list, species that arose from AsexualReproduction
  47. /// will have one Id, and species that arose from SexualReproduction
  48. /// will have two Ids.
  49. /// </remarks>
  50. public List<UniqueIdentifier> DerivedFromSpeciesIds
  51. {
  52. get
  53. {
  54. return this.derivedFromSpeciesIds;
  55. }
  56. }
  57. private readonly List<UniqueIdentifier> derivedFromSpeciesIds = new List<UniqueIdentifier>();
  58. /// <summary>
  59. /// The number of resources consumed from ResourceNodes
  60. /// across all agents in this species.
  61. /// </summary>
  62. public long ResourcesFromResourceNodes { get; private set; }
  63. /// <summary>
  64. /// The number of resources consumed from Agents
  65. /// across all agents in this species.
  66. /// </summary>
  67. public long ResourcesFromAgents { get; private set; }
  68. /// <summary>
  69. /// A classification of this species based of what it consumes.
  70. /// </summary>
  71. /// <remarks>
  72. /// 0-15% meat = herbivore
  73. /// 16-85% meat = omnivore
  74. /// 86-100% meat = carnivore
  75. /// </remarks>
  76. public DietType DietType
  77. {
  78. get
  79. {
  80. long totalConsumed = ResourcesFromAgents + ResourcesFromResourceNodes;
  81. if (totalConsumed == 0) return DietType.None;
  82. double percentMeat = (double)ResourcesFromAgents / (double)totalConsumed;
  83. if (percentMeat < 0.15)
  84. {
  85. return DietType.Herbivore;
  86. }
  87. else if (percentMeat > 0.85)
  88. {
  89. return DietType.Carnivore;
  90. }
  91. return DietType.Omnivore;
  92. }
  93. }
  94. private readonly ISimulation Simulation;
  95. protected readonly Dictionary<UniqueIdentifier, long> preyCounts = new Dictionary<UniqueIdentifier, long>();
  96. protected readonly Dictionary<UniqueIdentifier, long> predatorCounts = new Dictionary<UniqueIdentifier, long>();
  97. public Species(ISimulation simulation, IAgent exemplar, params UniqueIdentifier[] derivedFromSpeciesIds)
  98. {
  99. if (simulation == null) throw new ArgumentNullException("simulation");
  100. if (exemplar == null) throw new ArgumentNullException("exemplar");
  101. this.Simulation = simulation;
  102. this.firstSeen = simulation.CurrentGeneration;
  103. this.ResourcesFromResourceNodes = 0;
  104. this.ResourcesFromAgents = 0;
  105. this.Population = 0;
  106. this.id = CreateUniqueIdentifier(exemplar);
  107. this.derivedFromSpeciesIds.AddRange(derivedFromSpeciesIds);
  108. this.exemplar = exemplar.DeepCopy();
  109. }
  110. private static UniqueIdentifier CreateUniqueIdentifier(IAgent exemplar)
  111. {
  112. bool isFirst = true;
  113. // Build a list of tags, with a null between each agent's tags.
  114. var allTags = new List<Tag>();
  115. foreach (var cell in exemplar.Cells)
  116. {
  117. if (isFirst)
  118. {
  119. isFirst = false;
  120. }
  121. else
  122. {
  123. allTags.Add(null);
  124. }
  125. for (int i = 0; i < cell.ActiveTagsInModel; i++)
  126. {
  127. allTags.Add(cell.GetTagByIndex(i));
  128. }
  129. }
  130. return new UniqueIdentifier(IdentityType.Species, allTags.ToArray());
  131. }
  132. /// <summary>
  133. /// Report that an agent of this species consumed resources.
  134. /// </summary>
  135. public void RecordConsumptionOf(IIsUnique prey, int amount)
  136. {
  137. if (prey == null) throw new ArgumentNullException("prey");
  138. if (amount < 1) throw new ArgumentOutOfRangeException("amount");
  139. if (prey is ISpecies)
  140. {
  141. ResourcesFromAgents += amount;
  142. (prey as ISpecies).RecordPredation(this);
  143. }
  144. else if (prey is Corpse)
  145. {
  146. ResourcesFromAgents += amount;
  147. }
  148. else // IResourceNode
  149. {
  150. ResourcesFromResourceNodes += amount;
  151. }
  152. // Increment the counter for this consumption
  153. if (!preyCounts.ContainsKey(prey.Id))
  154. {
  155. preyCounts.Add(prey.Id, 0);
  156. }
  157. preyCounts[prey.Id] += 1;
  158. }
  159. /// <summary>
  160. /// Report that an agent of this species was successfully attacked by a predator.
  161. /// </summary>
  162. public void RecordPredation(ISpecies predator)
  163. {
  164. // Increment the counter for this consumption
  165. if (!predatorCounts.ContainsKey(predator.Id))
  166. {
  167. predatorCounts.Add(predator.Id, 0);
  168. }
  169. predatorCounts[predator.Id] += 1;
  170. }
  171. /// <summary>
  172. /// The total number of agents in the simulation with this species.
  173. /// </summary>
  174. public long Population { get; set; }
  175. /// <summary>
  176. /// The locations in the simulation where at least one member of this species can be found.
  177. /// </summary>
  178. public IEnumerable<ILocation> Habitat
  179. {
  180. get
  181. {
  182. return this.Simulation
  183. .Environment
  184. .Locations
  185. .Where(loc => loc.Agents.Any(agent => agent.Species == this));
  186. }
  187. }
  188. /// <summary>
  189. /// The foods that this species has consumed across all time, ordered by number of
  190. /// occurrences.
  191. /// </summary>
  192. public IEnumerable<IIsUnique> Prey
  193. {
  194. get
  195. {
  196. return this.preyCounts
  197. .OrderByDescending(kvp => kvp.Value)
  198. .Select(kvp =>
  199. {
  200. return (kvp.Key.Type == IdentityType.ResourceNode) ?
  201. this.Simulation.Environment.FindResourceNodeById(kvp.Key)
  202. : this.Simulation.GetSpeciesOrFossil(kvp.Key);
  203. });
  204. }
  205. }
  206. /// <summary>
  207. /// The agents that this species has been predated by across all time, ordered by number of
  208. /// occurences.
  209. /// </summary>
  210. public IEnumerable<IIsUnique> Predators
  211. {
  212. get
  213. {
  214. return this.predatorCounts
  215. .OrderByDescending(kvp => kvp.Value)
  216. .Select(kvp => this.Simulation.GetSpeciesOrFossil(kvp.Key));
  217. }
  218. }
  219. public string ToShortString()
  220. {
  221. return this.ToString();
  222. }
  223. public override string ToString()
  224. {
  225. return this.Id.ToString();
  226. }
  227. }
  228. }