Build-Your-Own-World / byow / Core / Rectangle.java
Rectangle.java
Raw
package byow.Core;

import byow.TileEngine.TETile;
import byow.TileEngine.Tileset;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Random;

public class Rectangle {

    static LinkedList<Room> hallways = new LinkedList<>();
    static LinkedList<Rectangle> rectangles = new LinkedList<>();
    Rectangle rectangleOne;
    Rectangle rectangleTwo;
    Room rectangle;
    Room room;
    public static final int MIN_SIZE = 6;
    public static final int MAX_SIZE = 10;
    public static final int MAP_WIDTH = 100;
    public static final int MAP_HEIGHT = 50;

    public Rectangle(Room room) {
        this.rectangle = room;
    }


    public Room getRoom() {
        if (this.isFinalRectangle()) {
            return this.room;
        }
        if (this.rectangleOne != null) {
            Room roomOne = this.rectangleOne.getRoom();
            if (roomOne.x != -1) {
                return roomOne;
            }
        }
        if (this.rectangleTwo != null) {
            Room roomTwo = this.rectangleTwo.getRoom();
            if (roomTwo.x != -1) {
                return roomTwo;
            }
        }
        return new Room(-1, -1, 0, 0);
    }

    public static void createHallway(Random random, Rectangle one, Rectangle two) {
        Room first = one.getRoom();
        Room second = two.getRoom();
        int oneX = RandomUtils.uniform(random, first.x, first.x + first.width - 1);
        int oneY = RandomUtils.uniform(random, first.y, first.y + first.height - 1);
        int twoX = RandomUtils.uniform(random, second.x, second.x + second.width - 1);
        int twoY = RandomUtils.uniform(random, second.y, second.y + second.height - 1);


        int width = oneX - twoX;
        int height = oneY - twoY;

        if (width != 0) {
            if (random.nextBoolean()) {

                hallways.addLast(new Room(oneX, oneY, Math.abs(width) + 1, 1));

                if (height < 0) {
                    hallways.addLast(new Room(twoX, oneY, 1, Math.abs(height)));
                } else {
                    hallways.addLast(new Room(twoX, oneY, 1, -(Math.abs(height))));
                }
            } else {
                if (height < 0) {
                    hallways.addLast(new Room(oneX, oneY, 1, Math.abs(height)));
                } else {
                    hallways.addLast(new Room(oneX, twoY, 1, Math.abs(height)));
                }
                hallways.addLast(new Room(oneX, twoY, Math.abs(width) + 1, 1));
            }
        } else {
            if (height < 0) {
                hallways.addLast(new Room(oneX, oneY, 1, Math.abs(height)));
            } else {
                hallways.addLast(new Room(twoX, twoY, 1, Math.abs(height)));
            }
        }
    }


    public static void makeHallwayTiles(Rectangle rectangle, TETile[][] world) {
        if (rectangle == null) {
            return;
        }
        makeHallwayTiles(rectangle.rectangleOne, world);
        makeHallwayTiles(rectangle.rectangleTwo, world);
        Iterator<Room> allHallways = rectangle.hallways.iterator();
        while (allHallways.hasNext()) {
            Room hallway = allHallways.next();
            for (int i = hallway.x; i < hallway.x + hallway.width; i++) {
                for (int j = hallway.y; j < hallway.y + hallway.height; j++) {
                    if (i > MAP_WIDTH - 5 || j > MAP_HEIGHT - 5) {
                        break;
                    } else {
                        world[i][j] = Tileset.FLOOR;
                    }
                }
            }
        }
    }


    public boolean isFinalRectangle() {
        return this.rectangleOne == null && this.rectangleTwo == null;
    }

    public boolean splitRectangle(Random random) {
        if (!this.isFinalRectangle()) {
            return false;
        }
        if (!rectangle.ableToSplit(this.rectangle.width, this.rectangle.height)) {
            return false;
        }
        boolean direction = getSplitDirection(random, this.rectangle.width, this.rectangle.height);
        int split;
        if (direction) {
            split = RandomUtils.uniform(random, MIN_SIZE, this.rectangle.height - MIN_SIZE + 1);
            this.rectangleOne = new Rectangle(new Room(this.rectangle.x, this.rectangle.y,
                    this.rectangle.width, split));
            this.rectangleTwo = new Rectangle(new Room(this.rectangle.x, this.rectangle.y + split,
                    this.rectangle.width, this.rectangle.height - split));
        } else {
            split = RandomUtils.uniform(random, MIN_SIZE, this.rectangle.width - MIN_SIZE + 1);
            this.rectangleOne = new Rectangle(new Room(this.rectangle.x, this.rectangle.y,
                    split, this.rectangle.height));
            this.rectangleTwo = new Rectangle(new Room(this.rectangle.x + split, this.rectangle.y,
                    this.rectangle.width - split, this.rectangle.height));
        }
        this.rectangles.addLast(this.rectangleOne);
        this.rectangles.addLast(this.rectangleTwo);
        return true;
    }


    public boolean getSplitDirection(Random random, int width, int height) {
        if (width / height >= 1.1) {
            return false;
        } else if (height / width >= 1.1) {
            return true;
        } else {
            return random.nextBoolean();
        }
    }


