public static void Erode(char[,] map, char wall = '#', char empty = ' ') { Coord size = map.GetSize(); Erode(map, coord => { char c = map.At(coord); if (c != wall) { return(false); } int count = 0; if (coord.row > 0 && map.At(coord + Coord.Up) == wall) { ++count; } if (coord.col > 0 && map.At(coord + Coord.Left) == wall) { ++count; } if (coord.row < size.row - 1 && map.At(coord + Coord.Down) == wall) { ++count; } if (coord.col < size.col - 1 && map.At(coord + Coord.Right) == wall) { ++count; } return(count == 1); }, c => map.SetAt(c, empty)); }
public Map2d(char[,] m) { Coord s = m.GetSize(); SetSize(m.GetSize()); s.ForEach(c => map.SetAt(c, m.At(c))); }
State IsMapWalkable(Coord position, Coord direction, Coord stepSize, Coord wallSize, char[,] map) { Coord size = map.GetSize(); Coord next = position + direction * stepSize; if (!next.IsWithin(size)) { return(State.OutOfBounds); } Coord end = next + direction * wallSize; if (!end.IsWithin(size)) { return(State.OutOfBounds); } char n = map.At(next), e = map.At(end); switch (n) { case Filled: switch (e) { case Filled: return(State.Unclaimed); case Walkable: return(State.Wall); default: return(State.Unknown); } case Walkable: switch (e) { case Filled: return(State.Incomplete); case Walkable: return(State.Empty); default: return(State.Unknown); } } return(State.Unknown); }
//public static void WriteMaze(int width, int height, int startx, int starty, // int stepx, int stepy, int wallx, int wally, int seed, string filename, int erosion = 0, ShowOption option = ShowOption.None) { // WriteMaze(new Coord(width, height), new Coord(startx, starty), // new Coord(stepx, stepy), new Coord(wallx, wally), seed, filename, erosion, option); //} //public static void WriteMaze(Coord size, Coord start, Coord step, Coord wall, int seed, string filename, int erosion = 0, // ShowOption option = ShowOption.None) { // string maze = CreateMaze(size, start, step, wall, seed, erosion, option); // System.IO.File.WriteAllText(filename, maze); //} //public static string CreateMaze(Coord size, Coord start, Coord step, Coord wall, int seed, int erosion = 0, ShowOption option = ShowOption.None) { // MazeGenerator mg = new MazeGenerator(seed); // mg.showOption = option; // char[,] map = mg.Generate(size, start, step, wall); // mg.Erode(map, erosion); // if ((mg.showOption & ShowOption.Final) != 0) mg.Show(map); // return ToString(map); //} public static string ToString(char[,] map) { StringBuilder sb = new StringBuilder(); Coord size = map.GetSize(), cursor; for (cursor.row = 0; cursor.row < size.row; ++cursor.row) { for (cursor.col = 0; cursor.col < size.col; ++cursor.col) { sb.Append(map.At(cursor)); } sb.Append('\n'); } return(sb.ToString()); }
public void Generate(NonStandard.Data.Random.NumberGenerator random) { int width = ((stage + 2) * 2) + 1; mazeGenerationArguments.size = new Vector2(width, width); if (mazeSrc == null) { int seed = mazeGenerationArguments.seed; if (seed < 0) { seed = (int)GameClock.Time; } MazeGenerator mg = new MazeGenerator(random.Next); char[,] map = mg.Generate(mazeGenerationArguments.size, mazeGenerationArguments.start, mazeGenerationArguments.step, mazeGenerationArguments.wall); mg.Erode(map, mazeGenerationArguments.erosion); // generate ramps Coord size = map.GetSize(); List <Coord>[] ramp = new List <Coord> [4]; for (int r = 0; r < ramp.Length; ++r) { ramp[r] = new List <Coord>(); } const int W = 0, N = 1, E = 2, S = 3;// todo nwse size.ForEach(c => { if (c.row == 0 || c.row == size.row - 1 || c.col == 0 || c.col == size.col - 1) { return; } char letter = map.At(c); char n = map.At(c + Coord.Up), s = map.At(c + Coord.Down), e = map.At(c + Coord.Right), w = map.At(c + Coord.Left); bool createAtDeadEnds = true; bool createAtPeninsula = true; if (n == s && e != w) { if (letter == e && w == n) { if (letter == ' ' && createAtDeadEnds) { ramp[W].Add(c); } if (letter == '#' && createAtPeninsula) { ramp[E].Add(c); } } if (letter == w && e == n) { if (letter == ' ' && createAtDeadEnds) { ramp[E].Add(c); } if (letter == '#' && createAtPeninsula) { ramp[W].Add(c); } } } if (e == w && n != s) { if (letter == n && s == w) { if (letter == ' ' && createAtDeadEnds) { ramp[S].Add(c); } if (letter == '#' && createAtPeninsula) { ramp[N].Add(c); } } if (letter == s && n == e) { if (letter == ' ' && createAtDeadEnds) { ramp[N].Add(c); } if (letter == '#' && createAtPeninsula) { ramp[S].Add(c); } } } }); //ramp[W].ForEach(c => { map.SetAt(c, 'w'); }); //ramp[N].ForEach(c => { map.SetAt(c, 'n'); }); //ramp[E].ForEach(c => { map.SetAt(c, 'e'); }); //ramp[S].ForEach(c => { map.SetAt(c, 's'); }); int totalRamps = ramp.Sum(r => r.Count); for (int i = 0; i < totalRamps && i < stage + 1; ++i) { int[] r = ramp.GetNestedIndex(random.Next(totalRamps)); //Debug.Log(r.JoinToString(", ")); Coord loc = ramp[r[0]][r[1]]; ramp[r[0]].RemoveAt(r[1]); char ch = "wnes"[r[0]]; map.SetAt(loc, ch); --totalRamps; } this.map = new Map2d(map); //Debug.Log(this.map); } else { map.LoadFromString(mazeSrc.text); } seen.Reset(); int count = map.Height * map.Width; while (mazeTiles.Count < count) { mazeTiles.Add(Instantiate(prefab_mazeTile.gameObject).GetComponent <MazeTile>()); } //int index = 0; Vector3 off = new Vector3(map.Width / -2f * tileSize.x, 0, map.Height / -2f * tileSize.z); floorTiles = new List <MazeTile>(); floorTileNeighborHistogram.SetEach(0); map.GetSize().ForEach(c => { MazeTile mt = GetTile(c);//mazeTiles[index++]; mt.maze = this; mt.coord = c; Transform t = mt.transform; t.SetParent(_t); t.localPosition = mt.CalcLocalPosition(); MazeTile.Kind k = MazeTile.Kind.None; switch (map[c]) { case ' ': k = MazeTile.Kind.Floor; break; case '#': k = MazeTile.Kind.Wall; break; case 'w': k = MazeTile.Kind.RampWest; break; case 'n': k = MazeTile.Kind.RampNorth; break; case 's': k = MazeTile.Kind.RampSouth; break; case 'e': k = MazeTile.Kind.RampEast; break; } mt.kind = k; mt.SetDiscovered(false, null, this); if (mt.kind == MazeTile.Kind.Floor) { floorTiles.Add(mt); mt.goalScore = TileScorer(mt, map); int index = (int)mt.goalScore; if (index >= floorTileNeighborHistogram.Length) { Array.Resize(ref floorTileNeighborHistogram, index + 1); } ++floorTileNeighborHistogram[index]; } else { mt.goalScore = float.PositiveInfinity; } }); floorTiles.Sort((a, b) => a.goalScore.CompareTo(b.goalScore)); }