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