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
new file mode 100644
index 000000000..0457030f6
--- /dev/null
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/builders/LineBuilder.java
@@ -0,0 +1,179 @@
+/*
+ * 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.special.ShopRoom;
+import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
+import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom;
+import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
+import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
+import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.tunnel.TunnelRoom;
+import com.watabou.utils.Random;
+
+import java.util.ArrayList;
+
+//A simple builder which puts most rooms in a straight line with a few branches
+public class LineBuilder extends Builder {
+ @Override
+ public ArrayList build(ArrayList rooms) {
+
+ Room entrance = null;
+ Room exit = null;
+ Room shop = null;
+ ArrayList standards = new ArrayList<>();
+ ArrayList specials = new ArrayList<>();
+
+ for (Room r : rooms){
+ if (r instanceof EntranceRoom){
+ entrance = r;
+ } else if (r instanceof ExitRoom) {
+ exit = r;
+ } else if (r instanceof ShopRoom){
+ shop = r;
+ } else if (r instanceof StandardRoom){
+ standards.add((StandardRoom)r);
+ } else if (r instanceof SpecialRoom){
+ specials.add((SpecialRoom)r);
+ }
+ }
+
+ if (entrance == null || exit == null){
+ return null;
+ }
+
+ ArrayList branchable = new ArrayList<>();
+
+ entrance.setSize();
+ entrance.setPos(0, -entrance.width()/2);
+ branchable.add(entrance);
+
+ if (shop != null){
+ shop.setSize();
+ shop.setPos(-shop.width(), -shop.height()/2);
+ shop.connect(entrance);
+ }
+
+ int standardsOnPath = standards.size()/2 + Random.Int(3) - 1;
+ standardsOnPath = Math.min(standardsOnPath, standards.size());
+
+ //standardsOnPath = standards.size();
+
+ Room curr = entrance;
+
+ for (int i = 0; i < standardsOnPath; i++){
+ if (Random.Int(3) == 0){
+ TunnelRoom t = new TunnelRoom();
+ t.setSize();
+ t.setPos( curr.right, -t.height()/2);
+ t.connect(curr);
+ rooms.add(t);
+ branchable.add(t);
+ curr = t;
+ }
+ if (Random.Int(3) == 0){
+ TunnelRoom t = new TunnelRoom();
+ t.setSize();
+ t.setPos( curr.right, -t.height()/2);
+ t.connect(curr);
+ rooms.add(t);
+ branchable.add(t);
+ curr = t;
+ }
+ StandardRoom s = standards.get(i);
+ s.setSize();
+ s.setPos( curr.right, -s.height()/2);
+ s.connect(curr);
+ branchable.add(s);
+ curr = s;
+ }
+
+ //place exit
+ exit.setSize();
+ exit.setPos( curr.right, -exit.height()/2);
+ exit.connect(curr);
+ branchable.add(exit);
+
+ ArrayList upBrancheable = new ArrayList<>(branchable);
+ ArrayList downBrancheable = new ArrayList<>(branchable);
+
+ //place branches
+ int i = standardsOnPath;
+ while (i < standards.size() + specials.size()){
+ boolean up = !upBrancheable.isEmpty() && (Random.Int(2) == 0 || downBrancheable.isEmpty());
+
+ if (up){
+ curr = Random.element(upBrancheable);
+ upBrancheable.remove(curr);
+ } else {
+ curr = Random.element(downBrancheable);
+ downBrancheable.remove(curr);
+ }
+
+ if (Random.Int(2) == 0){
+ TunnelRoom t = new TunnelRoom();
+ if (placeBranchRoom(up, curr, t, rooms)){
+ rooms.add(t);
+ } else {
+ continue;
+ }
+ curr = t;
+ }
+ if (Random.Int(3) == 0){
+ TunnelRoom t = new TunnelRoom();
+ if (placeBranchRoom(up, curr, t, rooms)){
+ rooms.add(t);
+ } else {
+ continue;
+ }
+ curr = t;
+ }
+ Room r;
+ if (i < standards.size()) {
+ r = standards.get(i);
+ } else {
+ r = specials.get(i - standards.size());
+ }
+
+ if (!placeBranchRoom(up, curr, r, rooms)){
+ continue;
+ }
+ if (r instanceof StandardRoom) {
+ if (up) upBrancheable.add(r);
+ else downBrancheable.add(r);
+ }
+ i++;
+ }
+
+ return rooms;
+
+ }
+
+ private boolean placeBranchRoom(boolean up, Room curr, Room next, ArrayList collision){
+ next.setSize();
+ next.setPos( curr.left + (curr.width()-next.width())/2, up ? curr.top - next.height()+1 : curr.bottom);
+ next.connect(curr);
+ return true;
+ }
+
+
+}
diff --git a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java
index 16a7547da..a4b3eb550 100644
--- a/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java
+++ b/core/src/main/java/com/shatteredpixel/shatteredpixeldungeon/levels/rooms/Room.java
@@ -123,22 +123,28 @@ public class Room extends Rect implements Graph.Node, Bundlable {
Random.Int( top + 1 + m, bottom - m ));
}
- public void addNeigbour( Room other ) {
+ public boolean addNeigbour( Room other ) {
+ if (neigbours.contains(other))
+ return true;
Rect i = intersect( other );
- if ((i.width() == 0 && i.height() >= 3) ||
- (i.height() == 0 && i.width() >= 3)) {
+ if ((i.width() == 0 && i.height() >= 2) ||
+ (i.height() == 0 && i.width() >= 2)) {
neigbours.add( other );
other.neigbours.add( this );
+ return true;
}
-
+ return false;
}
- public void connect( Room room ) {
+ public boolean connect( Room room ) {
+ if (!neigbours.contains(room) && !addNeigbour(room))
+ return false;
if (!connected.containsKey( room )) {
connected.put( room, null );
room.connected.put( this, null );
}
+ return true;
}
public boolean inside( Point p ) {