import impsoft.nexus.bots.color.constants.Areas; import impsoft.nexus.bots.color.scriptable.ColorSkeltonScriptable; import impsoft.nexus.bots.color.scriptable.components.MenuFinder; import impsoft.nexus.bots.color.scriptable.components.gamescreen.TopText; import impsoft.nexus.bots.color.structures.RGB; import impsoft.nexus.bots.color.structures.XY; import impsoft.nexus.bots.color.util.*; import impsoft.nexus.storage.SettingsManager; import java.awt.Color; import java.awt.Rectangle; import java.util.ArrayList; import java.util.Iterator; public class PublicEdgeRGBCluster { public PublicEdgeRGBCluster(RGB rgbs[], ColorSkeltonScriptable cs) { this(rgbs, cs, 18, 18); } public PublicEdgeRGBCluster(RGB rgbs[], ColorSkeltonScriptable cs, int blockWidth, int blockLength) { this(rgbs, cs, GAMESCREEN_EXCLUDING_TOPTEXT, GAMESCREEN_EXCLUDING_TOPTEXT.width / blockWidth, GAMESCREEN_EXCLUDING_TOPTEXT.height / blockLength, 5); } public PublicEdgeRGBCluster(RGB rgbs[], ColorSkeltonScriptable cs, Rectangle bounds, int theNumberOfHorizontalSearchZones, int theNumberOfVerticalSearchZones, int XYlinesToSkip) { DEBUG_PAINT_STEP_0 = true; DEBUG_PAINT_STEP_1 = true; DEBUG_PAINT_STEP_2 = true; DEBUG_PAINT_STEP_3 = true; points = new ArrayList(); paintTime = 2000; movingAccuracy = 10; sortBasedOnCenter = false; theColorScriptable = cs; this.bounds = bounds; width = bounds.width; height = bounds.height; xStart = bounds.x; yStart = bounds.y; xStop = bounds.x + width; yStop = bounds.y + height; this.theNumberOfHorizontalSearchZones = theNumberOfHorizontalSearchZones; this.theNumberOfVerticalSearchZones = theNumberOfVerticalSearchZones; zoneDx = (double)width / (double)theNumberOfHorizontalSearchZones; zoneDy = (double)height / (double)theNumberOfVerticalSearchZones; GameScreenEdges = new boolean[width][height]; if(DEBUG_PAINT_STEP_1) GameScreenEdgeBoxsPaint = new boolean[width][height]; else GameScreenEdgeBoxsPaint = null; xEdgeStart = xStart + 4; xEdgeStop = xStop - 4; yEdgeStart = yStart + 4; yEdgeStop = yStop - 4; incrementation = 1 + XYlinesToSkip; ratio = 0.25D / (double)(incrementation * incrementation); setRGBs(rgbs); } public RGB[] getRGBs() { return rgbs; } public void setRGBs(RGB rgbs[]) { this.rgbs = rgbs; int colorLength = rgbs.length; thePixelTolerances = new int[colorLength][3]; thePixels = new short[colorLength][3]; for(int i = 0; i < colorLength; i++) { thePixels[i][0] = rgbs[i].r; thePixels[i][1] = rgbs[i].g; thePixels[i][2] = rgbs[i].b; thePixelTolerances[i][0] = AutoTolerance.getGameScreenTolerance(thePixels[i][0]); thePixelTolerances[i][1] = AutoTolerance.getGameScreenTolerance(thePixels[i][1]); thePixelTolerances[i][2] = AutoTolerance.getGameScreenTolerance(thePixels[i][2]); } } public XY doAdvanceCustom(int xOffet, int yOffset, String topText, String action, boolean movingTarget, boolean fastReturn, boolean aquireNewPoints) throws InterruptedException { if(aquireNewPoints) { populateEdges(); populateBlocksFromEdges(); populateClusterBlocksFromBlocks(10); populatePoints(); } XY nextPoint; while((nextPoint = getNextPoint()) != null) { long mousetime = 0L; XY movingMouseTo = new XY(nextPoint.x + xOffet, nextPoint.y + yOffset); theColorScriptable.mouseMove(movingMouseTo.x, movingMouseTo.y, Areas.ENTIRE, true, false); do { mousetime = theColorScriptable.getInputTimeLeft(); if(mousetime != -1L) if(movingTarget) { updatePoints(); removeRedundantPoints(3); if((long)MINIMUM_UPDATE_WAIT > mousetime) mousetime = MINIMUM_UPDATE_WAIT; if(DEBUG_PAINT_STEP_3) paintPoints((int)mousetime, RGBClusterPointColor, 2); Thread.sleep(mousetime); nextPoint = getNextPoint(); if(nextPoint != null) { XY updatedMovingMouseTo = new XY(nextPoint.x + xOffet, nextPoint.y + yOffset); if(Sorting.distance(movingMouseTo, updatedMovingMouseTo) > movingAccuracy) { movingMouseTo = updatedMovingMouseTo; theColorScriptable.mouseMove(movingMouseTo.x, movingMouseTo.y, Areas.ENTIRE, true, false); Thread.sleep(10L); } } } else { if(DEBUG_PAINT_STEP_3) paintPoints((int)mousetime, RGBClusterPointColor, 2); Thread.sleep(mousetime); } } while(mousetime > 10L); if(nextPoint != null) { boolean click = topText == null; for(int i = 0; !click && i < 3; i++) { click = theColorScriptable.theTopText.isTopTextContaining(topText); if(!click) theColorScriptable.waitTillNextFrame(); } if(click) { boolean clickSucessful = false; if(action == null) { theColorScriptable.mouseClickLeft(new XY(nextPoint.x + xOffet, nextPoint.y + yOffset)); clickSucessful = true; } else { theColorScriptable.mouseClickRight(new XY(nextPoint.x + xOffet, nextPoint.y + yOffset)); if(theColorScriptable.theMenuFinder.doMenu(action)) clickSucessful = true; } if(clickSucessful) { if(!fastReturn) { for(; theColorScriptable.theMenuFinder.isAMenuIn(); theColorScriptable.waitTillNextFrame()); points = new ArrayList(1); points.add(nextPoint); Timer t = new Timer(20000L); Thread.sleep(500L); int sleepTime = SettingsManager.getiBotSleepTime(); do { if(DEBUG_PAINT_STEP_3) paintPoints(sleepTime * 3, RGBClusterPointColor, 4); updatePoints(); theColorScriptable.waitTillNextFrame(); updatePoints(); theColorScriptable.waitTillNextFrame(); updatePoints(); } while(theColorScriptable.isMoving() && !t.isUp()); nextPoint = getNextPoint(); } if(nextPoint != null) return new XY(nextPoint.x + xOffet, nextPoint.y + yOffset); else return null; } } removeLastPoint(); } } return null; } public XY doCustom(int xOffet, int yOffset, String topText, String action, boolean movingTarget, boolean fastReturn) throws InterruptedException { return doAdvanceCustom(xOffet, yOffset, topText, action, movingTarget, fastReturn, true); } public void sortPointsByDistanceToXY(XY location) { ArrayList result = new ArrayList(points.size()); XY thePoints[] = (XY[])points.toArray(new XY[points.size()]); for(int i = 0; i < thePoints.length; i++) { int indexClosest = -1; int Closestdistance = 0; for(int j = 0; j < thePoints.length; j++) if(thePoints[j] != null) { int distance = Sorting.distance(thePoints[j], location); if(indexClosest == -1 || Closestdistance > distance) { Closestdistance = distance; indexClosest = j; } } if(indexClosest != -1) { result.add(thePoints[indexClosest]); thePoints[indexClosest] = null; } } points = result; } public XY doMenu(String action) throws InterruptedException { return doCustom(0, 0, null, action, false, false); } public XY doMenuOnMoving(String action) throws InterruptedException { return doCustom(0, 0, null, action, true, false); } public XY doTopText(String topText) throws InterruptedException { return doCustom(0, 0, topText, null, false, false); } public XY doTopTextAndMenu(String topText, String action) throws InterruptedException { return doCustom(0, 0, topText, action, false, false); } public XY doTopTextAndMenuOnMoving(String topText, String action) throws InterruptedException { return doCustom(0, 0, topText, action, true, false); } public XY doTopTextOnMoving(String topText) throws InterruptedException { return doCustom(0, 0, topText, null, true, false); } public XY getNextPoint() { if(points.size() > 0) return (XY)points.get(0); else return null; } public void paintPoints(int timeToPaint, Color color, int size) { XY spot; for(Iterator iterator = points.iterator(); iterator.hasNext(); theColorScriptable.paintRectangle(new Rectangle(spot.x - size, spot.y - size, size * 2, size * 2), color, timeToPaint)) spot = (XY)iterator.next(); } public XY[] populateBlocksFromEdges() throws InterruptedException { return populateBlocksFromEdges(ratio); } public XY[] populateBlocksFromEdges(double density) throws InterruptedException { ArrayList xys = new ArrayList(100); for(int x = 0; x < theNumberOfHorizontalSearchZones; x++) { for(int y = 0; y < theNumberOfVerticalSearchZones; y++) { int xS = (int)((double)x * zoneDx); int yS = (int)((double)y * zoneDy); int xD = (int)((double)(x + 1) * zoneDx); int yD = (int)((double)(y + 1) * zoneDy); if(xD > width) xD = width; if(yD > height) yD = height; int trues = 0; for(int x2 = xS; x2 < xD; x2++) { boolean part[] = GameScreenEdges[x2]; for(int y2 = yS; y2 < yD; y2++) if(part[y2]) trues++; } int totalArea = (xD - xS) * (yD - yS); if((double)trues > density * (double)totalArea) { if(DEBUG_PAINT_STEP_1) { for(int frameX = xS; frameX < xD; frameX++) { boolean part[] = GameScreenEdgeBoxsPaint[frameX]; for(int frameY = yS; frameY < yD; frameY++) part[frameY] = true; } } xys.add(new XY(xS + xStart, yS + yStart)); } } } if(DEBUG_PAINT_STEP_1) theColorScriptable.paintBooleanMap(GameScreenEdgeBoxsPaint, xStart, yStart, EdgeBoxColor, paintTime); blocks = (XY[])xys.toArray(new XY[xys.size()]); return blocks; } public XY[] populateClusterBlocksFromBlocks(int numPoints) throws InterruptedException { short colorMap[][][] = theColorScriptable.getColorMap(); XY xys[] = blocks; int numXYs = xys.length; int numColors = thePixels.length; int counts[][] = new int[numXYs][numColors]; int totalColorCounts[] = new int[numColors]; for(int i = 0; i < numXYs; i++) { int xS = xys[i].x; int yS = xys[i].y; int xD = xS + (int)zoneDx; int yD = yS + (int)zoneDy; for(int k = 0; k < numColors; k++) { int count = 0; short pixel[] = thePixels[k]; int rTolerance = thePixelTolerances[k][0]; int gTolerance = thePixelTolerances[k][1]; int bTolerance = thePixelTolerances[k][2]; for(int x = xS; x < xD; x++) { short part[][] = colorMap[x]; for(int y = yS; y < yD; y++) { short part2[] = part[y]; int diff = pixel[0] - part2[0]; if((diff < 0 ? -diff : diff) <= rTolerance) { diff = pixel[1] - part2[1]; if((diff < 0 ? -diff : diff) <= gTolerance) { diff = pixel[2] - part2[2]; if((diff < 0 ? -diff : diff) <= bTolerance) count++; } } } } counts[i][k] = count; totalColorCounts[k] += count; } } float rgbWeight = 1.0F / (float)numColors; float weightedTotals[] = new float[numXYs]; for(int i = 0; i < numXYs; i++) { for(int k = 0; k < numColors; k++) { int colorCount = counts[i][k]; if(colorCount >= 1) weightedTotals[i] += (rgbWeight * (float)colorCount) / (float)totalColorCounts[k]; } } ArrayList result; for(result = new ArrayList(numPoints); result.size() < numPoints;) { float winner = 0.0F; int winnerIndex = -1; for(int i = 0; i < numXYs; i++) { float challenger = weightedTotals[i]; if(challenger > winner) { winnerIndex = i; winner = challenger; } } if(winnerIndex == -1) break; result.add(xys[winnerIndex]); weightedTotals[winnerIndex] = 0.0F; } clusterBlocks = result; XY answer[] = (XY[])result.toArray(new XY[result.size()]); if(DEBUG_PAINT_STEP_2) { for(int i = 0; i < answer.length; i++) theColorScriptable.paintRectangle(new Rectangle(answer[i].x, answer[i].y, (int)zoneDx, (int)zoneDy), RGBClusterColor, paintTime); } return answer; } public void populateEdges() throws InterruptedException { populateEdges(20, incrementation); } public void populateEdges(int tolerance, int incrementation) throws InterruptedException { double toleranceRatio = (double)tolerance / 255D; short colorMap[][][] = theColorScriptable.getColorMap(); for(int frameX = xEdgeStart; frameX < xEdgeStop; frameX += incrementation) { boolean resPiece[] = GameScreenEdges[(frameX - xEdgeStart) + 4]; short piece[][] = colorMap[frameX]; for(int frameY = yEdgeStart; frameY < yEdgeStop; frameY += incrementation) { short color[] = piece[frameY]; int redTolerance = 1 + (int)(toleranceRatio * (double)color[0]); int greenTolerance = 1 + (int)(toleranceRatio * (double)color[1]); int blueTolerance = 1 + (int)(toleranceRatio * (double)color[2]); boolean edge = true; for(int xIndex = frameX - 4; xIndex < frameX; xIndex++) { short rgb[] = colorMap[xIndex][frameY]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; for(int xIndex = frameX; xIndex < frameX + 4; xIndex++) { short rgb[] = colorMap[xIndex][frameY]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; for(int yIndex = frameY - 4; yIndex < frameY; yIndex++) { short rgb[] = colorMap[frameX][yIndex]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; for(int yIndex = frameY; yIndex < frameY + 4; yIndex++) { short rgb[] = colorMap[frameX][yIndex]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; int xIndex = frameX - 4; for(int yIndex = frameY - 4; xIndex < frameX && yIndex < frameY; yIndex++) { short rgb[] = colorMap[xIndex][yIndex]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } xIndex++; } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; xIndex = frameX - 4; for(int yIndex = frameY; xIndex < frameX && yIndex < frameY + 4; yIndex++) { short rgb[] = colorMap[xIndex][yIndex]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } xIndex++; } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; xIndex = frameX; for(int yIndex = frameY - 4; xIndex < frameX + 4 && yIndex < frameY; yIndex++) { short rgb[] = colorMap[xIndex][yIndex]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } xIndex++; } if(edge) { resPiece[(frameY - yEdgeStart) + 4] = true; } else { edge = true; xIndex = frameX; for(int yIndex = frameY; xIndex < frameX + 4 && yIndex < frameY + 4; yIndex++) { short rgb[] = colorMap[xIndex][yIndex]; int redChange = rgb[0] - color[0]; if((redChange < 0 ? -redChange : redChange) <= redTolerance) { int greenChange = rgb[1] - color[1]; if((greenChange < 0 ? -greenChange : greenChange) <= greenTolerance) { int blueChange = rgb[2] - color[2]; if((blueChange < 0 ? -blueChange : blueChange) <= blueTolerance) edge = false; } } xIndex++; } if(edge) resPiece[(frameY - yEdgeStart) + 4] = true; } } } } } } } } } if(DEBUG_PAINT_STEP_0) theColorScriptable.paintBooleanMap(GameScreenEdges, xStart, yStart, EdgeColor, paintTime); } public void populatePoints() throws InterruptedException { int numColors = thePixels.length; points.clear(); short colorMap[][][] = theColorScriptable.getColorMap(); for(Iterator iterator = clusterBlocks.iterator(); iterator.hasNext();) { XY clusterBlock = (XY)iterator.next(); int minX = clusterBlock.x; int minY = clusterBlock.y; int maxX = clusterBlock.x + (int)zoneDx; int maxY = clusterBlock.y + (int)zoneDy; int interval = 6; int smallerWinnerX = -1; int smallerWinnerY = -1; int smallerWinnerCount = -1; for(int x = minX; x < maxX; x += 6) { for(int y = minY; y < maxY; y += 6) { for(int k = 0; k < numColors; k++) { int count = 0; short pixel[] = thePixels[k]; int rTolerance = thePixelTolerances[k][0]; int gTolerance = thePixelTolerances[k][1]; int bTolerance = thePixelTolerances[k][2]; for(int xRed = x; xRed < x + 6; xRed++) { short part[][] = colorMap[xRed]; for(int yRed = y; yRed < y + 6; yRed++) { short part2[] = part[yRed]; int diff = pixel[0] - part2[0]; if((diff < 0 ? -diff : diff) <= rTolerance) { diff = pixel[1] - part2[1]; if((diff < 0 ? -diff : diff) <= gTolerance) { diff = pixel[2] - part2[2]; if((diff < 0 ? -diff : diff) <= bTolerance) count++; } } } } if(count > smallerWinnerCount) { smallerWinnerX = x + 3; smallerWinnerY = y + 3; smallerWinnerCount = count; } } } } if(smallerWinnerX != -1 && smallerWinnerY != -1) points.add(new XY(smallerWinnerX, smallerWinnerY)); } if(sortBasedOnCenter) sortPointsByDistanceToXY(new XY((int)bounds.getCenterX(), (int)bounds.getCenterY())); removeRedundantPoints(10); if(DEBUG_PAINT_STEP_3) paintPoints(paintTime, RGBClusterPointColor, 2); } public void setSortingFromCenter(boolean b) { sortBasedOnCenter = b; } public void removeLastPoint() { if(points.size() > 0) points.remove(0); } public void removeRedundantPoints(int distanceToEach) { for(int i = 0; i < points.size(); i++) { for(int j = 0; j < i; j++) { if(Sorting.distance((XY)points.get(i), (XY)points.get(j)) >= distanceToEach) continue; points.remove(i); break; } } } public void updatePoints() throws InterruptedException { ArrayList newpoints = new ArrayList(); int numColors = thePixels.length; short colorMap[][][] = theColorScriptable.getColorMap(); for(Iterator iterator = points.iterator(); iterator.hasNext();) { XY clusterBlock = (XY)iterator.next(); boolean success = false; for(int interval = 0; interval < 5; interval++) { int minX = clusterBlock.x - (int)((double)interval * zoneDx); int minY = clusterBlock.y - (int)((double)interval * zoneDy); int maxX = clusterBlock.x + (int)((double)interval * zoneDx); int maxY = clusterBlock.y + (int)((double)interval * zoneDy); if(minX < xStart) minX = xStart; if(minX > xStop) minX = xStop; if(maxX < xStart) maxX = xStart; if(maxX > xStop) maxX = xStop; if(minY < yStart) minY = yStart; if(maxY > yStop) maxY = yStop; if(maxY < yStart) maxY = yStart; if(maxY > yStop) maxY = yStop; int intervalSM = 6; int smallerWinnerX = -1; int smallerWinnerY = -1; int smallerWinnerCount = 0; for(int x = minX; x < maxX; x += intervalSM) { for(int y = minY; y < maxY; y += intervalSM) { int count = 0; for(int k = 0; k < numColors; k++) { short pixel[] = thePixels[k]; int rTolerance = thePixelTolerances[k][0]; int gTolerance = thePixelTolerances[k][1]; int bTolerance = thePixelTolerances[k][2]; for(int xRed = x; xRed < x + intervalSM; xRed++) { short part[][] = colorMap[xRed]; for(int yRed = y; yRed < y + intervalSM; yRed++) { short part2[] = part[yRed]; int diff = pixel[0] - part2[0]; if((diff < 0 ? -diff : diff) <= rTolerance) { diff = pixel[1] - part2[1]; if((diff < 0 ? -diff : diff) <= gTolerance) { diff = pixel[2] - part2[2]; if((diff < 0 ? -diff : diff) <= bTolerance) count++; } } } } } if(count > smallerWinnerCount) { smallerWinnerX = x + intervalSM / 2; smallerWinnerY = y + intervalSM / 2; smallerWinnerCount = count; } } } if(smallerWinnerX == -1 || smallerWinnerY == -1) continue; newpoints.add(new XY(smallerWinnerX, smallerWinnerY)); success = true; break; } if(!success) newpoints.add(clusterBlock); } points.clear(); points = newpoints; removeRedundantPoints(10); } public void removePointsNearColor(RGB rgb, int redTolerance, int greenTolerance, int blueTolerance, int size) throws InterruptedException { ArrayList results = new ArrayList(points.size()); short colorMap[][][] = theColorScriptable.getColorMap(); for(Iterator iterator = points.iterator(); iterator.hasNext();) { XY pt = (XY)iterator.next(); Rectangle zone = new Rectangle(pt.x - size / 2, pt.y - size / 2, size, size); zone = zone.intersection(bounds); int count = ColorMapAnaylsis.countRGB(colorMap, rgb, zone, redTolerance, greenTolerance, blueTolerance); if(count == 0) results.add(pt); } points = results; } public static int MINIMUM_UPDATE_WAIT = 3; public static final int EDGE_BORDER = 4; public static final double DEFAULT_RATIO = 0.25D; public static final int DEFAULT_TOLERANCE = 20; public static final int DEFAULT_INCREMENTATION = 1; public static final Rectangle GAMESCREEN_EXCLUDING_TOPTEXT; public static final Color EdgeColor = new Color(0, 0, 0, 255); public static final Color EdgeBoxColor = new Color(255, 0, 0, 25); public static final Color RGBClusterColor = new Color(255, 255, 0, 160); public static final Color RGBClusterPointColor = new Color(0, 255, 0, 255); public boolean DEBUG_PAINT_STEP_0; public boolean DEBUG_PAINT_STEP_1; public boolean DEBUG_PAINT_STEP_2; public boolean DEBUG_PAINT_STEP_3; public final Rectangle bounds; public final int width; public final int height; public final int xStart; public final int xEdgeStart; public final int xEdgeStop; public final int yEdgeStart; public final int yEdgeStop; public final int yStart; public final int xStop; public final int yStop; public final double zoneDx; public final double zoneDy; public final int theNumberOfHorizontalSearchZones; public final int theNumberOfVerticalSearchZones; public final ColorSkeltonScriptable theColorScriptable; public final int incrementation; DuncanRimmingtonMiner