1 package cz.cuni.amis.pogamut.ut2004.agent.navigation.loquenavigator;
2
3 import java.util.logging.Level;
4 import java.util.logging.Logger;
5
6 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObject;
7 import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
8 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
9 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
10 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
11 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.Players;
12 import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.Senses;
13 import cz.cuni.amis.pogamut.ut2004.agent.navigation.IUT2004PathRunner;
14 import cz.cuni.amis.pogamut.ut2004.bot.command.AdvancedLocomotion;
15 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
16 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbcommands.Move;
17 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointNeighbourLink;
18 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Player;
19 import cz.cuni.amis.utils.NullCheck;
20
21
22
23
24
25
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 public class LoqueRunner implements IUT2004PathRunner {
59
60
61
62 private int runnerStep = 0;
63
64
65
66
67 private int runnerSingleJump = 0;
68
69
70
71 private int runnerDoubleJump = 0;
72
73
74
75
76 private int collisionCount = 0;
77
78
79
80
81 private Location collisionSpot = null;
82
83
84
85
86
87
88 public void reset()
89 {
90
91 runnerStep = 0;
92 runnerSingleJump = 0;
93 runnerDoubleJump = 0;
94 collisionCount = 0;
95 collisionSpot = null;
96 }
97
98
99
100 private Move addFocus(Move move, ILocated focus) {
101 if (focus != null) {
102 if (focus instanceof Player && ((IWorldObject)focus).getId() instanceof UnrealId) {
103 move.setFocusTarget((UnrealId)((IWorldObject)focus).getId());
104 } else {
105 move.setFocusLocation(focus.getLocation());
106 }
107 }
108 return move;
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 public boolean runToLocation (Location fromLocation, Location firstLocation, Location secondLocation, ILocated focus, NavPointNeighbourLink navPointsLink, boolean reachable)
137 {
138
139 if (log != null && log.isLoggable(Level.FINER)) {
140 log.finer(
141 "Runner.runToLocation(): runnerStep is "
142 + runnerStep + ", reachable is " + reachable + ", navPointsLink is" + navPointsLink
143 );
144 }
145
146
147 runnerStep++;
148
149
150
151 if (runnerStep <= 0) {
152
153 return true;
154 }
155
156
157
158 if (runnerStep <= 1)
159 {
160
161 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
162
163
164
165 if ((navPointsLink != null) && (
166 navPointsLink.isForceDoubleJump()
167 || (navPointsLink.getNeededJump() != null)
168 || (navPointsLink.getFlags() & 8) != 0
169 )) {
170
171
172 if (((navPointsLink.getFlags() & 8) == 0) || (memory.getLocation().z - 100 <= firstLocation.z)) {
173 Location direction = Location.sub(firstLocation, memory.getLocation()).getNormalized();
174 Location velocityDir = new Location(memory.getVelocity().asVector3d()).getNormalized();
175 Double result = Math.acos(direction.dot(velocityDir));
176
177
178 if (memory.getVelocity().size() > 200 && !result.isNaN() && result < (Math.PI / 9))
179 return resolveJump(firstLocation, secondLocation, focus, navPointsLink, reachable);
180 }
181 }
182
183 return true;
184 }
185
186
187 if (runnerSingleJump > 0)
188 {
189
190 return iterateSingleJumpSequence (firstLocation, secondLocation, focus, reachable);
191 }
192
193 else if (runnerDoubleJump > 0)
194 {
195
196 return iterateDoubleJumpSequence (firstLocation, secondLocation, focus, reachable);
197 }
198
199 if (senses.isCollidingOnce())
200 {
201
202 return resolveCollision (firstLocation, secondLocation, focus, reachable);
203 }
204
205 else
206 if
207 (
208
209 (runnerSingleJump == 0) && (runnerDoubleJump == 0)
210 &&
211 (
212
213 !reachable
214
215 || (navPointsLink != null) &&
216 (
217 navPointsLink.isForceDoubleJump()
218 || (navPointsLink.getNeededJump() != null)
219 || (navPointsLink.getFlags() & 8) != 0
220 )
221
222
223
224
225
226
227
228 )
229 )
230 {
231
232 return resolveJump (firstLocation, secondLocation, focus, navPointsLink, reachable);
233 }
234
235
236 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
237
238 if (log != null && log.isLoggable(Level.FINER)) {
239 log.finer(
240 "Runner.runToLocation(): issuing default move command to: " + firstLocation
241 );
242 }
243
244 return true;
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261 private boolean resolveCollision (Location firstLocation, Location secondLocation, ILocated focus, boolean reachable)
262 {
263
264 if (
265
266 (collisionSpot == null)
267
268 || (memory.getLocation().getDistance2D(collisionSpot) > 120)
269 ) {
270
271 if (log != null && log.isLoggable(Level.FINER))
272 log.finer(
273 "Runner.resolveCollision(): collision at "
274 + (int) memory.getLocation().getDistance2D(firstLocation)
275 );
276 collisionSpot = memory.getLocation();
277 collisionCount = 1;
278
279 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
280 return true;
281 }
282
283
284 else
285 switch (collisionCount++ % 2) {
286 case 0:
287
288 if (log != null && log.isLoggable(Level.FINER))
289 log.finer(
290 "Runner.resolveCollision(): repeated collision (" + collisionCount + "):"
291 + " double-jumping at " + (int) memory.getLocation().getDistance2D(firstLocation)
292 );
293 return initDoubleJumpSequence (firstLocation, secondLocation, focus, reachable);
294
295 default:
296
297 if (log != null && log.isLoggable(Level.FINER))
298 log.finer(
299 "Runner.resolveCollision(): repeated collision (" + collisionCount + "):"
300 + " single-jumping at " + (int) memory.getLocation().getDistance2D(firstLocation)
301 );
302 return initSingleJumpSequence (firstLocation, secondLocation, focus, reachable);
303 }
304 }
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 private boolean resolveJump (Location firstLocation, Location secondLocation, ILocated focus, NavPointNeighbourLink navPointsLink, boolean reachable)
323 {
324
325 int distance = (int) memory.getLocation().getDistance2D(firstLocation);
326
327 int velocity = (int) memory.getVelocity().size();
328
329
330
331
332 int jumpDistance = distance % 1000;
333
334
335 int zDistance = (int) firstLocation.getDistanceZ(memory.getLocation());
336
337
338
339
340 jumpDistance += Math.min (200, Math.max (-200, zDistance));
341
342 log.finer("Runner.resolveJump: distance = " + distance + ", velocity = " + velocity + ", jumpDistance = " + jumpDistance + ", zDistance = " + zDistance);
343
344
345 boolean enforceDoubleJump = false;
346 if ((navPointsLink != null)
347 &&
348 ( (navPointsLink.getNeededJump() != null || (navPointsLink.getFlags() & 8 ) != 0)
349 && (zDistance > 60 || jumpDistance > 380)
350 )
351 ){
352
353
354 enforceDoubleJump = true;
355 log.finest("Runner.resolveJump(): double jump indicated");
356 }
357
358
359 if (jumpDistance < 370)
360 {
361
362
363 if (navPointsLink != null) {
364 if (navPointsLink.getNeededJump() != null || (navPointsLink.getFlags() & 8 ) != 0)
365
366 if (enforceDoubleJump) return initDoubleJumpSequence(firstLocation, secondLocation, focus, reachable);
367 return initSingleJumpSequence (firstLocation, secondLocation, focus, reachable);
368 }
369
370
371
372 if (reachable || (distance >= 1000))
373 {
374
375 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
376 return true;
377 }
378
379
380
381
382
383
384
385 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
386 return true;
387 }
388
389 else if (jumpDistance < 470)
390 {
391
392 if (enforceDoubleJump) return initDoubleJumpSequence(firstLocation, secondLocation, focus, reachable);
393
394 return initSingleJumpSequence (firstLocation, secondLocation, focus, reachable);
395 }
396
397
398 else if (jumpDistance < 600)
399 {
400
401 if (enforceDoubleJump) {
402
403
404 return initDoubleJumpSequence(firstLocation, secondLocation, focus, reachable);
405 }
406
407
408 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
409 return true;
410 }
411
412
413 else if ((jumpDistance < 700) && (velocity > 300))
414 {
415 if (!enforceDoubleJump) {
416
417
418 if (navPointsLink != null && (navPointsLink.getFlags() & 8 ) != 0) {
419
420 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
421 return true;
422 }
423 }
424
425
426
427 return initDoubleJumpSequence (firstLocation, secondLocation, focus, reachable);
428 }
429
430
431 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
432 return true;
433 }
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450 private boolean initSingleJumpSequence (Location firstLocation, Location secondLocation, ILocated focus, boolean reachable)
451 {
452
453 if ((runnerSingleJump > 0) || (runnerDoubleJump > 0))
454 throw new RuntimeException ("jumping sequence aleady started");
455
456 log.finer("Runner.initSingleJumpSequence() !");
457
458
459 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
460
461 body.jump ();
462
463 runnerSingleJump = 1;
464 return true;
465 }
466
467
468
469
470
471
472
473
474
475 private boolean iterateSingleJumpSequence (Location firstLocation, Location secondLocation, ILocated focus, boolean reachable)
476 {
477
478 int distance = (int) memory.getLocation().getDistance2D(firstLocation);
479
480 int zVelocity = (int) memory.getVelocity().z;
481
482
483 switch (runnerSingleJump)
484 {
485
486 case 1:
487
488 if (zVelocity > 100)
489 {
490
491 if (log != null && log.isLoggable(Level.FINER)) log.finer("Runner.iterateSingleJumpSequence(): single-jump registered at " + distance + ", z-velo " + zVelocity);
492 runnerSingleJump++;
493 }
494
495 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
496 return true;
497
498
499 default:
500
501 if (zVelocity <= 0)
502 {
503
504 if (log != null && log.isLoggable(Level.FINER)) log.finer("Runner.iterateSingleJumpSequence(): single-jump completed at " + distance + ", z-velo " + zVelocity);
505 runnerSingleJump = 0;
506 }
507
508 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
509 return true;
510 }
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527 private boolean initDoubleJumpSequence (Location firstLocation, Location secondLocation, ILocated focus, boolean reachable)
528 {
529
530 if ((runnerSingleJump > 0) || (runnerDoubleJump > 0))
531 throw new RuntimeException ("jumping sequence aleady started");
532
533
534
535
536
537 boolean doubleJump = true;
538 double delay = 0.39;
539 double jumpZ = 680;
540
541
542 double distanceZ = firstLocation.getDistanceZ(memory.getLocation());
543 double distance2D = firstLocation.getDistance2D(memory.getLocation());
544 log.finer("Runner.initDoubleJumpSequence(): disntane2D = " + distance2D + ", distanceZ = " + distanceZ);
545 if (distanceZ > 0) {
546 log.finer("Runner.initDoubleJumpSequence(): JUMPING UP! Adjusting parameters of the jump...");
547
548 double jumpZ_up = 680 * distanceZ / 70;
549 boolean doubleJump_up = jumpZ_up > 340;
550
551 double jumpZ_forward = 680;
552 boolean doubleJump_forward = true;
553 if (distance2D < 250) {
554
555 doubleJump_forward = false;
556 jumpZ_forward = 340 * distance2D / 250;
557 } else
558 if (distance2D < 350) {
559
560 jumpZ_forward = 340 + 340 * (distance2D - 250) / 100;
561 }
562
563 if (jumpZ_up > jumpZ_forward) {
564 jumpZ = jumpZ_up;
565 doubleJump = doubleJump_up;
566 log.finer("Runner.initDoubleJumpSequence(): jumping up more than jumping forward, jumpZ_up = " + jumpZ_up + " > " + jumpZ_forward + " = jumpZ_forward");
567 } else {
568 jumpZ = jumpZ_forward;
569 doubleJump = doubleJump_forward;
570 log.finer("Runner.initDoubleJumpSequence(): jumping forward more than jumping up, jumpZ_up = " + jumpZ_up + " < " + jumpZ_forward + " = jumpZ_forward");
571 }
572
573 } else {
574 log.finer("Runner.initDoubleJumpSequence(): FALLING DOWN! Adjusting parameters of the jump for falling...");
575
576
577
578 double distanceTravelledByFalling = 451/382 * Math.abs(distanceZ);
579
580 double remainingDistance2D = distance2D - distanceTravelledByFalling;
581
582
583
584
585
586
587 if (remainingDistance2D < 300) {
588 log.finer("Runner.initDoubleJumpSequence(): single jump suffice, distance2D = " + distance2D + ", estimated distance travelled by just falling = " + distanceTravelledByFalling + ", remaining distance 2D to jump = " + remainingDistance2D);
589 doubleJump = false;
590 jumpZ = 340 * remainingDistance2D / 300;
591 } else
592 if (remainingDistance2D < 450) {
593 log.finer("Runner.initDoubleJumpSequence(): smaller double jump is needed, distance2D = " + distance2D + ", estimated distance travelled by just falling = " + distanceTravelledByFalling + ", remaining distance 2D to jump = " + remainingDistance2D);
594 jumpZ = 340 + 340 * (remainingDistance2D - 220) * 150;
595 } else {
596 log.finer("Runner.initDoubleJumpSequence(): full double jump is needed, distance2D = " + distance2D + ", estimated distance travelled by just falling = " + distanceTravelledByFalling + ", remaining distance 2D to jump = " + remainingDistance2D);
597
598 }
599 }
600
601 log.finer("Runner.initDoubleJumpSequence(): " + (doubleJump ? "double jumping, double jump delay = " + delay : "single jumping") + ", jumpZ = " + jumpZ);
602
603
604
605
606 body.doubleJump(delay, jumpZ);
607
608 runnerDoubleJump = 1;
609 return true;
610 }
611
612
613
614
615
616
617
618
619
620 private boolean iterateDoubleJumpSequence (Location firstLocation, Location secondLocation, ILocated focus, boolean reachable)
621 {
622
623 int distance = (int) memory.getLocation().getDistance2D(firstLocation);
624
625 int zVelocity = (int) memory.getVelocity().z;
626
627
628 switch (runnerDoubleJump)
629 {
630
631 case 1:
632
633 if (zVelocity > 100)
634 {
635
636 if (log != null && log.isLoggable(Level.FINER)) log.finer("Runner.iterateDoubleJumpSequence(): double-jump registered at " + distance + ", z-velo " + zVelocity);
637 runnerDoubleJump++;
638 }
639
640 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
641 return true;
642
643
644 case 2:
645
646 if (zVelocity < 150)
647 {
648
649 if (log != null && log.isLoggable(Level.FINER)) log.finer("Runner.iterateDoubleJumpSequence(): double-jump boost at " + distance + ", z-velo " + zVelocity);
650 body.jump ();
651 runnerDoubleJump++;
652 return true;
653 }
654
655 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
656 return true;
657
658
659 default:
660
661 if (zVelocity <= 0)
662 {
663
664 runnerDoubleJump = 0;
665 }
666
667 bot.getAct().act(addFocus(new Move().setFirstLocation(firstLocation).setSecondLocation(secondLocation), focus));
668 return true;
669 }
670 }
671
672
673
674
675 protected UT2004Bot bot;
676
677 protected AgentInfo memory;
678
679 protected AdvancedLocomotion body;
680
681 protected Logger log;
682
683 protected Senses senses;
684
685
686
687
688
689
690
691
692 public LoqueRunner (UT2004Bot bot, AgentInfo agentInfo, AdvancedLocomotion locomotion, Logger log) {
693
694 NullCheck.check(bot, "bot");
695 this.bot = bot;
696 NullCheck.check(agentInfo, "agentInfo");
697 this.memory = agentInfo;
698 NullCheck.check(locomotion, "locomotion");
699 this.body = new AdvancedLocomotion(bot, log);
700 this.senses = new Senses(bot, memory, new Players(bot), log);
701 this.log = log;
702 }
703
704 }