void ConsumeMulch() { // consumes a mulch block if health below a certain amount and the only occupant of that mulch if (health < maxHealth / 3) { int x = (int)transform.position.x; int y = (int)(transform.position.y - 0.5f); int z = (int)transform.position.z; bool soloOccupied = true; if (wm.GetBlock(x, y, z) is Antymology.Terrain.MulchBlock && x > 5 && y > 5 && z > 5 && x < ConfigurationManager.Instance.World_Diameter * ConfigurationManager.Instance.Chunk_Diameter - 5 && y < ConfigurationManager.Instance.World_Height * ConfigurationManager.Instance.Chunk_Diameter - 5 && z < ConfigurationManager.Instance.World_Diameter * ConfigurationManager.Instance.Chunk_Diameter - 5) { foreach (GameObject ant in wm.Ants) { if (transform.position == ant.transform.position && !GameObject.ReferenceEquals(gameObject, ant)) { soloOccupied = false; } } if (soloOccupied) { AbstractBlock newBlock = new Antymology.Terrain.AirBlock(); wm.SetBlock(x, y, z, newBlock); transform.position = new Vector3(transform.position.x, transform.position.y - 1, transform.position.z); wm.surfaceBlocks[x, z]--; health = 1000; } } } }
/// <summary> /// Secrete some pheromone. The queen's pheromone is more intense. /// </summary> void Secrete(bool type, float amount) { int multiplier = 1; if (isQueen) { multiplier *= 10; } AirBlock here = (AirBlock)Surrounding[1, 3, 1]; here.pheromoneDeposits.AddOrUpdate(type, amount, (k, v) => v + amount * multiplier); }
/// <summary> /// Generates the preliminary world data based on perlin noise. /// </summary> private void GeneratePreliminaryWorld() { for (int x = 0; x < Blocks.GetLength(0); x++) { for (int z = 0; z < Blocks.GetLength(2); z++) { /** * These numbers have been fine-tuned and tweaked through trial and error. * Altering these numbers may produce weird looking worlds. **/ int stoneCeiling = SimplexNoise.GetPerlinNoise(x, 0, z, 10, 3, 1.2) + SimplexNoise.GetPerlinNoise(x, 300, z, 20, 4, 0) + 10; int grassHeight = SimplexNoise.GetPerlinNoise(x, 100, z, 30, 10, 0); int foodHeight = SimplexNoise.GetPerlinNoise(x, 200, z, 20, 5, 1.5); Topography[x, z] = stoneCeiling + grassHeight + foodHeight; for (int y = 0; y < Blocks.GetLength(1); y++) { if (y <= stoneCeiling) { Blocks[x, y, z] = new StoneBlock(); } else if (y <= stoneCeiling + grassHeight) { Blocks[x, y, z] = new GrassBlock(); } else if (y <= stoneCeiling + grassHeight + foodHeight) { Blocks[x, y, z] = new MulchBlock(); } else { Blocks[x, y, z] = new AirBlock(); } if ( x == 0 || x >= Blocks.GetLength(0) - 1 || z == 0 || z >= Blocks.GetLength(2) - 1 || y == 0 ) { Blocks[x, y, z] = new ContainerBlock(); } } } } }
/// <summary> /// This method performs a deep copy of the initial world state to a backup array for later restoration. /// </summary> private void CopyBlocks() { for (int x = 0; x < Blocks.GetLength(0); x++) { for (int y = 0; y < Blocks.GetLength(1); y++) { for (int z = 0; z < Blocks.GetLength(2); z++) { if (Blocks[x, y, z] is AirBlock) { InitialBlocks[x, y, z] = new AirBlock(); } else if (Blocks[x, y, z] is MulchBlock) { InitialBlocks[x, y, z] = new MulchBlock(); } else if (Blocks[x, y, z] is ContainerBlock) { InitialBlocks[x, y, z] = new ContainerBlock(); } else if (Blocks[x, y, z] is GrassBlock) { InitialBlocks[x, y, z] = new GrassBlock(); } else if (Blocks[x, y, z] is StoneBlock) { InitialBlocks[x, y, z] = new StoneBlock(); } else if (Blocks[x, y, z] is AcidicBlock) { InitialBlocks[x, y, z] = new AcidicBlock(); } else if (Blocks[x, y, z] is NestBlock) { InitialBlocks[x, y, z] = new NestBlock(); } InitialBlocks[x, y, z].worldXCoordinate = x; InitialBlocks[x, y, z].worldYCoordinate = y; InitialBlocks[x, y, z].worldZCoordinate = z; } } } }
void DigIfTooHigh() { // try to avoid getting stuck too high on a peak float groundHeight = transform.position.y - 0.5f; int x = (int)transform.position.x; int z = (int)transform.position.z; if (wm.surfaceBlocks[x - 1, z] + 2 < groundHeight && wm.surfaceBlocks[x + 1, z] + 2 < groundHeight && wm.surfaceBlocks[x, z - 1] + 2 < groundHeight && wm.surfaceBlocks[x, z + 1] + 2 < groundHeight) { int y = (int)(transform.position.y - 0.5f); if (wm.GetBlock(x, y, z) is Antymology.Terrain.GrassBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.StoneBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.AcidicBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.NestBlock) { AbstractBlock newBlock = new Antymology.Terrain.AirBlock(); wm.SetBlock(x, y, z, newBlock); transform.position = new Vector3(transform.position.x, transform.position.y - 1, transform.position.z); wm.surfaceBlocks[x, z]--; } } }
void Dig() { // dig up grasss, stone, acid, nest, or mulch blocks. helps to avoid getting stuck int x = (int)transform.position.x; int y = (int)(transform.position.y - 0.5f); int z = (int)transform.position.z; if (wm.GetBlock(x, y, z) is Antymology.Terrain.AirBlock) { transform.position = new Vector3(transform.position.x, transform.position.y - 1, transform.position.z); return; } if (wm.GetBlock(x, y, z) is Antymology.Terrain.GrassBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.StoneBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.AcidicBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.NestBlock || wm.GetBlock(x, y, z) is Antymology.Terrain.MulchBlock) { AbstractBlock newBlock = new Antymology.Terrain.AirBlock(); wm.SetBlock(x, y, z, newBlock); transform.position = new Vector3(transform.position.x, transform.position.y - 1, transform.position.z); wm.surfaceBlocks[x, z]--; } }
/// <summary> /// THIS CURRENTLY ONLY EXISTS AS A WAY OF SHOWING YOU WHATS POSSIBLE. /// </summary> /// <param name="neighbours"></param> public void Diffuse(AbstractBlock[,,] neighbours) { for (int i = 0; i < neighbours.GetLength(0); ++i) { for (int j = 0; i < neighbours.GetLength(1); ++j) { for (int k = 0; i < neighbours.GetLength(2); ++k) { AirBlock neighbour = neighbours[i, j, k] as AirBlock; if (neighbour != null) { foreach (KeyValuePair <bool, double> entry in neighbour.pheromoneDeposits) { pheromoneDeposits[entry.Key] = (pheromoneDeposits[entry.Key] + neighbour.pheromoneDeposits[entry.Key]) / 2; neighbour.pheromoneDeposits[entry.Key] = pheromoneDeposits[entry.Key]; } } } } } }
public void Reset(NeuralNetwork nextGen) { for (int i = 0; i < Blocks.GetLength(0); ++i) { for (int j = 0; j < Blocks.GetLength(1); ++j) { for (int k = 0; k < Blocks.GetLength(2); ++k) { Blocks[i, j, k] = new AirBlock(); } } } Destroy(GameObject.Find("Chunks")); for (int i = 0; i < Ants.Length; ++i) { Destroy(Ants[i]); } AntDirective = nextGen; Init(); }
public void Reset() { for (int i = 0; i < Blocks.GetLength(0); ++i) { for (int j = 0; j < Blocks.GetLength(1); ++j) { for (int k = 0; k < Blocks.GetLength(2); ++k) { Blocks[i, j, k] = new AirBlock(); } } } Destroy(GameObject.Find("Chunks")); for (int i = 0; i < Ants.Length; ++i) { Destroy(Ants[i]); } AntDirective.randomizeBiases(); AntDirective.randomizeWeights(); Init(); }
private void FixedUpdate() { if (ConfigurationManager.Instance.loadTopColony) { if (Input.GetKeyUp(KeyCode.KeypadPlus)) { topColony.MoveColony(); } return; } if (Input.GetKeyUp(KeyCode.End)) { pause = !pause; } if (pause && !Input.GetKeyUp(KeyCode.KeypadPlus)) { return; } // Update all ants // Must determine when to respawn everything bool allDead = true; // If all colonies dead, regenerate world and colonies foreach (Agents.Colony colony in colonies) { if (!colony.isAllDead()) { allDead = false; // Move all ants according to their environment and nervous system colony.MoveColony(); } } if (allDead) { generation++; float bestFitness = topColony.fitness(); foreach (Agents.Colony colony in colonies) { if (colony.getTotalNestBlocks() > bestFitness) { topColony.DestroyColony(); topColony = colony; bestFitness = colony.fitness(); noNewTopColonySince = generation; } } // Remove all but the best foreach (Agents.Colony colony1 in colonies) { if (colony1 != topColony) { colony1.DestroyColony(); } } Debug.Log("On generation " + generation.ToString() + " the best colony produced " + Mathf.Max(new float[] { colonies[0].getTotalNestBlocks(), colonies[1].getTotalNestBlocks(), colonies[2].getTotalNestBlocks(), colonies[3].getTotalNestBlocks() }).ToString() + " blocks."); Debug.Log("BUT no new top colony since generation " + noNewTopColonySince.ToString() + " with a global best of " + bestFitness.ToString()); Debug.Log("Queen of Top Colony size - nodes: " + topColony.queen.GetComponent <Agents.Ant>().getNervousSystem().nodes.Count.ToString() + " connections " + topColony.queen.GetComponent <Agents.Ant>().getNervousSystem().connections.Count.ToString()); if (bestFitness > prevBestFitness) { prevBestFitness = bestFitness; Serialize(new Agents.SerializableNS(topColony.bestAnt.GetComponent <Antymology.Agents.Ant>().getNervousSystem()), "ant.dat"); Serialize(new Agents.SerializableNS(topColony.queen.GetComponent <Antymology.Agents.Ant>().getNervousSystem()), "queen.dat"); } // Resetting the world if (generation % 10 == 0) { // Reset the world. Every 20 generations RNG = new System.Random((int)Time.time); SimplexNoise = new SimplexNoise((int)Time.time); // Initialize a new 3D array of blocks with size of the number of chunks times the size of each chunk Blocks = new AbstractBlock[ ConfigurationManager.Instance.World_Diameter * ConfigurationManager.Instance.Chunk_Diameter, ConfigurationManager.Instance.World_Height *ConfigurationManager.Instance.Chunk_Diameter, ConfigurationManager.Instance.World_Diameter *ConfigurationManager.Instance.Chunk_Diameter]; for (int i = 0; i < ConfigurationManager.Instance.World_Diameter * ConfigurationManager.Instance.Chunk_Diameter; i++) { for (int j = 0; j < ConfigurationManager.Instance.World_Height * ConfigurationManager.Instance.Chunk_Diameter; j++) { for (int k = 0; k < ConfigurationManager.Instance.World_Diameter * ConfigurationManager.Instance.Chunk_Diameter; k++) { Blocks[i, j, k] = new AirBlock(); } } } GameObject chunks = GameObject.Find("Chunks"); Destroy(chunks); // Initialize a new 3D array of chunks with size of the number of chunks Chunks = new Chunk[ ConfigurationManager.Instance.World_Diameter, ConfigurationManager.Instance.World_Height, ConfigurationManager.Instance.World_Diameter]; GenerateData(); GenerateChunks(); } GenerateAnts(); } }