001package squidpony.squidgrid.mapping;
002
003import squidpony.squidmath.GWTRNG;
004import squidpony.squidmath.IRNG;
005
006public class BasicCaveGenerator implements IDungeonGenerator {
007    public int width;
008    public int height;
009    public IRNG random;
010    public char[][] dungeon;
011    public BasicCaveGenerator(){
012        this(80, 40);
013    }
014    public BasicCaveGenerator(int width, int height) {
015        this(width, height, new GWTRNG());
016    }
017    public BasicCaveGenerator(int width, int height, IRNG random) {
018        this.width = width;
019        this.height = height;
020        this.random = random;
021    }
022
023    /**
024     * Generates a dungeon or other map as a 2D char array. Any implementation may allow its own configuration and
025     * customization of how dungeons are generated, but each must provide this as a sane default. Most implementations
026     * should use the convention of '#' representing a wall and '.' representing a bare floor, but beyond that, anything
027     * could be present in the char array.
028     *
029     * @return a 2D char array representing some kind of map, probably using standard conventions for walls/floors
030     */
031    @Override
032    public char[][] generate() {
033        if (dungeon == null || dungeon.length != width || dungeon.length <= 0 || dungeon[0].length != height || dungeon[0].length <= 0)
034            dungeon = new char[width][height];
035        for (int x = 0; x < width; x++) {
036            for (int y = 0; y < height; y++) {
037                if (random.nextDouble() < 0.5)
038                    dungeon[x][y] = '#';
039                else
040                    dungeon[x][y] = '.';
041            }
042        }
043        char[][] working = new char[width][height];
044        for (int iter = 0; iter < 5; iter++) {
045            for (int x = 0; x < width; x++) {
046                for (int y = 0; y < height; y++) {
047                    int sum = 0;
048                    for (int innerX = -1; innerX <= 1; innerX++) {
049                        for (int innerY = -1; innerY <= 1; innerY++) {
050                            if (x + innerX >= 0 && x + innerX < width
051                                    && y + innerY >= 0 && y + innerY < height
052                                    && dungeon[x + innerX][y + innerY] == '.')
053                                sum++;
054                        }
055                    }
056                    if (sum < 5)
057                        working[x][y] = '#';
058                    else
059                        working[x][y] = '.';
060                }
061            }
062            for (int x = 0; x < width; x++) {
063                                if (height >= 0) System.arraycopy(working[x], 0, dungeon[x], 0, height);
064            }
065        }
066        return dungeon;
067    }
068
069    /**
070     * Gets the most recently-produced dungeon as a 2D char array, usually produced by calling {@link #generate()} or
071     * some similar method present in a specific implementation. This normally passes a direct reference and not a copy,
072     * so you can normally modify the returned array to propagate changes back into this IDungeonGenerator.
073     *
074     * @return the most recently-produced dungeon/map as a 2D char array
075     */
076    @Override
077    public char[][] getDungeon() {
078        return dungeon;
079    }
080}