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