use of org.openbw.bwapi4j.WalkPosition in project BWAPI4J by OpenBW.
the class MapTest method assert_ChokePoints.
/**
* Tests that all chokepoint centers match between the original BWEM in C++ and this Java port.<br/>
*/
private void assert_ChokePoints(final List<WalkPosition> expectedChokePointCenters, final List<ChokePoint> actualChokePoints) {
final List<WalkPosition> actualChokepointCenters = new ArrayList<>();
for (final ChokePoint actualChokePoint : actualChokePoints) {
final WalkPosition actualChokePointCenter = actualChokePoint.getCenter();
actualChokepointCenters.add(actualChokePointCenter);
}
Assert.assertEquals("Chokepoint container sizes do not match. expected=" + expectedChokePointCenters.size() + ", actual=" + actualChokepointCenters.size(), expectedChokePointCenters.size(), actualChokepointCenters.size());
// If an exact position is not found, search within this WalkTile radius value.
final int tolerance = 20;
// Keep track of and do not use the same tolerant center more than once.
final List<WalkPosition> tolerantCenters = new ArrayList<>();
for (final WalkPosition expectedChokePointCenter : expectedChokePointCenters) {
final boolean found = actualChokepointCenters.contains(expectedChokePointCenter);
if (!found) {
logger.warn("Did not find original chokepoint: " + expectedChokePointCenter.toString() + ". Retrying with a max tolerance of " + tolerance + ".");
final int boundsLowerX = expectedChokePointCenter.getX() - tolerance;
final int boundsUpperX = expectedChokePointCenter.getX() + tolerance;
final int boundsLowerY = expectedChokePointCenter.getY() - tolerance;
final int boundsUpperY = expectedChokePointCenter.getY() + tolerance;
boolean foundTolerant = false;
for (int y = boundsLowerY; y <= boundsUpperY; ++y) {
for (int x = boundsLowerX; x <= boundsUpperX; ++x) {
final WalkPosition tolerantCenter = new WalkPosition(x, y);
if (actualChokepointCenters.contains(tolerantCenter)) {
Assert.assertEquals("Found a tolerant center but it has already been used: " + tolerantCenter.toString(), false, tolerantCenters.contains(tolerantCenter));
tolerantCenters.add(tolerantCenter);
foundTolerant = true;
logger.debug("Found tolerant center for chokepoint: " + expectedChokePointCenter.toString() + ", tolerant_center=" + tolerantCenter.toString() + ", tolerance=" + expectedChokePointCenter.subtract(tolerantCenter) + ".");
break;
}
}
if (foundTolerant) {
break;
}
}
Assert.assertEquals("Did not find original chokepoint even with a tolerance value. actualChokepointCenters=" + actualChokepointCenters.toString(), true, foundTolerant);
}
}
}
use of org.openbw.bwapi4j.WalkPosition in project BWAPI4J by OpenBW.
the class PairGenericMiniTileAltitudeComparatorTest method testPairGenericMiniTileAltitudeComparator.
@Test
public void testPairGenericMiniTileAltitudeComparator() {
final List<MutablePair<WalkPosition, MiniTile>> list = new ArrayList<>();
final MiniTile m1 = new MiniTileImpl();
((MiniTileImpl) m1).setAreaId(new AreaId(2));
((MiniTileImpl) m1).setAltitude(new Altitude(5));
final MiniTile m2 = new MiniTileImpl();
((MiniTileImpl) m2).setAreaId(new AreaId(1));
((MiniTileImpl) m2).setAltitude(new Altitude(2));
final MiniTile m3 = new MiniTileImpl();
((MiniTileImpl) m3).setAreaId(new AreaId(3));
((MiniTileImpl) m3).setAltitude(new Altitude(7));
final MiniTile m4 = new MiniTileImpl();
((MiniTileImpl) m4).setAreaId(new AreaId(5));
((MiniTileImpl) m4).setAltitude(new Altitude(1));
final MiniTile m5 = new MiniTileImpl();
((MiniTileImpl) m5).setAreaId(new AreaId(4));
((MiniTileImpl) m5).setAltitude(new Altitude(8));
list.add(new MutablePair<>(new WalkPosition(5, 15), m1));
list.add(new MutablePair<>(new WalkPosition(2, 98), m2));
list.add(new MutablePair<>(new WalkPosition(63, 123), m3));
list.add(new MutablePair<>(new WalkPosition(103, 435), m4));
list.add(new MutablePair<>(new WalkPosition(89, 77), m5));
// Sort by descending order.
Collections.sort(list, new PairGenericMiniTileAltitudeComparator<>());
Collections.reverse(list);
Assert.assertEquals(new MutablePair<>(new WalkPosition(89, 77), m5), list.get(0));
Assert.assertEquals(new MutablePair<>(new WalkPosition(63, 123), m3), list.get(1));
Assert.assertEquals(new MutablePair<>(new WalkPosition(5, 15), m1), list.get(2));
Assert.assertEquals(new MutablePair<>(new WalkPosition(2, 98), m2), list.get(3));
Assert.assertEquals(new MutablePair<>(new WalkPosition(103, 435), m4), list.get(4));
}
use of org.openbw.bwapi4j.WalkPosition in project BWAPI4J by OpenBW.
the class MapPrinterExample method pathExample.
public void pathExample(Map theMap) {
if (theMap.getData().getMapData().getStartingLocations().size() < 2)
return;
Color col = new Color(255, 255, 255);
WalkPosition a = (theMap.getData().getMapData().getStartingLocations().get(randomGenerator.nextInt(theMap.getData().getMapData().getStartingLocations().size()))).toWalkPosition();
WalkPosition b = a;
while (b.equals(a)) {
b = (theMap.getData().getMapData().getStartingLocations().get(randomGenerator.nextInt(theMap.getData().getMapData().getStartingLocations().size()))).toWalkPosition();
}
// Uncomment this to use random positions for a and b:
// a = WalkPosition(theMap.RandomPosition());
// b = WalkPosition(theMap.RandomPosition());
mapPrinter.circle(a, 6, col, MapPrinter.fill_t.fill);
mapPrinter.circle(b, 6, col, MapPrinter.fill_t.fill);
MutableInt length = new MutableInt(0);
CPPath path = theMap.getPath(a.toPosition(), b.toPosition(), length);
// cannot reach b from a
if (length.intValue() < 0)
return;
if (path.isEmpty()) {
// bwem_assert(theMap.getNearestArea(a) == theMap.getNearestArea(b));
if (!(theMap.getNearestArea(a).equals(theMap.getNearestArea(b)))) {
throw new IllegalStateException();
}
// just draw a single line between them:
mapPrinter.line(a, b, col, MapPrinter.dashed_t.dashed);
} else {
// bwem_assert(theMap.getNearestArea(a) != theMap.getNearestArea(b));
if (theMap.getNearestArea(a).equals(theMap.getNearestArea(b))) {
throw new IllegalStateException();
}
// draw a line between each ChokePoint in path:
ChokePoint cpPrevious = null;
for (ChokePoint cp : path) {
if (cpPrevious != null) {
mapPrinter.line(cpPrevious.getCenter(), cp.getCenter(), col, MapPrinter.dashed_t.dashed);
}
mapPrinter.circle(cp.getCenter(), 6, col);
cpPrevious = cp;
}
mapPrinter.line(a, path.get(0).getCenter(), col, MapPrinter.dashed_t.dashed);
mapPrinter.line(b, path.get(path.size() - 1).getCenter(), col, MapPrinter.dashed_t.dashed);
}
// TODO: Handle exception.
try {
mapPrinter.writeImageToFile(Paths.get("map.png"), "png");
} catch (IOException ex) {
ex.printStackTrace();
}
}
use of org.openbw.bwapi4j.WalkPosition in project BWAPI4J by OpenBW.
the class Graph method getNearestArea.
public Area getNearestArea(final WalkPosition walkPosition) {
final Area area = getArea(walkPosition);
if (area != null) {
return area;
}
final WalkPosition w = getMap().breadthFirstSearch(walkPosition, // findCond
args -> {
final Object ttile = args[0];
if (ttile instanceof MiniTile) {
final MiniTile miniTile = (MiniTile) ttile;
return (miniTile.getAreaId().intValue() > 0);
} else {
throw new IllegalArgumentException();
}
}, // visitCond
args -> true);
return getArea(w);
}
use of org.openbw.bwapi4j.WalkPosition in project BWAPI4J by OpenBW.
the class Graph method createChokePoints.
// ----------------------------------------------------------------------
// //////////////////////////////////////////////////////////////////////
// Creates a new Area for each pair (top, miniTiles) in AreasList (See Area::top() and Area::miniTiles())
public void createChokePoints(final List<StaticBuilding> staticBuildings, final List<Mineral> minerals, final List<MutablePair<MutablePair<AreaId, AreaId>, WalkPosition>> rawFrontier) {
Index newIndex = new Index(0);
final List<Neutral> blockingNeutrals = new ArrayList<>();
for (final StaticBuilding s : staticBuildings) {
if (s.isBlocking()) {
blockingNeutrals.add(s);
}
}
for (final Mineral m : minerals) {
if (m.isBlocking()) {
blockingNeutrals.add(m);
}
}
// Note: pseudoChokePointsToCreate is only used for pre-allocating the GetChokePoints array size.
// This number will highly likely be very small. There is no reason to set a minimum size.
// int pseudoChokePointsToCreate = 0;
// for (final Neutral blockingNeutral : blockingNeutrals) {
// if (blockingNeutral.getNextStacked() == null) {
// ++pseudoChokePointsToCreate;
// }
// }
// 1) size the matrix
initializeChokePointsMatrix(this.chokePointsMatrix, getAreaCount());
// 2) Dispatch the global raw frontier between all the relevant pairs of areas:
final java.util.Map<MutablePair<AreaId, AreaId>, List<WalkPosition>> rawFrontierByAreaPair = createRawFrontierByAreaPairMap(rawFrontier);
// 3) For each pair of areas (A, B):
for (final java.util.Map.Entry<MutablePair<AreaId, AreaId>, List<WalkPosition>> entry : rawFrontierByAreaPair.entrySet()) {
MutablePair<AreaId, AreaId> rawleft = entry.getKey();
final List<WalkPosition> rawFrontierAB = entry.getValue();
// Because our dispatching preserved order,
// and because Map::m_RawFrontier was populated in descending order of the altitude (see Map::computeAreas),
// we know that rawFrontierAB is also ordered the same way, but let's check it:
{
final List<Altitude> altitudes = new ArrayList<>();
for (final WalkPosition w : rawFrontierAB) {
altitudes.add(getMap().getData().getMiniTile(w).getAltitude());
}
// bwem_assert(is_sorted(altitudes.rbegin(), altitudes.rend()));
for (int i = 1; i < altitudes.size(); ++i) {
final int prev = altitudes.get(i - 1).intValue();
final int curr = altitudes.get(i).intValue();
if (prev < curr) {
throw new IllegalStateException();
}
}
}
// 3.1) Use that information to efficiently cluster rawFrontierAB in one or several chokepoints.
// Each cluster will be populated starting with the center of a chokepoint (max altitude)
// and finishing with the ends (min altitude).
final int clusterMinDist = (int) Math.sqrt(BwemExt.lake_max_miniTiles);
final List<List<WalkPosition>> clusters = new ArrayList<>();
for (final WalkPosition w : rawFrontierAB) {
boolean added = false;
for (final List<WalkPosition> cluster : clusters) {
final int distToFront = BwemExt.queenWiseDist(cluster.get(0), w);
final int distToBack = BwemExt.queenWiseDist(cluster.get(cluster.size() - 1), w);
if (Math.min(distToFront, distToBack) <= clusterMinDist) {
if (distToFront < distToBack) {
cluster.add(0, w);
} else {
cluster.add(w);
}
added = true;
break;
}
}
if (!added) {
final List<WalkPosition> list = new ArrayList<>();
list.add(w);
clusters.add(list);
}
}
// 3.2) Create one Chokepoint for each cluster:
final AreaId a = rawleft.getLeft();
final AreaId b = rawleft.getRight();
// getChokePoints(a, b).reserve(clusters.size() + pseudoChokePointsToCreate);
for (final List<WalkPosition> cluster : clusters) {
getChokePoints(a, b).add(new ChokePointImpl(this, newIndex, getArea(a), getArea(b), cluster));
newIndex = newIndex.add(1);
}
}
// 4) Create one Chokepoint for each pair of blocked areas, for each blocking Neutral:
for (final Neutral blockingNeutral : blockingNeutrals) {
if (blockingNeutral.getNextStacked() == null) {
// in the case where several neutrals are stacked, we only consider the top
final List<Area> blockedAreas = blockingNeutral.getBlockedAreas();
for (final Area blockedAreaA : blockedAreas) for (final Area blockedAreaB : blockedAreas) {
if (blockedAreaB.equals(blockedAreaA)) {
// breaks symmetry
break;
}
final WalkPosition center = getMap().breadthFirstSearch(blockingNeutral.getCenter().toWalkPosition(), // findCond
args -> {
Object ttile = args[0];
if (!(ttile instanceof MiniTile)) {
throw new IllegalArgumentException();
}
MiniTile miniTile = (MiniTile) ttile;
return miniTile.isWalkable();
}, // visitCond
args -> true);
final List<WalkPosition> list = new ArrayList<>();
list.add(center);
getChokePoints(blockedAreaA, blockedAreaB).add(new ChokePointImpl(this, newIndex, blockedAreaA, blockedAreaB, list, blockingNeutral));
newIndex = newIndex.add(1);
}
}
}
// 5) Set the references to the freshly created Chokepoints:
for (int loopA = 1; loopA <= getAreaCount(); ++loopA) for (int loopB = 1; loopB < loopA; ++loopB) {
final AreaId a = new AreaId(loopA);
final AreaId b = new AreaId(loopB);
if (!getChokePoints(a, b).isEmpty()) {
((AreaInitializer) getArea(a)).addChokePoints(getArea(b), getChokePoints(a, b));
((AreaInitializer) getArea(b)).addChokePoints(getArea(a), getChokePoints(a, b));
this.chokePoints.addAll(getChokePoints(a, b));
}
}
}
Aggregations