v0.6.0: added connection limit logic for rooms

This commit is contained in:
Evan Debenham 2017-04-11 17:35:05 -04:00
parent 3c48ea8c3a
commit 9a902d97bd
9 changed files with 149 additions and 59 deletions

View File

@ -23,10 +23,8 @@ 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.Point;
import com.watabou.utils.Random;
@ -42,8 +40,9 @@ public class LineBuilder extends Builder {
Room entrance = null;
Room exit = null;
Room shop = null;
ArrayList<StandardRoom> standards = new ArrayList<>();
ArrayList<SpecialRoom> specials = new ArrayList<>();
ArrayList<Room> multiConnections = new ArrayList<>();
ArrayList<Room> singleConnections = new ArrayList<>();
for (Room r : rooms){
if (r instanceof EntranceRoom){
@ -52,10 +51,10 @@ public class LineBuilder extends Builder {
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);
} else if (r.maxConnections(Room.ALL) > 1){
multiConnections.add(r);
} else if (r.maxConnections(Room.ALL) == 1){
singleConnections.add(r);
}
}
@ -71,19 +70,17 @@ public class LineBuilder extends Builder {
if (shop != null){
shop.setSize();
shop.setPos(-shop.width(), -shop.height()/2);
shop.setPos(-shop.width()+1, -shop.height()/2);
shop.connect(entrance);
}
int standardsOnPath = standards.size()/5 + Random.Int(2);
standardsOnPath = Math.min(standardsOnPath, standards.size());
//standardsOnPath = standards.size();
int roomsOnPath = multiConnections.size()/5 + Random.Int(2);
roomsOnPath = Math.min(roomsOnPath, multiConnections.size());
Room curr = entrance;
for (int i = 0; i < standardsOnPath; i++){
if (Random.Int(3) == 0){
for (int i = 0; i <= roomsOnPath; i++){
if (Random.Int(2) == 0){
TunnelRoom t = new TunnelRoom();
t.setSize();
t.setPos( curr.right, -t.height()/2);
@ -92,7 +89,7 @@ public class LineBuilder extends Builder {
branchable.add(t);
curr = t;
}
if (Random.Int(3) == 0){
if (Random.Int(2) == 0){
TunnelRoom t = new TunnelRoom();
t.setSize();
t.setPos( curr.right, -t.height()/2);
@ -101,27 +98,26 @@ public class LineBuilder extends Builder {
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;
Room r = (i == roomsOnPath ? exit : multiConnections.get(i));
r.setSize();
r.setPos( curr.right, -r.height()/2);
r.connect(curr);
branchable.add(r);
curr = r;
}
//place exit
exit.setSize();
exit.setPos( curr.right, -exit.height()/2);
exit.connect(curr);
branchable.add(exit);
ArrayList<Room> upBrancheable = new ArrayList<>(branchable);
ArrayList<Room> 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());
int i = roomsOnPath;
while (i < multiConnections.size() + singleConnections.size()){
if (upBrancheable.isEmpty() && downBrancheable.isEmpty())
return null;
boolean up = downBrancheable.isEmpty()
|| (Random.Int(2) == 0 && !upBrancheable.isEmpty());
if (up){
curr = Random.element(upBrancheable);
@ -131,7 +127,7 @@ public class LineBuilder extends Builder {
downBrancheable.remove(curr);
}
if (Random.Int(2) == 0){
if (Random.Int(3) == 0){
TunnelRoom t = new TunnelRoom();
if (placeBranchRoom(up, curr, t, rooms)){
rooms.add(t);
@ -150,16 +146,16 @@ public class LineBuilder extends Builder {
curr = t;
}
Room r;
if (i < standards.size()) {
r = standards.get(i);
if (i < multiConnections.size()) {
r = multiConnections.get(i);
} else {
r = specials.get(i - standards.size());
r = singleConnections.get(i - multiConnections.size());
}
if (!placeBranchRoom(up, curr, r, rooms)){
continue;
}
if (r instanceof StandardRoom && Random.Int(3) == 0) {
if (r.canConnect(up ? Room.TOP : Room.BOTTOM) && Random.Int(3) == 0) {
if (up) upBrancheable.add(r);
else downBrancheable.add(r);
}

View File

@ -68,7 +68,13 @@ public class Room extends Rect implements Graph.Node, Bundlable {
return this;
}
//Note: when overriding these it is STRONGLY ADVISED to store any randomly decided values.
//TODO make abstract
public void paint(Level level){ }
// **** Spatial logic ****
//Note: when overriding these YOU MUST store any randomly decided values.
//With the same room and the same parameters these should always return
//the same value over multiple calls, even if there's some randomness initially.
public int minWidth(){
@ -128,15 +134,78 @@ public class Room extends Rect implements Graph.Node, Bundlable {
return super.height()+1;
}
public void paint(Level level){ }
public Point random() {
return random( 0 );
return random( 1 );
}
public Point random( int m ) {
return new Point( Random.Int( left + 1 + m, right - m ),
Random.Int( top + 1 + m, bottom - m ));
return new Point( Random.Int( left + m, right - m ),
Random.Int( top + m, bottom - m ));
}
public boolean inside( Point p ) {
return p.x > left && p.y > top && p.x < right && p.y < bottom;
}
public Point center() {
return new Point(
(left + right) / 2 + (((right - left) % 2) == 1 ? Random.Int( 2 ) : 0),
(top + bottom) / 2 + (((bottom - top) % 2) == 1 ? Random.Int( 2 ) : 0) );
}
// **** Connection logic ****
public static final int ALL = 0;
public static final int LEFT = 1;
public static final int TOP = 2;
public static final int RIGHT = 3;
public static final int BOTTOM = 4;
//TODO make abstract
public int minConnections(int direction){ return -1; }
public int curConnections(int direction){
if (direction == ALL) {
return connected.size();
} else {
int total = 0;
for (Room r : connected.keySet()){
Rect i = intersect( r );
if (direction == LEFT && i.width() == 0 && i.left == left) total++;
else if (direction == TOP && i.height() == 0 && i.top == top) total++;
else if (direction == RIGHT && i.width() == 0 && i.right == right) total++;
else if (direction == BOTTOM && i.height() == 0 && i.bottom == bottom) total++;
}
return total;
}
}
public int remConnections(int direction){
if (curConnections(ALL) >= maxConnections(ALL)) return 0;
else return maxConnections(direction) - curConnections(direction);
}
//TODO make abstract
public int maxConnections(int direction){ return -1; }
public boolean canConnect(int direction){
return remConnections(direction) > 0;
}
public boolean canConnect( Room r ){
Rect i = intersect( r );
if (i.width() == 0 && i.left == left)
return canConnect(LEFT);
else if (i.height() == 0 && i.top == top)
return canConnect(TOP);
else if (i.width() == 0 && i.right == right)
return canConnect(RIGHT);
else if (i.height() == 0 && i.bottom == bottom)
return canConnect(BOTTOM);
else
return false;
}
public boolean addNeigbour( Room other ) {
@ -154,23 +223,13 @@ public class Room extends Rect implements Graph.Node, Bundlable {
}
public boolean connect( Room room ) {
if (!neigbours.contains(room) && !addNeigbour(room))
return false;
if (!connected.containsKey( room )) {
if ((neigbours.contains(room) || addNeigbour(room))
&& !connected.containsKey( room ) && canConnect(room) && room.canConnect(this)) {
connected.put( room, null );
room.connected.put( this, null );
}
return true;
}
public boolean inside( Point p ) {
return p.x > left && p.y > top && p.x < right && p.y < bottom;
}
public Point center() {
return new Point(
(left + right) / 2 + (((right - left) % 2) == 1 ? Random.Int( 2 ) : 0),
(top + bottom) / 2 + (((bottom - top) % 2) == 1 ? Random.Int( 2 ) : 0) );
return false;
}
// **** Graph.Node interface ****

View File

@ -57,7 +57,7 @@ public class BlacksmithRoom extends SpecialRoom {
Blacksmith npc = new Blacksmith();
do {
npc.pos = level.pointToCell(random( 1 ));
npc.pos = level.pointToCell(random( 2 ));
} while (level.heaps.get( npc.pos ) != null);
level.mobs.add( npc );

View File

@ -52,7 +52,7 @@ public class RatKingRoom extends SpecialRoom {
}
RatKing king = new RatKing();
king.pos = level.pointToCell(random( 1 ));
king.pos = level.pointToCell(random( 2 ));
level.mobs.add( king );
}

View File

@ -40,6 +40,17 @@ public class SpecialRoom extends Room {
}
public int maxHeight() { return 10; }
@Override
public int minConnections(int direction) {
if (direction == ALL) return 1;
else return 0;
}
@Override
public int maxConnections(int direction) {
return 1;
}
public Door entrance() {
return connected.values().iterator().next();
}

View File

@ -48,7 +48,7 @@ public class EntranceRoom extends StandardRoom {
}
do {
level.entrance = level.pointToCell(random(1));
level.entrance = level.pointToCell(random(2));
} while (level.findMob(level.entrance) != null);
Painter.set( level, level.entrance, Terrain.ENTRANCE );
}

View File

@ -47,7 +47,7 @@ public class ExitRoom extends StandardRoom {
door.set( Room.Door.Type.REGULAR );
}
level.exit = level.pointToCell(random( 1 ));
level.exit = level.pointToCell(random( 2 ));
Painter.set( level, level.exit, Terrain.EXIT );
}

View File

@ -54,6 +54,18 @@ public abstract class StandardRoom extends Room {
public int minHeight() { return sizeCat.minDim; }
public int maxHeight() { return sizeCat.maxDim; }
@Override
public int minConnections(int direction) {
if (direction == ALL) return 1;
else return 0;
}
@Override
public int maxConnections(int direction) {
if (direction == ALL) return 16;
else return 4;
}
private static HashMap<Class<?extends StandardRoom>, Float> chances = new HashMap<>();
static {

View File

@ -37,6 +37,18 @@ public class TunnelRoom extends Room {
public int minHeight() { return 3; }
public int maxHeight() { return 10; }
@Override
public int minConnections(int direction) {
if (direction == ALL) return 2;
else return 0;
}
@Override
public int maxConnections(int direction) {
if (direction == ALL) return 16;
else return 4;
}
public void paint(Level level) {
int floor = level.tunnelTile();