1 package cz.cuni.amis.pogamut.ut2004.agent.navigation.loquenavigator;
2
3 import java.util.Iterator;
4 import java.util.List;
5 import java.util.logging.Level;
6 import java.util.logging.Logger;
7
8 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
9 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
10 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
11 import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils;
12 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
13 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
14 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
15 import cz.cuni.amis.pogamut.ut2004.agent.navigation.AbstractUT2004PathNavigator;
16 import cz.cuni.amis.pogamut.ut2004.agent.navigation.IUT2004PathRunner;
17 import cz.cuni.amis.pogamut.ut2004.bot.command.AdvancedLocomotion;
18 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
19 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Mover;
20 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
21 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointNeighbourLink;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
23 import cz.cuni.amis.pogamut.ut2004.utils.LinkFlag;
24 import cz.cuni.amis.pogamut.ut2004.utils.UnrealUtils;
25 import cz.cuni.amis.utils.NullCheck;
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public class LoqueNavigator<PATH_ELEMENT extends ILocated> extends AbstractUT2004PathNavigator<PATH_ELEMENT>
73 {
74
75
76
77 private Location navigDestination = null;
78
79
80
81
82 private Stage navigStage = Stage.COMPLETED;
83
84
85
86
87
88
89 private ILocated focus = null;
90
91
92
93
94 private class SelfListener implements IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>>
95 {
96 private IWorldView worldView;
97
98
99
100
101
102 public SelfListener(IWorldView worldView)
103 {
104 this.worldView = worldView;
105 worldView.addObjectListener(Self.class, WorldObjectUpdatedEvent.class, this);
106 }
107
108 @Override
109 public void notify(WorldObjectUpdatedEvent<Self> event) {
110 self = event.getObject();
111 }
112 }
113
114
115 private SelfListener selfListener;
116
117
118
119
120
121
122
123
124 public static final int CLOSE_ENOUGH = 40;
125
126
127
128 @Override
129 protected void navigate(ILocated focus, int pathElementIndex) {
130 if (log != null && log.isLoggable(Level.FINE)) log.fine("Current stage: " + navigStage);
131 this.focus = focus;
132 switch (navigStage = keepNavigating()) {
133 case AWAITING_MOVER:
134 case RIDING_MOVER:
135 setBotWaiting(true);
136 break;
137 case TELEPORT:
138 case NAVIGATING:
139 case REACHING:
140 setBotWaiting(false);
141 break;
142
143 case TIMEOUT:
144 case CRASHED:
145 case CANCELED:
146 if (log != null && log.isLoggable(Level.WARNING)) log.warning("Navigation " + navigStage);
147 executor.stuck();
148 return;
149
150 case COMPLETED:
151 executor.targetReached();
152 break;
153 }
154 if (log != null && log.isLoggable(Level.FINE)) log.fine("Next stage: " + navigStage);
155 }
156
157 @Override
158 public void reset() {
159
160
161 navigCurrentLocation = null;
162 navigCurrentNode = null;
163 navigCurrentLink = null;
164 navigDestination = null;
165 navigIterator = null;
166 navigLastLocation = null;
167 navigLastNode = null;
168 navigNextLocation = null;
169 navigNextNode = null;
170 navigNextLocationOffset = 0;
171 navigStage = Stage.COMPLETED;
172 setBotWaiting(false);
173
174 resetNavigMoverVariables();
175 }
176
177 @Override
178 public void newPath(List<PATH_ELEMENT> path, ILocated focus) {
179
180 reset();
181
182
183 Location dest = path.get(path.size()-1).getLocation();
184
185
186 initPathNavigation(dest, path);
187
188
189 navigate(focus);
190 }
191
192 @Override
193 public void pathExtended(List<PATH_ELEMENT> path, int currentPathIndex) {
194 if (path == null || path.size() == 0) {
195 throw new RuntimeException("path is null or 0-sized!");
196 }
197 navigDestination = path.get(path.size() - 1).getLocation();
198 navigIterator = path.iterator();
199
200 int newOffset = -currentPathIndex;
201 for (int i = 0; i < path.size() && i < currentPathIndex+navigNextLocationOffset && navigIterator.hasNext(); ++i) {
202 ++newOffset;
203 navigIterator.next();
204 }
205 log.fine("PATH EXTEND ... curr index " + currentPathIndex + ", old offset " + navigNextLocationOffset + ", new offset " + newOffset + ", path size " + path.size());
206 navigNextLocationOffset = newOffset;
207 }
208
209 public NavPointNeighbourLink getCurrentLink() {
210 return navigCurrentLink;
211 }
212
213
214
215
216
217
218
219
220 protected void initDirectNavigation (Location dest)
221 {
222
223 int distance = (int) memory.getLocation().getDistance(dest);
224
225 if (log != null && log.isLoggable(Level.FINE)) log.fine (
226 "LoqueNavigator.initDirectNavigation(): initializing direct navigation"
227 + ", distance " + distance
228 );
229
230 initDirectly (dest);
231 }
232
233
234
235
236
237
238
239
240 protected void initPathNavigation(Location dest, List<PATH_ELEMENT> path)
241 {
242
243 if (log != null && log.isLoggable(Level.FINE))
244 log.fine (
245 "LoqueNavigator.initPathNavigation(): initializing path navigation"
246 + ", nodes " + path.size ()
247 );
248
249 if (!initAlongPath(dest, path))
250 {
251
252 initDirectNavigation(dest);
253 }
254 }
255
256
257
258
259
260
261
262 protected Stage keepNavigating ()
263 {
264
265 if (navigStage.terminated)
266 return navigStage;
267
268 if (log != null && log.isLoggable(Level.FINE)) {
269 if (navigLastNode != null) {
270 log.fine("LoqueNavigator.keepNavigating(): navigating from " + navigLastNode.getId().getStringId() + navigLastNode.getLocation() );
271 } else
272 if (navigLastLocation != null) {
273 log.fine("LoqueNavigator.keepNavigating(): navigating from " + navigLastLocation + " (navpoint is unknown)" );
274 }
275 if (navigCurrentNode != null) {
276 log.fine("LoqueNavigator.keepNavigating(): navigating to " + navigCurrentNode.getId().getStringId() + navigCurrentNode.getLocation() );
277 } else
278 if (navigCurrentLocation != null) {
279 log.fine("LoqueNavigator.keepNavigating(): navigating to " + navigCurrentLocation + " (navpoint is unknown)" );
280 }
281 if (navigLastLocation != null && navigCurrentLocation != null) {
282 log.fine("LoqueNavigator.keepNavigating(): distance in-between " + navigCurrentLocation.getDistance(navigLastLocation));
283 }
284 }
285
286
287 switch (navigStage)
288 {
289 case REACHING:
290 navigStage = navigDirectly();
291 break;
292 default:
293 navigStage = navigAlongPath();
294 break;
295 }
296
297
298 if (log != null && log.isLoggable(Level.FINEST)) log.finest ("Navigator.keepNavigating(): navigation stage " + navigStage);
299 return navigStage;
300 }
301
302
303
304
305
306
307
308
309
310 private Stage initDirectly(Location dest)
311 {
312
313 navigDestination = dest;
314
315 runner.reset();
316
317 return navigStage = Stage.REACHING;
318 }
319
320
321
322
323
324 private Stage navigDirectly ()
325 {
326
327 int distance = (int) memory.getLocation().getDistance(navigDestination);
328
329
330 if (distance <= CLOSE_ENOUGH)
331 {
332 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigDirectly(): destination close enough: " + distance);
333 return Stage.COMPLETED;
334 }
335
336
337 if (!runner.runToLocation (navigLastLocation, navigDestination, null, (focus == null ? navigDestination : focus), null, true, false))
338 {
339 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigDirectly(): direct navigation failed");
340 return Stage.CRASHED;
341 }
342
343
344 if (log != null && log.isLoggable(Level.FINEST)) log.finer ("LoqueNavigator.navigDirectly(): traveling directly, distance = " + distance);
345 return navigStage;
346 }
347
348
349
350
351
352
353 private Iterator<PATH_ELEMENT> navigIterator = null;
354
355
356
357
358 private int navigNextLocationOffset = 0;
359
360
361
362
363 private Location navigLastLocation = null;
364
365
366
367
368
369 private NavPoint navigLastNode = null;
370
371
372
373
374 private Location navigCurrentLocation = null;
375
376
377
378
379
380 private NavPoint navigCurrentNode = null;
381
382
383
384
385
386 private NavPointNeighbourLink navigCurrentLink = null;
387
388
389
390
391 private Location navigNextLocation = null;
392
393
394
395
396
397 private NavPoint navigNextNode = null;
398
399
400
401
402
403
404
405
406 protected NavPoint getNavPoint(ILocated location) {
407 if (location instanceof NavPoint) return (NavPoint) location;
408 NavPoint np = DistanceUtils.getNearest(main.getWorldView().getAll(NavPoint.class).values(), location);
409 if (np.getLocation().getDistance(location.getLocation()) < CLOSE_ENOUGH) return np;
410 return null;
411 }
412
413
414
415
416
417
418
419 private boolean initAlongPath(Location dest, List<PATH_ELEMENT> path)
420 {
421
422 navigDestination = dest;
423 navigIterator = path.iterator();
424
425 navigCurrentLocation = bot.getLocation();
426 navigCurrentNode = DistanceUtils.getNearest(bot.getWorldView().getAll(NavPoint.class).values(), bot.getLocation(), 40);
427
428 prepareNextNode();
429
430 navigStage = Stage.NAVIGATING;
431
432 return switchToNextNode ();
433 }
434
435
436
437
438
439 private Stage navigAlongPath()
440 {
441
442 int totalDistance = (int) memory.getLocation().getDistance(navigDestination);
443
444
445 if (totalDistance <= CLOSE_ENOUGH)
446 {
447 log.finest ("Navigator.navigAlongPath(): destination close enough: " + totalDistance);
448 return Stage.COMPLETED;
449 }
450
451
452 if (navigStage.mover) {
453 log.fine("MOVER");
454 return navigThroughMover();
455 } else
456 if (navigStage.teleport) {
457 log.fine("TELEPORT");
458 return navigThroughTeleport();
459 } else {
460 log.fine("STANDARD");
461 return navigToCurrentNode(true);
462 }
463 }
464
465
466
467
468
469
470
471
472 private void prepareNextNode ()
473 {
474 if (navigCurrentNode != null && navigCurrentNode.isTeleporter()) {
475
476 prepareNextNodeTeleporter();
477 return;
478 }
479
480
481
482 ILocated located = null;
483 navigNextLocation = null;
484 navigNextLocationOffset = 0;
485 while ((located == null) && navigIterator.hasNext ())
486 {
487
488 located = navigIterator.next();
489 navigNextLocationOffset += 1;
490 if (located == null) {
491 continue;
492 }
493 }
494
495
496 if (located == null) {
497 navigNextLocationOffset = 0;
498 return;
499 }
500
501 if (executor.getPathElementIndex() + navigNextLocationOffset >= executor.getPath().size()) {
502 navigNextLocationOffset = 0;
503 }
504
505
506 navigNextLocation = located.getLocation();
507
508 navigNextNode = getNavPoint(located);
509 }
510
511
512
513
514 private void prepareNextNodeTeleporter() {
515
516
517 ILocated located = null;
518 navigNextLocation = null;
519 navigNextLocationOffset = 0;
520 boolean nextTeleporterFound = false;
521 while ((located == null) && navigIterator.hasNext ())
522 {
523
524 located = navigIterator.next();
525 navigNextLocationOffset += 1;
526 if (located == null) {
527 continue;
528 }
529 navigNextNode = getNavPoint(located);
530 if (navigNextNode != null && navigNextNode.isTeleporter()) {
531
532 if (!nextTeleporterFound) {
533
534 located = null;
535 }
536 nextTeleporterFound = true;
537 } else {
538 break;
539 }
540 }
541
542
543 if (located == null) {
544 navigNextLocationOffset = 0;
545 return;
546 }
547
548 if (executor.getPathElementIndex() + navigNextLocationOffset >= executor.getPath().size()) {
549 navigNextLocationOffset = 0;
550 }
551
552
553 navigNextLocation = located.getLocation();
554
555 navigNextNode = getNavPoint(located);
556 }
557
558
559
560
561
562 private boolean switchToNextNode ()
563 {
564 if (log != null && log.isLoggable(Level.FINER)) log.finer ("Navigator.switchToNextNode(): switching!");
565
566
567 navigLastLocation = navigCurrentLocation;
568 navigLastNode = navigCurrentNode;
569
570
571 if (null == (navigCurrentLocation = navigNextLocation))
572 {
573
574 if (log != null && log.isLoggable(Level.FINER)) log.finer ("Navigator.switchToNextNode(): no nodes left");
575 navigCurrentNode = null;
576 return false;
577 }
578
579 navigCurrentNode = navigNextNode;
580
581
582 navigCurrentLink = getNavPointsLink(navigLastNode, navigCurrentNode);
583
584 if (navigCurrentLink == null) {
585 getNavPointsLink(navigLastNode, navigCurrentNode);
586 if (log.isLoggable(Level.INFO)) {
587 log.info("No link information...");
588 }
589 }
590
591
592 if (navigLastLocation == null) {
593 navigLastLocation = bot.getLocation();
594 navigLastNode = navigCurrentNode;
595 }
596
597
598 int localDistance = (int) memory.getLocation().getDistance(navigCurrentLocation.getLocation());
599
600 if (navigCurrentNode == null) {
601
602 runner.reset();
603 if (log != null && log.isLoggable(Level.FINE))
604 log.fine (
605 "LoqueNavigator.switchToNextNode(): switch to next location " + navigCurrentLocation
606 + ", distance " + localDistance
607 + ", mover " + navigStage.mover
608 );
609 } else {
610
611 if (navigCurrentNode.isTeleporter()) {
612 navigStage = Stage.TeleporterStage();
613 } else
614
615 if (navigCurrentNode.isLiftCenter())
616 {
617
618 navigStage = Stage.FirstMoverStage();
619 resetNavigMoverVariables();
620
621
622 if (memory.getLocation().getDistance(navigCurrentNode.getLocation()) < CLOSE_ENOUGH) {
623
624 navigStage = navigStage.next();
625 }
626 } else
627
628 if (navigStage.mover)
629 {
630 navigStage = navigStage.next();
631
632 runner.reset();
633 } else
634 if (navigStage.teleport) {
635 navigStage = navigStage.next();
636
637 runner.reset();
638 } else
639
640 {
641
642 runner.reset();
643 }
644
645
646 if (log != null && log.isLoggable(Level.FINE))
647 log.fine (
648 "LoqueNavigator.switchToNextNode(): switch to next node " + navigCurrentNode.getId().getStringId()
649 + ", distance " + localDistance
650 + ", reachable " + isReachable(navigCurrentNode)
651 + ", mover " + navigStage.mover
652 );
653 }
654
655
656 if (executor.getPathElementIndex() < 0) {
657 executor.switchToAnotherPathElement(0);
658 } else {
659 if (navigNextLocationOffset > 0) {
660 executor.switchToAnotherPathElement(executor.getPathElementIndex()+navigNextLocationOffset);
661 } else {
662 executor.switchToAnotherPathElement(executor.getPathElementIndex());
663 }
664 }
665 navigNextLocationOffset = 0;
666
667 prepareNextNode();
668
669 if (localDistance < 20) {
670 return switchToNextNode();
671 }
672
673 return true;
674 }
675
676 protected boolean isReachable(NavPoint node) {
677 if (node == null) return true;
678 int hDistance = (int) memory.getLocation().getDistance2D(node.getLocation());
679 int vDistance = (int) node.getLocation().getDistanceZ(memory.getLocation());
680 double angle;
681 if (hDistance == 0) {
682 angle = vDistance == 0 ? 0 : (vDistance > 0 ? Math.PI/2 : -Math.PI/2);
683 } else {
684 angle = Math.atan(vDistance / hDistance);
685 }
686 return Math.abs(vDistance) < 30 && Math.abs(angle) < Math.PI / 4;
687 }
688
689
690
691
692
693 private int navigMoverRideUpCount;
694
695 private int navigMoverRideDownCount;
696
697 private Boolean navigMoverIsRidingUp;
698
699 private Boolean navigMoverIsRidingDown;
700
701 private void resetNavigMoverVariables() {
702 navigMoverIsRidingUp = null;
703 navigMoverIsRidingDown = null;
704 navigMoverRideUpCount = 0;
705 navigMoverRideDownCount = 0;
706 }
707
708 private void checkMoverMovement(Mover mover) {
709
710 if (mover.getVelocity().z > 0) {
711
712 if (navigMoverIsRidingUp == null) {
713 navigMoverIsRidingUp = true;
714 navigMoverIsRidingDown = false;
715 navigMoverRideUpCount = 1;
716 navigMoverRideDownCount = 0;
717 } else
718 if (navigMoverIsRidingDown) {
719 navigMoverIsRidingUp = true;
720 navigMoverIsRidingDown = false;
721 ++navigMoverRideUpCount;
722 }
723 } else
724 if (mover.getVelocity().z < 0) {
725
726 if (navigMoverIsRidingDown == null) {
727 navigMoverIsRidingUp = false;
728 navigMoverIsRidingDown = true;
729 navigMoverRideUpCount = 0;
730 navigMoverRideDownCount = 1;
731 } else
732 if (navigMoverIsRidingUp) {
733 navigMoverIsRidingUp = false;
734 navigMoverIsRidingDown = true;
735 ++navigMoverRideDownCount;
736 }
737 }
738 }
739
740
741
742
743
744
745
746
747
748
749 private NavPointNeighbourLink getNavPointsLink(NavPoint start, NavPoint end) {
750 if (start == null) {
751
752 NavPoint tmp = getNavPoint(memory.getLocation());
753 if (tmp != null)
754 start = tmp;
755 else
756 return null;
757 }
758 if (end == null)
759 return null;
760
761 if (end.getIncomingEdges().containsKey(start.getId()))
762 return end.getIncomingEdges().get(start.getId());
763
764 return null;
765 }
766
767
768
769
770
771
772
773 private Stage navigToCurrentNode (boolean useFocus)
774 {
775 if (navigCurrentNode != null) {
776
777 navigCurrentLocation = navigCurrentNode.getLocation();
778 }
779 if (navigNextNode != null) {
780
781 navigNextLocation = navigNextNode.getLocation();
782 }
783
784
785 int localDistance = (int) memory.getLocation().getDistance(navigCurrentLocation.getLocation());
786
787 int localDistance2 = (int) memory.getLocation().getDistance(
788 Location.add(navigCurrentLocation.getLocation(), new Location (0,0,100))
789 );
790 int distanceZ = (int) memory.getLocation().getDistanceZ(navigCurrentLocation);
791
792
793 Location firstLocation = navigCurrentLocation.getLocation();
794
795 Location secondLocation = (navigNextNode != null ?
796 (navigNextNode.isLiftCenter() || navigNextNode.isLiftExit() ?
797 null
798 : navigNextNode.getLocation())
799 : navigNextLocation);
800
801 ILocated focus = (this.focus == null || !useFocus ?
802 ((navigNextLocation == null) ? firstLocation : navigNextLocation.getLocation())
803 :
804 this.focus
805 );
806
807
808 if (!runner.runToLocation (navigLastLocation, firstLocation, secondLocation, focus, navigCurrentLink, (navigCurrentNode == null ? true : isReachable(navigCurrentNode)), false)) {
809 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigToCurrentNode(): navigation to current node failed");
810 return Stage.CRASHED;
811 }
812
813
814 if (log != null && log.isLoggable(Level.FINEST)) log.finest ("LoqueNavigator.navigToCurrentNode(): traveling to current node, distance = " + localDistance);
815
816 int testDistance = 125;
817 if (navigCurrentNode != null && (navigCurrentNode.isLiftCenter() || navigCurrentNode.isLiftExit())) {
818
819 testDistance = 100;
820 }
821 if (navigCurrentLink != null && (navigCurrentLink.getFlags() & LinkFlag.JUMP.get()) != 0) {
822
823 localDistance2 = 10000;
824 }
825
826 if (navigCurrentLocation != null && navigCurrentLocation.equals(executor.getPath().get(executor.getPath().size()-1))
827 || (!navigIterator.hasNext() && (navigNextLocation == null || navigCurrentLocation == navigNextLocation))) {
828
829 testDistance = 2 * ((int) UnrealUtils.CHARACTER_COLLISION_RADIUS);
830 }
831
832
833 if ( distanceZ < 40 && ((localDistance < testDistance) || (localDistance2 < testDistance) ))
834 {
835
836 if (!switchToNextNode ())
837 {
838
839 if (log != null && log.isLoggable(Level.FINE)) log.fine("Navigator.navigToCurrentNode(): switching to direct navigation");
840 return initDirectly(navigDestination);
841 }
842 }
843
844
845 return navigStage;
846 }
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866 private Stage navigThroughMover ()
867 {
868 Stage stage = navigStage;
869
870 if (navigCurrentNode == null) {
871 if (log != null && log.isLoggable(Level.WARNING)) log.warning("LoqueNavigator.navigThroughMover("+stage+"): can't navigate through the mover without the navpoint instance (navigCurrentNode == null)");
872 return Stage.CRASHED;
873 }
874
875 Mover mover = (Mover) bot.getWorldView().get(navigCurrentNode.getMover());
876 if (mover == null) {
877 if (log != null && log.isLoggable(Level.WARNING)) log.warning("LoqueNavigator.navigThroughMover("+stage+"): can't navigate through the mover as current node does not represent a mover (moverId == null): " + navigCurrentNode);
878 return Stage.CRASHED;
879 }
880
881
882 navigCurrentLocation = navigCurrentNode.getLocation();
883
884 if (navigNextNode != null) {
885
886 navigNextLocation = navigNextNode.getLocation();
887 }
888
889 log.info("navig-curr: " + navigCurrentNode);
890 log.info("navig-next: " + navigNextNode);
891
892
893 int hDistance = (int) memory.getLocation().getDistance2D(navigCurrentLocation.getLocation());
894
895 int zDistance = (int) navigCurrentLocation.getLocation().getDistanceZ(memory.getLocation());
896
897 boolean moverRidingUp = mover.getVelocity().z > 0;
898
899 boolean moverRidingDown = mover.getVelocity().z < 0;
900
901 boolean moverStandingStill = Math.abs(mover.getVelocity().z) < Location.DISTANCE_ZERO;
902
903 if (navigStage == Stage.AWAITING_MOVER) {
904
905 if (zDistance > 0 && moverRidingUp) {
906
907 if (log != null && log.isLoggable(Level.FINER)) {
908 log.finer (
909 "LoqueNavigator.navigThroughMover("+stage+"): we are UNDER the mover and mover is RIDING UP ... getting back to waiting position"
910 + ", zDistance " + zDistance + ", mover.velocity.z " + mover.getVelocity().z + ", mover " + (moverRidingUp ? "riding UP" : (moverRidingDown ? "riding DOWN" : moverStandingStill ? "standing STILL" : " movement unknown"))
911 );
912 }
913
914
915 if (!runner.runToLocation(memory.getLocation(), navigLastLocation, null, navigCurrentLocation, null, (navigLastNode == null ? true : isReachable(navigLastNode)), false))
916 {
917 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigThroughMover("+stage+"): navigation to wait-for-mover node failed");
918 return Stage.CRASHED;
919 }
920 return navigStage;
921 }
922
923
924
925
926
927 if (hDistance > 400) {
928 if (log != null && log.isLoggable(Level.WARNING)) log.warning("LoqueNavigator.navigThroughMover("+stage+"): failed to get onto the mover as its 2D distance is > 400, hDistance " + hDistance + ", unsupported!");
929 return Stage.CRASHED;
930 }
931
932 if (zDistance > 30 && moverRidingUp)
933 {
934
935 if (log != null && log.isLoggable(Level.FINER)) {
936 log.finer (
937 "LoqueNavigator.navigThroughMover("+stage+"): waiting for the mover to come"
938 + " | zDistance " + zDistance + ", hDistance " + hDistance + ", mover " + (moverRidingUp ? "riding UP" : (moverRidingDown ? "riding DOWN" : moverStandingStill ? "standing STILL" : " movement unknown"))
939 + ", node " + navigCurrentNode.getId().getStringId()
940 );
941 }
942
943 if (!runner.runToLocation(memory.getLocation(), navigLastLocation, null, navigCurrentLocation, navigCurrentLink, (navigLastNode == null ? true : isReachable(navigLastNode)), false)) {
944 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigThroughMover("+stage+"): navigation to last node failed");
945 return Stage.CRASHED;
946 }
947
948 return navigStage;
949 }
950
951
952 if (log != null && log.isLoggable(Level.FINER))
953 log.finer (
954 "Navigator.navigThroughMover("+stage+"): mover arrived"
955 + " | zDistance " + zDistance + ", hDistance " + hDistance + ", mover " + (moverRidingUp ? "riding UP" : (moverRidingDown ? "riding DOWN" : moverStandingStill ? "standing STILL" : " movement unknown"))
956 + ", node " + navigCurrentNode.getId().getStringId()
957 );
958
959
960 return navigToCurrentNode(false);
961 } else
962 if (navigStage == Stage.RIDING_MOVER) {
963 checkMoverMovement(mover);
964
965 if (navigMoverRideDownCount > 2 || navigMoverRideUpCount > 2) {
966
967 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigThroughMover("+stage+"): navigation to mover exit node failed, we've rided twice up & down and there was no place suitable to exit the mover in order to get to get to " + navigCurrentNode);
968 return Stage.CRASHED;
969 }
970
971 if (hDistance > 400) {
972 if (log != null && log.isLoggable(Level.WARNING)) log.warning("LoqueNavigator.navigThroughMover("+stage+"): navigation to mover exit node failed, the node is too far, hDistance " + hDistance + " > 400, unsupported (wiered navigation graph link)");
973 return Stage.CRASHED;
974 }
975
976
977 if ( Math.abs(zDistance) > 50 ) {
978
979 if (log != null && log.isLoggable(Level.FINER))
980 log.finer (
981 "LoqueNavigator.navigThroughMover("+stage+"): riding the mover"
982 + " | zDistance " + zDistance + ", hDistance " + hDistance + ", mover " + (moverRidingUp ? "riding UP" : (moverRidingDown ? "riding DOWN" : moverStandingStill ? "standing STILL" : " movement unknown"))
983 + ", node " + navigCurrentNode.getId().getStringId()
984 );
985
986
987 if (!runner.runToLocation(memory.getLocation(), navigLastLocation, null, navigCurrentLocation, navigCurrentLink, (navigLastNode == null ? true : isReachable(navigLastNode)), false))
988 {
989 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigThroughMover("+stage+"): navigation to last node failed");
990 return Stage.CRASHED;
991 }
992
993
994 return navigStage;
995 }
996
997
998 if (log != null && log.isLoggable(Level.FINER))
999 log.finer (
1000 "Navigator.navigThroughMover("+stage+"): exiting the mover"
1001 + " | zDistance " + zDistance + ", hDistance " + hDistance + ", mover " + (moverRidingUp ? "riding UP" : (moverRidingDown ? "riding DOWN" : moverStandingStill ? "standing STILL" : " movement unknown"))
1002 + ", node " + navigCurrentNode.getId().getStringId()
1003 );
1004
1005
1006 return navigToCurrentNode(false);
1007 } else {
1008 if (log != null && log.isLoggable(Level.WARNING)) {
1009 log.warning("Navigator.navigThroughMover("+stage+"): invalid stage, neither AWAITING_MOVER nor RIDING MOVER");
1010 }
1011 return Stage.CRASHED;
1012 }
1013
1014 }
1015
1016
1017
1018
1019
1020
1021
1022 private Stage navigThroughTeleport()
1023 {
1024 if (navigCurrentNode != null) {
1025
1026 navigCurrentLocation = navigCurrentNode.getLocation();
1027 }
1028
1029 if (navigNextNode != null) {
1030
1031 navigNextLocation = navigNextNode.getLocation();
1032 }
1033
1034
1035
1036
1037
1038
1039
1040
1041 int localDistance1_1 = (int) memory.getLocation().getDistance(navigCurrentLocation.getLocation());
1042
1043 int localDistance1_2 = (int) memory.getLocation().getDistance(
1044 Location.add(navigCurrentLocation.getLocation(), new Location (0,0,100))
1045 );
1046
1047
1048
1049 int localDistance2_1 = Integer.MAX_VALUE;
1050 int localDistance2_2 = Integer.MAX_VALUE;
1051 for (NavPointNeighbourLink link : navigCurrentNode.getOutgoingEdges().values()) {
1052 if (link.getToNavPoint().isTeleporter()) {
1053 localDistance2_1 = (int)memory.getLocation().getDistance(link.getToNavPoint().getLocation());
1054 localDistance2_2 = (int) memory.getLocation().getDistance(
1055 Location.add(link.getToNavPoint().getLocation(), new Location (0,0,100))
1056 );
1057 break;
1058 }
1059 }
1060
1061 boolean switchedToNextNode = false;
1062
1063 if ( (localDistance2_1 < 200) || (localDistance2_2 < 200))
1064 {
1065
1066
1067 if (!switchToNextNode ())
1068 {
1069
1070 if (log != null && log.isLoggable(Level.FINE)) log.fine ("Navigator.navigToCurrentNode(): switch to direct navigation");
1071 return initDirectly(navigDestination);
1072 }
1073 switchedToNextNode = true;
1074 }
1075
1076
1077 Location firstLocation = navigCurrentLocation.getLocation();
1078
1079 Location secondLocation = (navigNextNode != null && !navigNextNode.isLiftCenter() && !navigNextNode.isLiftCenter() ?
1080 navigNextNode.getLocation() :
1081 navigNextLocation);
1082
1083 ILocated focus = (this.focus == null ?
1084 ((navigNextLocation == null) ? firstLocation : navigNextLocation.getLocation())
1085 :
1086 this.focus
1087 );
1088
1089
1090 if (!runner.runToLocation(navigLastLocation, firstLocation, secondLocation, focus, navigCurrentLink, (navigCurrentNode == null ? true : isReachable(navigCurrentNode)), false)) {
1091 if (log != null && log.isLoggable(Level.FINE)) log.fine ("LoqueNavigator.navigToCurrentNode(): navigation to current node failed");
1092 return Stage.CRASHED;
1093 }
1094
1095
1096 if (log != null && log.isLoggable(Level.FINEST)) log.finest ("LoqueNavigator.navigToCurrentNode(): traveling to current node");
1097
1098
1099 if ( !switchedToNextNode && ((localDistance1_1 < 200) || (localDistance1_2 < 200)) )
1100 {
1101
1102 if (!switchToNextNode ())
1103 {
1104
1105 if (log != null && log.isLoggable(Level.FINE)) log.fine ("Navigator.navigToCurrentNode(): switch to direct navigation");
1106 return initDirectly(navigDestination);
1107 }
1108 }
1109
1110
1111 return navigStage;
1112 }
1113
1114
1115
1116
1117
1118
1119 private enum TerminatingStageType {
1120
1121 SUCCESS (false),
1122
1123 FAILURE (true);
1124
1125
1126 public boolean failure;
1127
1128
1129
1130
1131
1132 private TerminatingStageType (boolean failure)
1133 {
1134 this.failure = failure;
1135 }
1136 };
1137
1138
1139
1140
1141 private enum MoverStageType {
1142
1143 WAITING,
1144
1145 RIDING;
1146 };
1147
1148
1149
1150
1151 private enum TeleportStageType {
1152
1153 GOING_THROUGH;
1154 };
1155
1156
1157
1158
1159 public enum Stage
1160 {
1161
1162
1163
1164 REACHING ()
1165 {
1166 protected Stage next () { return this; }
1167 },
1168
1169
1170
1171 NAVIGATING ()
1172 {
1173 protected Stage next () { return this; }
1174 },
1175
1176
1177
1178 AWAITING_MOVER (MoverStageType.WAITING)
1179 {
1180 protected Stage next () { return RIDING_MOVER; }
1181 },
1182
1183
1184
1185 RIDING_MOVER (MoverStageType.RIDING)
1186 {
1187 protected Stage next () { return NAVIGATING; }
1188 },
1189
1190
1191
1192 CANCELED (TerminatingStageType.FAILURE)
1193 {
1194 protected Stage next () { return this; }
1195 },
1196
1197
1198
1199 TIMEOUT (TerminatingStageType.FAILURE)
1200 {
1201 protected Stage next () { return this; }
1202 },
1203
1204
1205
1206 CRASHED (TerminatingStageType.FAILURE)
1207 {
1208 protected Stage next () { return this; }
1209 },
1210
1211
1212
1213 COMPLETED (TerminatingStageType.SUCCESS)
1214 {
1215 protected Stage next () { return this; }
1216 },
1217
1218
1219
1220 TELEPORT (TeleportStageType.GOING_THROUGH) {
1221 protected Stage next() { return NAVIGATING; };
1222 };
1223
1224
1225
1226
1227
1228
1229
1230 private boolean mover;
1231
1232
1233
1234 public boolean terminated;
1235
1236
1237
1238 public boolean failure;
1239
1240
1241
1242 public boolean teleport;
1243
1244
1245
1246
1247
1248
1249 private Stage ()
1250 {
1251 this.mover = false;
1252 this.teleport = false;
1253 this.terminated = false;
1254 this.failure = false;
1255 }
1256
1257 private Stage(TeleportStageType type) {
1258 this.mover = false;
1259 this.teleport = true;
1260 this.failure = false;
1261 this.terminated = false;
1262 }
1263
1264
1265
1266
1267
1268 private Stage (MoverStageType type)
1269 {
1270 this.mover = true;
1271 this.teleport = false;
1272 this.terminated = false;
1273 this.failure = false;
1274 }
1275
1276
1277
1278
1279
1280 private Stage (TerminatingStageType type)
1281 {
1282 this.mover = false;
1283 this.teleport = false;
1284 this.terminated = true;
1285 this.failure = type.failure;
1286 }
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 protected abstract Stage next ();
1297
1298
1299
1300
1301
1302
1303
1304 protected static Stage FirstMoverStage ()
1305 {
1306 return AWAITING_MOVER;
1307 }
1308
1309
1310
1311
1312
1313 protected static Stage TeleporterStage() {
1314 return Stage.TELEPORT;
1315 }
1316 }
1317
1318
1319
1320
1321
1322
1323 private IUT2004PathRunner runner;
1324
1325
1326
1327
1328 protected UT2004Bot main;
1329
1330 protected AgentInfo memory;
1331
1332 protected AdvancedLocomotion body;
1333
1334 protected Logger log;
1335
1336
1337
1338
1339
1340
1341
1342
1343 public LoqueNavigator (UT2004Bot bot, AgentInfo info, AdvancedLocomotion move, Logger log)
1344 {
1345 this(bot, info, move, new KefikRunner(bot, info, move, log),log);
1346 }
1347
1348
1349
1350
1351
1352
1353 public LoqueNavigator (UT2004Bot bot, AgentInfo info, AdvancedLocomotion move, IUT2004PathRunner runner, Logger log)
1354 {
1355
1356 this.main = bot;
1357 this.memory = info;
1358 this.body = move;
1359 this.log = log;
1360
1361 this.selfListener = new SelfListener( bot.getWorldView() );
1362
1363
1364 this.runner = runner;
1365 NullCheck.check(this.runner, "runner");
1366 }
1367
1368 public Logger getLog() {
1369 return log;
1370 }
1371
1372 }