public void ConnectWith(Cell other) { var segment = new Line2D(new Point2D(x, y), new Point2D(other.X, other.Y)); var connector = new CellConnector(this, other, segment, ConnectorState.Unlinked); connectors.Add(connector); other.connectors.Add(connector); }
public void PlaceLocksAndKeys(Cell entrance, List<Cell> cells, Color[] keyColors) { if (keyColors.Length > cells.Count - 2) { throw new InvalidOperationException("The operation would require placing more than one key per cell or placing a key on the entrance."); } var lockedCells = cells.Where(x => x != entrance).Shuffle(random).Take(keyColors.Length).ToArray(); for (var i = 0 ; i < keyColors.Length; i++) { lockedCells[i].LockColor = keyColors[i]; } // Handle case where all entrance neighbors have a lock: Redistribute one lock elsewhere. var entranceNeighborCells = entrance.Connectors.Where(x => x.State == ConnectorState.Linked).Select(x => x.Other(entrance)); if (entranceNeighborCells.All(x => x.LockColor != Color.Empty)) { // Remove lock from random entrance neighbor and place in any other cell. var recipientCell = cells.Where(x => x.LockColor == Color.Empty).Shuffle().First(); var entranceNeighborCell = entranceNeighborCells.Shuffle().First(); recipientCell.LockColor = entranceNeighborCell.LockColor; entranceNeighborCell.LockColor = Color.Empty; } var visited = new HashSet<Cell>(); var frontline = new List<Cell>(); var keyable = new List<Cell>(); visited.Add(entrance); entrance.Connectors.Where(x => x.State == ConnectorState.Linked).Select(x => x.Other(entrance)).ForEach(frontline.Add); int keysRemaining = keyColors.Length; while (frontline.Any()) { var frontlineCellIndex = (int)(random.NextDouble() * frontline.Count); var frontlineCell = frontline[frontlineCellIndex]; frontline.RemoveAt(frontlineCellIndex); Console.WriteLine("!" + frontlineCell); if (frontlineCell.LockColor != Color.Empty) { var keyableCellIndex = (int)(random.NextDouble() * keyable.Count); var keyableCell = keyable[keyableCellIndex]; keyable.RemoveAt(keyableCellIndex); keyableCell.KeyColor = frontlineCell.LockColor; keysRemaining--; } keyable.Add(frontlineCell); if (keyable.Count > keysRemaining + keyColors.Length / 5) { keyable.RemoveAt(0); } visited.Add(frontlineCell); foreach (var neighbor in frontlineCell.Connectors.Where(x => x.State == ConnectorState.Linked).Select(x => x.Other(frontlineCell))) { if (!visited.Contains(neighbor)) { frontline.Add(neighbor); } } } }
public List<Cell> FillRegion(Cell initialSeed, Renderer renderer = null) { var seeds = new List<Cell>(); seeds.Add(initialSeed); var cells = new List<Cell>(); // includes all seeds - any room which has a clearly defined entrance cells.Add(initialSeed); while (seeds.Any()) { var index = (int)(seeds.Count * Math.Pow(random.NextDouble(), 0.25)); var seed = seeds.ElementAt(index); //GetRandomIntegerWeightedTowardEnd(seeds.Count, random)); var candidates = seed.Connectors.Where((c) => c.State == ConnectorState.Unlinked && !cells.Contains(c.Other(seed))).ToArray(); if (!candidates.Any()) { seeds.Remove(seed); continue; } CellConnector connector; if (candidates.Count() == 1) { seeds.Remove(seed); connector = candidates.First(); } else { connector = candidates.SelectRandom(); } connector.Connect(); var cell = connector.Other(seed); seeds.Add(cell); cells.Add(cell); renderer?.RenderGrid(grid); } return cells; }
public Grid(Cell[] cells, int width, int height) { this.cells = cells; this.width = width; this.height = height; }
public Cell Other(Cell cell) { if (cell == first) { return second; } else if (cell == second) { return first; } else { throw new InvalidOperationException(); } }
public CellConnector(Cell first, Cell second, Line2D segment, ConnectorState connectorState = ConnectorState.Unlinked) { this.first = first; this.second = second; this.segment = segment; this.connectorState = connectorState; }