📄 randommapgenerator.java
字号:
// check if we swallowed an entire country if (eatCheck.contains(shapeBounds[i])) { // then we have eaten shape i. abort this shape. //debug("oops, shapeCount = "+shapeCount+" almost swallowed "+i); shapes[shapeCount] = null; return; } } eatCheck = shape.getBounds2D(); for (int i = 0; i < shapeCount; i++) { // check if we swallowed an entire country if (shapeBounds[i].contains( eatCheck )) { // then we have eaten shape i. abort this shape. //debug("oops, shapeCount = "+shapeCount+" was almost created inside "+i); shapes[shapeCount] = null; return; } } return; // hooray }private Point2D pointFromPolar( Point2D origin, double theta, double radius) { return new Point2D.Double(origin.getX() + (double)(Math.cos(theta)*radius), origin.getY() + (double)(Math.sin(theta)*radius)); }// returns -1 if there was an errorprivate double calcTheta( Point2D origin, Point2D p ) { double lastTheta; double ydiff = p.getY() - origin.getY(); double xdiff = p.getX() - origin.getX(); double yabs = Math.abs(ydiff); double radius = p.distance( origin ); if (radius <= 0) return -1; if (ydiff >= 0 && xdiff >= 0) lastTheta = Math.asin(yabs/radius); // quadrant 1 else if (ydiff >= 0) lastTheta = Math.PI - Math.asin(yabs/radius); // quadrant 2 else if (ydiff < 0 && xdiff < 0) lastTheta = Math.PI + Math.asin(yabs/radius); // quadrant 3 else lastTheta = Math.PI*2 - Math.asin(yabs/radius); // quadrant 4 return lastTheta; }/** Ensure that all the countries that 'c' connects to also connect to 'c'. */private void addReverseLinks(Country c) { Country[] adList = c.getAdjoiningList(); if (adList != null) for (int i = 0; i < adList.length; i++) adList[i].addToAdjoiningList( c, this ); }private int getClosestBorderNotInShape(Point2D p, int shape, int notShape) { int closestPoint = -1; double dist,closestDistance = 100000000; for (int i = 0; i < points[shape].size(); i++) { Point2D next = (Point2D) points[shape].get(i); dist = p.distance( next ); if (dist < closestDistance) { // We must check to make sure that this point is not in <notShape> boolean usePoint = true; for (int j = 0; j < points[notShape].size() && usePoint; j++) { Point2D point = (Point2D) points[notShape].get(j); if (next.getX() == point.getX() && next.getY() == point.getY()) usePoint = false; } if (usePoint) { closestDistance = dist; closestPoint = i; } } } if (closestPoint == -1) { // this should never happen, because one of the points must be closest System.out.println("Error in CreateBoard.getClosestBorderNotInShape p="+p+", shape="+shape); } return closestPoint; }/** Find the point in 'shape" closest to 'p'. */private int getClosestBorder(Point2D p, int shape) { int closestPoint = -1; double dist,closestDistance = 100000000; for (int i = 0; i < points[shape].size(); i++) { Point2D next = (Point2D) points[shape].get(i); if (next.getX() != p.getX() || next.getY() != p.getY()) // this ensures that we don't return a point that is equal to <p> { dist = p.distance( next ); if (dist < closestDistance) { closestDistance = dist; closestPoint = i; } } } if (closestPoint == -1) { // this should never happen, because one of the points must be closest System.out.println("Error in CreateBoard.getClosestBorder p="+p+", shape="+shape); } return closestPoint; }/** Return a vector with all the Country's that can be reached from 'from'. */private Vector getTouching(int from) { Vector touches = new Vector(); touches.add( countries[from] ); for ( int i = 0; i < touches.size(); i++ ) { // load its neighbors to the Que Country[] lookTouches = ((Country)touches.get(i)).getAdjoiningList(); if (lookTouches != null) { for (int n = 0; n < lookTouches.length; n++) { if ( ! touches.contains(lookTouches[n]) ) { touches.add(lookTouches[n]); } } } } return touches; }// this marks the connected[] array as true for any countries reachable from <from> private void markConnectedFrom(int from) { // We mark everything that this guy touches as connected: Vector toLookAt = new Vector(); toLookAt.add( countries[from] ); while ( toLookAt.size() > 0 ) { // mark the shape at the front of the Que connected[ ((Country)toLookAt.get(0)).getCode() ] = true; // load its neighbors to the Que Country[] lookTouches = ((Country)toLookAt.get(0)).getAdjoiningList(); if (lookTouches != null) { for (int i = 0; i < lookTouches.length; i++) { if ( ! connected[ lookTouches[i].getCode() ] ) toLookAt.add(lookTouches[i]); } } // and pop the front toLookAt.removeElementAt(0); } }private void markContinentCodeFrom(int from, int code) { // We mark everything that this guy touches as connected: Vector touches = getTouching(from); for (int i = 0; i < touches.size(); i++) { countries[((Country)touches.get(i)).getCode()].setContinentCode(code, this); contCodes[((Country)touches.get(i)).getCode()] = code; } }private boolean isFullyConnected() { for (int i = 0; i < connected.length; i++) if (! connected[i]) return false; return true; }/** Return the ID number of the shape that the point is inside. If the point is free then it returns -1. */private int isInShapes( Point2D p ) { for (int i = 0; i < shapeCount; i++) { if (shapeBounds[i].contains(p) && shapes[i].contains(p)) { return i; } } return -1; }/** Return a random number near to 'near', depending on the class-variable 'variance'. */public double nearNumber (double near ) { // This gives a double with mean 0.0 and standard deviation 1.0 double next = rand.nextGaussian(); // But we want a variance of up to <variance>: next *= variance; // And centered around near: next += near; return (double) next; }/** Returns false if the point is too close to the borders of the drawing area. */private boolean validPoint( Point2D point ) { double x = point.getX(); double y = point.getY(); int minX = 20, minY = 15, maxX = topx-20, maxY = topy-40; if (x < minX || y < minY || x > maxX || y > maxY) return false; return true; }/** Tests to see if a line can safely be drawn between the two shapes.Will return false if the line would cross any shapes or other lines. */public boolean lineCanExistBetween( int s1, int s2 ) { Point2D p1 = null; Point2D p2 = null; int smallDist = distanceBetween(s1, s2); int dist; // now find the points that are that distance apart (they would form the line) for (int i = 0; i < points[s1].size() && p1==null; i++) for (int j = 0; j < points[s2].size() && p1==null; j++) { dist = (int)((Point2D)points[s1].get(i)).distance((Point2D)points[s2].get(j)); if (dist == smallDist) { p1 = (Point2D)points[s1].get(i); p2 = (Point2D)points[s2].get(j); } } // First check it against the other lines: for (int i = 0; i < lines.size(); i++) { Line2D check = (Line2D)lines.get(i); if ( check.intersectsLine(p1.getX(), p1.getY(), p2.getX(), p2.getY()) ) { return false; } } // Dissallow lines that are inside the bounding box of other shapes. // this is an upper bound for intersecting the shapes themselves for (int i = 0; i < shapeCount; i++) { if (i != s1 && i != s2 && shapeBounds[i].intersectsLine(p1.getX(), p1.getY(), p2.getX(), p2.getY())) return false; } return true; }/** Returns the point in between pa and p2. */public Point2D getMiddlePoint( Point2D p1, Point2D p2 ) { return new Point2D.Double( (p1.getX()+p2.getX())/2, (p1.getY()+p2.getY())/2 ); }private void addLineBetweenShapes(int from, int to) { int smallDist = distanceBetween(from, to), dist; // now find the points that are that distance apart and connect them: for (int i = 0; i < points[from].size(); i++) { for (int j = 0; j < points[to].size(); j++) { dist = (int)((Point2D)points[from].get(i)).distance((Point2D)points[to].get(j)); if (dist == smallDist) { lines.add( new Line2D.Double( (Point2D)points[from].get(i), (Point2D)points[to].get(j)) ); return; } } } }/** Add the connection to the adjoiningLists. */private void makeCountriesTouch(int from, int to ) { countries[from].addToAdjoiningListBoth( countries[to], this ); }/** Computes the cloest distance between the two finished GeneralPaths. */private int distanceBetween(int from, int to) { if (distanceMemory[from][to] == -1) { double smallDist = 1000000, dist; for (int i = 0; i < points[from].size(); i++) for (int j = 0; j < points[to].size(); j++) { dist = ((Point2D)points[from].get(i)).distance((Point2D)points[to].get(j)); if (dist < smallDist) { smallDist = dist; } } distanceMemory[from][to] = (int)smallDist; distanceMemory[to][from] = (int)smallDist; } return distanceMemory[from][to]; }private String getRandomTheme() { int code = rand.nextInt(11); if (code < 5) return "Ocean"; if (code < 8) return "Space"; if (code < 10) return "Air"; else return "Huh"; }public boolean saveBoard(PrintWriter file, String mapName) { if (numContinents < 2) { // fail on boards with only one continent return false; } file.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<luxboard>"); file.println("<version>1.1</version>"); file.println("<width>"+topx+"</width>"); file.println("<height>"+topy+"</height>"); file.println("<title>"+mapName+"</title>"); file.println("<theme>"+getRandomTheme()+"</theme>"); file.println("<author>Lux version "+loader.getLuxVersion()+"</author>"); file.println("<email>lux@sillysoft.net</email>"); file.println("<webpage>http://sillysoft.net</webpage>"); file.println("<description>A randomly generated map.</description>"); file.println(""); ContinentIterator continentIter; int scenarioOwnerCount = getScenarioPlayerCountForSize(boardSize)-1; for (int i = 0; i < numContinents; i++) { file.println("<continent>"); file.println("<bonus>"+contBonus[i]+"</bonus>"); // Output all the countries in this continent continentIter = new ContinentIterator(i, countries); while (continentIter.hasNext()) { Country c = continentIter.next(); int code = c.getCode(); // Build the polygon co-ordinate list: String pointList = ""; for (int n = 0; n < points[code].size(); n++) pointList = pointList+(int)((Point2D)points[code].get(n)).getX()+","+(int)((Point2D)points[code].get(n)).getY()+" "; // Build the adjoining list: Country[] neighbors = c.getAdjoiningList(); String adList = String.valueOf(neighbors[0].getCode()); for (int n = 1; n < neighbors.length; n++) adList = adList+","+neighbors[n].getCode(); file.println("<country><id>"+code +"</id><polygon>"+pointList +"</polygon><adjoining>"+adList +"</adjoining><initialOwner>"+scenarioOwnerCount+"</initialOwner></country>"); scenarioOwnerCount--; if (scenarioOwnerCount < 0) scenarioOwnerCount = getScenarioPlayerCountForSize(boardSize)-1; } file.println("</continent>"); } for (int i = 0; i < lines.size(); i++) { Line2D line = (Line2D)lines.get(i); file.println("<line><position>"+(int)line.getP1().getX()+","+(int)line.getP1().getY()+" "+(int)line.getP2().getX()+","+(int)line.getP2().getY()+"</position></line>"); } file.println("</luxboard>"); file.close(); return true; }private void debug(Object text) { System.out.println(text);// System.out.flush(); } public int getScenarioPlayerCountForSize(String boardSize) { if (boardSize.equals("tiny")) return 3; if (boardSize.equals("small")) return 4; if (boardSize.equals("medium")) return 4; if (boardSize.equals("large")) return 5; if (boardSize.equals("huge")) return 6; return 0; } public String message( String message, Object data ) { if ("scenarioPlayerCount".equals(message)) { // How many players does the scenario for this size have? String choice = (String) data; return ""+getScenarioPlayerCountForSize(choice); } return null; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -