v0.6.0: Implemented room initialization, converted loads of logic to new levelgen structure

This commit is contained in:
Evan Debenham 2017-04-13 00:10:33 -04:00
parent 7153104e4d
commit 01b4653938
21 changed files with 397 additions and 211 deletions

View File

@ -134,7 +134,7 @@ public class Rect {
} }
public ArrayList<Point> getPoints() { public ArrayList<Point> getPoints() {
ArrayList<Point> points = new ArrayList<>(square()*2); ArrayList<Point> points = new ArrayList<>();
for (int i = left; i <= right; i++) for (int i = left; i <= right; i++)
for (int j = top; j <= bottom; j++) for (int j = top; j <= bottom; j++)
points.add(new Point(i, j)); points.add(new Point(i, j));

View File

@ -76,8 +76,6 @@ import java.util.HashSet;
public class Dungeon { public class Dungeon {
public static int transmutation; // depth number for a well of transmutation
//enum of items which have limited spawns, records how many have spawned //enum of items which have limited spawns, records how many have spawned
//could all be their own separate numbers, but this allows iterating, much nicer for bundling/initializing. //could all be their own separate numbers, but this allows iterating, much nicer for bundling/initializing.
//TODO: this is fairly brittle when it comes to bundling, should look into a more flexible solution. //TODO: this is fairly brittle when it comes to bundling, should look into a more flexible solution.
@ -156,9 +154,7 @@ public class Dungeon {
Potion.initColors(); Potion.initColors();
Ring.initGems(); Ring.initGems();
transmutation = Random.IntRange( 6, 14 ); SpecialRoom.initForRun();
SpecialRoom.shuffleTypes();
Random.seed(); Random.seed();
@ -454,8 +450,6 @@ public class Dungeon {
quickslot.storePlaceholders( bundle ); quickslot.storePlaceholders( bundle );
bundle.put( WT, transmutation );
int[] dropValues = new int[limitedDrops.values().length]; int[] dropValues = new int[limitedDrops.values().length];
for (limitedDrops value : limitedDrops.values()) for (limitedDrops value : limitedDrops.values())
dropValues[value.ordinal()] = value.count; dropValues[value.ordinal()] = value.count;
@ -563,8 +557,6 @@ public class Dungeon {
quickslot.restorePlaceholders( bundle ); quickslot.restorePlaceholders( bundle );
if (fullLoad) { if (fullLoad) {
transmutation = bundle.getInt( WT );
int[] dropValues = bundle.getIntArray(LIMDROPS); int[] dropValues = bundle.getIntArray(LIMDROPS);
for (limitedDrops value : limitedDrops.values()) for (limitedDrops value : limitedDrops.values())
value.count = value.ordinal() < dropValues.length ? value.count = value.ordinal() < dropValues.length ?

View File

@ -33,8 +33,7 @@ import com.shatteredpixel.shatteredpixeldungeon.items.quest.DarkGold;
import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe; import com.shatteredpixel.shatteredpixeldungeon.items.quest.Pickaxe;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.ScrollOfUpgrade;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.BlacksmithRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.BlacksmithRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite; import com.shatteredpixel.shatteredpixeldungeon.sprites.BlacksmithSprite;
@ -279,27 +278,13 @@ public class Blacksmith extends NPC {
} }
} }
//FIXME: refactor this to work with new levelgen public static ArrayList<Room> spawn( ArrayList<Room> rooms ) {
public static boolean spawn( ArrayList<Room> rooms ) {
if (!spawned && Dungeon.depth > 11 && Random.Int( 15 - Dungeon.depth ) == 0) { if (!spawned && Dungeon.depth > 11 && Random.Int( 15 - Dungeon.depth ) == 0) {
Room blacksmith; rooms.add(new BlacksmithRoom());
for (Room r : rooms) {
if (r instanceof StandardRoom && r.width() >= 6 && r.height() >= 6) {
blacksmith = new BlacksmithRoom().set(r);
rooms.set(rooms.indexOf(r), blacksmith);
spawned = true;
alternative = Random.Int( 2 ) == 0;
given = false;
break;
}
}
} }
return spawned; return rooms;
} }
} }
} }

View File

@ -37,7 +37,6 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.MassGraveRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.MassGraveRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RotGardenRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RotGardenRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.RitualSiteRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.RitualSiteRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.plants.Rotberry; import com.shatteredpixel.shatteredpixeldungeon.plants.Rotberry;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
@ -283,8 +282,7 @@ public class Wandmaker extends NPC {
} }
} }
//FIXME: refactor this to work with new levelgen public static ArrayList<Room> spawnRoom( ArrayList<Room> rooms) {
public static boolean spawnRoom( ArrayList<Room> rooms) {
questRoomSpawned = false; questRoomSpawned = false;
if (!spawned && (type != 0 || (Dungeon.depth > 6 && Random.Int( 10 - Dungeon.depth ) == 0))) { if (!spawned && (type != 0 || (Dungeon.depth > 6 && Random.Int( 10 - Dungeon.depth ) == 0))) {
@ -292,41 +290,22 @@ public class Wandmaker extends NPC {
// but if the no herbalism challenge is enabled, only pick 1 or 2, no rotberry. // but if the no herbalism challenge is enabled, only pick 1 or 2, no rotberry.
if (type == 0) type = Random.Int(Dungeon.isChallenged(Challenges.NO_HERBALISM) ? 2 : 3)+1; if (type == 0) type = Random.Int(Dungeon.isChallenged(Challenges.NO_HERBALISM) ? 2 : 3)+1;
//note that we set the type but can fail here. This ensures that if a level needs to be re-generated
//we don't re-roll the quest, it will try to assign itself to that new level with the same type.
Room questRoom = null;
for (Room r : rooms){
if (r instanceof StandardRoom && r.width() >= 7 && r.height() >= 7){
if (type == 2 || r.connected.size() == 1){
questRoom = r;
break;
}
}
}
if (questRoom == null){
return false;
}
Room temp = questRoom;
switch (type){ switch (type){
case 1: default: case 1: default:
questRoom = new MassGraveRoom().set(temp); rooms.add(new MassGraveRoom());
break; break;
case 2: case 2:
questRoom = new RitualSiteRoom().set(temp); rooms.add(new RitualSiteRoom());
break; break;
case 3: case 3:
questRoom = new RotGardenRoom().set(temp); rooms.add(new RotGardenRoom());
break; break;
} }
rooms.set(rooms.indexOf(temp), questRoom);
questRoomSpawned = true; questRoomSpawned = true;
return true;
} else {
return true;
} }
return rooms;
} }
public static void complete() { public static void complete() {

View File

@ -23,6 +23,7 @@ package com.shatteredpixel.shatteredpixeldungeon.levels;
import com.shatteredpixel.shatteredpixeldungeon.Assets; import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
@ -56,6 +57,8 @@ import com.watabou.utils.PointF;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import com.watabou.utils.Rect; import com.watabou.utils.Rect;
import java.util.ArrayList;
public class CavesLevel extends RegularLevel { public class CavesLevel extends RegularLevel {
{ {
@ -65,6 +68,21 @@ public class CavesLevel extends RegularLevel {
viewDistance = 6; viewDistance = 6;
} }
@Override
protected ArrayList<Room> initRooms() {
return Blacksmith.Quest.spawn(super.initRooms());
}
@Override
protected int standardRooms() {
return 5+Random.chances(new float[]{2, 2, 3, 2, 1, 1});
}
@Override
protected int specialRooms() {
return 1+Random.chances(new float[]{3, 3, 2, 1});
}
@Override @Override
public String tilesTex() { public String tilesTex() {
return Assets.TILES_CAVES; return Assets.TILES_CAVES;

View File

@ -58,6 +58,16 @@ public class CityLevel extends RegularLevel {
color2 = 0xf2f2f2; color2 = 0xf2f2f2;
} }
@Override
protected int standardRooms() {
return 6+Random.chances(new float[]{2, 3, 3, 2, 1});
}
@Override
protected int specialRooms() {
return 1 + Random.chances(new float[]{2, 3, 3, 1});
}
@Override @Override
public String tilesTex() { public String tilesTex() {
return Assets.TILES_CITY; return Assets.TILES_CITY;

View File

@ -59,7 +59,6 @@ import javax.microedition.khronos.opengles.GL10;
public class HallsLevel extends RegularLevel { public class HallsLevel extends RegularLevel {
{ {
minRoomSize = 7;
viewDistance = Math.max( 25 - Dungeon.depth, 1 ); viewDistance = Math.max( 25 - Dungeon.depth, 1 );
@ -67,6 +66,16 @@ public class HallsLevel extends RegularLevel {
color2 = 0xa68521; color2 = 0xa68521;
} }
@Override
protected int standardRooms() {
return 8+Random.chances(new float[]{3, 3, 2, 2, 1});
}
@Override
protected int specialRooms() {
return 1 + Random.chances(new float[]{1, 3, 3, 2});
}
@Override @Override
public void create() { public void create() {
addItemToSpawn( new Torch() ); addItemToSpawn( new Torch() );

View File

@ -28,11 +28,17 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder; import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LegacyBuilder; 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.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.FissureRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages; import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.watabou.noosa.Group; import com.watabou.noosa.Group;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import java.util.ArrayList;
public class LastShopLevel extends RegularLevel { public class LastShopLevel extends RegularLevel {
{ {
@ -50,11 +56,27 @@ public class LastShopLevel extends RegularLevel {
return Assets.WATER_CITY; return Assets.WATER_CITY;
} }
@Override
protected ArrayList<Room> initRooms() {
ArrayList<Room> rooms = new ArrayList<>();
rooms.add ( roomEntrance = new EntranceRoom());
rooms.add( roomExit = new ExitRoom());
if (Imp.Quest.isCompleted()){
rooms.add( new ShopRoom() );
} else {
rooms.add( new FissureRoom() );
}
return rooms;
}
@Override @Override
protected Builder builder() { protected Builder builder() {
feeling = Feeling.CHASM; feeling = Feeling.CHASM;
return new LegacyBuilder(LegacyBuilder.Type.LAST_SHOP, //TODO want to use strict line builder here
width, height, minRoomSize, maxRoomSize); return super.builder();
} }
@Override @Override

View File

@ -260,8 +260,6 @@ public abstract class Level implements Bundlable {
} while (!build()); } while (!build());
decorate(); decorate();
PathFinder.setMapSize(width(), height());
buildFlagMaps(); buildFlagMaps();
cleanWalls(); cleanWalls();

View File

@ -26,6 +26,7 @@ import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
import com.shatteredpixel.shatteredpixeldungeon.effects.Halo; import com.shatteredpixel.shatteredpixeldungeon.effects.Halo;
import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle; import com.shatteredpixel.shatteredpixeldungeon.effects.particles.FlameParticle;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.AlarmTrap; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.AlarmTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ChillingTrap; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ChillingTrap;
import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ConfusionTrap; import com.shatteredpixel.shatteredpixeldungeon.levels.traps.ConfusionTrap;
@ -48,6 +49,8 @@ import com.watabou.noosa.particles.Emitter;
import com.watabou.utils.PointF; import com.watabou.utils.PointF;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import java.util.ArrayList;
public class PrisonLevel extends RegularLevel { public class PrisonLevel extends RegularLevel {
{ {
@ -55,6 +58,21 @@ public class PrisonLevel extends RegularLevel {
color2 = 0x88924c; color2 = 0x88924c;
} }
@Override
protected ArrayList<Room> initRooms() {
return Wandmaker.Quest.spawnRoom(super.initRooms());
}
@Override
protected int standardRooms() {
return 4+Random.chances(new float[]{2, 3, 3, 2, 1});
}
@Override
protected int specialRooms() {
return 1+Random.chances(new float[]{4, 3, 3});
}
@Override @Override
public String tilesTex() { public String tilesTex() {
return Assets.TILES_PRISON; return Assets.TILES_PRISON;

View File

@ -33,11 +33,13 @@ import com.shatteredpixel.shatteredpixeldungeon.items.potions.Potion;
import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth; import com.shatteredpixel.shatteredpixeldungeon.items.rings.RingOfWealth;
import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll; import com.shatteredpixel.shatteredpixeldungeon.items.scrolls.Scroll;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder; import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LegacyBuilder; import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LineBuilder;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.RegularPainter; import com.shatteredpixel.shatteredpixeldungeon.levels.painters.RegularPainter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.WeakFloorRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.WeakFloorRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
@ -70,25 +72,53 @@ public abstract class RegularLevel extends Level {
builder = builder(); builder = builder();
rooms = builder.build(null);
if (rooms == null){ ArrayList<Room> initRooms = initRooms();
return false; Collections.shuffle(initRooms);
}
roomEntrance = ((LegacyBuilder)builder).roomEntrance; do {
roomExit = ((LegacyBuilder)builder).roomExit; for (Room r : initRooms){
r.neigbours.clear();
r.connected.clear();
}
rooms = builder.build(initRooms);
} while (rooms == null);
if (!painter().paint(this, rooms)){ return painter().paint(this, rooms);
return false;
}
return true; }
protected ArrayList<Room> initRooms() {
ArrayList<Room> initRooms = new ArrayList<>();
initRooms.add ( roomEntrance = new EntranceRoom());
initRooms.add( roomExit = new ExitRoom());
int standards = standardRooms();
for (int i = 0; i < standards; i++)
initRooms.add(StandardRoom.createRoom());
if (Dungeon.shopOnLevel())
initRooms.add(new ShopRoom());
int specials = specialRooms();
SpecialRoom.initForFloor();
for (int i = 0; i < specials; i++)
initRooms.add(SpecialRoom.createRoom());
return initRooms;
}
protected int standardRooms(){
return 0;
}
protected int specialRooms(){
return 0;
} }
protected Builder builder(){ protected Builder builder(){
return new LegacyBuilder(LegacyBuilder.Type.REGULAR, //TODO need a much better builder here
width, height, minRoomSize, maxRoomSize); return new LineBuilder();
} }
protected Painter painter(){ protected Painter painter(){
@ -137,9 +167,6 @@ public abstract class RegularLevel extends Level {
return new float[]{1}; return new float[]{1};
} }
protected int minRoomSize = 8;
protected int maxRoomSize = 10;
@Override @Override
public int nMobs() { public int nMobs() {
switch(Dungeon.depth) { switch(Dungeon.depth) {

View File

@ -21,7 +21,6 @@
package com.shatteredpixel.shatteredpixeldungeon.levels; package com.shatteredpixel.shatteredpixeldungeon.levels;
import com.shatteredpixel.shatteredpixeldungeon.Assets;
import com.shatteredpixel.shatteredpixeldungeon.Bones; import com.shatteredpixel.shatteredpixeldungeon.Bones;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor; import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
@ -30,17 +29,17 @@ import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Mob;
import com.shatteredpixel.shatteredpixeldungeon.items.Heap; import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
import com.shatteredpixel.shatteredpixeldungeon.items.Item; import com.shatteredpixel.shatteredpixeldungeon.items.Item;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder; import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LegacyBuilder;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RatKingRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.SewerBossEntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
import com.shatteredpixel.shatteredpixeldungeon.messages.Messages;
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene; import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
import com.watabou.noosa.Group;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.PathFinder;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class SewerBossLevel extends RegularLevel { import java.util.ArrayList;
public class SewerBossLevel extends SewerLevel {
{ {
color1 = 0x48763c; color1 = 0x48763c;
@ -50,41 +49,26 @@ public class SewerBossLevel extends RegularLevel {
private int stairs = 0; private int stairs = 0;
@Override @Override
public String tilesTex() { protected ArrayList<Room> initRooms() {
return Assets.TILES_SEWERS; ArrayList<Room> initRooms = new ArrayList<>();
initRooms.add ( roomEntrance = roomExit = new SewerBossEntranceRoom());
int standards = standardRooms();
for (int i = 0; i < standards; i++)
initRooms.add(StandardRoom.createRoom());
initRooms.add(new RatKingRoom());
return initRooms;
} }
@Override @Override
public String waterTex() { protected int standardRooms() {
return Assets.WATER_SEWERS; return 3+Random.chances(new float[]{4, 2, 2});
}
@Override
protected boolean build() {
if (!super.build())
return false;
//sticks the exit in the room entrance.
exit = roomEntrance.top * width() + (roomEntrance.left + roomEntrance.right) / 2;
map[exit] = Terrain.LOCKED_EXIT;
//make sure the exit is only visible in the entrance room.
int count = 0;
for (int i : PathFinder.NEIGHBOURS8){
//exit must have exactly 3 non-wall tiles around it.
if (map[exit+i] != Terrain.WALL)
count++;
}
if (count > 3)
return false;
return true;
} }
protected Builder builder(){ protected Builder builder(){
return new LegacyBuilder(LegacyBuilder.Type.SEWER_BOSS, //TODO want to use a more simple circular builder here
width, height, minRoomSize, maxRoomSize); return super.builder();
} }
@Override @Override
@ -111,29 +95,6 @@ public class SewerBossLevel extends RegularLevel {
return 0; return 0;
} }
@Override
protected void decorate() {
int start = roomExit.top * width() + roomExit.left + 1;
int end = start + roomExit.width() - 2;
for (int i=start; i < end; i++) {
if (i != exit && map[i] == Terrain.WALL) {
map[i] = Terrain.WALL_DECO;
map[i + width()] = Terrain.WATER;
} else {
map[i + width()] = Terrain.EMPTY;
}
}
placeSign();
}
@Override
public Group addVisuals() {
super.addVisuals();
SewerLevel.addSewerVisuals(this, visuals);
return visuals;
}
@Override @Override
protected void createMobs() { protected void createMobs() {
Mob mob = Bestiary.mob( Dungeon.depth ); Mob mob = Bestiary.mob( Dungeon.depth );
@ -209,26 +170,4 @@ public class SewerBossLevel extends RegularLevel {
stairs = bundle.getInt( STAIRS ); stairs = bundle.getInt( STAIRS );
roomExit = roomEntrance; roomExit = roomEntrance;
} }
@Override
public String tileName( int tile ) {
switch (tile) {
case Terrain.WATER:
return Messages.get(SewerLevel.class, "water_name");
default:
return super.tileName( tile );
}
}
@Override
public String tileDesc(int tile) {
switch (tile) {
case Terrain.EMPTY_DECO:
return Messages.get(SewerLevel.class, "empty_deco_desc");
case Terrain.BOOKSHELF:
return Messages.get(SewerLevel.class, "bookshelf_desc");
default:
return super.tileDesc( tile );
}
}
} }

View File

@ -53,6 +53,24 @@ public class SewerLevel extends RegularLevel {
color2 = 0x59994a; color2 = 0x59994a;
} }
@Override
protected int standardRooms() {
if (Dungeon.depth == 1){
return 5+Random.chances(new float[]{4, 3, 3});
} else {
return 4+Random.chances(new float[]{2, 4, 2, 1});
}
}
@Override
protected int specialRooms() {
if (Dungeon.depth == 1){
return 1;
} else {
return 1+Random.chances(new float[]{4, 4, 2});
}
}
@Override @Override
public String tilesTex() { public String tilesTex() {
return Assets.TILES_SEWERS; return Assets.TILES_SEWERS;

View File

@ -21,28 +21,11 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.builders; package com.shatteredpixel.shatteredpixeldungeon.levels.builders;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon; import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Imp;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Wandmaker;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ArmoryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.CryptRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.GardenRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.LaboratoryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.LibraryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.MagicWellRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.PitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RatKingRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.RatKingRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.ShopRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.SpecialRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.StatueRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.TreasuryRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.VaultRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special.WeakFloorRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.EntranceRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
@ -58,6 +41,9 @@ import java.util.ListIterator;
//This builder exactly mimics pre-0.6.0 levelgen, including all of its limitations //This builder exactly mimics pre-0.6.0 levelgen, including all of its limitations
//Currently implemented during this transition period, it will likely not survive to 0.6.0 release //Currently implemented during this transition period, it will likely not survive to 0.6.0 release
//this is now broken due to changes elsewhere and serves only as a reference for older logic.
//DO NOT USE, pending deletion before 0.6.0 release.
public class LegacyBuilder extends Builder { public class LegacyBuilder extends Builder {
public enum Type{ public enum Type{
@ -190,6 +176,7 @@ public class LegacyBuilder extends Builder {
} }
} }
/*
specials = new ArrayList<>( SpecialRoom.SPECIALS ); specials = new ArrayList<>( SpecialRoom.SPECIALS );
if (Dungeon.bossLevel( Dungeon.depth + 1 )) { if (Dungeon.bossLevel( Dungeon.depth + 1 )) {
specials.remove( WeakFloorRoom.class ); specials.remove( WeakFloorRoom.class );
@ -201,19 +188,21 @@ public class LegacyBuilder extends Builder {
if (Dungeon.isChallenged( Challenges.NO_HERBALISM )){ if (Dungeon.isChallenged( Challenges.NO_HERBALISM )){
//sorry warden, no lucky sungrass or blandfruit seeds for you! //sorry warden, no lucky sungrass or blandfruit seeds for you!
specials.remove( GardenRoom.class ); specials.remove( GardenRoom.class );
} }*/
if (!assignRoomType()) if (!assignRoomType())
return null; return null;
//Quest generation logic //Quest generation logic
//disabled due to incompatibilities with old logic
/*
if (Dungeon.depth >= 6 && Dungeon.depth <= 9){ if (Dungeon.depth >= 6 && Dungeon.depth <= 9){
if (!Wandmaker.Quest.spawnRoom( rooms ) && Dungeon.depth == 9) if (!Wandmaker.Quest.spawnRoom( rooms ) && Dungeon.depth == 9)
return null; return null;
} else if (Dungeon.depth >= 11 && Dungeon.depth <= 14){ } else if (Dungeon.depth >= 11 && Dungeon.depth <= 14){
if (!Blacksmith.Quest.spawn( rooms ) && Dungeon.depth == 14) if (!Blacksmith.Quest.spawn( rooms ) && Dungeon.depth == 14)
return null; return null;
} }*/
ArrayList<Room> resultRooms = new ArrayList<>(); ArrayList<Room> resultRooms = new ArrayList<>();
for (Room r : rooms) for (Room r : rooms)
@ -478,6 +467,8 @@ public class LegacyBuilder extends Builder {
boolean pitMade = false; boolean pitMade = false;
ListIterator<Room> it = rooms.listIterator(); ListIterator<Room> it = rooms.listIterator();
/*
while (it.hasNext()) { while (it.hasNext()) {
Room r = it.next(); Room r = it.next();
Room temp; Room temp;
@ -555,7 +546,7 @@ public class LegacyBuilder extends Builder {
} }
if (Level.pitRoomNeeded && !pitMade) return false; if (Level.pitRoomNeeded && !pitMade) return false;
*/
Class<? extends Room> tunnelType = TunnelRoom.class; Class<? extends Room> tunnelType = TunnelRoom.class;
if ((Dungeon.depth > 5 && Dungeon.depth <= 10) || if ((Dungeon.depth > 5 && Dungeon.depth <= 10) ||
(Dungeon.depth > 15 && Dungeon.depth <= 20)){ (Dungeon.depth > 15 && Dungeon.depth <= 20)){

View File

@ -58,7 +58,7 @@ public class LineBuilder extends Builder {
} }
} }
if (entrance == null || exit == null){ if (entrance == null){
return null; return null;
} }
@ -80,6 +80,9 @@ public class LineBuilder extends Builder {
Room curr = entrance; Room curr = entrance;
for (int i = 0; i <= roomsOnPath; i++){ for (int i = 0; i <= roomsOnPath; i++){
if (i == roomsOnPath && exit == null)
continue;
if (Random.Int(2) == 0){ if (Random.Int(2) == 0){
TunnelRoom t = new TunnelRoom(); TunnelRoom t = new TunnelRoom();
t.setSize(); t.setSize();

View File

@ -82,8 +82,6 @@ public class RegularPainter extends Painter {
level.setSize(width+1, height+1); level.setSize(width+1, height+1);
PathFinder.setMapSize(level.width(), level.height());
for (Room r : rooms) { for (Room r : rooms) {
placeDoors( r ); placeDoors( r );
r.paint( level ); r.paint( level );

View File

@ -21,7 +21,6 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special; package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon; import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfAwareness; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfAwareness;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfHealth; import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfHealth;
@ -38,6 +37,8 @@ public class MagicWellRoom extends SpecialRoom {
private static final Class<?>[] WATERS = private static final Class<?>[] WATERS =
{WaterOfAwareness.class, WaterOfHealth.class, WaterOfTransmutation.class}; {WaterOfAwareness.class, WaterOfHealth.class, WaterOfTransmutation.class};
public Class<?extends WellWater> overrideWater = null;
public void paint( Level level ) { public void paint( Level level ) {
Painter.fill( level, this, Terrain.WALL ); Painter.fill( level, this, Terrain.WALL );
@ -48,12 +49,12 @@ public class MagicWellRoom extends SpecialRoom {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Class<? extends WellWater> waterClass = Class<? extends WellWater> waterClass =
Dungeon.depth >= Dungeon.transmutation ? overrideWater != null ?
WaterOfTransmutation.class : overrideWater :
(Class<? extends WellWater>)Random.element( WATERS ); (Class<? extends WellWater>)Random.element( WATERS );
if (waterClass == WaterOfTransmutation.class) { if (waterClass == WaterOfTransmutation.class) {
Dungeon.transmutation = Integer.MAX_VALUE; SpecialRoom.disableGaranteedWell();
} }
WellWater water = (WellWater)level.blobs.get( waterClass ); WellWater water = (WellWater)level.blobs.get( waterClass );

View File

@ -92,6 +92,12 @@ public class ShopRoom extends SpecialRoom {
return Math.max(7, (int)(Math.sqrt(itemsToSpawn.size())+3)); return Math.max(7, (int)(Math.sqrt(itemsToSpawn.size())+3));
} }
//FIXME this is messy, the floor 21 shop should probably just be its own class.
@Override
public int maxConnections(int direction) {
return Dungeon.depth == 21 ? 2 : 1;
}
@Override @Override
public int minHeight() { public int minHeight() {
if (itemsToSpawn == null) generateItems(); if (itemsToSpawn == null) generateItems();

View File

@ -21,12 +21,17 @@
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special; package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special;
import com.shatteredpixel.shatteredpixeldungeon.Challenges;
import com.shatteredpixel.shatteredpixeldungeon.Dungeon;
import com.shatteredpixel.shatteredpixeldungeon.ShatteredPixelDungeon;
import com.shatteredpixel.shatteredpixeldungeon.actors.blobs.WaterOfTransmutation;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room; import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.watabou.utils.Bundle; import com.watabou.utils.Bundle;
import com.watabou.utils.Random; import com.watabou.utils.Random;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
public class SpecialRoom extends Room { public class SpecialRoom extends Room {
@ -60,41 +65,112 @@ public class SpecialRoom extends Room {
TreasuryRoom.class, TrapsRoom.class, StorageRoom.class, StatueRoom.class, LaboratoryRoom.class, VaultRoom.class TreasuryRoom.class, TrapsRoom.class, StorageRoom.class, StatueRoom.class, LaboratoryRoom.class, VaultRoom.class
) ); ) );
public static ArrayList<Class<? extends Room>> SPECIALS = new ArrayList<>(); public static ArrayList<Class<? extends Room>> runSpecials = new ArrayList<>();
public static ArrayList<Class<? extends Room>> floorSpecials = new ArrayList<>();
public static void shuffleTypes() { private static int pitNeededDepth = Integer.MAX_VALUE;
SPECIALS = (ArrayList<Class<?extends Room>>)ALL_SPEC.clone(); private static int guaranteedWellDepth = Integer.MAX_VALUE;
int size = SPECIALS.size();
for (int i=0; i < size - 1; i++) { public static void initForRun() {
int j = Random.Int( i, size ); runSpecials = (ArrayList<Class<?extends Room>>)ALL_SPEC.clone();
if (j != i) {
Class<?extends Room> c = SPECIALS.get( i ); //remove special rooms disallowed by challenges
SPECIALS.set( i, SPECIALS.get( j ) ); if (Dungeon.isChallenged( Challenges.NO_ARMOR )){
SPECIALS.set( j, c ); //no sense in giving an armor reward room on a run with no armor.
} runSpecials.remove( CryptRoom.class );
}
if (Dungeon.isChallenged( Challenges.NO_HERBALISM )){
//sorry warden, no lucky sungrass or blandfruit seeds for you!
runSpecials.remove( GardenRoom.class );
}
guaranteedWellDepth = Random.IntRange( 6, 14 );
Collections.shuffle(runSpecials);
}
public static void initForFloor(){
floorSpecials = (ArrayList<Class<?extends Room>>) runSpecials.clone();
}
private static void useType( Class<?extends Room> type ) {
if (runSpecials.remove( type )) {
floorSpecials.remove( type );
runSpecials.add( type );
} }
} }
public static void useType( Class<?extends Room> type ) { public static void disableGaranteedWell(){
if (SPECIALS.remove( type )) { guaranteedWellDepth = Integer.MAX_VALUE;
SPECIALS.add( type ); }
public static SpecialRoom createRoom(){
if (Dungeon.depth == pitNeededDepth){
pitNeededDepth = -1;
floorSpecials.remove( ArmoryRoom.class );
floorSpecials.remove( CryptRoom.class );
floorSpecials.remove( LaboratoryRoom.class );
floorSpecials.remove( LibraryRoom.class );
floorSpecials.remove( StatueRoom.class );
floorSpecials.remove( TreasuryRoom.class );
floorSpecials.remove( VaultRoom.class );
floorSpecials.remove( WeakFloorRoom.class );
return new PitRoom();
//TODO should laboratory rooms be more common like this?
} else if (Dungeon.depth % 5 == 2 && floorSpecials.contains( LaboratoryRoom.class )) {
useType(LaboratoryRoom.class);
return new LaboratoryRoom();
} else if (Dungeon.depth >= guaranteedWellDepth) {
useType( MagicWellRoom.class );
MagicWellRoom r = new MagicWellRoom();
r.overrideWater = WaterOfTransmutation.class;
guaranteedWellDepth = Integer.MAX_VALUE;
return r;
} else {
if (Dungeon.bossLevel(Dungeon.depth + 1)){
floorSpecials.remove(WeakFloorRoom.class);
}
Room r = null;
try {
r = floorSpecials.get( Math.min( Random.Int( floorSpecials.size() ), Random.Int( floorSpecials.size() ) ) ).newInstance();
} catch (Exception e) {
ShatteredPixelDungeon.reportException(e);
}
if (r instanceof WeakFloorRoom){
pitNeededDepth = Dungeon.depth + 1;
}
useType( r.getClass() );
return (SpecialRoom)r;
} }
} }
private static final String ROOMS = "special_rooms"; private static final String ROOMS = "special_rooms";
private static final String PIT = "pit_needed";
private static final String WELL = "guaranteed_well";
public static void restoreRoomsFromBundle( Bundle bundle ) { public static void restoreRoomsFromBundle( Bundle bundle ) {
if (bundle.contains( ROOMS )) { runSpecials.clear();
SPECIALS.clear(); for (Class<?extends Room> type : bundle.getClassArray( ROOMS )) {
for (Class<?extends Room> type : bundle.getClassArray( ROOMS )) { runSpecials.add( type );
SPECIALS.add( type );
}
} else {
shuffleTypes();
} }
pitNeededDepth = bundle.getInt(PIT);
guaranteedWellDepth = bundle.getInt(WELL);
} }
public static void storeRoomsInBundle( Bundle bundle ) { public static void storeRoomsInBundle( Bundle bundle ) {
bundle.put( ROOMS, SPECIALS.toArray(new Class[0]) ); bundle.put( ROOMS, runSpecials.toArray(new Class[0]) );
bundle.put( PIT, pitNeededDepth );
bundle.put( WELL, guaranteedWellDepth );
} }
} }

View File

@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> * along with this program. If not, see <http://www.gnu.org/licenses/>
*/ */
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.special; package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard;
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith; import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.npcs.Blacksmith;
import com.shatteredpixel.shatteredpixeldungeon.items.Generator; import com.shatteredpixel.shatteredpixeldungeon.items.Generator;
@ -30,9 +30,19 @@ import com.shatteredpixel.shatteredpixeldungeon.levels.traps.FireTrap;
import com.watabou.utils.Point; import com.watabou.utils.Point;
import com.watabou.utils.Random; import com.watabou.utils.Random;
public class BlacksmithRoom extends SpecialRoom { public class BlacksmithRoom extends StandardRoom {
public void paint( Level level ) { @Override
public int minWidth() {
return Math.max(super.minWidth(), 6);
}
@Override
public int minHeight() {
return Math.max(super.minHeight(), 6);
}
public void paint(Level level ) {
Painter.fill( level, this, Terrain.WALL ); Painter.fill( level, this, Terrain.WALL );
Painter.fill( level, this, 1, Terrain.TRAP ); Painter.fill( level, this, 1, Terrain.TRAP );

View File

@ -0,0 +1,86 @@
/*
* 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 <http://www.gnu.org/licenses/>
*/
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard;
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
import com.watabou.utils.Point;
public class SewerBossEntranceRoom extends EntranceRoom {
@Override
public int minWidth() {
return 11;
}
@Override
public int maxWidth() {
return 11;
}
@Override
public int minHeight() {
return 5;
}
@Override
public int maxHeight() {
return 8;
}
//TODO perhaps I just want to deny all top-side connections
@Override
public boolean canConnect(Point p) {
//refuses connections on the center 3 tiles on the top side
return super.canConnect(p)
&& !(p.y == top && p.x >= (left + (width()/2 - 1)) && p.x <= (left + (width()/2 + 1)));
}
public void paint(Level level ) {
Painter.fill( level, this, Terrain.WALL );
Painter.fill( level, this, 1, Terrain.EMPTY );
Painter.fill( level, left+1, top+1, width()-2, 1, Terrain.WALL_DECO);
Painter.fill( level, left+1, top+2, width()-2, 1, Terrain.WATER);
Painter.set( level, left+width()/2, top+1, Terrain.LOCKED_EXIT);
level.exit = level.pointToCell(new Point(left+width()/2, top+1));
do {
level.entrance = level.pointToCell(random(3));
} while (level.findMob(level.entrance) != null);
Painter.set( level, level.entrance, Terrain.ENTRANCE );
for (Room.Door door : connected.values()) {
door.set( Room.Door.Type.REGULAR );
if (door.y == top){
Painter.set( level, door.x, door.y+1, Terrain.WATER);
}
}
}
}