├── ProjectSettings ├── ProjectVersion.txt ├── TagManager.asset ├── TimeManager.asset ├── AudioManager.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── DynamicsManager.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── NetworkManager.asset ├── ProjectSettings.asset ├── QualitySettings.asset ├── Physics2DSettings.asset ├── ClusterInputManager.asset ├── EditorBuildSettings.asset └── UnityConnectSettings.asset ├── Assets ├── bob's maze.unity ├── Materials │ ├── Exit.mat │ ├── Path.mat │ ├── Wall.mat │ ├── Start.mat │ ├── Exit.mat.meta │ ├── Path.mat.meta │ ├── Start.mat.meta │ └── Wall.mat.meta ├── prefabs │ ├── exit.prefab │ ├── path.prefab │ ├── start.prefab │ ├── wall.prefab │ ├── exit.prefab.meta │ ├── path.prefab.meta │ ├── wall.prefab.meta │ └── start.prefab.meta ├── bob's maze.unity.meta ├── prefabs.meta ├── scripts.meta ├── Materials.meta └── scripts │ ├── Genome.cs.meta │ ├── GeneticAlgorithm.cs.meta │ ├── MazeController.cs.meta │ ├── Genome.cs │ ├── MazeController.cs │ └── GeneticAlgorithm.cs ├── README.md └── .gitignore /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.5.1f1 2 | -------------------------------------------------------------------------------- /Assets/bob's maze.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/bob's maze.unity -------------------------------------------------------------------------------- /Assets/Materials/Exit.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/Materials/Exit.mat -------------------------------------------------------------------------------- /Assets/Materials/Path.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/Materials/Path.mat -------------------------------------------------------------------------------- /Assets/Materials/Wall.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/Materials/Wall.mat -------------------------------------------------------------------------------- /Assets/Materials/Start.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/Materials/Start.mat -------------------------------------------------------------------------------- /Assets/prefabs/exit.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/prefabs/exit.prefab -------------------------------------------------------------------------------- /Assets/prefabs/path.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/prefabs/path.prefab -------------------------------------------------------------------------------- /Assets/prefabs/start.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/prefabs/start.prefab -------------------------------------------------------------------------------- /Assets/prefabs/wall.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/Assets/prefabs/wall.prefab -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/createthis/UnityGeneticAlgorithmMaze/HEAD/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /Assets/bob's maze.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 350fcc5b8bcae4938a9d86696b98c37c 3 | timeCreated: 1488663594 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Exit.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d888dc35ee4804c45a8dd4bb19680532 3 | timeCreated: 1488667263 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Path.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d87b91c5f378344a7850540d9f52ce26 3 | timeCreated: 1488667281 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Start.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01b0e9fe0c9794cd4adb9476baa15022 3 | timeCreated: 1488935974 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Wall.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc0e24779caeb435d93f257a87a2a1a1 3 | timeCreated: 1488667231 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/prefabs/exit.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e58ea0110ef4d43d08d694d5a60d75c6 3 | timeCreated: 1488669503 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/prefabs/path.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8598842c9cb9243538e56dc660e66b9d 3 | timeCreated: 1489023711 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/prefabs/wall.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79e74ed4f9b4b49c188fd5a5fe0eb347 3 | timeCreated: 1488667555 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/prefabs/start.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: be75a82a3d2e84d72829af014c5079c3 3 | timeCreated: 1488936140 4 | licenseType: Free 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/prefabs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 78589ef59e5b94330a4b602b07b38844 3 | folderAsset: yes 4 | timeCreated: 1488667522 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c10912f274fc45f79bdc8d1aec934de 3 | folderAsset: yes 4 | timeCreated: 1488663739 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 23340c6a635bb43f0a3c21c6b032cc84 3 | folderAsset: yes 4 | timeCreated: 1488667208 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/scripts/Genome.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0714c0683323e4c92af471f2be61ea9e 3 | timeCreated: 1488664827 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/GeneticAlgorithm.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 295d1d555fb454bdf98236ccc332561a 3 | timeCreated: 1488665956 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/scripts/MazeController.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 61bd68a7277a948c3aa1753daf06345a 3 | timeCreated: 1488663720 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityGeneticAlgorithmMaze 2 | Modern reimplementation in Unity of Bob's Map from [AI Techniques for Game Programming](http://amzn.to/2uJVV7w). 3 | 4 | To try it: 5 | 6 | 1. Clone this repo. 7 | 1. Download Unity 5.5.x. 8 | 1. Open the project with Unity 9 | 1. Open the scene `Assets/bob's maze.unity` 10 | 1. Press the play button. 11 | 12 | Or watch the video: 13 | 14 | [![Genetic Algorithm Youtube Video Demo](https://img.youtube.com/vi/mRGJZ9nDCkc/0.jpg)](https://www.youtube.com/watch?v=mRGJZ9nDCkc) 15 | -------------------------------------------------------------------------------- /Assets/scripts/Genome.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | 6 | public class Genome { 7 | public List bits; 8 | public double fitness; 9 | 10 | public Genome() { 11 | Initialize (); 12 | } 13 | 14 | public Genome(int numBits) { 15 | Initialize (); 16 | 17 | for (int i = 0; i < numBits; i++) { 18 | System.Random randomNumberGen = new System.Random(DateTime.Now.GetHashCode() * SystemInfo.processorFrequency.GetHashCode()); 19 | 20 | bits.Add(randomNumberGen.Next(0, 2)); 21 | } 22 | } 23 | 24 | private void Initialize() { 25 | fitness = 0; 26 | bits = new List (); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | [Bb]uild/ 2 | [Ll]ibrary/ 3 | [Oo]bj/ 4 | [Tt]emp/ 5 | UnityGenerated/ 6 | sysinfo.txt 7 | load.obj 8 | load.mtl 9 | load_orig.obj 10 | left.png 11 | right.png 12 | top.png 13 | bottom.png 14 | front.png 15 | back.png 16 | settings.json 17 | alignment_tools.json 18 | 19 | # Visual Studio/MonoDevelop/XCode generated 20 | 21 | *.booproj 22 | /*.csproj 23 | *.DotSettings 24 | *.opensdf 25 | *.pdb 26 | *.pdb.meta 27 | *.pidb 28 | *.sdf 29 | /*.sln 30 | *.suo 31 | *.svd 32 | *.unityproj 33 | *.user 34 | *.userprefs 35 | Assets/UnityVS* 36 | DerivedData/ 37 | ExportedObj/ 38 | Debug/ 39 | ipch/ 40 | Release/ 41 | 42 | # OS generated 43 | 44 | .DS_Store 45 | .DS_Store? 46 | ._* 47 | .Spotlight-V100 48 | .Trashes 49 | ehthumbs.db 50 | Thumbs.db 51 | 52 | # Icon must end with two \r 53 | Icon? 54 | 55 | # Coherent generated 56 | 57 | Assets/CoherentUI/DebuggerWindows.meta 58 | 59 | # External tools 60 | 61 | Assets/SteamVR/ 62 | Assets/SteamVR.meta 63 | 64 | min/ 65 | min.meta 66 | 67 | # Ion, nested clone 68 | ion 69 | ion-win 70 | ion-mac 71 | 72 | prepros 73 | prepros.meta 74 | prepros.cfg 75 | prepros.cfg.meta 76 | *.swp 77 | */*.swp 78 | -------------------------------------------------------------------------------- /Assets/scripts/MazeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | 7 | public class MazeController : MonoBehaviour { 8 | public int[,] map; 9 | public Vector2 startPosition; 10 | public Vector2 endPosition; 11 | public GameObject wallPrefab; 12 | public GameObject exitPrefab; 13 | public GameObject startPrefab; 14 | public GameObject pathPrefab; 15 | public GeneticAlgorithm geneticAlgorithm; 16 | public List fittestDirections; 17 | public List pathTiles; 18 | public GameObject text; 19 | 20 | public GameObject PrefabByTile(int tile) { 21 | if (tile == 1) return wallPrefab; 22 | if (tile == 5) return startPrefab; 23 | if (tile == 8) return exitPrefab; 24 | return null; 25 | } 26 | 27 | public Vector2 Move(Vector2 position, int direction) { 28 | switch (direction) { 29 | case 0: // North 30 | if (position.y - 1 < 0 || map [(int)(position.y - 1), (int)position.x] == 1) { 31 | break; 32 | } else { 33 | position.y -= 1; 34 | } 35 | break; 36 | case 1: // South 37 | if (position.y + 1 >= map.GetLength (0) || map [(int)(position.y + 1), (int)position.x] == 1) { 38 | break; 39 | } else { 40 | position.y += 1; 41 | } 42 | break; 43 | case 2: // East 44 | if (position.x + 1 >= map.GetLength (1) || map [(int)position.y, (int)(position.x + 1)] == 1) { 45 | break; 46 | } else { 47 | position.x += 1; 48 | } 49 | break; 50 | case 3: // West 51 | if (position.x - 1 < 0 || map [(int)position.y, (int)(position.x - 1)] == 1) { 52 | break; 53 | } else { 54 | position.x -= 1; 55 | } 56 | break; 57 | } 58 | return position; 59 | } 60 | 61 | public double TestRoute(List directions) { 62 | Vector2 position = startPosition; 63 | 64 | for (int directionIndex = 0; directionIndex < directions.Count; directionIndex++) { 65 | int nextDirection = directions [directionIndex]; 66 | position = Move (position, nextDirection); 67 | } 68 | 69 | Vector2 deltaPosition = new Vector2( 70 | Math.Abs(position.x - endPosition.x), 71 | Math.Abs(position.y - endPosition.y)); 72 | double result = 1 / (double)(deltaPosition.x + deltaPosition.y + 1); 73 | if (result == 1) 74 | Debug.Log ("TestRoute result=" + result + ",("+position.x+","+position.y+")"); 75 | return result; 76 | } 77 | 78 | public void Populate() { 79 | Debug.Log ("length(0)=" + map.GetLength(0)); 80 | Debug.Log ("length(1)=" + map.GetLength(1)); 81 | 82 | for (int y = 0; y < map.GetLength(0); y++) { 83 | for (int x = 0; x < map.GetLength(1); x++) { 84 | GameObject prefab = PrefabByTile (map [y, x]); 85 | if (prefab != null) { 86 | GameObject wall = Instantiate (prefab); 87 | wall.transform.position = new Vector3 (x, 0, -y); 88 | } 89 | } 90 | } 91 | } 92 | 93 | // Use this for initialization 94 | void Start () { 95 | map = new int[,] { 96 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, 97 | {1,0,1,0,0,0,0,0,1,1,1,0,0,0,1}, 98 | {8,0,0,0,0,0,0,0,1,1,1,0,0,0,1}, 99 | {1,0,0,0,1,1,1,0,0,1,0,0,0,0,1}, 100 | {1,0,0,0,1,1,1,0,0,0,0,0,1,0,1}, 101 | {1,1,0,0,1,1,1,0,0,0,0,0,1,0,1}, 102 | {1,0,0,0,0,1,0,0,0,0,1,1,1,0,1}, 103 | {1,0,1,1,0,0,0,1,0,0,0,0,0,0,5}, 104 | {1,0,1,1,0,0,0,1,0,0,0,0,0,0,1}, 105 | {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} 106 | }; 107 | Populate (); 108 | startPosition = new Vector2 (14f, 7f); 109 | endPosition = new Vector2 (0f, 2f); 110 | fittestDirections = new List (); 111 | pathTiles = new List (); 112 | 113 | geneticAlgorithm = new GeneticAlgorithm (); 114 | geneticAlgorithm.mazeController = this; 115 | geneticAlgorithm.Run (); 116 | } 117 | 118 | public void ClearPathTiles() { 119 | foreach (GameObject pathTile in pathTiles) { 120 | Destroy(pathTile); 121 | } 122 | pathTiles.Clear(); 123 | } 124 | 125 | public void RenderFittestChromosomePath() { 126 | ClearPathTiles (); 127 | Genome fittestGenome = geneticAlgorithm.genomes[geneticAlgorithm.fittestGenome]; 128 | List fittestDirections = geneticAlgorithm.Decode (fittestGenome.bits); 129 | Vector2 position = startPosition; 130 | 131 | foreach (int direction in fittestDirections) { 132 | position = Move (position, direction); 133 | GameObject pathTile = Instantiate (pathPrefab); 134 | pathTile.transform.position = new Vector3(position.x, 0, -position.y); 135 | pathTiles.Add (pathTile); 136 | } 137 | } 138 | 139 | // Update is called once per frame 140 | void Update () { 141 | if (geneticAlgorithm.busy) geneticAlgorithm.Epoch (); 142 | RenderFittestChromosomePath (); 143 | TextMesh textMesh = text.GetComponent (); 144 | Vector3 lastPosition = pathTiles.Last ().transform.position; 145 | textMesh.text = "Generation: " + geneticAlgorithm.generation + " (" + lastPosition.x + "," + lastPosition.z + ")"; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /Assets/scripts/GeneticAlgorithm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEngine; 6 | 7 | public class GeneticAlgorithm { 8 | public List genomes; 9 | public List lastGenerationGenomes; 10 | 11 | 12 | public int populationSize = 140; 13 | public double crossoverRate = 0.7f; 14 | public double mutationRate = 0.001f; 15 | public int chromosomeLength = 70; 16 | public int geneLength = 2; 17 | public int fittestGenome; 18 | public double bestFitnessScore; 19 | public double totalFitnessScore; 20 | public int generation; 21 | public MazeController mazeController; 22 | public MazeController mazeControllerDisplay; 23 | public bool busy; 24 | 25 | public GeneticAlgorithm() { 26 | busy = false; 27 | genomes = new List (); 28 | lastGenerationGenomes = new List (); 29 | } 30 | 31 | public void Mutate(List bits) { 32 | for (int i = 0; i < bits.Count; i++) { 33 | // flip this bit? 34 | if (UnityEngine.Random.value < mutationRate) { 35 | // flip the bit 36 | bits [i] = bits [i] == 0 ? 1 : 0; 37 | } 38 | } 39 | } 40 | 41 | public void Crossover(List mom, List dad, List baby1, List baby2) { 42 | if (UnityEngine.Random.value > crossoverRate || mom == dad) { 43 | baby1.AddRange(mom); 44 | baby2.AddRange(dad); 45 | 46 | return; 47 | } 48 | 49 | System.Random rnd = new System.Random (); 50 | 51 | int crossoverPoint = rnd.Next (0, chromosomeLength - 1); 52 | 53 | for (int i = 0; i < crossoverPoint; i++) { 54 | baby1.Add (mom [i]); 55 | baby2.Add (dad [i]); 56 | } 57 | 58 | for (int i = crossoverPoint; i < mom.Count; i++) { 59 | baby1.Add (dad [i]); 60 | baby2.Add (mom [i]); 61 | } 62 | } 63 | 64 | public Genome RouletteWheelSelection() { 65 | double slice = UnityEngine.Random.value * totalFitnessScore; 66 | double total = 0; 67 | int selectedGenome = 0; 68 | 69 | for (int i = 0; i < populationSize; i++) { 70 | total += genomes [i].fitness; 71 | 72 | if (total > slice) { 73 | selectedGenome = i; 74 | break; 75 | } 76 | } 77 | return genomes[selectedGenome]; 78 | } 79 | 80 | public void UpdateFitnessScores() { 81 | fittestGenome = 0; 82 | bestFitnessScore = 0; 83 | totalFitnessScore = 0; 84 | 85 | for (int i = 0; i < populationSize; i++) { 86 | List directions = Decode (genomes [i].bits); 87 | 88 | genomes [i].fitness = mazeController.TestRoute (directions); 89 | 90 | totalFitnessScore += genomes [i].fitness; 91 | 92 | if (genomes [i].fitness > bestFitnessScore) { 93 | bestFitnessScore = genomes [i].fitness; 94 | fittestGenome = i; 95 | 96 | // Has chromosome found the exit? 97 | if (genomes [i].fitness == 1) { 98 | busy = false; // stop the run 99 | return; 100 | } 101 | } 102 | } 103 | } 104 | 105 | //---------------------------Decode------------------------------------- 106 | // 107 | // decodes a List of bits into a List of directions (ints) 108 | // 109 | // 0=North, 1=South, 2=East, 3=West 110 | //----------------------------------------------------------------------- 111 | public List Decode(List bits) { 112 | List directions = new List (); 113 | 114 | for (int geneIndex = 0; geneIndex < bits.Count; geneIndex += geneLength) { 115 | List gene = new List (); 116 | 117 | for (int bitIndex = 0; bitIndex < geneLength; bitIndex++) { 118 | gene.Add (bits [geneIndex + bitIndex]); 119 | } 120 | 121 | directions.Add (GeneToInt (gene)); 122 | } 123 | return directions; 124 | } 125 | 126 | //-------------------------------GeneToInt------------------------------- 127 | // converts a List of bits into an integer 128 | //---------------------------------------------------------------------- 129 | public int GeneToInt(List gene) { 130 | int value = 0; 131 | int multiplier = 1; 132 | 133 | for (int i = gene.Count; i > 0; i--) { 134 | value += gene [i - 1] * multiplier; 135 | multiplier *= 2; 136 | } 137 | return value; 138 | } 139 | 140 | public void CreateStartPopulation() { 141 | genomes.Clear (); 142 | 143 | for (int i = 0; i < populationSize; i++) { 144 | Genome baby = new Genome (chromosomeLength); 145 | genomes.Add (baby); 146 | } 147 | } 148 | 149 | public void Run() { 150 | CreateStartPopulation (); 151 | busy = true; 152 | } 153 | 154 | public void Epoch() { 155 | if (!busy) return; 156 | UpdateFitnessScores (); 157 | 158 | if (!busy) { 159 | lastGenerationGenomes.Clear(); 160 | lastGenerationGenomes.AddRange (genomes); 161 | return; 162 | } 163 | 164 | int numberOfNewBabies = 0; 165 | 166 | List babies = new List (); 167 | while (numberOfNewBabies < populationSize) { 168 | // select 2 parents 169 | Genome mom = RouletteWheelSelection (); 170 | Genome dad = RouletteWheelSelection (); 171 | Genome baby1 = new Genome(); 172 | Genome baby2 = new Genome(); 173 | Crossover (mom.bits, dad.bits, baby1.bits, baby2.bits); 174 | Mutate (baby1.bits); 175 | Mutate (baby2.bits); 176 | babies.Add (baby1); 177 | babies.Add (baby2); 178 | 179 | numberOfNewBabies += 2; 180 | } 181 | 182 | // save last generation for display purposes 183 | lastGenerationGenomes.Clear(); 184 | lastGenerationGenomes.AddRange (genomes); 185 | // overwrite population with babies 186 | genomes = babies; 187 | 188 | // increment the generation counter 189 | generation++; 190 | } 191 | } 192 | --------------------------------------------------------------------------------