public IMemberContainer CopyGenotype() { List<TileNode> newGraph = new List<TileNode>(); Dictionary<TileNode, TileNode> oldToNewMapping = new Dictionary<TileNode, TileNode>(); foreach (TileNode o in graph.nodes) { TileNode n = TileNode.Copy(o); oldToNewMapping.Add(o, n); newGraph.Add(n); } foreach (TileNode o in graph.nodes) { foreach (TileNode c in o.connectedNodes) { oldToNewMapping[o].AddConnectedNode(oldToNewMapping[c]); } } MemberTilePCG ret = new MemberTilePCG(); ret.graph = new TileGraph(newGraph); return ret; }
public IMemberContainer[] Crossover(IMemberContainer otherParent) { // This is difficult. // First (and bad) attempt: // 1. draw the same line through the origin in both graphs, splitting them. // 2. for each child, pick two nodes in the two halves as close to the origin as possible that have doors that used to be connected. // 3. connect the nodes on each half via the single door. // NOTE: THIS IS PRONE TO FAIL CATASTROPHICALLY. If the one new connection cannot be made, the entire crossover will fail. float angle = Random.Range(0, 180); // turn angle into vector Vector3 lineCheck = Quaternion.AngleAxis(angle, Vector3.up) * Vector3.forward; List<TileNode>[] mySplit = CreateHalvesAndCandidates(lineCheck, this); List<TileNode>[] otherSplit = CreateHalvesAndCandidates(lineCheck, (MemberTilePCG)otherParent); // Child 1 List<TileNode> firstChild = new List<TileNode>(); Dictionary<TileNode, TileNode> firstOldToNewMapping = new Dictionary<TileNode, TileNode>(); // First Half Copy foreach (TileNode t in mySplit[0]) { TileNode newTile = TileNode.Copy(t); firstOldToNewMapping[t] = newTile; firstChild.Add(newTile); foreach (TileNode c in t.connectedNodes) { if (firstOldToNewMapping.ContainsKey(c)) { newTile.AddConnectedNode(firstOldToNewMapping[c]); firstOldToNewMapping[c].AddConnectedNode(newTile); } } } // Second Half Copy foreach (TileNode t in otherSplit[1]) { TileNode newTile = TileNode.Copy(t); firstOldToNewMapping[t] = newTile; firstChild.Add(newTile); foreach (TileNode c in t.connectedNodes) { if (firstOldToNewMapping.ContainsKey(c)) { newTile.AddConnectedNode(firstOldToNewMapping[c]); firstOldToNewMapping[c].AddConnectedNode(newTile); } } } // Child 2 List<TileNode> secondChild = new List<TileNode>(); Dictionary<TileNode, TileNode> secondOldToNewMapping = new Dictionary<TileNode, TileNode>(); // First Half Copy foreach (TileNode t in mySplit[1]) { TileNode newTile = TileNode.Copy(t); secondOldToNewMapping[t] = newTile; secondChild.Add(newTile); foreach (TileNode c in t.connectedNodes) { if (secondOldToNewMapping.ContainsKey(c)) { newTile.AddConnectedNode(secondOldToNewMapping[c]); secondOldToNewMapping[c].AddConnectedNode(newTile); } } } // Second Half Copy foreach (TileNode t in otherSplit[0]) { TileNode newTile = TileNode.Copy(t); secondOldToNewMapping[t] = newTile; secondChild.Add(newTile); foreach (TileNode c in t.connectedNodes) { if (secondOldToNewMapping.ContainsKey(c)) { newTile.AddConnectedNode(secondOldToNewMapping[c]); secondOldToNewMapping[c].AddConnectedNode(newTile); } } } ConnectCandidates(this, mySplit[2], (MemberTilePCG)otherParent, otherSplit[3], firstOldToNewMapping); ConnectCandidates(this, mySplit[3], (MemberTilePCG)otherParent, otherSplit[2], secondOldToNewMapping); MemberTilePCG[] containers = new MemberTilePCG[2]; containers[0] = new MemberTilePCG(); containers[0].graph = new TileGraph(firstChild); containers[1] = new MemberTilePCG(); containers[1].graph = new TileGraph(secondChild); return containers; }