package impsoft.nexus.bots.color.scriptobjects; import java.awt.Color; import java.awt.Graphics; import java.awt.Rectangle; import java.util.ArrayList; import impsoft.nexus.bots.color.constants.Areas; import impsoft.nexus.bots.color.methods.ColorScript; import impsoft.nexus.bots.color.methods.GameScreenMethods; import impsoft.nexus.bots.color.methods.SortMethods; import impsoft.nexus.bots.color.methods.StaticColorMethods; import impsoft.nexus.components.paint.SimplePaintJob; public class RGBCluster { private Rectangle bounds = new Rectangle(Areas.GAME.x,Areas.GAME.y-30,Areas.GAME.width,Areas.GAME.height+30); private RGB theRGBs[]; private GameScreenMethods theScript; private XY[] theXYs = new XY[0]; private int[] theCounts = new int[0]; private boolean[] checked = new boolean[0]; private float zoneDx; private float zoneDy; public RGBCluster(RGB rgbs[], GameScreenMethods methods) { theRGBs = rgbs; theScript = methods; } public XY[] getPoints() { return theXYs; } public void gatherNewPoints(int points) { boolean filterThoseNearBy = true; long start = System.currentTimeMillis(); // calculate the tolerance for each RGB int[][] tolerances = new int[theRGBs.length][3]; for (int i = 0; i < theRGBs.length; i++) { tolerances[i][0] = theScript.getGameScreenTolerance(theRGBs[i].r); tolerances[i][1] = theScript.getGameScreenTolerance(theRGBs[i].g); tolerances[i][2] = theScript.getGameScreenTolerance(theRGBs[i].b); } // get the Color Map short[][][] colorMap = theScript.getColorArray2d(); // Divide the Screen into blocks int xParts = 15; int yParts = 10; zoneDx = (float) bounds.width / xParts; zoneDy = (float) bounds.height / yParts; // count the colors in each block int[][][] counts = new int[xParts][yParts][theRGBs.length]; int[] totalColorCounts = new int[theRGBs.length]; for (int x = 0; x < xParts; x++) { for (int y = 0; y < yParts; y++) { int xS = bounds.x + x * (int) zoneDx; int yS = bounds.y + y * (int) zoneDy; for (int k = 0; k < theRGBs.length; k++) { int count = StaticColorMethods.numRGBs(colorMap, theRGBs[k], xS, yS, xS + (int) zoneDx, yS + (int) zoneDy, tolerances[k][0], tolerances[k][1], tolerances[k][2]); counts[x][y][k] = count; totalColorCounts[k] += count; } } } /* * Calulate the zones, which are 2 blocks x 2 blocks Value is based on * the (# matched colors in zone ) / (total matched colors in bounds) * Values is added for each RGB Colors are weighed equally. */ float actualZones[][] = new float[xParts - 1][yParts - 1]; float rgbWeight = (float) 1 / theRGBs.length; for (int x = 0; x < xParts - 1; x++) { for (int y = 0; y < yParts - 1; y++) { for (int k = 0; k < theRGBs.length; k++) { if (totalColorCounts[k] > 0) { int colorCount = 0; colorCount += counts[x][y][k]; colorCount += counts[x + 1][y][k]; colorCount += counts[x][y + 1][k]; colorCount += counts[x + 1][y + 1][k]; actualZones[x][y] += (rgbWeight * colorCount) / totalColorCounts[k]; } } } } // Sort the Zones into the highest count first and ignore the Zones near // previous zones boolean selected[][] = new boolean[xParts - 1][yParts - 1]; XY result[] = new XY[points]; theCounts = new int[points]; checked = new boolean[points]; for (int i = 0; i < points; i++) { int winnerX = -1; int winnerY = -1; double winner = -1; for (int x = 0; x < xParts - 1; x++) { for (int y = 0; y < yParts - 1; y++) { if (!selected[x][y]) { if (actualZones[x][y] > winner) { winnerX = x; winnerY = y; winner = actualZones[x][y]; } } } } if (winnerX == -1 || winnerY == -1 || winner == 0.0) { XY newResult[] = new XY[i]; System.arraycopy(result, 0, newResult, 0, i); result = newResult; break; } else { selected[winnerX][winnerY] = true; if (filterThoseNearBy) { boolean innerXinRange = winnerX - 1 != -1; boolean outerXinRange = winnerX + 1 != xParts - 1; boolean outerYinRange = winnerY + 1 != yParts - 1; boolean innerYinRange = winnerY - 1 != -1; if (outerXinRange) { selected[winnerX + 1][winnerY] = true; // if (outerYinRange) { // selected[winnerX + 1][winnerY + 1] = true; // } // if (innerYinRange) { // selected[winnerX + 1][winnerY - 1] = true; // } } if (innerXinRange) { selected[winnerX - 1][winnerY] = true; // if (outerYinRange) { // selected[winnerX - 1][winnerY + 1] = true; // } // if (innerYinRange) { // selected[winnerX - 1][winnerY - 1] = true; // } } if (outerYinRange) { selected[winnerX][winnerY + 1] = true; } if (innerYinRange) { selected[winnerX][winnerY - 1] = true; } } // find the Most Dense 6px x 6px part in the Zone final int minX = bounds.x + (int) (zoneDx * winnerX); final int minY = bounds.y + (int) (zoneDy * winnerY); final int maxX = bounds.x + (int) (zoneDx * (winnerX + 2)); final int maxY = bounds.y + (int) (zoneDy * (winnerY + 2)); final int interval = 6; int smallerWinnerX = -1; int smallerWinnerY = -1; int smallerWinnerCount = -1; for (int x = minX; x < maxX; x += interval) { for (int y = minY; y < maxY; y += interval) { int count = 0; for (int k = 0; k < theRGBs.length; k++) { count += StaticColorMethods.numRGBs(colorMap, theRGBs[k], x, y, x + interval, y + interval, tolerances[k][0], tolerances[k][1], tolerances[k][2]); } if (count > smallerWinnerCount) { smallerWinnerX = x + interval / 2; smallerWinnerY = y + interval / 2; smallerWinnerCount = count; } } } final int smallerWinnerXcopy = smallerWinnerX; final int smallerWinnerYcopy = smallerWinnerY; theScript.addPaintJob(new SimplePaintJob(5000) { @Override public void paint(Graphics g) { g.setColor(Color.black); g.drawRect(minX, minY, maxX - minX, maxY - minY); g.setColor(Color.YELLOW); g.drawRect(smallerWinnerXcopy - 2, smallerWinnerYcopy - 2, 4, 4); } }); // System.out.println("dx="+(minX-smallerWinnerX)+" // dy="+(minY-smallerWinnerY)); result[i] = new XY(smallerWinnerX, smallerWinnerY); theCounts[i] = smallerWinnerCount; } } theXYs = result; theScript.debug("findRGBsCluster() took" + (System.currentTimeMillis() - start)); } public boolean doMenu(String action) throws InterruptedException { return doCluster(0, 0, null, action, false); } public boolean doTopTextAndMenu(String topText, String action) throws InterruptedException { return doCluster(0, 0, topText, action, false); } public boolean doMenuOnMoving(String action) throws InterruptedException { return doCluster(0, 0, null, action, false); } public boolean doTopTextAndMenuOnMoving(String topText, String action) throws InterruptedException { return doCluster(0, 0, topText, action, true); } public boolean doCluster(int xOffet, int yOffset, String topText, String action, boolean moving) throws InterruptedException { removeRedundantPoints(3); sortPointsByDistanceToXY(new XY((int) bounds.getCenterX(), (int) bounds.getCenterY())); XY nextPoint; while ((nextPoint = getNext()) != null) { int mouseTime = theScript.mouseTime(new XY(nextPoint.x + xOffet, nextPoint.y + yOffset)); theScript.mouseMove(nextPoint.x + xOffet, nextPoint.y + yOffset, mouseTime); if (moving) { Timer mouseMove = new Timer(mouseTime); while (!mouseMove.isUp()) { int interval = StaticColorMethods.defaultmaxAgeInMillisecs * 2; updatePoints(); removeRedundantPoints(3); paintPoints(interval); Thread.sleep(interval); } } else { paintPoints(mouseTime); Thread.sleep(mouseTime); } nextPoint = getNext(); if (nextPoint != null) { if (SortMethods.distance(nextPoint, theScript.currentMouseXY()) < 30) { if (topText != null) { Thread.sleep(StaticColorMethods.defaultmaxAgeInMillisecs); if (theScript.getTopText().contains(topText)) { theScript.mouseClickRight(new XY(nextPoint.x + xOffet, nextPoint.y + yOffset)); Menu menu = theScript.getMenu(Areas.GAME, 2000); if (menu != null && menu.selectContains(action)) { return true; } } } else { theScript.mouseClickRight(new XY(nextPoint.x + xOffet, nextPoint.y + yOffset)); Menu menu = theScript.getMenu(Areas.GAME, 2000); if (menu != null && menu.selectContains(action)) { return true; } } pop(); } } } return false; } public XY pop() { for (int i = 0; i < theXYs.length; i++) { if (!checked[i]) { checked[i] = true; return theXYs[i]; } } return null; } public XY getNext() { for (int i = 0; i < theXYs.length; i++) { if (!checked[i]) { return theXYs[i]; } } return null; } public void sortPointsByDistanceToXY(XY location) { ArrayList result = new ArrayList(); ArrayList ints = new ArrayList(); ArrayList bools = new ArrayList(); for (int i = 0; i < theXYs.length; i++) { int indexClosest = -1; int Closestdistance = 0; for (int j = 0; j < i; j++) { if (theXYs[j] == null) { continue; } int distance = SortMethods.distance(theXYs[j], location); if (indexClosest == -1 || Closestdistance > distance) { Closestdistance = distance; indexClosest = j; } } if (indexClosest != -1) { result.add(theXYs[indexClosest]); ints.add(theCounts[indexClosest]); bools.add(checked[indexClosest]); theXYs[indexClosest] = null; } } theXYs = new XY[result.size()]; theCounts = new int[result.size()]; checked = new boolean[result.size()]; for (int i = 0; i < theXYs.length; i++) { theXYs[i] = result.get(i); theCounts[i] = ints.get(i); checked[i] = bools.get(i); } } public void removePointsNearColor(RGB rgb) { int redTolerance = theScript.getGameScreenTolerance(rgb.r); int greenTolerance = theScript.getGameScreenTolerance(rgb.g); int blueTolerance = theScript.getGameScreenTolerance(rgb.b); int size=100; ArrayList result = new ArrayList(); ArrayList ints = new ArrayList(); ArrayList bools = new ArrayList(); short[][][] colorMap = theScript.getColorArray2d(); for (int i = 0; i < theXYs.length; i++) { boolean valid = true; for (int j = 0; j < i; j++) { Rectangle zone = new Rectangle(theXYs[i].x-size/2,theXYs[i].y-size/2,size,size); zone = zone.intersection(bounds); int count = StaticColorMethods.numRGBs(colorMap, rgb, zone, redTolerance, greenTolerance, blueTolerance); if(count>0){ valid=false; } } if (valid) { result.add(theXYs[i]); ints.add(theCounts[i]); bools.add(checked[i]); } } theXYs = new XY[result.size()]; theCounts = new int[result.size()]; checked = new boolean[result.size()]; for (int i = 0; i < theXYs.length; i++) { theXYs[i] = result.get(i); theCounts[i] = ints.get(i); checked[i] = bools.get(i); } } public void removeRedundantPoints(int distanceToEach) { ArrayList result = new ArrayList(); ArrayList ints = new ArrayList(); ArrayList bools = new ArrayList(); for (int i = 0; i < theXYs.length; i++) { boolean valid = true; for (int j = 0; j < i; j++) { if (SortMethods.distance(theXYs[i], theXYs[j]) < distanceToEach) { valid = false; break; } } if (valid) { result.add(theXYs[i]); ints.add(theCounts[i]); bools.add(checked[i]); } } theXYs = new XY[result.size()]; theCounts = new int[result.size()]; checked = new boolean[result.size()]; for (int i = 0; i < theXYs.length; i++) { theXYs[i] = result.get(i); theCounts[i] = ints.get(i); checked[i] = bools.get(i); } } public void updatePoints() { int minXGame = bounds.x; int minYGame = bounds.y; int maxXGame = bounds.x + bounds.width; int maxYGame = bounds.y + bounds.height; int[][] tolerances = new int[theRGBs.length][3]; for (int i = 0; i < theRGBs.length; i++) { tolerances[i][0] = theScript.getGameScreenTolerance(theRGBs[i].r); tolerances[i][1] = theScript.getGameScreenTolerance(theRGBs[i].g); tolerances[i][2] = theScript.getGameScreenTolerance(theRGBs[i].b); } short[][][] colorMap = theScript.getColorArray2d(); for (int i = 0; i < theXYs.length; i++) { boolean done = false; for (int size = 1; size < 5 && !done; size++) { int minX = (int) (theXYs[i].x - size * zoneDx / 2); int minY = (int) (theXYs[i].y - size * zoneDy / 2); int maxX = (int) (theXYs[i].x + size * zoneDx / 2); int maxY = (int) (theXYs[i].y + size * zoneDy / 2); if (minX < minXGame) { minX = minXGame; } if (minY < minYGame) { minY = minYGame; } if (maxX > maxXGame) { maxX = maxXGame; } if (maxY > maxYGame) { maxY = maxYGame; } final int interval = 6; int smallerWinnerX = -1; int smallerWinnerY = -1; int smallerWinnerCount = -1; for (int x = minX; x < maxX; x += interval) { for (int y = minY; y < maxY; y += interval) { int count = 0; for (int k = 0; k < theRGBs.length; k++) { count += StaticColorMethods.numRGBs(colorMap, theRGBs[k], x, y, x + interval, y + interval, tolerances[k][0], tolerances[k][1], tolerances[k][2]); } if (count > smallerWinnerCount) { smallerWinnerX = x + interval / 2; smallerWinnerY = y + interval / 2; smallerWinnerCount = count; } } } if (smallerWinnerCount * 2 > theCounts[i]) { done = true; theXYs[i] = new XY(smallerWinnerX, smallerWinnerY); theCounts[i] = smallerWinnerCount; } } } } public void paintPoints(final int timeToPaint) { for (int i = 0; i < theXYs.length; i++) { final XY spot = theXYs[i]; theScript.addPaintJob(new SimplePaintJob(timeToPaint) { @Override public void paint(Graphics g) { g.setColor(Color.YELLOW); g.drawRect(spot.x - 2, spot.y - 2, 4, 4); } }); } } }