public void ConnectTo(RenderedTileInfo incoming) { if (!connectedTiles.Contains(incoming)) { connectedTiles.Add(incoming); } sourceNode.AddConnectedNode(incoming.sourceNode); }
// This attempts to add a new node to an existing graph. Both used by the initial generation and also used for mutation. public static void TryAddNodeToGraph(List <TileNode> graph) { TileData newTileType = TileGraphPCG.tileMap[PickRandomTile()]; TileNode connectionCandidate = graph[Random.Range(0, graph.Count)]; int b = 0; while (connectionCandidate.connectedNodes.Count >= connectionCandidate.type.doorLocs.Length && b <= graph.Count) { connectionCandidate = graph[Random.Range(0, graph.Count)]; b++; } // Failed to add. if (b == graph.Count) { Debug.LogWarning("Add node to graph failed"); return; } TileNode curr = new TileNode(newTileType); connectionCandidate.AddConnectedNode(curr); curr.AddConnectedNode(connectionCandidate); graph.Add(curr); }
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; }