package org.petah.spring.bai.map.metal; import com.springrts.ai.oo.AIFloat3; import org.petah.spring.bai.cache.CachedMetalMap; import java.util.Iterator; import java.util.LinkedList; import org.petah.common.option.Option; import org.petah.common.option.OptionsManager; import org.petah.common.util.GameMath; import org.petah.spring.bai.cache.CachedUnit; /** * * @author Petah */ public class MetalFinder { // Options private static Option<Integer> metalSpotJiggleAmount = OptionsManager.getOption( new Option<Integer>("metalSpotJiggleAmount", 20)); private static Option<Float> metalSpotSpacingFactor = OptionsManager.getOption( new Option<Float>("metalSpotSpacingFactor", 0.4f)); public static LinkedList<MetalSpot> getMetalSpots(CachedMetalMap cachedMetalMap) { LinkedList<MetalSpot> metalSpots = getAllMetalSpots(cachedMetalMap); Iterator<MetalSpot> i; int totalValue = 0; for (MetalSpot metalSpot : metalSpots) { totalValue += metalSpot.getValue(); } int average = totalValue / metalSpots.size(); average /= 2; i = metalSpots.iterator(); while (i.hasNext()) { MetalSpot metalSpot = i.next(); if (metalSpot.getValue() < average) { i.remove(); } } if (metalSpots.size() < 1000) { i = metalSpots.iterator(); while (i.hasNext()) { MetalSpot outer = i.next(); Iterator<MetalSpot> j = metalSpots.iterator(); while (j.hasNext()) { MetalSpot inner = j.next(); if (outer == inner) { continue; } double distance = GameMath.pointDistance(outer.getX(), outer.getY(), inner.getX(), inner.getY()); if (outer.getValue() <= inner.getValue() && distance <= cachedMetalMap.getMetalExtractorRadius() * 2) { i.remove(); break; } } } } // Find center of metal spot for (MetalSpot metalSpot : metalSpots) { int highestX = Integer.MIN_VALUE; int highestY = Integer.MIN_VALUE; int lowestX = Integer.MAX_VALUE; int lowestY = Integer.MAX_VALUE; for (int x = 0; x < cachedMetalMap.getMetalExtractorRadius()*2; x++) { for (int y = 0; y < cachedMetalMap.getMetalExtractorRadius()*2; y++) { int realX = (int) (x + metalSpot.getX() - cachedMetalMap.getMetalExtractorRadius()); int realY = (int) (y + metalSpot.getY() - cachedMetalMap.getMetalExtractorRadius()); float distance = GameMath.pointDistance(realX, realY, metalSpot.getX(), metalSpot.getY()); // System.err.println(distance + "\t<=\t" + cachedMetalMap.getMetalExtractorRadius() + "\t&&\t" + // cachedMetalMap.getValue(realX, realY) + "\t>\t" + cachedMetalMap.getAverageMetal() + // "\t::" + realX + "," + realY); if (distance <= cachedMetalMap.getMetalExtractorRadius() && cachedMetalMap.getValue(realX, realY) > cachedMetalMap.getAverageMetal()) { if (realX < lowestX) { lowestX = realX; } if (realY < lowestY) { lowestY = realY; } if (realX > highestX) { highestX = realX; } if (realY > highestY) { highestY = realY; } } } } metalSpot.setX(lowestX + ((highestX - lowestX) / 2)); metalSpot.setY(lowestY + ((highestY - lowestY) / 2)); } // Jiggle metal spot // List<MetalSpot> newMetalSpots = new ArrayList<MetalSpot>(); // i = metalSpots.iterator(); // while (i.hasNext()) { // MetalSpot metalSpot = i.next(); // MetalSpot bestMetalSpot = null; // for (int j = 0; j < metalSpotJiggleAmount.getValue(); j++) { // int x = metalSpot.getX(); // int y = metalSpot.getY(); // int jiggleSize = (int) (cachedMetalMap.getMetalExtractorRadius() * 2); // x += Math.random() * jiggleSize - jiggleSize / 2; // y += Math.random() * jiggleSize - jiggleSize / 2; // MetalSpot newMetalSpot = getMetalSpot(cachedMetalMap, x, y); // if (newMetalSpot != null) { // if (bestMetalSpot != null) { // if (newMetalSpot.getValue() >= bestMetalSpot.getValue()) { // bestMetalSpot = newMetalSpot; // } // } else if (newMetalSpot.getValue() >= metalSpot.getValue()) { // bestMetalSpot = newMetalSpot; // } // } // } // if (bestMetalSpot != null) { // i.remove(); // newMetalSpots.add(bestMetalSpot); // } // } // metalSpots.addAll(newMetalSpots); return metalSpots; } public static LinkedList<MetalZone> getMetalZones(CachedMetalMap cachedMetalMap) { LinkedList<MetalZone> metalZones = new LinkedList<MetalZone>(); // TODO: improve metal zone finder // int zoneWidth = cachedMetalMap.getWidth() / 30; // int zoneHeight = cachedMetalMap.getHeight() / 30; // zoneWidth = Math.max(zoneWidth, zoneHeight); // zoneHeight = Math.max(zoneWidth, zoneHeight); // for (int y = 0; y < cachedMetalMap.getHeight(); y += zoneHeight) { // for (int x = 0; x < cachedMetalMap.getWidth(); x += zoneWidth) { // MetalZone metalZone = new MetalZone(x, y, zoneWidth, zoneHeight); // if (metalZone.getAverageMetal() > cachedMetalMap.getAverageMetal()) { // metalZones.add(metalZone); // } // } // } return metalZones; } private static LinkedList<MetalSpot> getAllMetalSpots(CachedMetalMap cachedMetalMap) { LinkedList<MetalSpot> metalSpots = new LinkedList<MetalSpot>(); boolean stagger = true; float factor = metalSpotSpacingFactor.getValue(); for (float y = cachedMetalMap.getMetalExtractorRadius(); y < cachedMetalMap.getHeight(); y += cachedMetalMap.getMetalExtractorRadius() * factor) { stagger = !stagger; for (float x = cachedMetalMap.getMetalExtractorRadius() + (stagger ? cachedMetalMap.getMetalExtractorRadius() * factor : 0); x < cachedMetalMap.getWidth(); x += cachedMetalMap.getMetalExtractorRadius() * (1 + factor)) { // for (int y = radius / 2; y < height; y += radius) { // for (int x = radius / 2; x < width; x += radius) { MetalSpot metalSpot = getMetalSpot(cachedMetalMap, (int) x, (int) y); if (metalSpot != null) { metalSpots.add(metalSpot); } } } return metalSpots; } private static int getMetalSpotValue(CachedMetalMap cachedMetalMap, int x, int y) { int value = 0; for (int h = (int) -cachedMetalMap.getMetalExtractorRadius(); h < cachedMetalMap.getMetalExtractorRadius(); h++) { for (int w = (int) -cachedMetalMap.getMetalExtractorRadius(); w < cachedMetalMap.getMetalExtractorRadius(); w++) { try { value += cachedMetalMap.getValue(x + w, y + h); } catch (Exception e) { //Catch when outside map bounds and presume 0 } } } return value; } private static MetalSpot getMetalSpot(CachedMetalMap cachedMetalMap, int x, int y) { int value = getMetalSpotValue(cachedMetalMap, x, y); if (value > 0) { return new MetalSpot(x, y, value); } return null; } }