private static void associateDeadEnds() { // For each cell, if it's a dead end (borders on three sides), make sure that the association points out, so we can trim it. foreach (var cell in cells) { directions dirOut = directions.multi; if (cell.associates != directions.multi) { continue; // Already associated! } for (int k = 0; k < 4; k++) { if (cell.IsBorder((directions)k)) { continue; } pwCell newCell = cell.InDirection((directions)k); if (newCell.associates == (directions)((k + 2) % 4)) { continue; // if associates to this one, it might as well be a border! } if (dirOut != directions.multi) { dirOut = directions.multi; break; } dirOut = (directions)k; } if (dirOut != directions.multi) { cell.associates = dirOut; Console.WriteLine($"Associating dead-end cell at {cell.myPoint} to direction {dirOut}"); changesThisPass++; } } }
private static void copyBorders() { // For all cells associated with a symmetry point, copy their association and borders. foreach (var cell in cells) { if (cell.centerPoint != invalid) { for (int k = 0; k < 4; k++) { if (cell.IsBorder((directions)k)) { Point opposite = Symmetry(cell.myPoint, cell.centerPoint); pwCell newCell = cells[(int)opposite.x, (int)opposite.y]; directions oppside = (directions)((k + 2) % 4); if (!newCell.IsBorder(oppside)) { Console.WriteLine($"Copying border from {cell.myPoint} to {opposite}."); newCell.SetBorder(oppside); } } } } } }
static void Create(int x, int y, char cell) { pwCell c = cells[x, y] = new pwCell(); c.myPoint = new Point { x = x, y = y }; if (x == 0) { c.SetBorder(directions.left); } if (y == 0) { c.SetBorder(directions.up); } if (x == width - 1) { c.SetBorder(directions.right); } if (y == height - 1) { c.SetBorder(directions.down); } switch (cell) { case 'w': c.associates = directions.none; // Associates with itself. c.centerPoint = c.myPoint; c.filled = false; break; case 'b': c.associates = directions.none; // Associates with itself. c.centerPoint = c.myPoint; c.filled = true; break; case ')': c.associates = directions.left; c.centerPoint = new Point { x = x - .5f, y = y }; c.filled = cells[x - 1, y].filled; cells[x - 1, y].associates = directions.right; cells[x - 1, y].centerPoint = c.centerPoint; break; case 'v': case 'V': c.associates = directions.up; c.centerPoint = new Point { x = x, y = y - .5f }; c.filled = cells[x, y - 1].filled; cells[x, y - 1].associates = directions.down; cells[x, y - 1].centerPoint = c.centerPoint; break; case '\\': // bottom left of a four. c.associates = directions.up; c.centerPoint = new Point { x = x + .5f, y = y - .5f }; c.filled = cells[x, y - 1].filled; cells[x, y - 1].associates = directions.right; cells[x, y - 1].centerPoint = c.centerPoint; break; case '/': // bottom right of a four. // bottom right c.associates = directions.left; c.centerPoint = new Point { x = x - .5f, y = y - .5f }; c.filled = cells[x, y - 1].filled; cells[x, y - 1].associates = directions.down; cells[x, y - 1].centerPoint = c.centerPoint; break; } }
private static void findConstrainedPoints() { // for each unassociated cell, if it can only reach cells of a single symmetry point, the cell must be associated with that symmetry point. // This code only looks one cell away. foreach (var cell in cells) { if (cell.centerPoint != invalid) { continue; } Point putativePoint = invalid; for (int k = 0; k < 4; k++) { if (cell.IsBorder((directions)k)) { continue; } pwCell newCell = cell.InDirection((directions)k); if (newCell.associates == (directions)((k + 2) % 4)) { continue; // if associates to this one, it might as well be a border! } if (newCell == null) { throw new Exception("You can't have a null cell the other side of a non-border"); // Shouldn't ever happen. } if (newCell.centerPoint != invalid) { if (putativePoint == invalid) { putativePoint = newCell.centerPoint; } else if (putativePoint != newCell.centerPoint) { putativePoint = invalid; break; // Can't set the center point to anything specific. } } else { // If it connects with an undecided cell, it's undecided. putativePoint = invalid; break; } } if (putativePoint != invalid) { Console.WriteLine($"Setting cell at {cell.myPoint} to associate with {putativePoint}"); cell.centerPoint = putativePoint; cell.filled = cells[(int)putativePoint.x, (int)putativePoint.y].filled; Point oppSide = Symmetry(cell.myPoint, putativePoint); pwCell oppCell = cells[(int)oppSide.x, (int)oppSide.y]; if (oppCell.centerPoint != invalid && oppCell.centerPoint != putativePoint) { throw new Exception("Can't associate symmetry point that's already associated elsewhere!"); } oppCell.centerPoint = putativePoint; oppCell.filled = cells[(int)putativePoint.x, (int)putativePoint.y].filled; changesThisPass++; } } }
public static void Initialize(int[,] dotArray) { width = (dotArray.GetUpperBound(0) + 1) / 2; height = (dotArray.GetUpperBound(1) + 1) / 2; cells = new pwCell[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { pwCell c = cells[x, y] = new pwCell(); c.myPoint = new Point { x = x, y = y }; if (x == 0) { c.SetBorder(directions.left); } if (y == 0) { c.SetBorder(directions.up); } if (x == width - 1) { c.SetBorder(directions.right); } if (y == height - 1) { c.SetBorder(directions.down); } } } for (int i = 0; i <= dotArray.GetUpperBound(0); i++) { for (int j = 0; j <= dotArray.GetUpperBound(1); j++) { Point centerPoint = new Point() { x = (float)i / 2.0f, y = (float)j / 2.0f }; pwCell c; int il, ih, jl, jh; if (i % 2 == 0) { ih = il = i / 2; } else { ih = 1 + (il = (i - 1) / 2); } if (j % 2 == 0) { jh = jl = j / 2; } else { jh = j + (jl = (j - 1) / 2); } for (int ii = il; ii <= ih; ii++) { for (int ij = jl; ij <= jh; ij++) { c = cells[ii, ij]; c.centerPoint = centerPoint; c.filled = (dotArray[i, j] == 2); c.associates = directions.none; // Associates with itself. if (ii == il && ij == jl && il != ih) { c.associates = directions.right; } if (ii == ih && ij == jh && il != ih) { c.associates = directions.left; } if (ij == jl && ii == ih && jl != jh) { c.associates = directions.down; } if (ij == jh && ii == il && jl != jh) { c.associates = directions.up; } } } } } }