public void NewGeneration(int newDNACount = 0, bool crossoverNewDNA = false) { // amount of DNA to hold in the new population int finalCount = _population.Count + newDNACount; // if there are no DNA to be generated then return if (finalCount <= 0) { return; } // if there is an existing population if (_population.Count > 0) { // recalculate the fitness rating CalculateFitness(); // sort the by best fitness rating _population.Sort(CompareDNA); } _newPopulation.Clear(); // generate a new population for (int i = 0; i < finalCount; i++) // finalCount or _population.Count { // elitism if (i < _elitism && i < _population.Count) { _newPopulation.Add(_population [i]); } else if (i < _population.Count || crossoverNewDNA == true) { // splice the DNA of the best parents AIDNA <T> parentA = ChooseParent(); AIDNA <T> parentB = ChooseParent(); // splice AIDNA <T> child = parentA.Splice(parentB); // change to mutate child.Mutate(_mutationRate); _newPopulation.Add(child); } else { // add a new DNA to the pool _newPopulation.Add(new AIDNA <T> (_DNACount, _rand, _getRandomGene, _fitnessFunction, true)); } } // keep track of old and new population List <AIDNA <T> > tempList = _population; _population = _newPopulation; _newPopulation = tempList; _currGeneration++; }
private void SpawnWave() { if (_genticAlgorithm.bestFitness == 1.0f) { Debug.Log("!!!!!BEST DNA REACHED!!!!!!!"); } else { // generate a new generation of DNA _genticAlgorithm.NewGeneration(); currentGeneration++; // update debug representation debugPopulation.Clear(); for (int i = 0; i < _genticAlgorithm.population.Count; i++) { debugPopulation.Add(_genticAlgorithm.population[i].genes[0]); } } // clear the population ready to spawn in new enemies _AIPopulation.Clear(); // keep track of spawn in locations so that there is no spawning // on a node that already contains an enemy List <Node> spawnedInNodes = new List <Node> (); for (int i = 0; i < _genticAlgorithm.population.Count; i++) { // get the traits from the population AIDNA <EvolutionTraits> traits = _genticAlgorithm.population [i]; // spawn in the enemy using the prefab GameObject newAI = Instantiate(_enemyPrefab); // apply to speed and damage from the traits/genes newAI.GetComponent <SimpleEnemyState> ().damage = Mathf.RoundToInt(traits.genes [0].muscleArm); newAI.GetComponent <SimpleEnemyState> ().speed = traits.genes [0].muscleLeg; // spawn enemy at an adjacent tile from the Boss (this.transform) List <Node> neighbours = _Grid.GetNeighbours(_Grid.NodeFromWorldPoint(this.transform.position)); foreach (Node node in neighbours) { // node must be walkable and not have been spawned on by another enemy if (node.walkable == true && spawnedInNodes.Contains(node) == false) { // update position newAI.transform.position = new Vector3(node.worldPosition.x, 1.0f, node.worldPosition.z); _AIPopulation.Add(newAI); spawnedInNodes.Add(node); break; } } } }
// Calculates the fitness rating for a gene in the population private float FitnessFunction(int index) { float score = 0.0f; // score between 0 and 100% AIDNA <EvolutionTraits> dna = _genticAlgorithm.population[index]; //one strong enemy is just as effective as many weak but fast enemies. // for this reason both the strengths are taken into one equation equally. score += dna.genes [0].muscleArm / _maxArm; score += dna.genes [0].muscleLeg / _maxLeg; score /= 2.0f; // as it is out of 1 return(score); }
// Better fitness rating means better DNA public int CompareDNA(AIDNA <T> a, AIDNA <T> b) { if (a.fitnessRating > b.fitnessRating) { return(-1); } else if (a.fitnessRating < b.fitnessRating) { return(1); } else { return(0); } }
public AIDNA <T> Splice(AIDNA <T> otherParent) { AIDNA <T> child = new AIDNA <T> (_genes.Length, _rand, _getRandomGene, _fitnessFunction, false); // splice choosing the next gene from a either of the parents // (50% chance of parent A, 50% chance of parent B) for (int i = 0; i < _genes.Length; i++) { if (_rand.NextDouble() < 0.5) { child._genes [i] = _genes[i]; } else { child._genes [i] = otherParent._genes [i]; } } return(child); }
public void CalculateFitness() { _fitnessTotal = 0; // find the best DNA in the population AIDNA <T> best = _population [0]; for (int i = 0; i < _population.Count; i++) { _fitnessTotal += _population [i].CalculateFitness(i); if (_population [i].fitnessRating > best.fitnessRating) { best = _population [i]; } } // store best fitness rating and its genes _bestFitness = best.fitnessRating; best.genes.CopyTo(_bestGenes, 0); }