    public static void createBSP(Random random, Rectangle rectangle) {
        if (rectangle.isFinalRectangle()) {
            if (rectangle.rectangle.width > MAX_SIZE || rectangle.rectangle.height > MAX_SIZE) {
                if (rectangle.splitRectangle(random)) {
                    createBSP(random, rectangle.rectangleOne);
                    createBSP(random, rectangle.rectangleTwo);
                }
            }
        }
    }





    public static TETile[][] initialize(String seed) {
        Random random = Helpers.seedToRandom(seed);
        Rectangle startingRectangle = new Rectangle(new Room(1, 1, MAP_WIDTH - 5, MAP_HEIGHT - 5));
        createBSP(random, startingRectangle);
        startingRectangle.makeRoom(random);
        //universe.initialize(MAP_WIDTH, MAP_HEIGHT);
        TETile[][] world = new TETile[MAP_WIDTH][MAP_HEIGHT];
        for (int x = 0; x < MAP_WIDTH; x += 1) {
            for (int y = 0; y < MAP_HEIGHT; y += 1) {
                world[x][y] = Tileset.NOTHING;
            }
        }
        makeRoomTiles(startingRectangle, world);
        makeHallwayTiles(startingRectangle, world);
        makeWalls(world);
        addAvatar(world);
        return world;
    }

    public static void addAvatar(TETile[][] world) {
        for (int i = 0; i < MAP_WIDTH; i++) {
            for (int j = 0; j < MAP_HEIGHT; j++) {
                if (world[i][j] == Tileset.FLOOR) {
                    world[i][j] = Tileset.AVATAR;
                    return;
                }
            }
        }
    }


    public void makeRoom(Random random) {
        if (this.rectangleOne != null) {
            this.rectangleOne.makeRoom(random);
        }
        if (this.rectangleTwo != null) {
            this.rectangleTwo.makeRoom(random);
        }
        if (this.rectangleOne != null && this.rectangleTwo != null) {
            createHallway(random, this.rectangleOne, this.rectangleTwo);
        }
        if (this.isFinalRectangle()) {
            int width = RandomUtils.uniform(random, this.rectangle.width / 2,
                    this.rectangle.width - 1);
            int height = RandomUtils.uniform(random, this.rectangle.height / 2,
                    this.rectangle.height - 1);
            int x = RandomUtils.uniform(random, 1, this.rectangle.width - width);
            int y = RandomUtils.uniform(random, 1, this.rectangle.height - height);
            this.room = new Room(this.rectangle.x + x, this.rectangle.y + y, width, height);
        }

    }


    public static void makeWalls(TETile[][] world) {
        for (int i = 1; i < MAP_WIDTH  - 1; i++) {
            for (int j = 1; j < MAP_HEIGHT - 1; j++) {
                if (world[i][j] == Tileset.NOTHING) {
                    if (world[i + 1][j + 1] == Tileset.FLOOR
                            || world[i][j + 1] == Tileset.FLOOR
                            || world[i - 1][j + 1] == Tileset.FLOOR
                            || world[i - 1][j] == Tileset.FLOOR
                            || world[i - 1][j - 1] == Tileset.FLOOR
                            || world[i][j - 1] == Tileset.FLOOR
                            || world[i + 1][j - 1] == Tileset.FLOOR
                            || world[i + 1][j] == Tileset.FLOOR) {
                        world[i][j] = Tileset.WALL;
                    }
                }
            }
        }
        for (int i = 1; i < MAP_WIDTH - 1; i++) {
            for (int j = 1; j < MAP_HEIGHT - 1; j++) {
                if (world[i][j] == Tileset.WALL) {
                    if (world[i][j + 1] == Tileset.FLOOR && world[i][j - 1] == Tileset.FLOOR
                            || world[i - 1][j] == Tileset.FLOOR && world[i + 1][j] == Tileset.FLOOR) {
                        world[i][j] = Tileset.FLOOR;
                    }
                }
            }
        }
    }

    public static void makeRoomTiles(Rectangle rectangle, TETile[][] world) {
        if (rectangle == null) {
            return;
        }

        if (rectangle.isFinalRectangle()) {
            for (int i = rectangle.room.x; i < rectangle.room.x + rectangle.room.width; i++) {
                for (int j = rectangle.room.y; j < rectangle.room.y + rectangle.room.height; j++) {
                    world[i][j] = Tileset.FLOOR;
                }
            }
            for (int i = rectangle.room.x; i <= rectangle.room.x + rectangle.room.width; i++) {
                world[i][rectangle.room.y] = Tileset.WALL;
                world[i][rectangle.room.y + rectangle.room.height] = Tileset.WALL;
            }
            for (int j = rectangle.room.y; j <= rectangle.room.y + rectangle.room.height; j++) {
                world[rectangle.room.x][j] = Tileset.WALL;
                world[rectangle.room.x + rectangle.room.width][j] = Tileset.WALL;
            }
        }
        else {
            makeRoomTiles(rectangle.rectangleOne, world);
            makeRoomTiles(rectangle.rectangleTwo, world);
        }
    }
}