/// <summary> /// Remove a population from the RPM. /// </summary> public void RemovePopulation(Population population) { if (!Populations.Contains(population)) { return; } Populations.Remove(population); TypesOfTerrain.Remove(population); openID.Enqueue(PopulationToID[population]); PopulationByID.Remove(PopulationToID[population]); // free ID PopulationToID.Remove(population); // free ID CleanupAccessMapForRecycledID(); }
/// <summary> /// Add a population to the RPM. /// </summary> public void AddPopulation(Population population) { if (!Populations.Contains(population)) { // ignore their old id and assign it a new one int id = openID.Dequeue(); // since IDs after maxPopulation-1 are recycled ids, we need to do clean up old values if (id == lastRecycledID) { CleanupAccessMapForRecycledID(); } PopulationToID.Add(population, id); PopulationByID.Add(id, population); Populations.Add(population); TypesOfTerrain.Add(population, new int[(int)TileType.TypesOfTiles]); // generate the map with the new id GenerateMap(population); } }
/// <summary> /// Populate the access map for a population with depth first search. /// </summary> /// <param name="population">The population to be generated, assumed to be in Populations</param> /// <remarks>When this is called that means the terrain had changed for sure</remarks> private void GenerateMap(Population population) { Stack <Vector3Int> stack = new Stack <Vector3Int>(); HashSet <Vector3Int> accessible = new HashSet <Vector3Int>(); HashSet <Vector3Int> unaccessible = new HashSet <Vector3Int>(); Vector3Int cur; List <Vector3Int> newAccessibleLocations = new List <Vector3Int>(); List <Vector3Int> newLiquidLocations = new List <Vector3Int>(); List <float[]> newLiquidCompositions = new List <float[]>(); if (!this.AccessibleArea.ContainsKey(population)) { this.AccessibleArea.Add(population, new List <Vector3Int>()); } // Number of shared tiles long[] SharedTiles = new long[maxPopulation]; TileDataController gridSystemReference = GameManager.Instance.m_tileDataController; // starting location Vector3Int location = gridSystemReference.WorldToCell(population.transform.position); stack.Push(location); // Clear TypesOfTerrain for given population this.TypesOfTerrain[population] = new int[(int)TileType.TypesOfTiles]; // iterate until no tile left in list, ends in iteration 1 if population.location is not accessible while (stack.Count > 0) { // next point cur = stack.Pop(); if (accessible.Contains(cur) || unaccessible.Contains(cur)) { // checked before, move on continue; } // Check tiles that are under construction, make them inaccessible //if (this.buildBufferManager.IsConstructing(cur.x,cur.y)) //{ // unaccessible.Add(cur); // population.HasAccessibilityChanged = true; // continue; //} // check if tilemap has tile and if population can access the tile (e.g. some cannot move through water) GameTile tile = gridSystemReference.GetGameTileAt(cur); // Get liquid tile info if (tile != null && tile.type == TileType.Liquid) { float[] composition = new float[] { 0, 0, 0 }; LiquidbodyController.Instance.GetLiquidContentsAt(cur, out composition, out bool constructing); if (!this.populationAccessibleLiquidCompositions.ContainsKey(population)) { this.populationAccessibleLiquidCompositions.Add(population, new List <float[]>()); } if (!this.populationAccessibleLiquidLocations.ContainsKey(population)) { this.populationAccessibleLiquidLocations.Add(population, new List <Vector3Int>()); } newLiquidCompositions.Add(composition); newLiquidLocations.Add(cur); } if (tile != null && population.Species.AccessibleTerrain.Contains(tile.type)) { // save the accessible location accessible.Add(cur); // save to accessible location newAccessibleLocations.Add(cur); TypesOfTerrain[population][(int)tile.type]++; if (!AccessMap.ContainsKey(cur)) { AccessMap.Add(cur, 0L); } AccessMap[cur] |= 1L << PopulationToID[population]; // Collect info on how the population's space overlaps with others for (int i = 0; i < Populations.Count; i++) { SharedTiles[i] += (AccessMap[cur] >> PopulationToID[Populations[i]]) & 1L; } // check all 4 tiles around, may be too expensive/awaiting optimization stack.Push(cur + Vector3Int.left); stack.Push(cur + Vector3Int.up); stack.Push(cur + Vector3Int.right); stack.Push(cur + Vector3Int.down); } else { // save the Vector3Int since it is already checked unaccessible.Add(cur); } population.HasAccessibilityChanged = true; } // Amount of accessible area //Spaces[population] = accessible.Count; // Store the info on overlapping space int id = PopulationToID[population]; SharedSpaces[id] = SharedTiles; // Update the new info for pre-existing populations for (int i = 0; i < SharedSpaces[id].Length; i++) { if (PopulationByID.ContainsKey(i) && SharedSpaces[id][i] != 0) { SharedSpaces[i][id] = SharedSpaces[id][i]; } } // Update space if (population.HasAccessibilityChanged) { this.AccessibleArea[population] = newAccessibleLocations; this.populationAccessibleLiquidCompositions[population] = newLiquidCompositions; this.populationAccessibleLiquidLocations[population] = newLiquidLocations; } }