📄 boardutilities.java
字号:
int count = minHexes; if ((maxHexes - minHexes) > 0) { count += Compute.randomInt(maxHexes-minHexes); } IHex field; HashSet alreadyUsed = new HashSet(); HashSet unUsed = new HashSet(); field = board.getHex(p.x, p.y); if (!field.containsTerrain(terrainType)) { unUsed.add(field); } else { findAllUnused(board, terrainType, alreadyUsed, unUsed, field, reverseHex); } ITerrainFactory f = Terrains.getTerrainFactory(); for (int i = 0; i < count; i++) { if (unUsed.isEmpty()) { return; } int which = Compute.randomInt(unUsed.size()); Iterator iter = unUsed.iterator(); for (int n = 0; n < (which - 1); n++) iter.next(); field = (IHex)iter.next(); if (exclusive) { field.removeAllTerrains(); } int tempInt = (Compute.randomInt(100) < probMore)? 2 : 1; ITerrain tempTerrain = f.createTerrain(terrainType, tempInt); field.addTerrain(tempTerrain); unUsed.remove(field); findAllUnused(board, terrainType, alreadyUsed, unUsed, field, reverseHex); } if (terrainType == Terrains.WATER) { /* if next to an Water Hex is an lower lvl lower the hex. First we search for lowest Hex next to the lake */ int min = Integer.MAX_VALUE; Iterator iter = unUsed.iterator(); while (iter.hasNext()) { field = (IHex)iter.next(); if (field.getElevation() < min) { min = field.getElevation(); } } iter = alreadyUsed.iterator(); while (iter.hasNext()) { field = (IHex)iter.next(); field.setElevation(min); } } } /** * Searching starting from one Hex, all Terrains not matching * terrainType, next to one of terrainType. * @param terrainType The terrainType which the searching hexes * should not have. * @param alreadyUsed The hexes which should not looked at * (because they are already supposed to visited in some way) * @param unUsed In this set the resulting hexes are stored. They * are stored in addition to all previously stored. * @param searchFrom The Hex where to start */ private static void findAllUnused(IBoard board, int terrainType, HashSet alreadyUsed, HashSet unUsed, IHex searchFrom, HashMap reverseHex) { IHex field; HashSet notYetUsed = new HashSet(); notYetUsed.add(searchFrom); do { Iterator iter = notYetUsed.iterator(); field = (IHex)iter.next(); if (field == null) { continue; } for (int dir = 0; dir < 6; dir++) { Point loc = (Point) reverseHex.get(field); IHex newHex = board.getHexInDir(loc.x, loc.y, dir); if ((newHex != null) && (!alreadyUsed.contains(newHex)) && (!notYetUsed.contains(newHex)) && (!unUsed.contains(newHex))) { ((newHex.containsTerrain(terrainType)) ? notYetUsed : unUsed ).add(newHex); } } notYetUsed.remove(field); alreadyUsed.add(field); } while (!notYetUsed.isEmpty()); } /** * add a crater to the board */ public static void addCraters(IBoard board, int minRadius, int maxRadius,int minCraters, int maxCraters) { int numberCraters = minCraters; if (maxCraters > minCraters) { numberCraters += Compute.randomInt(maxCraters - minCraters); } for (int i = 0; i < numberCraters; i++) { int width = board.getWidth(); int height = board.getHeight(); Point center = new Point(Compute.randomInt(width), Compute.randomInt(height)); int radius = Compute.randomInt(maxRadius - minRadius + 1) + minRadius; int maxLevel = 3; if (radius < 3) { maxLevel = 1; } if ((radius >= 3) && (radius <= 8)) { maxLevel = 2; } if (radius > 14) { maxLevel = 4; } int maxHeight = Compute.randomInt(maxLevel) + 1; /* generate CraterProfile */ int cratHeight[] = new int[radius]; for (int x = 0; x < radius; x++) { cratHeight[x] = craterProfile((double)x / (double)radius, maxHeight); } /* btw, I am interested if someone actually reads this comments, so send me and email to f.stock@tu-bs.de, if you do ;-) */ /* now recalculate every hex */ for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { int distance = (int)distance(center, new Point(w,h)); if (distance < radius) { IHex field = board.getHex(w, h); field.setElevation(//field.getElevation() + cratHeight[distance]); } } } } } /** * The profile of a crater: interior is exp-function, exterior cos function. * @param x The x value of the function. range 0..1. * 0=center of crater. 1=border of outer wall. * @param scale Apply this scale before returning the result * (recommend instead of afterwards scale, cause this way the intern * floating values are scaled, instead of int result). * @return The height of the crater at the position x from * center. Unscaled, the results are between -0.5 and 1 (that * means, if no scale is applied -1, 0 or 1). */ public static int craterProfile(double x, int scale) { double result = 0; result = (x < 0.75) ? ((Math.exp(x * 5.0 / 0.75 - 3) - 0.04979) * 1.5 / 7.33926) - 0.5 : ((Math.cos((x-0.75)*4.0)+1.0) / 2.0); return (int)(result * scale); } /** * calculate the distance between two points */ private static double distance(Point p1, Point p2) { double x = p1.x - p2.x; double y = p1.y - p2.y; return Math.sqrt(x*x + y*y); } /** * Adds an River to the map (if the map is at least 5x5 hexes * big). The river has an width of 1-3 hexes (everything else is * no more a river). The river goes from one border to another. * Nor Params, no results. */ public static void addRiver(IBoard board, HashMap reverseHex) { int minElevation = Integer.MAX_VALUE; HashSet riverHexes = new HashSet(); IHex field; Point p = null; int direction = 0; int nextLeft = 0; int nextRight = 0; int width = board.getWidth(); int height = board.getHeight(); /* if map is smaller than 5x5 no real space for an river */ if ((width < 5) || (height < 5)) { return; } /* First select start and the direction */ switch (Compute.randomInt(4)) { case 0: p = new Point(0, Compute.randomInt(5) - 2 + height / 2); direction = Compute.randomInt(2) + 1; nextLeft = direction - 1; nextRight = direction + 1; break; case 1: p = new Point(width - 1, Compute.randomInt(5) - 2 + height / 2); direction = Compute.randomInt(2) + 4; nextLeft = direction - 1; nextRight = (direction + 1) % 6; break; case 2: case 3: p = new Point(Compute.randomInt(5) - 2 + width / 2, 0); direction = 2; nextRight = 3; nextLeft = 4; break; } // switch /* place the river */ field = board.getHex(p.x, p.y); ITerrainFactory f = Terrains.getTerrainFactory(); do { /* first the hex itself */ field.removeAllTerrains(); field.addTerrain(f.createTerrain(Terrains.WATER, 1)); riverHexes.add(field); p = (Point)reverseHex.get(field); /* then maybe the left and right neighbours */ riverHexes.addAll(extendRiverToSide(board, p, Compute.randomInt(3), nextLeft, reverseHex)); riverHexes.addAll(extendRiverToSide(board, p, Compute.randomInt(3), nextRight, reverseHex)); switch (Compute.randomInt(4)) { case 0: field = board.getHexInDir(p.x, p.y, (direction + 5) % 6); break; case 1: field = board.getHexInDir(p.x, p.y, (direction + 1) % 6); break; default: field = board.getHexInDir(p.x, p.y, direction); break; } } while (field != null); /* search the elevation for the river */ HashSet tmpRiverHexes = (HashSet)riverHexes.clone(); while (!tmpRiverHexes.isEmpty()) { Iterator iter = tmpRiverHexes.iterator(); field = (IHex)iter.next(); if (field.getElevation() < minElevation) { minElevation = field.getElevation(); } tmpRiverHexes.remove(field); Point thisHex = (Point)reverseHex.get(field); /* and now the six neighbours */ for (int i = 0; i < 6; i++) { field = board.getHexInDir(thisHex.x, thisHex.y, i); if ((field != null) && (field.getElevation() < minElevation)) { minElevation = field.getElevation(); } tmpRiverHexes.remove(field); } } /* now adjust the elevation to same height */ Iterator iter = riverHexes.iterator(); while (iter.hasNext()) { field = (IHex)iter.next(); field.setElevation(minElevation); } return; } /** * Extends a river hex to left and right sides. * @param hexloc The location of the river hex, * from which it should get started. * @param width The width to wich the river should extend in * the direction. So the actual width of the river is * 2*width+1. * @param direction Direction too which the riverhexes should be * extended. * @return Hashset with the hexes from the side. */ private static HashSet extendRiverToSide(IBoard board, Point hexloc, int width, int direction, HashMap reverseHex) { Point current = new Point(hexloc); HashSet result = new HashSet(); IHex hex; hex = board.getHexInDir(current.x, current.y, direction); while ((hex != null) && (width-- > 0)) { hex.removeAllTerrains(); hex.addTerrain(Terrains.getTerrainFactory().createTerrain(Terrains.WATER, 1)); result.add(hex); current = (Point)reverseHex.get(hex); hex = board.getHexInDir(current.x, current.y, direction); } return result; } /** Flood negative hex levels * Shoreline / salt marshes effect * Works best with more elevation */ protected static void PostProcessFlood(IHex[] hexSet, int modifier) { int n; IHex field; ITerrainFactory f = Terrains.getTerrainFactory(); for (n=0;n<hexSet.length;n++) { field = hexSet[n]; int elev = field.getElevation() - modifier; if(elev == 0 && !(field.containsTerrain(Terrains.WATER)) && !(field.containsTerrain(Terrains.PAVEMENT))) { field.addTerrain(f.createTerrain(Terrains.SWAMP,1)); } else if(elev < 0) { if(elev < -4) elev=-4; field.removeAllTerrains(); field.addTerrain(f.createTerrain(Terrains.WATER,-elev)); field.setElevation(modifier); } } } /** * Converts water hexes to ice hexes. * Works best with snow&ice theme. */ protected static void PostProcessDeepFreeze(IHex[] hexSet, int modifier) { int n; IHex field; ITerrainFactory f = Terrains.getTerrainFactory(); for (n=0;n<hexSet.length;n++) { field = hexSet[n]; if(field.containsTerrain(Terrains.WATER)) { int level = field.terrainLevel(Terrains.WATER); if(modifier != 0) { level -= modifier; field.removeTerrain(Terrains.WATER); if(level > 0) { field.addTerrain(f.createTerrain(Terrains.WATER, level)); } } field.addTerrain(f.createTerrain(Terrains.ICE,1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -