Search code examples
javaalgorithmroguelike

Libgdx Generate RogueLIke Dungeon - Algorithm Error


I have used Libgdx to generate a dungeon out of keyboard characters. I have decided to print out the array as a text file.

However this is what I got:

I get this

Furthermore, It isn't consistent

Sometimes I get this

I don't get what is wrong? I checked over my algorithm and didn't find anything wrong.

Here is my code:

public class test1 extends ApplicationAdapter {
    SpriteBatch batch;
    Texture img;

    int X = 50;
    int Y = 25;

    ////////// # wall
    ////////// . ground
    char[][][] mapChars = new char[1000][1000][1000];

        private void genDung() {
        int clearance = 4;
        for (int i = 0; i < Y; i++) {
            for (int j = 0; j <= X; j++) {
                if(j == X)
                    mapChars[0][i][j] = '\n';
                else
                    mapChars[0][i][j] = '#';
            }
        }
        int roomCount = MathUtils.random(2, 2);
        int[] roomPosX = new int[roomCount];
        int[] roomPosY = new int[roomCount];
        int[] roomCenterPosX = new int[roomCount];
        int[] roomCenterPosY = new int[roomCount];
        int[] roomSizeX = new int[roomCount];
        int[] roomSizeY = new int[roomCount];

        for (int i = 0; i < roomCount; i++) {
            int attempts = 0;
            while(true) {
                boolean rePosition = false;
                roomPosX[i] = MathUtils.random(1, X-1);
                roomPosY[i] = MathUtils.random(1, Y-1);
                roomSizeX[i] = MathUtils.random(2, 12);
                roomSizeY[i] = MathUtils.random(2, 8);
                for(int j = 0; j <= i; j++) {
                    if(i != j) {
                        if(roomPosX[i] >= roomPosX[j] && roomPosX[i] <= (roomPosX[j] + roomSizeX[j] + clearance)) {
                            if(roomPosY[i] >= roomPosY[j] && roomPosY[i] <= (roomPosY[j] + roomSizeY[j] + clearance)) {
                                rePosition = true;
                                break;
                            }
                        }
                        if((roomPosX[i]+roomSizeX[i]) >= roomPosX[j] && (roomPosX[i]+roomSizeX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
                            if((roomPosY[i]+roomSizeY[i]) >= roomPosY[j] && (roomPosY[i]+roomSizeY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
                                rePosition = true;
                                break;
                            }
                        }
                        if((roomPosX[i]) >= roomPosX[j] && (roomPosX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
                            if((roomPosY[i]+roomSizeY[i]) >= roomPosY[j] && (roomPosY[i]+roomSizeY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
                                rePosition = true;
                                break;
                            }
                        }
                        if((roomPosX[i]+roomSizeX[i]) >= roomPosX[j] && (roomPosX[i]+roomSizeX[i]) <= (roomPosX[j] + roomSizeX[j] + clearance)) {
                            if((roomPosY[i]) >= roomPosY[j] && (roomPosY[i]) <= (roomPosY[j] + roomSizeY[j] + clearance)) {
                                rePosition = true;
                                break;
                            }
                        }
                    }
                    else if(roomPosX[j] + roomSizeX[j] >= X-1){
                        rePosition = true;
                    }
                    else if(roomPosY[j] + roomSizeY[j] >= Y-1){
                        rePosition = true;
                    }
                }
                attempts++;
                if(attempts >= 10000) break;
                if(!rePosition) break;
            }
        }

        for(int r = 0; r < roomCount; r++) {
            for (int a = roomPosX[r]; a <= (roomPosX[r] + roomSizeX[r]); a++) {
                for (int b = roomPosY[r]; b <= (roomPosY[r] + roomSizeY[r]); b++) {
                    mapChars[0][b][a] = '.';
                }
            }
        }

        Gdx.app.log("roomCount", String.valueOf(roomCount)+"\n\n\n");
        for(int i =0; i< roomCount; i++) {
            roomCenterPosX[i] = roomPosX[i] + roomSizeX[i]/2;
            roomCenterPosY[i] = roomPosY[i] + roomSizeY[i]/2;
            Gdx.app.log("room", String.valueOf(i)+"\n");
            Gdx.app.log("roomPosX", String.valueOf(roomPosX[i]));
            Gdx.app.log("roomPosY", String.valueOf(roomPosY[i]));
            Gdx.app.log("roomSizeX", String.valueOf(roomSizeX[i]));
            Gdx.app.log("roomSizeY", String.valueOf(roomSizeY[i])+"\n");
            Gdx.app.log("RoomCenterPosX", String.valueOf(roomCenterPosX[i]));
            Gdx.app.log("RoomCenterPosY", String.valueOf(roomCenterPosY[i])+"\n\n");
        }

        int difference = X;
        int[] roomNum = new int[2];
        for(int i = 0; i < roomCount; i++) {
            for(int j = 0; j < roomCount; j++) {
                if(i != j) {
                    if(abs(roomCenterPosX[i] - roomCenterPosX[j]) < difference) {
                        difference = abs(roomCenterPosX[i] - roomCenterPosX[j]);
                        roomNum[0] = i;
                        roomNum[1] = j;
                    }
                }
            }
        }
        Gdx.app.log("FarthestRooms", String.valueOf(roomNum[0]));
        Gdx.app.log("FarthestRooms", String.valueOf(roomNum[1]));

        int differenceX = X;
        int differenceY = Y;
        int[] connectRooms = new int[2];
//        int[] roomsConnected = new int[roomCount];

        connectRooms[0] = MathUtils.random(0, roomCount - 1);
//        roomsConnected[0] = connectRooms[0];

        int count;

        for(int i = 0; i < roomCount-1; i++) {
            int j;
            while(true) {
                connectRooms[1] = MathUtils.random(0, roomCount - 1);
/*                while (true) {
                    connectRooms[1] = MathUtils.random(0, roomCount - 1);
                    count = 0;
                    for (j = 0; j < i; j++) {
                        if (connectRooms[1] != roomsConnected[j] && connectRooms[0] != roomsConnected[j]){
                            count++;
                        }
                    }
                    if(count >= i-2)
                        break;
                }*/
                if(connectRooms[0] != connectRooms[1])
                    break;
            }
//            roomsConnected[i+1] = connectRooms[1];

            differenceX = roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]];
            differenceY = roomCenterPosY[connectRooms[0]] - roomCenterPosY[connectRooms[1]];
            if(roomCenterPosX[connectRooms[0]] < roomCenterPosX[connectRooms[1]])
                differenceX *= -1;
            if(roomCenterPosY[connectRooms[0]] < roomCenterPosY[connectRooms[1]])
                differenceY *= -1;

            int k;

            try {
                if (differenceX > 0) {
                    for (k = 0; k < differenceX; k++) {
                        mapChars[0][roomCenterPosY[i]][roomCenterPosX[i] + k] = '.';
                    }
                } else if (differenceX < 0) {
                    for (k = 0; k > differenceX; k--) {
                        mapChars[0][roomCenterPosY[i]][roomCenterPosX[i] + k] = '.';
                    }
                } else k = 0;

                if (differenceY < 0) {
                    for (int z = 0; z > differenceY; z--) {
                        mapChars[0][roomCenterPosY[i] + z][roomCenterPosX[i] + k] = '.';
                    }
                } else if (differenceY > 0) {
                    for (int z = 0; z < differenceY; z++) {
                        mapChars[0][roomCenterPosY[i] + z][roomCenterPosX[i] + k] = '.';
                    }
                } else {
                }
            }
            catch (ArrayIndexOutOfBoundsException e) {
                Gdx.app.log("Non Fatal Exception", String.valueOf(e));
            }

            Gdx.app.log("Connect", String.valueOf(connectRooms[0]));
            Gdx.app.log("Connect", String.valueOf(connectRooms[1]));
            Gdx.app.log("DifferenceX", String.valueOf(differenceX));
            Gdx.app.log("DifferenceY", String.valueOf(differenceY)+"\n");

        }

        for(int q = 0; q < Y; q++) {
            mapChars[0][q][X] = '\n';
        }
        for(int w = 0; w < Y; w++) {
            mapChars[0][w][X-1] = '#';
        }
        for(int e = 0; e < Y; e++) {
            mapChars[0][Y-1][e] = '#';
        }

    }

    private void export() {
        if(Gdx.files.isLocalStorageAvailable()) {
            FileHandle fileHandle = Gdx.files.local("map.txt");
            if(Gdx.files.local("map.txt").exists())
                fileHandle.writeString("", false);
            for(int i = 0; i<= Y; i++) {
                for (int j = 0; j <= X; j++) {
                    fileHandle.writeString(""+mapChars[0][i][j] , true);
                }
            }
        }
    }

    @Override
    public void create () {
        batch = new SpriteBatch();
        img = new Texture("badlogic.jpg");

//        genMap();
//        for(int i = 0; i< 4; i++)
//            refineMap();
        genDung();
        export();
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.draw(img, 0, 0);
        batch.end();

        if(Gdx.input.isTouched()) {
//            genMap();
//            for(int i = 0; i< 4; i++)
//                refineMap();
            genDung();
            export();
        }

    }
}

I want the two rooms to connect properly every time. As you can see, one of the time, the rooms connected The other time the rooms don't connect.

Thanks in advance


Solution

  • The whole thing can be simplified and definitely needs refactoring. Regarding the 2 room connection - check this piece carefully

            differenceX = roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]];
            differenceY = roomCenterPosY[connectRooms[0]] - roomCenterPosY[connectRooms[1]];
            if(roomCenterPosX[connectRooms[0]] < roomCenterPosX[connectRooms[1]])
                differenceX *= -1;
            if(roomCenterPosY[connectRooms[0]] < roomCenterPosY[connectRooms[1]])
                differenceY *= -1;
    

    As @kiheru pointed out it is equivalent to Math.abs(roomCenterPosX[connectRooms[0]] - roomCenterPosX[connectRooms[1]]) (same for Y). So you always "dig" to right and down, never up or left.

    Drop that invertion and have fun with the rest of your algorithm :)