|
@@ -296,57 +296,6 @@ public class DungeonUtility {
|
|
|
return portion;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Takes a dungeon map with either '#' as the only wall character or the unicode
|
|
|
- * box drawing characters used by hashesToLines(), and returns a new char[][]
|
|
|
- * dungeon map with two characters per cell, mostly filling the spaces next to
|
|
|
- * non-walls with space characters, and only doing anything different if a
|
|
|
- * box-drawing character would continue into an adjacent cell, or if a '#' wall
|
|
|
- * needs another '#' wall next to it. The recommended approach is to keep both
|
|
|
- * the original non-double-width map and the newly-returned double-width map,
|
|
|
- * since the single-width maps can be used more easily for pathfinding. If you
|
|
|
- * need to undo this function, call unDoubleWidth().
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] that uses either '#' or box-drawing characters for
|
|
|
- * walls, but one per cell
|
|
|
- * @return a widened copy of map that uses two characters for every cell,
|
|
|
- * connecting box-drawing chars correctly
|
|
|
- */
|
|
|
- public static char[][] doubleWidth(char[][] map) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- char[][] paired = new char[width * 2][height];
|
|
|
- for (int y = 0; y < height; y++) {
|
|
|
- for (int x = 0, px = 0; x < width; x++, px += 2) {
|
|
|
- paired[px][y] = map[x][y];
|
|
|
- switch (paired[px][y]) {
|
|
|
- // case '┼ ├ ┤ ┴ ┬ ┌ ┐ └ ┘ │ ─'
|
|
|
- case '┼':
|
|
|
- case '├':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '└':
|
|
|
- case '─':
|
|
|
- paired[px + 1][y] = '─';
|
|
|
- break;
|
|
|
- case '#':
|
|
|
- paired[px + 1][y] = '#';
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- paired[px + 1][y] = ' ';
|
|
|
- break;
|
|
|
- /*
|
|
|
- * case '.': case '┤': case '┐': case '┘': case '│':
|
|
|
- */
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return paired;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Takes a dungeon map that uses two characters per cell, and condenses it to
|
|
|
* use only the left (lower index) character in each cell. This should
|
|
@@ -372,767 +321,6 @@ public class DungeonUtility {
|
|
|
return unpaired;
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with any palette of your choice for
|
|
|
- * methods in SquidPanel or for your own rendering method. 1 is used as a
|
|
|
- * default and for tiles with nothing in them; if the background is black, then
|
|
|
- * white would make sense as this default. Other indices used are 2 for walls
|
|
|
- * (this doesn't care if the walls are hashes or lines), 3 for floors (usually
|
|
|
- * '.'), 4 for doors ('+' and '/' in the map), 5 for water, 6 for traps, and 20
|
|
|
- * for grass.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] containing foreground characters that you want
|
|
|
- * foreground palette indices for
|
|
|
- * @return a 2D array of ints that can be used as indices into a palette;
|
|
|
- * palettes are available in related modules
|
|
|
- */
|
|
|
- public static int[][] generatePaletteIndices(char[][] map) {
|
|
|
-
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 2;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- case ':':
|
|
|
- portion[i][j] = 3;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = 4;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- case '~':
|
|
|
- portion[i][j] = 5;
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = 20;
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 6;
|
|
|
- break;
|
|
|
- default:
|
|
|
- portion[i][j] = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with any palette of your choice for
|
|
|
- * methods in SquidPanel or for your own rendering method. 1 is used as a
|
|
|
- * default and for tiles with nothing in them; if the background is black, then
|
|
|
- * white would make sense as this default. Other indices used are 2 for walls
|
|
|
- * (this doesn't care if the walls are hashes or lines), 3 for floors (usually
|
|
|
- * '.'), 4 for doors ('+' and '/' in the map), 5 for water, 6 for traps, and 20
|
|
|
- * for grass.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] containing foreground characters that you want
|
|
|
- * foreground palette indices for
|
|
|
- * @return a 2D array of ints that can be used as indices into a palette;
|
|
|
- * palettes are available in related modules
|
|
|
- */
|
|
|
- public static int[][] generatePaletteIndices(char[][] map, char deepChar, int deepIndex, char shallowChar,
|
|
|
- int shallowIndex) {
|
|
|
-
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 2;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- case ':':
|
|
|
- portion[i][j] = 3;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = 4;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- case '~':
|
|
|
- portion[i][j] = 5;
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = 20;
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 6;
|
|
|
- break;
|
|
|
- default:
|
|
|
- if (map[i][j] == deepChar)
|
|
|
- portion[i][j] = deepIndex;
|
|
|
- else if (map[i][j] == shallowChar)
|
|
|
- portion[i][j] = shallowIndex;
|
|
|
- else
|
|
|
- portion[i][j] = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with any palette of your choice for
|
|
|
- * methods in SquidPanel or for your own rendering method, but meant for the
|
|
|
- * background palette. This will produce 0 for most characters, but deep water
|
|
|
- * (represented by '~') will produce 24 (in the default palette, this is dark
|
|
|
- * blue-green), shallow water (represented by ',') will produce 23 (medium
|
|
|
- * blue-green), and grass (represented by '"') will produce 21 (dark green). If
|
|
|
- * you use SquidLayers, you can cause the lightness of water and grass to vary
|
|
|
- * as if currents or wind are moving their surface using getLightnessModifiers()
|
|
|
- * and a frame count argument.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] containing foreground characters that you want
|
|
|
- * background palette indices for
|
|
|
- * @return a 2D array of ints that can be used as indices into a palette;
|
|
|
- * palettes are available in related modules
|
|
|
- */
|
|
|
- public static int[][] generateBGPaletteIndices(char[][] map) {
|
|
|
-
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ':':
|
|
|
- portion[i][j] = 35;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- portion[i][j] = 23;
|
|
|
- break;
|
|
|
- case '~':
|
|
|
- portion[i][j] = 24;
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = 21;
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- default:
|
|
|
- portion[i][j] = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with any palette of your choice for
|
|
|
- * methods in SquidPanel or for your own rendering method, but meant for the
|
|
|
- * background palette. This will produce 0 for most characters, but deep water
|
|
|
- * (represented by '~') will produce 24 (in the default palette, this is dark
|
|
|
- * blue-green), shallow water (represented by ',') will produce 23 (medium
|
|
|
- * blue-green), and grass (represented by '"') will produce 21 (dark green). If
|
|
|
- * you use SquidLayers, you can cause the lightness of water and grass to vary
|
|
|
- * as if currents or wind are moving their surface using getLightnessModifiers()
|
|
|
- * and a frame count argument.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] containing foreground characters that you want
|
|
|
- * background palette indices for
|
|
|
- * @return a 2D array of ints that can be used as indices into a palette;
|
|
|
- * palettes are available in related modules
|
|
|
- */
|
|
|
- public static int[][] generateBGPaletteIndices(char[][] map, char deepChar, int deepIndex, char shallowChar,
|
|
|
- int shallowIndex) {
|
|
|
-
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ':':
|
|
|
- portion[i][j] = 35;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- portion[i][j] = 23;
|
|
|
- break;
|
|
|
- case '~':
|
|
|
- portion[i][j] = 24;
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = 21;
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- default:
|
|
|
- if (map[i][j] == deepChar)
|
|
|
- portion[i][j] = deepIndex;
|
|
|
- else if (map[i][j] == shallowChar)
|
|
|
- portion[i][j] = shallowIndex;
|
|
|
- else
|
|
|
- portion[i][j] = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with SquidLayers to alter the background
|
|
|
- * colors.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] that you want to be find background lightness modifiers
|
|
|
- * for
|
|
|
- * @return a 2D array of lightness values from -255 to 255 but usually close to
|
|
|
- * 0; can be passed to SquidLayers
|
|
|
- */
|
|
|
- public static int[][] generateLightnessModifiers(char[][] map) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 30;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ':':
|
|
|
- portion[i][j] = -15;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = -10;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- portion[i][j] = (int) (70 * (PerlinNoise.noise(i / 4.0, j / 4.0) / 2.5 - 0.45));
|
|
|
- break;
|
|
|
- case '~':
|
|
|
- portion[i][j] = (int) (100 * (PerlinNoise.noise(i / 4.0, j / 4.0) / 2.5 - 0.65));
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = (int) (75 * (PerlinNoise.noise(i / 4.0, j / 4.0) / 4.0 - 1.5));
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 40;
|
|
|
- break;
|
|
|
- default:
|
|
|
- portion[i][j] = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with SquidLayers to alter the background
|
|
|
- * colors, accepting a parameter for animation frame if rippling water and
|
|
|
- * waving grass using Perlin Noise are desired.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] that you want to be find background lightness modifiers
|
|
|
- * for
|
|
|
- * @param frame
|
|
|
- * a counter that typically should increase by between 10.0 and 20.0
|
|
|
- * each second; higher numbers make water and grass move more
|
|
|
- * @return a 2D array of lightness values from -255 to 255 but usually close to
|
|
|
- * 0; can be passed to SquidLayers
|
|
|
- */
|
|
|
- public static int[][] generateLightnessModifiers(char[][] map, double frame) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 30;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ':':
|
|
|
- portion[i][j] = -15;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = -10;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- portion[i][j] = (int) (70 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 25.0) / 2.5 - 0.45));
|
|
|
- break;
|
|
|
- case '~':
|
|
|
- portion[i][j] = (int) (100 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 25.0) / 2.5 - 0.65));
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = (int) (75 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 35.0) / 4.0 - 1.5));
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 40;
|
|
|
- break;
|
|
|
- default:
|
|
|
- portion[i][j] = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Produces an int[][] that can be used with SquidLayers to alter the background
|
|
|
- * colors, accepting a parameter for animation frame if rippling water and
|
|
|
- * waving grass using Perlin Noise are desired. Also allows additional chars to
|
|
|
- * be treated like deep and shallow water regarding the ripple animation.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a char[][] that you want to be find background lightness modifiers
|
|
|
- * for
|
|
|
- * @param frame
|
|
|
- * a counter that typically should increase by between 10.0 and 20.0
|
|
|
- * each second; higher numbers make water and grass move more
|
|
|
- * @param deepLiquid
|
|
|
- * a char that will be treated like deep water when animating ripples
|
|
|
- * @param shallowLiquid
|
|
|
- * a char that will be treated like shallow water when animating
|
|
|
- * ripples
|
|
|
- * @return a 2D array of lightness values from -255 to 255 but usually close to
|
|
|
- * 0; can be passed to SquidLayers
|
|
|
- */
|
|
|
- public static int[][] generateLightnessModifiers(char[][] map, double frame, char deepLiquid, char shallowLiquid) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- int[][] portion = new int[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 30;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- portion[i][j] = 0;
|
|
|
- break;
|
|
|
- case ':':
|
|
|
- portion[i][j] = -15;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- case '/':
|
|
|
- portion[i][j] = -10;
|
|
|
- break;
|
|
|
- case ',':
|
|
|
- portion[i][j] = (int) (70 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 25.0) / 2.5 - 0.45));
|
|
|
- break;
|
|
|
- case '~':
|
|
|
- portion[i][j] = (int) (100 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 25.0) / 2.5 - 0.65));
|
|
|
- break;
|
|
|
- case '"':
|
|
|
- portion[i][j] = (int) (75 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 35.0) / 4.0 - 1.5));
|
|
|
- break;
|
|
|
- case '^':
|
|
|
- portion[i][j] = 40;
|
|
|
- break;
|
|
|
- default:
|
|
|
- if (map[i][j] == deepLiquid)
|
|
|
- portion[i][j] = (int) (180 * (PerlinNoise.noise(i / 5.0, j / 5.0, frame / 21.0) / 2.5 - 0.7));
|
|
|
- else if (map[i][j] == shallowLiquid)
|
|
|
- portion[i][j] = (int) (110 * (PerlinNoise.noise(i / 4.0, j / 4.0, frame / 30.0) / 2.5 - 0.45));
|
|
|
- else
|
|
|
- portion[i][j] = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Given a char[][] for the map, produces a double[][] that can be used with
|
|
|
- * FOV.calculateFOV(). It expects any doors to be represented by '+' if closed
|
|
|
- * or '/' if open (which can be caused by calling DungeonUtility.closeDoors() ),
|
|
|
- * any walls to be '#' or line drawing characters, and it doesn't care what
|
|
|
- * other chars are used (only doors, including open ones, and walls obscure
|
|
|
- * light and thus have a resistance by default).
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a dungeon, width by height, with any closed doors as '+' and open
|
|
|
- * doors as '/' as per closeDoors()
|
|
|
- * @return a resistance map suitable for use with the FOV class
|
|
|
- */
|
|
|
- public static double[][] generateResistances(char[][] map) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- double[][] portion = new double[width][height];
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- switch (map[i][j]) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = 1.0;
|
|
|
- break;
|
|
|
- case '/':
|
|
|
- case '"':
|
|
|
- portion[i][j] = 0.15;
|
|
|
- break;
|
|
|
- case '+':
|
|
|
- portion[i][j] = 0.95;
|
|
|
- break;
|
|
|
- case '.':
|
|
|
- case ',':
|
|
|
- case '~':
|
|
|
- case '^':
|
|
|
- default:
|
|
|
- portion[i][j] = 0.0;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Given a char[][] for the map, a Map of Character keys to Double values that
|
|
|
- * will be used to determine costs, and a double value for unhandled characters,
|
|
|
- * produces a double[][] that can be used as a costMap by DijkstraMap. It
|
|
|
- * expects any doors to be represented by '+' if closed or '/' if open (which
|
|
|
- * can be caused by calling DungeonUtility.closeDoors() ) and any walls to be
|
|
|
- * '#' or line drawing characters. In the parameter costs, there does not need
|
|
|
- * to be an entry for '#' or any box drawing characters, but if one is present
|
|
|
- * for '#' it will apply that cost to both '#' and all box drawing characters,
|
|
|
- * and if one is not present it will default to a very high number. For any
|
|
|
- * other entry in costs, a char in the 2D char array that matches the key will
|
|
|
- * correspond (at the same x,y position in the returned 2D double array) to that
|
|
|
- * key's value in costs. If a char is used in the map but does not have a
|
|
|
- * corresponding key in costs, it will be given the value of the parameter
|
|
|
- * defaultValue.
|
|
|
- * <p/>
|
|
|
- * The values in costs are multipliers, so should not be negative, should only
|
|
|
- * be 0.0 in cases where you want infinite movement across all adjacent squares
|
|
|
- * of that kind, should be higher than 1.0 for difficult terrain (2.0 and 3.0
|
|
|
- * are reasonable), should be between 0.0 and 1.0 for easy terrain, and should
|
|
|
- * be 1.0 for normal terrain. If a cell should not be possible to enter for this
|
|
|
- * character, 999.0 should be a reasonable value for a cost.
|
|
|
- * <p/>
|
|
|
- * An example use for this would be to make a creature unable to enter any
|
|
|
- * non-water cell (like a fish), unable to enter doorways (like some
|
|
|
- * mythological versions of vampires), or to make a wheeled vehicle take more
|
|
|
- * time to move across rubble or rough terrain.
|
|
|
- * <p/>
|
|
|
- * A potentially common case that needs to be addressed is NPC movement onto
|
|
|
- * staircases in games that have them; some games may find it desirable for NPCs
|
|
|
- * to block staircases and others may not, but in either case you should give
|
|
|
- * both '>' and '<', the standard characters for staircases, the same
|
|
|
- * value in costs.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a dungeon, width by height, with any closed doors as '+' and open
|
|
|
- * doors as '/' as per closeDoors() .
|
|
|
- * @param costs
|
|
|
- * a Map of Character keys representing possible elements in map, and
|
|
|
- * Double values for their cost.
|
|
|
- * @param defaultValue
|
|
|
- * a double that will be used as the cost for any characters that
|
|
|
- * don't have a key in costs.
|
|
|
- * @return a cost map suitable for use with DijkstraMap
|
|
|
- */
|
|
|
- public static double[][] generateCostMap(char[][] map, Map<Character, Double> costs, double defaultValue) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- double[][] portion = new double[width][height];
|
|
|
- char current;
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- current = map[i][j];
|
|
|
- if (costs.containsKey(current)) {
|
|
|
- portion[i][j] = costs.get(current);
|
|
|
- } else {
|
|
|
- switch (current) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = (costs.containsKey('#')) ? costs.get('#') : squidpony.squidai.DijkstraMap.WALL;
|
|
|
- break;
|
|
|
- default:
|
|
|
- portion[i][j] = defaultValue;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Given a char[][] for the map, a Map of Character keys to Double values that
|
|
|
- * will be used to determine costs, and a double value for unhandled characters,
|
|
|
- * produces a double[][] that can be used as a map by AStarSearch. It expects
|
|
|
- * any doors to be represented by '+' if closed or '/' if open (which can be
|
|
|
- * caused by calling DungeonUtility.closeDoors() ) and any walls to be '#' or
|
|
|
- * line drawing characters. In the parameter costs, there does not need to be an
|
|
|
- * entry for '#' or any box drawing characters, but if one is present for '#' it
|
|
|
- * will apply that cost to both '#' and all box drawing characters, and if one
|
|
|
- * is not present it will default to a negative number, meaning it is impassable
|
|
|
- * for AStarSearch. For any other entry in costs, a char in the 2D char array
|
|
|
- * that matches the key will correspond (at the same x,y position in the
|
|
|
- * returned 2D double array) to that key's value in costs. If a char is used in
|
|
|
- * the map but does not have a corresponding key in costs, it will be given the
|
|
|
- * value of the parameter defaultValue, which is typically 0 unless a creature
|
|
|
- * is limited to only moving in some terrain.
|
|
|
- * <p/>
|
|
|
- * The values in costs are different from those expected for DijkstraMap;
|
|
|
- * negative numbers are impassable, 0 is the cost for a normal walkable tile,
|
|
|
- * and higher numbers are harder to enter.
|
|
|
- * <p/>
|
|
|
- * An example use for this would be to make a creature unable to enter any
|
|
|
- * non-water cell (like a fish), unable to enter doorways (like some
|
|
|
- * mythological versions of vampires), or to make a wheeled vehicle take more
|
|
|
- * time to move across rubble or rough terrain.
|
|
|
- * <p/>
|
|
|
- * A potentially common case that needs to be addressed is NPC movement onto
|
|
|
- * staircases in games that have them; some games may find it desirable for NPCs
|
|
|
- * to block staircases and others may not, but in either case you should give
|
|
|
- * both '>' and '<', the standard characters for staircases, the same
|
|
|
- * value in costs.
|
|
|
- *
|
|
|
- * @param map
|
|
|
- * a dungeon, width by height, with any closed doors as '+' and open
|
|
|
- * doors as '/' as per closeDoors() .
|
|
|
- * @param costs
|
|
|
- * a Map of Character keys representing possible elements in map, and
|
|
|
- * Double values for their cost.
|
|
|
- * @param defaultValue
|
|
|
- * a double that will be used as the cost for any characters that
|
|
|
- * don't have a key in costs.
|
|
|
- * @return a cost map suitable for use with AStarSearch
|
|
|
- */
|
|
|
- public static double[][] generateAStarCostMap(char[][] map, Map<Character, Double> costs, double defaultValue) {
|
|
|
- int width = map.length;
|
|
|
- int height = map[0].length;
|
|
|
- double[][] portion = new double[width][height];
|
|
|
- char current;
|
|
|
- for (int i = 0; i < width; i++) {
|
|
|
- for (int j = 0; j < height; j++) {
|
|
|
- current = map[i][j];
|
|
|
- if (costs.containsKey(current)) {
|
|
|
- portion[i][j] = costs.get(current);
|
|
|
- } else {
|
|
|
- switch (current) {
|
|
|
- case '\1':
|
|
|
- case '├':
|
|
|
- case '┤':
|
|
|
- case '┴':
|
|
|
- case '┬':
|
|
|
- case '┌':
|
|
|
- case '┐':
|
|
|
- case '└':
|
|
|
- case '┘':
|
|
|
- case '│':
|
|
|
- case '─':
|
|
|
- case '┼':
|
|
|
- case '#':
|
|
|
- portion[i][j] = (costs.containsKey('#')) ? costs.get('#') : squidpony.squidai.DijkstraMap.WALL;
|
|
|
- break;
|
|
|
- default:
|
|
|
- portion[i][j] = defaultValue;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return portion;
|
|
|
- }
|
|
|
-
|
|
|
- public static double[][] translateAStarToDijkstra(double[][] astar) {
|
|
|
- if (astar == null)
|
|
|
- return null;
|
|
|
- if (astar.length <= 0 || astar[0].length <= 0)
|
|
|
- return new double[0][0];
|
|
|
- double[][] dijkstra = new double[astar.length][astar[0].length];
|
|
|
- for (int x = 0; x < astar.length; x++) {
|
|
|
- for (int y = 0; y < astar[x].length; y++) {
|
|
|
- if (astar[x][y] < 0)
|
|
|
- dijkstra[x][y] = DijkstraMap.WALL;
|
|
|
- else
|
|
|
- dijkstra[x][y] = DijkstraMap.FLOOR;
|
|
|
- }
|
|
|
- }
|
|
|
- return dijkstra;
|
|
|
- }
|
|
|
-
|
|
|
- public static double[][] translateDijkstraToAStar(double[][] dijkstra) {
|
|
|
- if (dijkstra == null)
|
|
|
- return null;
|
|
|
- if (dijkstra.length <= 0 || dijkstra[0].length <= 0)
|
|
|
- return new double[0][0];
|
|
|
- double[][] astar = new double[dijkstra.length][dijkstra[0].length];
|
|
|
- for (int x = 0; x < dijkstra.length; x++) {
|
|
|
- for (int y = 0; y < dijkstra[x].length; y++) {
|
|
|
- if (dijkstra[x][y] > DijkstraMap.FLOOR)
|
|
|
- astar[x][y] = -1;
|
|
|
- else
|
|
|
- astar[x][y] = 1;
|
|
|
- }
|
|
|
- }
|
|
|
- return astar;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * @param rng
|
|
|
- * @param map
|
|
|
- * @param acceptable
|
|
|
- * @param frustration
|
|
|
- * The number of trials that this method can do. Usually 16 or 32.
|
|
|
- * @return A random cell in {@code map} whose symbol is in {@code acceptable}.
|
|
|
- * Or {@code null} if not found.
|
|
|
- */
|
|
|
- public static /* @Nullable */Coord getRandomCell(RNG rng, char[][] map, Set<Character> acceptable,
|
|
|
- int frustration) {
|
|
|
- if (frustration < 0)
|
|
|
- throw new IllegalStateException("Frustration should not be negative");
|
|
|
- final int width = map.length;
|
|
|
- final int height = width == 0 ? 0 : map[0].length;
|
|
|
- if (width == 0 || height == 0)
|
|
|
- throw new IllegalStateException("Map must be non-empty to get a cell from it");
|
|
|
- int i = 0;
|
|
|
- while (i < frustration) {
|
|
|
- final int x = rng.nextInt(width);
|
|
|
- final int y = rng.nextInt(height);
|
|
|
- if (acceptable.contains(map[x][y]))
|
|
|
- return Coord.get(x, y);
|
|
|
- i++;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* @param level
|
|
|
* dungeon/map level as 2D char array. x,y indexed
|