diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/Maze.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/Maze.java new file mode 100644 index 000000000..5c8b62b3c --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/features/Maze.java @@ -0,0 +1,144 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.levels.features; + +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.watabou.utils.Random; +import com.watabou.utils.Rect; + +public class Maze { + + public static boolean EMPTY = false; + public static boolean FILLED = true; + + public static boolean[][] generate(Room r){ + boolean[][] maze = new boolean[r.width()][r.height()]; + + for (int x = 0; x < maze.length; x++) { + for (int y = 0; y < maze[0].length; y++) { + if (x == 0 || x == maze.length - 1 || + y == 0 || y == maze[0].length - 1) { + + maze[x][y] = FILLED; + + } + } + } + + //set spaces where there are doors + for (Room.Door d : r.connected.values()) { + maze[d.x - r.left][d.y - r.top] = EMPTY; + } + + return generate(maze); + } + + public static boolean[][] generate(Rect r){ + return generate(r.width()+1, r.height()+1); + } + + public static boolean[][] generate(int width, int height){ + return generate(new boolean[width][height]); + } + + public static boolean[][] generate(boolean[][] maze){ + int fails = 0; + int x, y, moves; + int[] mov; + while (fails < 2500) { + + //find a random wall point + do { + x = Random.Int(maze.length); + y = Random.Int(maze[0].length); + } while (!maze[x][y]); + + //decide on how we're going to move + mov = decideDirection(maze, x, y); + if (mov == null) { + fails++; + } else { + + fails = 0; + moves = 0; + do { + x += mov[0]; + y += mov[1]; + maze[x][y] = FILLED; + moves++; + } while (Random.Int(moves+1) == 0 && checkValidMove(maze, x, y, mov)); + + } + + } + + return maze; + } + + private static int[] decideDirection(boolean[][] maze, int x, int y){ + + //attempts to move up + if (Random.Int(4) == 0 && //1 in 4 chance + checkValidMove(maze, x, y, new int[]{0, -1})){ + return new int[]{0, -1}; + } + + //attempts to move right + if (Random.Int(3) == 0 && //1 in 3 chance + checkValidMove(maze, x, y, new int[]{1, 0})){ + return new int[]{1, 0}; + } + + //attempts to move down + if (Random.Int(2) == 0 && //1 in 2 chance + checkValidMove(maze, x, y, new int[]{0, 1})){ + return new int[]{0, 1}; + } + + //attempts to move left + if ( + checkValidMove(maze, x, y, new int[]{-1, 0})){ + return new int[]{-1, 0}; + } + + return null; + } + + private static boolean checkValidMove( boolean[][] maze, int x, int y, int[] mov){ + int sideX = 1 - Math.abs(mov[0]); + int sideY = 1 - Math.abs(mov[1]); + + //checking two tiles forward in the movement, and the tiles to their left/right + for (int i = 0; i < 2; i ++) { + x += mov[0]; + y += mov[1]; + //checks if tiles we're examining are valid and open + if ( x > 0 && x < maze.length-1 && y > 0 && y < maze[0].length-1 && + !maze[x][y] && !maze[x + sideX][y+ sideY] && !maze[x - sideX][y - sideY]){ + continue; + } else { + return false; + } + } + return true; + } +} diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/MazeRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/MazeRoom.java index 6269db3fd..5aa655f17 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/MazeRoom.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/MazeRoom.java @@ -23,8 +23,8 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.rooms; import com.shatteredpixel.shatteredpixeldungeon.levels.Level; import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.levels.features.Maze; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; -import com.watabou.utils.Random; //TODO figure out where this should go, tunnel room type perhaps? public class MazeRoom extends Room { @@ -33,110 +33,15 @@ public class MazeRoom extends Room { Painter.fill(level, this, 1, Terrain.EMPTY); //true = space, false = wall - boolean[][] maze = new boolean[width()][height()]; - - for (int x = 0; x < maze.length; x++) { - for (int y = 0; y < maze[0].length; y++) { - if (x == 0 || x == maze.length - 1 || - y == 0 || y == maze[0].length - 1) { - - //set spaces where there are doors - for (Door d : connected.values()) { - if (d.x == x + left && d.y == y + top) { - maze[x][y] = true; - break; - } - } - - } else { - maze[x][y] = true; - } - } - } - - int fails = 0; - while (fails < 10000) { - - //find a random wall point - int x, y; - do { - x = Random.Int(maze.length); - y = Random.Int(maze[0].length); - } while (maze[x][y]); - - //decide on how we're going to move - int[] mov = decideDirection(maze, x, y); - if (mov == null) { - fails++; - } else { - - fails = 0; - int moves = 0; - do { - x += mov[0]; - y += mov[1]; - maze[x][y] = false; - moves++; - } while (Random.Int(moves+1) == 0 && checkValidMove(maze, x, y, mov)); - - } - - } + boolean[][] maze = Maze.generate(this); Painter.fill(level, this, 1, Terrain.EMPTY); for (int x = 0; x < maze.length; x++) for (int y = 0; y < maze[0].length; y++) { - if (!maze[x][y]) { + if (maze[x][y] == Maze.FILLED) { Painter.fill(level, x + left, y + top, 1, 1, Terrain.WALL); } } } - private static int[] decideDirection(boolean[][] maze, int x, int y){ - - //attempts to move up - if (Random.Int(4) == 0 && //1 in 4 chance - checkValidMove(maze, x, y, new int[]{0, -1})){ - return new int[]{0, -1}; - } - - //attempts to move right - if (Random.Int(3) == 0 && //1 in 3 chance - checkValidMove(maze, x, y, new int[]{1, 0})){ - return new int[]{1, 0}; - } - - //attempts to move down - if (Random.Int(2) == 0 && //1 in 2 chance - checkValidMove(maze, x, y, new int[]{0, 1})){ - return new int[]{0, 1}; - } - - //attempts to move left - if ( - checkValidMove(maze, x, y, new int[]{-1, 0})){ - return new int[]{-1, 0}; - } - - return null; - } - - private static boolean checkValidMove( boolean[][] maze, int x, int y, int[] mov){ - int sideX = 1 - Math.abs(mov[0]); - int sideY = 1 - Math.abs(mov[1]); - - //checking two tiles forward in the movement, and the tiles to their left/right - for (int i = 0; i < 2; i ++) { - x += mov[0]; - y += mov[1]; - //checks if tiles we're examining are valid and open - if ( x > 0 && x < maze.length-1 && y > 0 && y < maze[0].length-1 && - maze[x][y] && maze[x + sideX][y+ sideY] && maze[x - sideX][y - sideY]){ - continue; - } else { - return false; - } - } - return true; - } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/connection/MazeConnectionRoom.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/connection/MazeConnectionRoom.java new file mode 100644 index 000000000..785e0a312 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/connection/MazeConnectionRoom.java @@ -0,0 +1,52 @@ +/* + * Pixel Dungeon + * Copyright (C) 2012-2015 Oleg Dolya + * + * Shattered Pixel Dungeon + * Copyright (C) 2014-2017 Evan Debenham + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection; + +import com.shatteredpixel.shatteredpixeldungeon.levels.Level; +import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain; +import com.shatteredpixel.shatteredpixeldungeon.levels.features.Maze; +import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; + +public class MazeConnectionRoom extends ConnectionRoom { + + @Override + public void paint(Level level) { + super.paint(level); + + Painter.fill(level, this, 1, Terrain.EMPTY); + + //true = space, false = wall + boolean[][] maze = Maze.generate(this); + + Painter.fill(level, this, 1, Terrain.EMPTY); + for (int x = 0; x < maze.length; x++) + for (int y = 0; y < maze[0].length; y++) { + if (maze[x][y] == Maze.FILLED) { + Painter.fill(level, x + left, y + top, 1, 1, Terrain.WALL); + } + } + + for (Door door : connected.values()) { + door.set( Door.Type.TUNNEL ); + } + } +}