From d6005ad5d7b768f7a7e38e3f62bf4ec726132bd9 Mon Sep 17 00:00:00 2001 From: Evan Debenham Date: Tue, 2 May 2017 19:07:00 -0400 Subject: [PATCH] v0.6.0: refactored builder logic around a regular builder class --- .../levels/builders/BranchesBuilder.java | 40 +--- .../levels/builders/Builder.java | 73 -------- .../levels/builders/LineBuilder.java | 60 +----- .../levels/builders/LoopBuilder.java | 61 +----- .../levels/builders/RegularBuilder.java | 173 ++++++++++++++++++ 5 files changed, 184 insertions(+), 223 deletions(-) create mode 100644 core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/BranchesBuilder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/BranchesBuilder.java index 3458ab5b0..1f360e1ca 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/BranchesBuilder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/BranchesBuilder.java @@ -22,53 +22,17 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.builders; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; import com.watabou.utils.Random; import java.util.ArrayList; //A builder that creates only branches, very simple and very random -public class BranchesBuilder extends Builder { - - private float[] branchTunnelChances = new float[]{3, 2, 1}; - - public BranchesBuilder setTunnelLength( float[] branch){ - branchTunnelChances = branch; - return this; - } - - private float extraConnectionChance = 0.1f; - - public BranchesBuilder setExtraConnectionChance( float chance ){ - extraConnectionChance = chance; - return this; - } +public class BranchesBuilder extends RegularBuilder { @Override public ArrayList build(ArrayList rooms) { - Room entrance = null; - Room exit = null; - Room shop = null; - - ArrayList multiConnections = new ArrayList<>(); - ArrayList singleConnections = new ArrayList<>(); - - for (Room r : rooms){ - if (r instanceof EntranceRoom){ - entrance = r; - } else if (r instanceof ExitRoom) { - exit = r; - } else if (r instanceof ShopRoom && r.maxConnections(Room.ALL) == 1){ - shop = r; - } else if (r.maxConnections(Room.ALL) > 1){ - multiConnections.add(r); - } else if (r.maxConnections(Room.ALL) == 1){ - singleConnections.add(r); - } - } + setupRooms( rooms ); if (entrance == null){ return null; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java index 2ea66a5e7..9f63a69c4 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/Builder.java @@ -22,7 +22,6 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.builders; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom; import com.watabou.utils.GameMath; import com.watabou.utils.Point; import com.watabou.utils.PointF; @@ -242,76 +241,4 @@ public abstract class Builder { return -1; } } - - //places the rooms in roomsToBranch into branches from rooms in branchable. - //note that the three arrays should be separate, they may contain the same rooms however - protected static void createBranches( ArrayList rooms, ArrayList branchable, - ArrayList roomsToBranch, float[] connChances){ - - int i = 0; - float angle; - int tries; - Room curr; - ArrayList connectingRoomsThisBranch = new ArrayList<>(); - while (i < roomsToBranch.size()){ - - connectingRoomsThisBranch.clear(); - curr = Random.element(branchable); - - int connectingRooms = Random.chances(connChances); - for (int j = 0; j < connectingRooms; j++){ - ConnectionRoom t = ConnectionRoom.createRoom(); - tries = 10; - - do { - angle = placeRoom(rooms, curr, t, Random.Float(360f)); - tries--; - } while (angle == -1 && tries >= 0); - - if (angle == -1) { - for (Room r : connectingRoomsThisBranch){ - r.clearConnections(); - rooms.remove(r); - } - connectingRoomsThisBranch.clear(); - break; - } else { - connectingRoomsThisBranch.add(t); - rooms.add(t); - } - - curr = t; - } - - if (connectingRoomsThisBranch.size() != connectingRooms){ - continue; - } - - Room r = roomsToBranch.get(i); - - tries = 10; - - do { - angle = placeRoom(rooms, curr, r, Random.Float(360f)); - tries--; - } while (angle == -1 && tries >= 0); - - if (angle == -1){ - for (Room t : connectingRoomsThisBranch){ - t.clearConnections(); - rooms.remove(t); - } - connectingRoomsThisBranch.clear(); - continue; - } - - for (Room t : connectingRoomsThisBranch){ - branchable.add(t); - } - if (r.maxConnections(Room.ALL) > 1 && Random.Int(2) == 0) - branchable.add(r); - - i++; - } - } } diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LineBuilder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LineBuilder.java index fa6997ef8..5a52c2cf5 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LineBuilder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LineBuilder.java @@ -23,73 +23,17 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.builders; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; import com.watabou.utils.Random; import java.util.ArrayList; //A simple builder which utilizes a line as its core feature. -public class LineBuilder extends Builder { - - private float pathVariance = 45f; - - public LineBuilder setPathVariance( float var ){ - pathVariance = var; - return this; - } - - //path length is the percentage of pathable rooms that are on the path - private float pathLength = 0.1f; - //The chance weights for extra rooms to be added to the path - private float[] pathLenJitterChances = new float[]{0, 2, 1}; - - public LineBuilder setPathLength( float len, float[] jitter ){ - pathLength = len; - pathLenJitterChances = jitter; - return this; - } - - private float[] pathTunnelChances = new float[]{2, 3, 1}; - private float[] branchTunnelChances = new float[]{3, 2, 1}; - - public LineBuilder setTunnelLength( float[] path, float[] branch){ - pathTunnelChances = path; - branchTunnelChances = branch; - return this; - } - - private float extraConnectionChance = 0.1f; - - public LineBuilder setExtraConnectionChance( float chance ){ - extraConnectionChance = chance; - return this; - } +public class LineBuilder extends RegularBuilder { @Override public ArrayList build(ArrayList rooms) { - Room entrance = null; - Room exit = null; - Room shop = null; - - ArrayList multiConnections = new ArrayList<>(); - ArrayList singleConnections = new ArrayList<>(); - - for (Room r : rooms){ - if (r instanceof EntranceRoom){ - entrance = r; - } else if (r instanceof ExitRoom) { - exit = r; - } else if (r instanceof ShopRoom && r.maxConnections(Room.ALL) == 1){ - shop = r; - } else if (r.maxConnections(Room.ALL) > 1){ - multiConnections.add(r); - } else if (r.maxConnections(Room.ALL) == 1){ - singleConnections.add(r); - } - } + setupRooms(rooms); if (entrance == null){ return null; diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java index 7f3be771d..cadee87b3 100644 --- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LoopBuilder.java @@ -23,66 +23,19 @@ package com.shatteredpixel.shatteredpixeldungeon.levels.builders; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EmptyRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; -import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; import com.watabou.utils.Random; import java.util.ArrayList; //A builder with one core loop as its primary element -public class LoopBuilder extends Builder { +public class LoopBuilder extends RegularBuilder { //TODO customizeable equation for angle changes (currently we're just linear) - //path length is the percentage of pathable rooms that are on the loop - private float pathLength = 0.1f; - //The chance weights for extra rooms to be added to the path - private float[] pathLenJitterChances = new float[]{0, 2, 1}; - - public LoopBuilder setPathLength( float len, float[] jitter ){ - pathLength = len; - pathLenJitterChances = jitter; - return this; - } - - private float[] pathTunnelChances = new float[]{2, 3, 1}; - private float[] branchTunnelChances = new float[]{3, 2, 1}; - - public LoopBuilder setTunnelLength( float[] path, float[] branch){ - pathTunnelChances = path; - branchTunnelChances = branch; - return this; - } - - private float extraConnectionChance = 0.1f; - - public LoopBuilder setExtraConnectionChance( float chance ){ - extraConnectionChance = chance; - return this; - } - @Override public ArrayList build(ArrayList rooms) { - Room entrance = null; - Room exit = null; - Room shop = null; - - ArrayList multiConnections = new ArrayList<>(); - ArrayList singleConnections = new ArrayList<>(); - - for (Room r : rooms){ - if (r instanceof EntranceRoom){ - entrance = r; - } else if (r instanceof ExitRoom) { - exit = r; - } else if (r.maxConnections(Room.ALL) > 1){ - multiConnections.add(r); - } else if (r.maxConnections(Room.ALL) == 1){ - singleConnections.add(r); - } - } + setupRooms(rooms); if (entrance == null){ return null; @@ -116,13 +69,16 @@ public class LoopBuilder extends Builder { Room prev = entrance; float targetAngle = startAngle; float angleChange = 360f / loop.size(); - for (int i = 0; i < loop.size(); i++){ + for (int i = 1; i < loop.size(); i++){ Room r = loop.get(i); targetAngle += angleChange; if (placeRoom(rooms, prev, r, targetAngle) != -1) { prev = r; if (!rooms.contains(prev)) rooms.add(prev); + } else { + //FIXME this is lazy, there are ways to do this without relying on chance + return null; } } @@ -131,10 +87,7 @@ public class LoopBuilder extends Builder { return null; } - ArrayList branchable = new ArrayList<>(); - for (Room r : loop){ - if (r instanceof EmptyRoom) branchable.add(r); - } + ArrayList branchable = new ArrayList<>(loop); ArrayList roomsToBranch = new ArrayList<>(); roomsToBranch.addAll(multiConnections); diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java new file mode 100644 index 000000000..ed150bcf4 --- /dev/null +++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/RegularBuilder.java @@ -0,0 +1,173 @@ +/* + * 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.builders; + +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; +import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; +import com.watabou.utils.Random; + +import java.util.ArrayList; + +//Introduces the concept of a major path, and branches +// with tunnels padding rooms placed in them +public abstract class RegularBuilder extends Builder { + + // *** Parameter values for level building logic *** + // note that implementations do not have to use al of these variables + + protected float pathVariance = 45f; + + public RegularBuilder setPathVariance( float var ){ + pathVariance = var; + return this; + } + + //path length is the percentage of pathable rooms that are on + protected float pathLength = 0.1f; + //The chance weights for extra rooms to be added to the path + protected float[] pathLenJitterChances = new float[]{0, 2, 1}; + + public RegularBuilder setPathLength( float len, float[] jitter ){ + pathLength = len; + pathLenJitterChances = jitter; + return this; + } + + protected float[] pathTunnelChances = new float[]{2, 3, 1}; + protected float[] branchTunnelChances = new float[]{3, 2, 1}; + + public RegularBuilder setTunnelLength( float[] path, float[] branch){ + pathTunnelChances = path; + branchTunnelChances = branch; + return this; + } + + protected float extraConnectionChance = 0.1f; + + public RegularBuilder setExtraConnectionChance( float chance ){ + extraConnectionChance = chance; + return this; + } + + // *** Room Setup *** + + protected Room entrance = null; + protected Room exit = null; + protected Room shop = null; + + protected ArrayList multiConnections = new ArrayList<>(); + protected ArrayList singleConnections = new ArrayList<>(); + + protected void setupRooms(ArrayList rooms){ + entrance = exit = shop = null; + singleConnections.clear(); + multiConnections.clear(); + for (Room r : rooms){ + if (r instanceof EntranceRoom){ + entrance = r; + } else if (r instanceof ExitRoom) { + exit = r; + } else if (r.maxConnections(Room.ALL) > 1){ + multiConnections.add(r); + } else if (r.maxConnections(Room.ALL) == 1){ + singleConnections.add(r); + } + } + } + + // *** Branch Placement *** + + //places the rooms in roomsToBranch into branches from rooms in branchable. + //note that the three arrays should be separate, they may contain the same rooms however + protected static void createBranches(ArrayList rooms, ArrayList branchable, + ArrayList roomsToBranch, float[] connChances){ + + int i = 0; + float angle; + int tries; + Room curr; + ArrayList connectingRoomsThisBranch = new ArrayList<>(); + while (i < roomsToBranch.size()){ + + connectingRoomsThisBranch.clear(); + curr = Random.element(branchable); + + int connectingRooms = Random.chances(connChances); + for (int j = 0; j < connectingRooms; j++){ + ConnectionRoom t = ConnectionRoom.createRoom(); + tries = 10; + + do { + angle = placeRoom(rooms, curr, t, Random.Float(360f)); + tries--; + } while (angle == -1 && tries >= 0); + + if (angle == -1) { + for (Room r : connectingRoomsThisBranch){ + r.clearConnections(); + rooms.remove(r); + } + connectingRoomsThisBranch.clear(); + break; + } else { + connectingRoomsThisBranch.add(t); + rooms.add(t); + } + + curr = t; + } + + if (connectingRoomsThisBranch.size() != connectingRooms){ + continue; + } + + Room r = roomsToBranch.get(i); + + tries = 10; + + do { + angle = placeRoom(rooms, curr, r, Random.Float(360f)); + tries--; + } while (angle == -1 && tries >= 0); + + if (angle == -1){ + for (Room t : connectingRoomsThisBranch){ + t.clearConnections(); + rooms.remove(t); + } + connectingRoomsThisBranch.clear(); + continue; + } + + for (Room t : connectingRoomsThisBranch){ + branchable.add(t); + } + if (r.maxConnections(Room.ALL) > 1 && Random.Int(2) == 0) + branchable.add(r); + + i++; + } + } + +}