From 1f1d2420cbff097bf51be2aca35958fa9150d30d Mon Sep 17 00:00:00 2001 From: dgant Date: Tue, 3 Nov 2026 14:09:31 -0500 Subject: [PATCH 1/2] Fix BWEM chokepoint identity for parallel passages --- src/main/java/bwem/ChokePoint.java | 17 +++---------- src/test/java/bwapi/BWEMTest.java | 41 ++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/main/java/bwem/ChokePoint.java b/src/main/java/bwem/ChokePoint.java index 71204f43..e64e32fc 100644 --- a/src/main/java/bwem/ChokePoint.java +++ b/src/main/java/bwem/ChokePoint.java @@ -313,25 +313,14 @@ public boolean equals(final Object object) { return false; } else { final ChokePoint that = (ChokePoint) object; - final boolean lel = this.areas.getLeft().equals(that.areas.getLeft()); - final boolean ler = this.areas.getLeft().equals(that.areas.getRight()); - final boolean rer = this.areas.getRight().equals(that.areas.getRight()); - final boolean rel = this.areas.getRight().equals(that.areas.getLeft()); - return lel && rer - || ler && rel; /* true if area pairs are an exact match or if one pair is reversed. */ + // Parallel connections can share areas or even a center, but not a graph/index. + return this.graph == that.graph && this.index == that.index; } } @Override public int hashCode() { - int idLeft = areas.getLeft().getId().intValue(); - int idRight = areas.getRight().getId().intValue(); - if (idLeft > idRight) { - final int idLeftTmp = idLeft; - idLeft = idRight; - idRight = idLeftTmp; - } - return Objects.hash(idLeft, idRight); + return Objects.hash(graph, index); } /** diff --git a/src/test/java/bwapi/BWEMTest.java b/src/test/java/bwapi/BWEMTest.java index 65558961..5ef8ea3e 100644 --- a/src/test/java/bwapi/BWEMTest.java +++ b/src/test/java/bwapi/BWEMTest.java @@ -2,13 +2,19 @@ import bwem.BWEM; import bwem.BWMap; +import bwta.BWTA; +import bwta.Chokepoint; +import bwta.Region; import org.junit.Test; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; +import java.util.List; import java.util.Map; -import static org.junit.Assert.assertEquals; +import static org.junit.Assert.*; public class BWEMTest { static class BWEMMap{ @@ -66,13 +72,38 @@ public int hashCode() { mapData.put("(4)Roadrunner.scx", new BWEMMap(26, 12, 35)); } + @Test + public void chokePointsFromDifferentMapsAreDistinct() throws IOException { + BWEM first = new BWEM(GameBuilder.createGame()); + first.initialize(); + BWEM second = new BWEM(GameBuilder.createGame()); + second.initialize(); + assertTrue(Collections.disjoint(first.getMap().getChokePoints(), second.getMap().getChokePoints())); + } + @Test public void checkSSCAITMaps() throws IOException { for (String mapName : mapData.keySet()) { - Game game = GameBuilder.createGame(mapName); - BWEM bwem = new BWEM(game); - bwem.initialize(); - assertEquals(new BWEMMap(bwem.getMap()), mapData.get(mapName)); + BWTA.readMap(GameBuilder.createGame(mapName)); + BWTA.analyze(); + BWMap map = BWTA.getBWEM().getMap(); + assertEquals(new BWEMMap(map), mapData.get(mapName)); + assertEquals(mapName, map.getChokePoints().size(), new HashSet<>(map.getChokePoints()).size()); + + List chokes = BWTA.getChokepoints(); + assertEquals(mapName, map.getChokePoints().size(), chokes.size()); + for (Chokepoint choke : chokes) { + assertTrue(choke.getRegions().getLeft().getChokepoints().contains(choke)); + assertTrue(choke.getRegions().getRight().getChokepoints().contains(choke)); + } + for (Region region : BWTA.getRegions()) { + for (Chokepoint choke : region.getChokepoints()) { + assertNotNull(mapName, choke); + assertTrue(mapName, chokes.contains(choke)); + assertTrue(choke.getRegions().getLeft().equals(region) + || choke.getRegions().getRight().equals(region)); + } + } } } } From 2fcd599f1402ec180f1cd8649f52f3025380c448 Mon Sep 17 00:00:00 2001 From: dgant Date: Tue, 10 Nov 2026 16:21:35 -0500 Subject: [PATCH 2/2] Identify chokepoints by map hash and index and test through BWEM --- src/main/java/bwem/ChokePoint.java | 7 +++-- src/test/java/bwapi/BWEMTest.java | 49 ++++++++++++++++-------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/main/java/bwem/ChokePoint.java b/src/main/java/bwem/ChokePoint.java index e64e32fc..b62a7d13 100644 --- a/src/main/java/bwem/ChokePoint.java +++ b/src/main/java/bwem/ChokePoint.java @@ -43,6 +43,7 @@ public final class ChokePoint { private final Graph graph; private final boolean isPseudo; private final int index; + private final String mapHash; private final Pair areas; private final WalkPosition[] nodes; private final List> nodesInArea; @@ -64,6 +65,7 @@ public final class ChokePoint { this.graph = graph; this.index = index; + this.mapHash = graph.getMap().game.mapHash(); this.areas = new Pair<>(area1, area2); this.geometry = geometry; @@ -313,14 +315,13 @@ public boolean equals(final Object object) { return false; } else { final ChokePoint that = (ChokePoint) object; - // Parallel connections can share areas or even a center, but not a graph/index. - return this.graph == that.graph && this.index == that.index; + return this.index == that.index && Objects.equals(this.mapHash, that.mapHash); } } @Override public int hashCode() { - return Objects.hash(graph, index); + return Objects.hash(this.index, this.mapHash); } /** diff --git a/src/test/java/bwapi/BWEMTest.java b/src/test/java/bwapi/BWEMTest.java index 5ef8ea3e..f90faf8a 100644 --- a/src/test/java/bwapi/BWEMTest.java +++ b/src/test/java/bwapi/BWEMTest.java @@ -1,20 +1,19 @@ package bwapi; +import bwem.Area; import bwem.BWEM; import bwem.BWMap; -import bwta.BWTA; -import bwta.Chokepoint; -import bwta.Region; +import bwem.ChokePoint; import org.junit.Test; import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.List; import java.util.Map; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class BWEMTest { static class BWEMMap{ @@ -72,11 +71,21 @@ public int hashCode() { mapData.put("(4)Roadrunner.scx", new BWEMMap(26, 12, 35)); } + @Test + public void chokePointsFromSameMapAreEqual() throws IOException { + BWEM first = new BWEM(GameBuilder.createGame("(2)Destination.scx")); + first.initialize(); + BWEM second = new BWEM(GameBuilder.createGame("(2)Destination.scx")); + second.initialize(); + assertEquals(first.getMap().getChokePoints(), second.getMap().getChokePoints()); + assertEquals(new HashSet<>(first.getMap().getChokePoints()), new HashSet<>(second.getMap().getChokePoints())); + } + @Test public void chokePointsFromDifferentMapsAreDistinct() throws IOException { - BWEM first = new BWEM(GameBuilder.createGame()); + BWEM first = new BWEM(GameBuilder.createGame("(2)Benzene.scx")); first.initialize(); - BWEM second = new BWEM(GameBuilder.createGame()); + BWEM second = new BWEM(GameBuilder.createGame("(2)Destination.scx")); second.initialize(); assertTrue(Collections.disjoint(first.getMap().getChokePoints(), second.getMap().getChokePoints())); } @@ -84,24 +93,20 @@ public void chokePointsFromDifferentMapsAreDistinct() throws IOException { @Test public void checkSSCAITMaps() throws IOException { for (String mapName : mapData.keySet()) { - BWTA.readMap(GameBuilder.createGame(mapName)); - BWTA.analyze(); - BWMap map = BWTA.getBWEM().getMap(); + Game game = GameBuilder.createGame(mapName); + BWEM bwem = new BWEM(game); + bwem.initialize(); + BWMap map = bwem.getMap(); assertEquals(new BWEMMap(map), mapData.get(mapName)); assertEquals(mapName, map.getChokePoints().size(), new HashSet<>(map.getChokePoints()).size()); - List chokes = BWTA.getChokepoints(); - assertEquals(mapName, map.getChokePoints().size(), chokes.size()); - for (Chokepoint choke : chokes) { - assertTrue(choke.getRegions().getLeft().getChokepoints().contains(choke)); - assertTrue(choke.getRegions().getRight().getChokepoints().contains(choke)); - } - for (Region region : BWTA.getRegions()) { - for (Chokepoint choke : region.getChokepoints()) { - assertNotNull(mapName, choke); - assertTrue(mapName, chokes.contains(choke)); - assertTrue(choke.getRegions().getLeft().equals(region) - || choke.getRegions().getRight().equals(region)); + for (Area area : map.getAreas()) { + for (ChokePoint firstChokePoint : area.getChokePoints()) { + for (ChokePoint secondChokePoint : area.getChokePoints()) { + if (!firstChokePoint.isBlocked() && !secondChokePoint.isBlocked()) { + assertTrue(mapName, firstChokePoint.accessibleFrom(secondChokePoint)); + } + } } } }