|
18 | 18 | import bwapi.WalkPosition; |
19 | 19 | import bwem.util.BwemExt; |
20 | 20 | import bwem.util.CheckMode; |
21 | | -import bwem.util.MutableInt; |
22 | 21 | import bwem.util.Utils; |
23 | 22 |
|
24 | 23 | import java.util.*; |
@@ -146,94 +145,12 @@ public CPPath getPath(ChokePoint cpA, ChokePoint cpB) { |
146 | 145 | .get(cpB.getIndex()); |
147 | 146 | } |
148 | 147 |
|
149 | | - public CPPath getPath(final Position a, final Position b, final MutableInt pLength) { |
150 | | - final Area areaA = getNearestArea(a.toWalkPosition()); |
151 | | - final Area areaB = getNearestArea(b.toWalkPosition()); |
152 | | - |
153 | | - if (areaA.equals(areaB)) { |
154 | | - if (pLength != null) { |
155 | | - pLength.setValue(BwemExt.getApproxDistance(a, b)); |
156 | | - } |
157 | | - return new CPPath(); |
158 | | - } |
159 | | - |
160 | | - if (!areaA.isAccessibleFrom(areaB)) { |
161 | | - if (pLength != null) { |
162 | | - pLength.setValue(-1); |
163 | | - } |
164 | | - return new CPPath(); |
165 | | - } |
166 | | - |
167 | | - int minDistAB = Integer.MAX_VALUE; |
168 | | - |
169 | | - ChokePoint pBestCpA = null; |
170 | | - ChokePoint pBestCpB = null; |
171 | | - |
172 | | - for (final ChokePoint cpA : areaA.getChokePoints()) { |
173 | | - if (!cpA.isBlocked()) { |
174 | | - final int distACpA = BwemExt.getApproxDistance(a, cpA.getCenter().toPosition()); |
175 | | - for (final ChokePoint cpB : areaB.getChokePoints()) { |
176 | | - if (!cpB.isBlocked()) { |
177 | | - final int distBToCPB = BwemExt.getApproxDistance(b, cpB.getCenter().toPosition()); |
178 | | - final int distAToB = distACpA + distBToCPB + distance(cpA, cpB); |
179 | | - if (distAToB < minDistAB) { |
180 | | - minDistAB = distAToB; |
181 | | - pBestCpA = cpA; |
182 | | - pBestCpB = cpB; |
183 | | - } |
184 | | - } |
185 | | - } |
186 | | - } |
187 | | - } |
188 | | - |
189 | | - if (minDistAB == Integer.MAX_VALUE) { |
190 | | - throw new IllegalStateException(); |
191 | | - } |
192 | | - |
193 | | - final CPPath path = getPath(pBestCpA, pBestCpB); |
194 | | - |
195 | | - if (pLength != null) { |
196 | | - if (!(path.size() >= 1)) { |
197 | | - throw new IllegalStateException(); |
198 | | - } |
199 | | - |
200 | | - pLength.setValue(minDistAB); |
201 | | - |
202 | | - if (path.size() == 1) { |
203 | | - if (!pBestCpA.equals(pBestCpB)) { |
204 | | - throw new IllegalStateException(); |
205 | | - } |
206 | | - |
207 | | - final Position cpEnd1 = BwemExt.center(pBestCpA.getNodePosition(ChokePoint.Node.END1)); |
208 | | - final Position cpEnd2 = BwemExt.center(pBestCpA.getNodePosition(ChokePoint.Node.END2)); |
209 | | - if (Utils.intersect( |
210 | | - a.getX(), |
211 | | - a.getY(), |
212 | | - b.getX(), |
213 | | - b.getY(), |
214 | | - cpEnd1.getX(), |
215 | | - cpEnd1.getY(), |
216 | | - cpEnd2.getX(), |
217 | | - cpEnd2.getY())) { |
218 | | - pLength.setValue(BwemExt.getApproxDistance(a, b)); |
219 | | - } else { |
220 | | - for (final ChokePoint.Node node : |
221 | | - new ChokePoint.Node[]{ChokePoint.Node.END1, ChokePoint.Node.END2}) { |
222 | | - final Position c = BwemExt.center(pBestCpA.getNodePosition(node)); |
223 | | - final int distAToB = BwemExt.getApproxDistance(a, c) + BwemExt.getApproxDistance(b, c); |
224 | | - if (distAToB < pLength.intValue()) { |
225 | | - pLength.setValue(distAToB); |
226 | | - } |
227 | | - } |
228 | | - } |
229 | | - } |
230 | | - } |
231 | | - |
232 | | - return getPath(pBestCpA, pBestCpB); |
| 148 | + public Optional<PathingResult> getPathingResult(Position a, Position b) { |
| 149 | + return new Pathing(a, b).getPathWithLength(); |
233 | 150 | } |
234 | 151 |
|
235 | | - public CPPath getPath(Position a, Position b) { |
236 | | - return getPath(a, b, null); |
| 152 | + public Optional<CPPath> getPath(final Position a, final Position b) { |
| 153 | + return new Pathing(a, b).getPath(); |
237 | 154 | } |
238 | 155 |
|
239 | 156 | public List<Base> getBases() { |
@@ -762,4 +679,100 @@ private void setPath(final ChokePoint cpA, final ChokePoint cpB, final CPPath pa |
762 | 679 | private boolean isValid(AreaId id) { |
763 | 680 | return (1 <= id.intValue() && id.intValue() <= getAreaCount()); |
764 | 681 | } |
| 682 | + |
| 683 | + private class Pathing { |
| 684 | + private final Position a; |
| 685 | + private final Position b; |
| 686 | + private final Area areaA; |
| 687 | + private final Area areaB; |
| 688 | + private final CPPath path; |
| 689 | + private ChokePoint pBestCpA; |
| 690 | + private ChokePoint pBestCpB; |
| 691 | + private int minDistAB; |
| 692 | + |
| 693 | + Pathing(Position a, Position b) { |
| 694 | + this.a = a; |
| 695 | + this.b = b; |
| 696 | + areaA = getNearestArea(a.toWalkPosition()); |
| 697 | + areaB = getNearestArea(b.toWalkPosition()); |
| 698 | + |
| 699 | + if (areaA.equals(areaB)) { |
| 700 | + path = CPPath.EMPTY_PATH; |
| 701 | + return; |
| 702 | + } |
| 703 | + |
| 704 | + if (!areaA.isAccessibleFrom(areaB)) { |
| 705 | + path = null; |
| 706 | + return; |
| 707 | + } |
| 708 | + |
| 709 | + minDistAB = Integer.MAX_VALUE; |
| 710 | + |
| 711 | + for (final ChokePoint cpA : areaA.getChokePoints()) { |
| 712 | + if (!cpA.isBlocked()) { |
| 713 | + final int distACpA = BwemExt.getApproxDistance(a, cpA.getCenter().toPosition()); |
| 714 | + for (final ChokePoint cpB : areaB.getChokePoints()) { |
| 715 | + if (!cpB.isBlocked()) { |
| 716 | + final int distBToCPB = BwemExt.getApproxDistance(b, cpB.getCenter().toPosition()); |
| 717 | + final int distAToB = distACpA + distBToCPB + distance(cpA, cpB); |
| 718 | + if (distAToB < minDistAB) { |
| 719 | + minDistAB = distAToB; |
| 720 | + pBestCpA = cpA; |
| 721 | + pBestCpB = cpB; |
| 722 | + } |
| 723 | + } |
| 724 | + } |
| 725 | + } |
| 726 | + } |
| 727 | + |
| 728 | + if (minDistAB == Integer.MAX_VALUE) { |
| 729 | + throw new IllegalStateException(); |
| 730 | + } |
| 731 | + |
| 732 | + path = Graph.this.getPath(pBestCpA, pBestCpB); |
| 733 | + } |
| 734 | + |
| 735 | + Optional<PathingResult> getPathWithLength() { |
| 736 | + if (path == null) { |
| 737 | + return Optional.empty(); |
| 738 | + } |
| 739 | + if (areaA.equals(areaB)) { |
| 740 | + return Optional.of(new PathingResult(path, BwemExt.getApproxDistance(a, b))); |
| 741 | + } |
| 742 | + |
| 743 | + if (path.size() == 1) { |
| 744 | + if (!pBestCpA.equals(pBestCpB)) { |
| 745 | + throw new IllegalStateException(); |
| 746 | + } |
| 747 | + |
| 748 | + final Position cpEnd1 = BwemExt.center(pBestCpA.getNodePosition(ChokePoint.Node.END1)); |
| 749 | + final Position cpEnd2 = BwemExt.center(pBestCpA.getNodePosition(ChokePoint.Node.END2)); |
| 750 | + if (Utils.intersect( |
| 751 | + a.getX(), |
| 752 | + a.getY(), |
| 753 | + b.getX(), |
| 754 | + b.getY(), |
| 755 | + cpEnd1.getX(), |
| 756 | + cpEnd1.getY(), |
| 757 | + cpEnd2.getX(), |
| 758 | + cpEnd2.getY())) { |
| 759 | + return Optional.of(new PathingResult(path, BwemExt.getApproxDistance(a, b))); |
| 760 | + } else { |
| 761 | + int pLength = minDistAB; |
| 762 | + for (final ChokePoint.Node node : |
| 763 | + new ChokePoint.Node[]{ChokePoint.Node.END1, ChokePoint.Node.END2}) { |
| 764 | + Position c = BwemExt.center(pBestCpA.getNodePosition(node)); |
| 765 | + int distAToB = BwemExt.getApproxDistance(a, c) + BwemExt.getApproxDistance(b, c); |
| 766 | + pLength = Math.min(pLength, distAToB); |
| 767 | + } |
| 768 | + return Optional.of(new PathingResult(path, pLength)); |
| 769 | + } |
| 770 | + } |
| 771 | + return Optional.of(new PathingResult(path, minDistAB)); |
| 772 | + } |
| 773 | + |
| 774 | + Optional<CPPath> getPath() { |
| 775 | + return Optional.ofNullable(path); |
| 776 | + } |
| 777 | + } |
765 | 778 | } |
0 commit comments