001package squidpony.squidai; 002 003import squidpony.squidgrid.LOS; 004import squidpony.squidgrid.Measurement; 005import squidpony.squidgrid.Radius; 006import squidpony.squidgrid.mapping.DungeonUtility; 007import squidpony.squidmath.Coord; 008import squidpony.squidmath.OrderedMap; 009import squidpony.squidmath.OrderedSet; 010 011import java.io.Serializable; 012import java.util.ArrayList; 013import java.util.Arrays; 014import java.util.Collection; 015import java.util.Queue; 016 017/** 018 * Line Area of Effect that affects an slightly expanded (DDA) line from a given origin Coord to a given end Coord, 019 * plus an optional radius of cells around the path of the line, while respecting obstacles in its path and possibly 020 * stopping if obstructed. You can specify the RadiusType to Radius.DIAMOND for Manhattan distance, RADIUS.SQUARE for 021 * Chebyshev, or RADIUS.CIRCLE for Euclidean. 022 * <br> 023 * You may want the BeamAOE class instead of this. LineAOE travels point-to-point and does not restrict length, while 024 * BeamAOE travels a specific length (and may have a radius, like LineAOE) but then stops only after the travel down the 025 * length and radius has reached its end. This difference is relevant if a game has effects that have a definite 026 * area measured in a rectangle or elongated pillbox shape, such as a "20-foot-wide bolt of lightning, 100 feet long." 027 * BeamAOE is more suitable for that effect, while LineAOE may be more suitable for things like focused lasers that 028 * pass through small (likely fleshy) obstacles but stop after hitting the aimed-at target. 029 * <br> 030 * LineAOE will strike a small area behind the user and in the opposite direction of the target if the radius is 031 * greater than 0. This behavior may be altered in a future version. 032 * <br> 033 * This will produce doubles for its {@link #findArea()} method which are equal to 1.0. 034 * <br> 035 * This class uses {@link LOS} and {@link DijkstraMap} to create its area of effect. 036 * Created by Tommy Ettinger on 7/14/2015. 037 */ 038public class LineAOE implements AOE, Serializable { 039 private static final long serialVersionUID = 2L; 040 private Coord origin, end; 041 private int radius; 042 private char[][] dungeon; 043 private DijkstraMap dijkstra; 044 private Radius rt; 045 private LOS los; 046 private Reach reach = new Reach(1, 1, Radius.SQUARE, AimLimit.FREE); 047 public LineAOE(Coord origin, Coord end) 048 { 049 dijkstra = new DijkstraMap(); 050 dijkstra.measurement = Measurement.CHEBYSHEV; 051 rt = Radius.SQUARE; 052 this.origin = origin; 053 this.end = end; 054 radius = 0; 055 los = new LOS(LOS.DDA); 056 } 057 public LineAOE(Coord origin, Coord end, int radius) 058 { 059 dijkstra = new DijkstraMap(); 060 dijkstra.measurement = Measurement.CHEBYSHEV; 061 rt = Radius.SQUARE; 062 this.origin = origin; 063 this.end = end; 064 this.radius = radius; 065 los = new LOS(LOS.DDA); 066 } 067 public LineAOE(Coord origin, Coord end, int radius, Radius radiusType) 068 { 069 dijkstra = new DijkstraMap(); 070 rt = radiusType; 071 switch (radiusType) 072 { 073 case OCTAHEDRON: 074 case DIAMOND: 075 dijkstra.measurement = Measurement.MANHATTAN; 076 break; 077 case CUBE: 078 case SQUARE: 079 dijkstra.measurement = Measurement.CHEBYSHEV; 080 break; 081 default: 082 dijkstra.measurement = Measurement.EUCLIDEAN; 083 break; 084 } 085 this.origin = origin; 086 this.end = end; 087 this.radius = radius; 088 los = new LOS(LOS.DDA); 089 } 090 public LineAOE(Coord origin, Coord end, int radius, Radius radiusType, int minRange, int maxRange) 091 { 092 dijkstra = new DijkstraMap(); 093 rt = radiusType; 094 switch (radiusType) 095 { 096 case OCTAHEDRON: 097 case DIAMOND: 098 dijkstra.measurement = Measurement.MANHATTAN; 099 break; 100 case CUBE: 101 case SQUARE: 102 dijkstra.measurement = Measurement.CHEBYSHEV; 103 break; 104 default: 105 dijkstra.measurement = Measurement.EUCLIDEAN; 106 break; 107 } 108 this.origin = origin; 109 this.end = end; 110 this.radius = radius; 111 reach.minDistance = minRange; 112 reach.maxDistance = maxRange; 113 los = new LOS(LOS.DDA); 114 } 115 private double[][] initDijkstra() 116 { 117 los.isReachable(dungeon, origin.x, origin.y, end.x, end.y, rt); 118 Queue<Coord> lit = los.getLastPath(); 119 120 dijkstra.initialize(dungeon); 121 for(Coord p : lit) 122 { 123 dijkstra.setGoal(p); 124 } 125 if(radius == 0) 126 return dijkstra.gradientMap; 127 return dijkstra.partialScan(radius, null); 128 } 129 130 @Override 131 public Coord getOrigin() { 132 return origin; 133 } 134 135 @Override 136 public void setOrigin(Coord origin) { 137 this.origin = origin; 138 dijkstra.resetMap(); 139 dijkstra.clearGoals(); 140 } 141 142 @Override 143 public AimLimit getLimitType() { 144 return reach.limit; 145 } 146 147 @Override 148 public int getMinRange() { 149 return reach.minDistance; 150 } 151 152 @Override 153 public int getMaxRange() { 154 return reach.maxDistance; 155 } 156 157 @Override 158 public Radius getMetric() { 159 return reach.metric; 160 } 161 162 /** 163 * Gets the same values returned by getLimitType(), getMinRange(), getMaxRange(), and getMetric() bundled into one 164 * Reach object. 165 * 166 * @return a non-null Reach object. 167 */ 168 @Override 169 public Reach getReach() { 170 return reach; 171 } 172 173 @Override 174 public void setLimitType(AimLimit limitType) { 175 reach.limit = limitType; 176 177 } 178 179 @Override 180 public void setMinRange(int minRange) { 181 reach.minDistance = minRange; 182 } 183 184 @Override 185 public void setMaxRange(int maxRange) { 186 reach.maxDistance = maxRange; 187 188 } 189 190 @Override 191 public void setMetric(Radius metric) { 192 reach.metric = metric; 193 } 194 195 /** 196 * Sets the same values as setLimitType(), setMinRange(), setMaxRange(), and setMetric() using one Reach object. 197 * 198 * @param reach a non-null Reach object. 199 */ 200 @Override 201 public void setReach(Reach reach) { 202 if(reach != null) 203 this.reach = reach; 204 } 205 206 207 public Coord getEnd() { 208 return end; 209 } 210 211 public void setEnd(Coord end) { 212 if (dungeon != null && end.isWithin(dungeon.length, dungeon[0].length) && 213 AreaUtils.verifyReach(reach, origin, end)) { 214 this.end = end; 215 dijkstra.resetMap(); 216 dijkstra.clearGoals(); 217 } 218 } 219 220 public int getRadius() { 221 return radius; 222 } 223 224 public void setRadius(int radius) { 225 this.radius = radius; 226 } 227 228 public Radius getRadiusType() 229 { 230 return rt; 231 } 232 public void setRadiusType(Radius radiusType) 233 { 234 rt = radiusType; 235 switch (radiusType) 236 { 237 case OCTAHEDRON: 238 case DIAMOND: 239 dijkstra.measurement = Measurement.MANHATTAN; 240 break; 241 case CUBE: 242 case SQUARE: 243 dijkstra.measurement = Measurement.CHEBYSHEV; 244 break; 245 default: 246 dijkstra.measurement = Measurement.EUCLIDEAN; 247 break; 248 } 249 } 250 251 @Override 252 public void shift(Coord aim) { 253 setEnd(aim); 254 } 255 256 @Override 257 public boolean mayContainTarget(Collection<Coord> targets) { 258 for (Coord p : targets) 259 { 260 if(rt.radius(origin.x, origin.y, p.x, p.y) + rt.radius(end.x, end.y, p.x, p.y) - 261 rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius) 262 return true; 263 } 264 return false; 265 } 266 267 @Override 268 public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Collection<Coord> targets, Collection<Coord> requiredExclusions) { 269 if(targets == null) 270 return new OrderedMap<>(); 271 if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); 272 273 //requiredExclusions.remove(origin); 274 int totalTargets = targets.size(); 275 OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8); 276 277 if(totalTargets == 0) 278 return bestPoints; 279 280 Coord[] ts = targets.toArray(new Coord[0]); 281 Coord[] exs = requiredExclusions.toArray(new Coord[0]); 282 Coord t; 283 284 double[][][] compositeMap = new double[ts.length][dungeon.length][dungeon[0].length]; 285 286 char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length]; 287 for (int i = 0; i < dungeon.length; i++) { 288 System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length); 289 } 290 DijkstraMap dt = new DijkstraMap(dungeon, dijkstra.measurement); 291 double[][] resMap = DungeonUtility.generateResistances(dungeon); 292 Coord tempPt; 293 for (int i = 0; i < exs.length; ++i) { 294 t = exs[i]; 295 dt.resetMap(); 296 dt.clearGoals(); 297 298 los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt); 299 Queue<Coord> lit = los.getLastPath(); 300 301 for(Coord p : lit) 302 { 303 dt.setGoal(p); 304 } 305 if(radius > 0) 306 dt.partialScan(radius, null); 307 308 for (int x = 0; x < dungeon.length; x++) { 309 for (int y = 0; y < dungeon[x].length; y++) { 310 tempPt = Coord.get(x, y); 311 dungeonCopy[x][y] = (dt.gradientMap[x][y] < DijkstraMap.FLOOR || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y]; 312 } 313 } 314 } 315 316 for (int i = 0; i < ts.length; ++i) { 317 DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement); 318 319 t = ts[i]; 320 dt.resetMap(); 321 dt.clearGoals(); 322 los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt); 323 Queue<Coord> lit = los.getLastPath(); 324 325 for(Coord p : lit) 326 { 327 dt.setGoal(p); 328 } 329 if(radius > 0) 330 dt.partialScan(radius, null); 331 332 333 double dist; 334 for (int x = 0; x < dungeon.length; x++) { 335 for (int y = 0; y < dungeon[x].length; y++) { 336 if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){ 337 dist = reach.metric.radius(origin.x, origin.y, x, y); 338 if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) 339 compositeMap[i][x][y] = dm.physicalMap[x][y]; 340 else 341 compositeMap[i][x][y] = DijkstraMap.WALL; 342 } 343 else compositeMap[i][x][y] = DijkstraMap.WALL; 344 } 345 } 346 if(compositeMap[i][ts[i].x][ts[i].y] > DijkstraMap.FLOOR) 347 { 348 for (int x = 0; x < dungeon.length; x++) { 349 Arrays.fill(compositeMap[i][x], 99999.0); 350 } 351 continue; 352 } 353 354 355 dm.initialize(compositeMap[i]); 356 dm.setGoal(t); 357 dm.scan(null, null); 358 for (int x = 0; x < dungeon.length; x++) { 359 for (int y = 0; y < dungeon[x].length; y++) { 360 compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 99999.0; 361 } 362 } 363 dm.resetMap(); 364 dm.clearGoals(); 365 } 366 double bestQuality = 99999 * ts.length; 367 double[][] qualityMap = new double[dungeon.length][dungeon[0].length]; 368 for (int x = 0; x < qualityMap.length; x++) { 369 for (int y = 0; y < qualityMap[x].length; y++) { 370 qualityMap[x][y] = 0.0; 371 long bits = 0; 372 for (int i = 0; i < ts.length; ++i) { 373 qualityMap[x][y] += compositeMap[i][x][y]; 374 if(compositeMap[i][x][y] < 99999.0 && i < 63) 375 bits |= 1 << i; 376 } 377 if(qualityMap[x][y] < bestQuality) 378 { 379 ArrayList<Coord> ap = new ArrayList<>(); 380 381 for (int i = 0; i < ts.length && i < 63; ++i) { 382 if((bits & (1 << i)) != 0) 383 ap.add(ts[i]); 384 } 385 if(ap.size() > 0) { 386 bestQuality = qualityMap[x][y]; 387 bestPoints.clear(); 388 bestPoints.put(Coord.get(x, y), ap); 389 } 390 } 391 else if(qualityMap[x][y] == bestQuality) 392 { 393 ArrayList<Coord> ap = new ArrayList<>(); 394 395 for (int i = 0; i < ts.length && i < 63; ++i) { 396 if((bits & (1 << i)) != 0) 397 ap.add(ts[i]); 398 } 399 400 if (ap.size() > 0) { 401 bestPoints.put(Coord.get(x, y), ap); 402 } 403 } 404 } 405 } 406 407 return bestPoints; 408 } 409 410 @Override 411 public OrderedMap<Coord, ArrayList<Coord>> idealLocations(Collection<Coord> priorityTargets, Collection<Coord> lesserTargets, Collection<Coord> requiredExclusions) { 412 if(priorityTargets == null) 413 return idealLocations(lesserTargets, requiredExclusions); 414 if(requiredExclusions == null) requiredExclusions = new OrderedSet<>(); 415 416 //requiredExclusions.remove(origin); 417 int totalTargets = priorityTargets.size() + lesserTargets.size(); 418 OrderedMap<Coord, ArrayList<Coord>> bestPoints = new OrderedMap<>(totalTargets * 8); 419 420 if(totalTargets == 0) 421 return bestPoints; 422 423 Coord[] pts = priorityTargets.toArray(new Coord[0]); 424 Coord[] lts = lesserTargets.toArray(new Coord[0]); 425 Coord[] exs = requiredExclusions.toArray(new Coord[0]); 426 Coord t; 427 428 double[][][] compositeMap = new double[totalTargets][dungeon.length][dungeon[0].length]; 429 430 char[][] dungeonCopy = new char[dungeon.length][dungeon[0].length], 431 dungeonPriorities = new char[dungeon.length][dungeon[0].length]; 432 for (int i = 0; i < dungeon.length; i++) { 433 System.arraycopy(dungeon[i], 0, dungeonCopy[i], 0, dungeon[i].length); 434 Arrays.fill(dungeonPriorities[i], '#'); 435 } 436 DijkstraMap dt = new DijkstraMap(dungeon, dijkstra.measurement); 437 double[][] resMap = DungeonUtility.generateResistances(dungeon); 438 Coord tempPt; 439 for (int i = 0; i < exs.length; ++i) { 440 t = exs[i]; 441 dt.resetMap(); 442 dt.clearGoals(); 443 los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt); 444 Queue<Coord> lit = los.getLastPath(); 445 446 for(Coord p : lit) 447 { 448 dt.setGoal(p); 449 } 450 if(radius > 0) 451 dt.partialScan(radius, null); 452 453 for (int x = 0; x < dungeon.length; x++) { 454 for (int y = 0; y < dungeon[x].length; y++) { 455 tempPt = Coord.get(x, y); 456 dungeonCopy[x][y] = (dt.gradientMap[x][y] < DijkstraMap.FLOOR || !AreaUtils.verifyReach(reach, origin, tempPt)) ? '!' : dungeonCopy[x][y]; 457 } 458 } 459 } 460 461 for (int i = 0; i < pts.length; ++i) { 462 DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement); 463 t = pts[i]; 464 dt.resetMap(); 465 dt.clearGoals(); 466 los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt); 467 Queue<Coord> lit = los.getLastPath(); 468 469 for(Coord p : lit) 470 { 471 dt.setGoal(p); 472 } 473 if(radius > 0) 474 dt.partialScan(radius, null); 475 476 477 double dist; 478 for (int x = 0; x < dungeon.length; x++) { 479 for (int y = 0; y < dungeon[x].length; y++) { 480 if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){ 481 dist = reach.metric.radius(origin.x, origin.y, x, y); 482 if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) { 483 compositeMap[i][x][y] = dm.physicalMap[x][y]; 484 dungeonPriorities[x][y] = dungeon[x][y]; 485 } 486 else 487 compositeMap[i][x][y] = DijkstraMap.WALL; 488 } 489 else compositeMap[i][x][y] = DijkstraMap.WALL; 490 } 491 } 492 if(compositeMap[i][pts[i].x][pts[i].y] > DijkstraMap.FLOOR) 493 { 494 for (int x = 0; x < dungeon.length; x++) { 495 Arrays.fill(compositeMap[i][x], 399999.0); 496 } 497 continue; 498 } 499 500 501 dm.initialize(compositeMap[i]); 502 dm.setGoal(t); 503 dm.scan(null, null); 504 for (int x = 0; x < dungeon.length; x++) { 505 for (int y = 0; y < dungeon[x].length; y++) { 506 compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR && dungeonCopy[x][y] != '!') ? dm.gradientMap[x][y] : 399999.0; 507 } 508 } 509 dm.resetMap(); 510 dm.clearGoals(); 511 } 512 513 for (int i = pts.length; i < totalTargets; ++i) { 514 DijkstraMap dm = new DijkstraMap(dungeon, dijkstra.measurement); 515 t = lts[i - pts.length]; 516 dt.resetMap(); 517 dt.clearGoals(); 518 los.isReachable(resMap, origin.x, origin.y, t.x, t.y, rt); 519 Queue<Coord> lit = los.getLastPath(); 520 521 for(Coord p : lit) 522 { 523 dt.setGoal(p); 524 } 525 if(radius > 0) 526 dt.partialScan(radius, null); 527 528 double dist; 529 for (int x = 0; x < dungeon.length; x++) { 530 for (int y = 0; y < dungeon[x].length; y++) { 531 if (dt.gradientMap[x][y] < DijkstraMap.FLOOR){ 532 dist = reach.metric.radius(origin.x, origin.y, x, y); 533 if(dist <= reach.maxDistance + radius && dist >= reach.minDistance - radius) 534 compositeMap[i][x][y] = dm.physicalMap[x][y]; 535 else 536 compositeMap[i][x][y] = DijkstraMap.WALL; 537 } 538 else compositeMap[i][x][y] = DijkstraMap.WALL; 539 } 540 } 541 if(compositeMap[i][lts[i - pts.length].x][lts[i - pts.length].y] > DijkstraMap.FLOOR) 542 { 543 for (int x = 0; x < dungeon.length; x++) 544 { 545 Arrays.fill(compositeMap[i][x], 99999.0); 546 } 547 continue; 548 } 549 550 551 dm.initialize(compositeMap[i]); 552 dm.setGoal(t); 553 dm.scan(null, null); 554 for (int x = 0; x < dungeon.length; x++) { 555 for (int y = 0; y < dungeon[x].length; y++) { 556 compositeMap[i][x][y] = (dm.gradientMap[x][y] < DijkstraMap.FLOOR && dungeonCopy[x][y] != '!' && dungeonPriorities[x][y] != '#') ? dm.gradientMap[x][y] : 99999.0; 557 } 558 } 559 dm.resetMap(); 560 dm.clearGoals(); 561 } 562 double bestQuality = 99999 * lts.length + 399999 * pts.length; 563 double[][] qualityMap = new double[dungeon.length][dungeon[0].length]; 564 for (int x = 0; x < qualityMap.length; x++) { 565 for (int y = 0; y < qualityMap[x].length; y++) { 566 qualityMap[x][y] = 0.0; 567 long pbits = 0, lbits = 0; 568 for (int i = 0; i < pts.length; ++i) { 569 qualityMap[x][y] += compositeMap[i][x][y]; 570 if(compositeMap[i][x][y] < 399999.0 && i < 63) 571 pbits |= 1 << i; 572 } 573 for (int i = pts.length; i < totalTargets; ++i) { 574 qualityMap[x][y] += compositeMap[i][x][y]; 575 if(compositeMap[i][x][y] < 99999.0 && i < 63) 576 lbits |= 1 << i; 577 } 578 if(qualityMap[x][y] < bestQuality) 579 { 580 ArrayList<Coord> ap = new ArrayList<>(); 581 582 for (int i = 0; i < pts.length && i < 63; ++i) { 583 if((pbits & (1 << i)) != 0) 584 ap.add(pts[i]); 585 } 586 for (int i = pts.length; i < totalTargets && i < 63; ++i) { 587 if((lbits & (1 << i)) != 0) 588 ap.add(lts[i - pts.length]); 589 } 590 591 if(ap.size() > 0) { 592 bestQuality = qualityMap[x][y]; 593 bestPoints.clear(); 594 bestPoints.put(Coord.get(x, y), ap); 595 } 596 } 597 else if(qualityMap[x][y] == bestQuality) { 598 ArrayList<Coord> ap = new ArrayList<>(); 599 600 for (int i = 0; i < pts.length && i < 63; ++i) { 601 if ((pbits & (1 << i)) != 0) { 602 ap.add(pts[i]); 603 ap.add(pts[i]); 604 ap.add(pts[i]); 605 ap.add(pts[i]); 606 } 607 } 608 for (int i = pts.length; i < totalTargets && i < 63; ++i) { 609 if ((lbits & (1 << i)) != 0) 610 ap.add(lts[i - pts.length]); 611 } 612 613 if (ap.size() > 0) { 614 bestPoints.put(Coord.get(x, y), ap); 615 } 616 } 617 } 618 } 619 620 return bestPoints; 621 } 622 623/* 624 @Override 625 public ArrayList<ArrayList<Coord>> idealLocations(Set<Coord> targets, Set<Coord> requiredExclusions) { 626 int totalTargets = targets.size() + 1; 627 int volume = (int)(rt.radius(1, 1, dungeon.length - 2, dungeon[0].length - 2) * radius * 2.1); 628 ArrayList<ArrayList<Coord>> locs = new ArrayList<ArrayList<Coord>>(totalTargets); 629 for(int i = 0; i < totalTargets; i++) 630 { 631 locs.add(new ArrayList<Coord>(volume)); 632 } 633 if(totalTargets == 1) 634 return locs; 635 636 int ctr = 0; 637 638 boolean[][] tested = new boolean[dungeon.length][dungeon[0].length]; 639 for (int x = 1; x < dungeon.length - 1; x += radius) { 640 for (int y = 1; y < dungeon[x].length - 1; y += radius) { 641 642 if(mayContainTarget(requiredExclusions, x, y)) 643 continue; 644 ctr = 0; 645 for(Coord tgt : targets) 646 { 647 if(rt.radius(origin.x, origin.y, tgt.x, tgt.y) + rt.radius(end.x, end.y, tgt.x, tgt.y) - 648 rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius) 649 ctr++; 650 } 651 if(ctr > 0) 652 locs.get(totalTargets - ctr).add(Coord.get(x, y)); 653 } 654 } 655 Coord it; 656 for(int t = 0; t < totalTargets - 1; t++) 657 { 658 if(locs.get(t).size() > 0) { 659 int numPoints = locs.get(t).size(); 660 for (int i = 0; i < numPoints; i++) { 661 it = locs.get(t).get(i); 662 for (int x = Math.max(1, it.x - radius / 2); x < it.x + (radius + 1) / 2 && x < dungeon.length - 1; x++) { 663 for (int y = Math.max(1, it.y - radius / 2); y <= it.y + (radius - 1) / 2 && y < dungeon[0].length - 1; y++) 664 { 665 if(tested[x][y]) 666 continue; 667 tested[x][y] = true; 668 669 if(mayContainTarget(requiredExclusions, x, y)) 670 continue; 671 672 ctr = 0; 673 for(Coord tgt : targets) 674 { 675 if(rt.radius(origin.x, origin.y, tgt.x, tgt.y) + rt.radius(end.x, end.y, tgt.x, tgt.y) - 676 rt.radius(origin.x, origin.y, end.x, end.y) <= 3.0 + radius) 677 ctr++; 678 } 679 if(ctr > 0) 680 locs.get(totalTargets - ctr).add(Coord.get(x, y)); 681 } 682 } 683 } 684 } 685 } 686 return locs; 687 } 688*/ 689 @Override 690 public void setMap(char[][] map) { 691 dungeon = map; 692 dijkstra.resetMap(); 693 dijkstra.clearGoals(); 694 } 695 696 @Override 697 public OrderedMap<Coord, Double> findArea() { 698 double[][] dmap = initDijkstra(); 699 dmap[origin.x][origin.y] = DijkstraMap.DARK; 700 dijkstra.resetMap(); 701 dijkstra.clearGoals(); 702 return AreaUtils.dijkstraToHashMap(dmap); 703 } 704 705}