package mightypork.rogue.world.gen.rooms; import java.util.Random; import mightypork.gamecore.util.annot.DefaultImpl; import mightypork.gamecore.util.math.algo.Coord; import mightypork.gamecore.util.math.algo.Moves; import mightypork.rogue.world.gen.MapTheme; import mightypork.rogue.world.gen.RoomBuilder; import mightypork.rogue.world.gen.RoomEntry; import mightypork.rogue.world.gen.ScratchMap; import mightypork.rogue.world.gen.TileProtectLevel; import mightypork.rogue.world.tile.TileModel; public abstract class AbstractRectRoom implements RoomBuilder { @Override public RoomEntry buildRoom(ScratchMap map, MapTheme theme, Random rand, Coord center) { // half width, half height actually final Coord innerSize = getInnerSize(rand); final int width = 2 + innerSize.x - 1; final int height = 2 + innerSize.y - 1; final int wLow = (int) Math.round(width / 2D); final int wHigh = width - wLow; final int hLow = (int) Math.round(height / 2D); final int hHigh = height - hLow; final Coord min = new Coord(center.x - wLow, center.y - hLow); final Coord max = new Coord(center.x + wHigh, center.y + hHigh); if (!map.isClear(min.add(-1, -1), max)) return null; map.fill(min, max, getFloor(theme)); map.border(min, max, getWall(theme)); map.protect(min, max, getWallProtectionLevel()); placeDoors(map, theme, rand, min, max); buildExtras(map, theme, rand, min, max); return new RoomEntry(min.add(-1, -1), max); } protected TileModel getWall(MapTheme theme) { return theme.wall(); } protected TileModel getFloor(MapTheme theme) { return theme.floor(); } protected void placeDoors(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { final int width = max.x - min.x; final int height = max.y - min.y; for (int i = 0, j = 0; i < getDoorCount(rand) && j < 100; j++) { // j is to prevent inf loop final Coord door = min.copy(); switch (rand.nextInt(4)) { case 0: door.y = min.y; door.x += 1 + rand.nextInt(width - 1); break; case 1: door.y = max.y; door.x += 1 + rand.nextInt(width - 1); break; case 2: door.x = min.x; door.y += 1 + rand.nextInt(height - 1); break; case 3: door.x = max.x; door.y += 1 + rand.nextInt(height - 1); break; } if ((map.findDoors(door) & Moves.BITS_CARDINAL) == 0) { map.set(door, getDoorType(theme, rand)); i++; // increment pointer } } } @DefaultImpl protected void buildExtras(ScratchMap map, MapTheme theme, Random rand, Coord min, Coord max) { } protected abstract Coord getInnerSize(Random rand); protected abstract TileProtectLevel getWallProtectionLevel(); protected abstract TileModel getDoorType(MapTheme theme, Random rand); protected abstract int getDoorCount(Random rand); }