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.pogamut.ut2004.utils.LinkFlag;
20 import cz.cuni.amis.pogamut.ut2004.utils.UnrealUtils;
21 import cz.cuni.amis.utils.NullCheck;
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class KefikRunner implements IUT2004PathRunner {
76
77
78
79
80
81
82 private int runnerStep = 0;
83
84
85
86
87 private int jumpStep = 0;
88
89
90
91
92 private int collisionNum = 0;
93
94
95
96
97 private Location collisionSpot = null;
98
99
100
101
102
103
104 private double distance;
105
106
107
108
109 private double distance2D;
110
111
112
113
114 private double distanceZ;
115
116
117
118
119 private double velocity;
120
121
122
123
124 private double velocityZ;
125
126
127
128
129 private boolean jumpRequired;
130
131
132
133
134 private double fallDistance;
135
136
137
138
139
140
141 private Location runningFrom;
142
143
144
145
146 private Location firstLocation;
147
148
149
150
151 private Location secondLocation;
152
153
154
155
156 private ILocated focus;
157
158
159
160
161 private NavPointNeighbourLink link;
162
163
164
165
166 private boolean reachable;
167
168
169
170
171
172
173 public NavPointNeighbourLink getLink() {
174 return link;
175 }
176
177
178
179
180
181
182 public void reset()
183 {
184
185 runnerStep = 0;
186 jumpStep = 0;
187 collisionNum = 0;
188 collisionSpot = null;
189 distance = 0;
190 distance2D = 0;
191 distanceZ = 0;
192 velocity = 0;
193 velocityZ = 0;
194 jumpRequired = false;
195 }
196
197
198
199 private void debug(String message) {
200 if (log.isLoggable(Level.FINER)) log.finer("Runner: " + message);
201 }
202
203
204
205
206
207
208 private double getFallDistance(double distanceZ) {
209 distanceZ = Math.abs(distanceZ);
210 if (distanceZ == 60) return 160;
211 if (distanceZ < 60) return 2.66667*distanceZ;
212 return 1.3714 * distanceZ + 35.527;
213 }
214
215
216
217
218
219
220
221
222
223
224 private double getMaxJumpDistance(boolean doubleJump, double jumpDelay, double jumpForce, double distanceZ, double velocity) {
225 if (doubleJump) {
226 jumpForce = Math.min(UnrealUtils.FULL_DOUBLEJUMP_FORCE, jumpForce);
227 } else {
228 jumpForce = Math.min(UnrealUtils.FULL_JUMP_FORCE, jumpForce);
229 }
230 jumpDelay = Math.min(0.75, jumpDelay);
231
232 if (distanceZ >= -5) {
233
234 if (doubleJump) {
235 return velocity * jumpDelay + (jumpForce / UnrealUtils.FULL_DOUBLEJUMP_FORCE) * 400 * (1 + jumpDelay);
236 } else {
237 return velocity * jumpForce;
238 }
239 } else {
240
241 return getFallDistance(distanceZ) + getMaxJumpDistance(doubleJump, jumpDelay, jumpForce, 0, velocity);
242 }
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256 private double getJumpUpDistance(boolean doubleJump, double jumpDelay, double jumpForce, double distanceZ, double velocity) {
257 double jumpForceHeight;
258
259 double result;
260
261 if (doubleJump) {
262
263
264 jumpDelay = Math.min(0.75, jumpDelay);
265 jumpForce = Math.min(UnrealUtils.FULL_DOUBLEJUMP_FORCE, jumpForce);
266
267
268 jumpForceHeight = (jumpForce / UnrealUtils.FULL_DOUBLEJUMP_FORCE) * 125;
269
270
271 double totalTimeOfTheJump = (jumpForce / UnrealUtils.FULL_DOUBLEJUMP_FORCE) + jumpDelay;
272
273 if (jumpForceHeight > distanceZ) {
274
275 result =
276
277 velocity * jumpDelay
278
279 + UnrealUtils.MAX_VELOCITY * ((totalTimeOfTheJump-jumpDelay)/2)
280
281 + UnrealUtils.MAX_VELOCITY * (((totalTimeOfTheJump-jumpDelay)/2) * (1-distanceZ/jumpForceHeight));
282 } else {
283
284 result =
285
286 velocity * jumpDelay
287
288 + ((totalTimeOfTheJump-jumpDelay)/2) * UnrealUtils.MAX_VELOCITY;
289 }
290
291 } else {
292
293
294 jumpForce = Math.min(UnrealUtils.FULL_JUMP_FORCE, jumpForce);
295
296
297 jumpForceHeight = (jumpForce / UnrealUtils.FULL_JUMP_FORCE) * 55;
298
299
300 double totalTimeOfTheJump = jumpForce / UnrealUtils.FULL_JUMP_FORCE;
301
302 if (jumpForceHeight > distanceZ) {
303
304 result =
305
306 velocity * (totalTimeOfTheJump/2)
307
308 + velocity * ((totalTimeOfTheJump/2) * (1 - (distanceZ / jumpForceHeight)));
309 } else {
310
311 result = velocity * (totalTimeOfTheJump/2);
312 }
313 }
314
315 return result;
316 }
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342 @Override
343 public boolean runToLocation(Location runningFrom, Location firstLocation, Location secondLocation, ILocated focus, NavPointNeighbourLink navPointsLink, boolean reachable)
344 {
345
346 runnerStep++;
347
348
349 this.runningFrom = runningFrom;
350 this.firstLocation = firstLocation;
351 this.secondLocation = secondLocation;
352 this.focus = focus;
353 this.link = navPointsLink;
354 this.reachable = reachable;
355
356
357
358 distance = memory.getLocation().getDistance(firstLocation);
359 distance2D = memory.getLocation().getDistance2D(firstLocation);
360 distanceZ = firstLocation.getDistanceZ(memory.getLocation());
361 if (distanceZ >= 0) fallDistance = 0;
362 else fallDistance = getFallDistance(distanceZ);
363 velocity = memory.getVelocity().size();
364 velocityZ = memory.getVelocity().z;
365 jumpRequired =
366 !reachable ||
367 (link != null
368 && (((link.getFlags() & LinkFlag.JUMP.get()) != 0)
369 || (link.isForceDoubleJump())
370 || (link.getNeededJump() != null)
371 )
372 )
373 ;
374
375
376
377 if (log != null && log.isLoggable(Level.FINER)) {
378 debug("KefikRunner!");
379 debug("running to = " + firstLocation + " and than to " + secondLocation + " and focusing to " + focus);
380 debug("bot position = " + memory.getLocation());
381 debug("distance = " + distance);
382 debug("distance2D = " + distance2D);
383 debug("distanceZ = " + distanceZ);
384 debug("fallDistance = " + fallDistance);
385 debug("velocity = " + velocity);
386 debug("velocityZ = " + velocityZ);
387 debug("jumpRequired = " + jumpRequired
388 + (!reachable ? " NOT_REACHABLE" : "")
389 + (link == null ?
390 ""
391 : (
392 (link.getFlags() & LinkFlag.JUMP.get()) != 0 ? " JUMP_FLAG" : "") + (link.isForceDoubleJump() ? " DOUBLE_JUMP_FORCED" : "") + (link.getNeededJump() != null ? " AT[" + link.getNeededJump() + "]" : ""
393 )
394 )
395 );
396 debug("reachable = " + reachable);
397 if (link != null) {
398 debug("link = " + link);
399 } else {
400 debug("LINK NOT PRESENT");
401 }
402 debug("collisionNum = " + collisionNum);
403 debug("collisionSpot = " + collisionSpot);
404 debug("jumpStep = " + jumpStep);
405 debug("runnerStep = " + runnerStep);
406 }
407
408
409
410 if (runnerStep <= 1) {
411 debug("FIRST STEP - start running towards new location");
412 move(firstLocation, secondLocation, focus);
413 }
414
415
416 if (jumpStep > 0)
417 {
418 debug("we're already jumping");
419 return iterateJumpSequence();
420 }
421
422
423 if (senses.isCollidingOnce())
424 {
425 debug("sensing collision");
426
427 return resolveCollision();
428 } else {
429 if (collisionSpot != null || collisionNum != 0) {
430 debug("no collision, clearing collision data");
431 collisionNum = 0;
432 collisionSpot = null;
433 }
434 }
435
436 if (velocity < 5 && runnerStep > 1) {
437 debug("velocity is zero and we're in the middle of running");
438 if (link != null && (link.getFromNavPoint().isLiftCenter() || link.getFromNavPoint().isLiftExit())) {
439 if (link.getFromNavPoint().isLiftCenter()) {
440 debug("we're standing on the lift center, ok");
441 } else {
442 debug("we're standing on the lift exit, ok");
443 }
444 } else {
445 debug("and we're not standing on the lift center");
446 return initJump(true);
447 }
448 }
449
450
451 if (jumpRequired) {
452 debug("jump is required");
453 return resolveJump();
454 }
455
456
457 debug("keeping running to the target");
458 move(firstLocation, secondLocation, focus);
459
460 return true;
461 }
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477 private boolean resolveJump()
478 {
479 debug("resolveJump(): called");
480
481
482
483
484 int jumpDistance2D = ((int)distance2D) % 1000;
485
486 debug("resolveJump(): jumpDistance2D = " + jumpDistance2D);
487
488
489 boolean jumpIndicated = false;
490 boolean mustJumpIfIndicated = false;
491
492 boolean goingToJump = false;
493
494
495
496 if (link != null &&
497 ( ((link.getFlags() & LinkFlag.JUMP.get()) != 0)
498 || (link.isForceDoubleJump())
499 || (link.getNeededJump() != null)
500 )) {
501 debug("resolveJump(): deliberation - jumping condition present");
502 jumpIndicated = true;
503 }
504
505 if (jumpDistance2D < 250) {
506 debug("resolveJump(): we've missed all jumping opportunities (jumpDistance2D < 250)");
507 if (runnerStep > 1) {
508 debug("resolveJump(): and runnerStep > 1, if indicated we will be forced to jump right now");
509 mustJumpIfIndicated = true;
510 } else {
511 debug("resolveJump(): but runnerStep <= 1, can't force jump yet");
512 }
513 }
514
515 debug("resolveJump(): jumpIndicated = " + jumpIndicated);
516 debug("resolveJump(): mustJumpIfIndicated = " + mustJumpIfIndicated);
517
518 if (jumpIndicated && mustJumpIfIndicated) {
519 if (distanceZ > 0) {
520 debug("resolveJump(): we MUST jump!");
521 return prepareJump(true);
522 } else {
523 debug("resolveJump(): we MUST fall down with a jump!");
524 return prepareJump(true);
525 }
526 } else
527 if (jumpIndicated) {
528 debug("resolveJump(): we should jump");
529 return prepareJump(false);
530 } else {
531 debug("resolveJump(): we do not need to jump, waiting to reach the right spot to jump from");
532
533
534 move(firstLocation, secondLocation, focus);
535 return true;
536 }
537 }
538
539
540
541
542
543
544
545
546
547
548
549
550
551 private boolean prepareJump(boolean jumpForced) {
552 debug("prepareJump(): called");
553
554 Location direction = Location.sub(firstLocation, memory.getLocation());
555 direction.z = 0;
556 direction = direction.getNormalized();
557 Location velocityDir = new Location(memory.getVelocity().asVector3d());
558 velocityDir.z = 0;
559 velocityDir = velocityDir.getNormalized();
560 Double jumpAngleDeviation = Math.acos(direction.dot(velocityDir));
561
562 boolean angleSuitable = !jumpAngleDeviation.isNaN() && jumpAngleDeviation < (Math.PI / 9);
563
564 debug("prepareJump(): jumpAngleDeviation = " + jumpAngleDeviation);
565 debug("prepareJump(): angleSuitable = " + angleSuitable);
566
567 if (jumpForced) {
568 debug("prepareJump(): jump is forced, bypassing jump checks!");
569 } else {
570 debug("prepareJump(): jump is not forced, checking jump conditions");
571
572
573 if (velocity < 200 && distance2D > getMaxJumpDistance(true, UnrealUtils.FULL_DOUBLEJUMP_DELAY, UnrealUtils.FULL_DOUBLEJUMP_FORCE, distanceZ, velocity)) {
574 debug("prepareJump(): velocity is too low for jump (velocity < 200) and target is too far away to jump there with double jump");
575 debug("prepareJump(): proceeding with the straight movement to gain speed");
576 move(firstLocation, secondLocation, focus);
577 return true;
578 }
579
580 if (!angleSuitable) {
581 debug("prepareJump(): angle is not suitable for jumping (angle > 20 degrees)");
582 debug("prepareJump(): proceeding with the straight movement to gain speed");
583 move(firstLocation, secondLocation, focus);
584 return true;
585 }
586
587 debug("prepareJump(): velocity & angle is OK!");
588 }
589
590 if (distanceZ >= 0) {
591 debug("prepareJump(): JUMP (distanceZ >= 0)");
592 return initJump(jumpForced);
593 } else {
594 debug("prepareFall(): FALL (distanceZ < 0)");
595 return initFall(jumpForced);
596 }
597 }
598
599
600
601 private double adjustJumpForce(double distanceSafeZone, boolean doubleJump, double jumpForce, double jumpDelay) {
602 double distanceJumped = getJumpUpDistance(doubleJump, jumpDelay, jumpForce, distanceZ, velocity);
603 debug("initJump(): adjusting jumpForce...");
604 while (distanceJumped-distanceSafeZone < distance2D &&
605 ( (doubleJump && jumpForce < UnrealUtils.FULL_DOUBLEJUMP_FORCE)
606 || (!doubleJump && jumpForce < UnrealUtils.FULL_JUMP_FORCE))
607 ) {
608 jumpForce += 10;
609 distanceJumped = getJumpUpDistance(doubleJump, jumpDelay, jumpForce, distanceZ, velocity);
610 }
611
612 if (doubleJump) {
613 jumpForce = Math.min(jumpForce, UnrealUtils.FULL_DOUBLEJUMP_FORCE);
614 } else {
615 jumpForce = Math.min(jumpForce, UnrealUtils.FULL_JUMP_FORCE);
616 }
617 debug("initJump(): jumpForce = " + jumpForce);
618 return jumpForce;
619 }
620
621
622
623
624
625
626
627
628
629
630 private boolean initJump(boolean jumpForced) {
631 debug("initJump(): called");
632
633 boolean shouldJump = true;
634
635 boolean doubleJump = true;
636 double jumpForce = UnrealUtils.FULL_DOUBLEJUMP_FORCE;
637 double jumpDelay = UnrealUtils.FULL_DOUBLEJUMP_DELAY;
638
639 if (distanceZ > 130) {
640 debug("initJump(): jump could not be made (distanceZ = " + distanceZ + " > 130)");
641 if (jumpForced) {
642 debug("initJump(): but jump is being forced!");
643 } else {
644 debug("initJump(): jump is not forced ... we will wait till the bot reach the right jumping spot");
645 move(firstLocation, secondLocation, focus);
646 jumpStep = 0;
647 return true;
648 }
649 }
650
651 if (distanceZ < 55 && distance2D < velocity * 0.85) {
652 debug("initJump(): single jump suffices (distanceZ < 55 && distance2D = " + distance2D + " < " + (velocity*0.85) +" = velocity * 0.85))");
653 doubleJump = false;
654 jumpForce = UnrealUtils.FULL_JUMP_FORCE;
655 }
656
657 double jumpUp_force = 0;
658 if (doubleJump) {
659 jumpUp_force = UnrealUtils.FULL_DOUBLEJUMP_FORCE * ((distanceZ+5) / 125);
660 jumpUp_force = Math.min(jumpUp_force, UnrealUtils.FULL_DOUBLEJUMP_FORCE);
661 } else {
662 jumpUp_force = UnrealUtils.FULL_JUMP_FORCE * ((distanceZ+5) / 60);
663
664 jumpUp_force = Math.min(jumpUp_force, UnrealUtils.FULL_JUMP_FORCE);
665 }
666 debug("initJump(): minimum force to jump to height " + distanceZ + " with " + (doubleJump ? "double" : "single") + " is " + jumpUp_force);
667 double distanceSafeZone = 0;
668 debug("initJump(): adjusting force to match jumping distance = " + distance2D + " = distance2D (safe zone = " + distanceSafeZone + ")");
669 jumpForce = adjustJumpForce(distanceSafeZone, doubleJump, jumpUp_force, jumpDelay);
670 double distanceJumped = getJumpUpDistance(doubleJump, jumpDelay, jumpForce, distanceZ, velocity);
671 if (distanceJumped-distanceSafeZone < distance2D) {
672 debug("initJump(): too short! (distanceJumped-" + distanceSafeZone + " = " + (distanceJumped-distanceSafeZone) + " < " + distance2D + " = distance2D)");
673 if (!doubleJump) {
674 debug("initJump(): trying double jump");
675 doubleJump = true;
676 jumpUp_force = UnrealUtils.FULL_DOUBLEJUMP_FORCE * ((distanceZ+5) / 125);
677 jumpUp_force = Math.min(jumpUp_force, UnrealUtils.FULL_DOUBLEJUMP_FORCE);
678 debug("initJump(): minimum force to jump to height " + distanceZ + " with double jump is " + jumpUp_force);
679 debug("initJump(): adjusting force to match jumping distance = " + distance2D + " = distance2D (safe zone = " + distanceSafeZone + ")");
680 jumpForce = adjustJumpForce(distanceSafeZone, doubleJump, jumpUp_force, jumpDelay);
681 distanceJumped = getMaxJumpDistance(doubleJump, jumpDelay, jumpForce, distanceZ, velocity);
682 if (distanceJumped-distanceSafeZone < distance2D) {
683 debug("initJump(): still too short! (distanceJumped-" + distanceSafeZone + " = " + (distanceJumped-distanceSafeZone) + " < " + distance2D + " = distance2D)");
684 shouldJump = false;
685 } else {
686 debug("initJump(): distance ok (distanceJumped-" + distanceSafeZone + " = " + (distanceJumped-distanceSafeZone) + " >= " + distance2D + " = distance2D)");
687 shouldJump = true;
688 }
689 } else {
690 shouldJump = false;
691 }
692 } else {
693 debug("initJump(): distance ok (distanceJumped-" + distanceSafeZone + " = " + (distanceJumped-distanceSafeZone) + " >= " + distance2D + " = distance2D)");
694 shouldJump = true;
695 }
696
697 if (shouldJump || jumpForced) {
698 if (jumpForced && !shouldJump) {
699 debug("initJump(): we should not be jumping, but jump is FORCED!");
700 }
701 jumpStep = 1;
702 return jump(true, jumpDelay, jumpForce);
703 } else {
704 debug("initJump(): jump is not forced ... we will wait till the bot reach the right jumping spot");
705 move(firstLocation, secondLocation, focus);
706 jumpStep = 0;
707 return true;
708 }
709 }
710
711
712
713
714
715 private boolean initFall(boolean jumpForced) {
716 debug("initFall(): called");
717
718 jumpStep = 1;
719
720 log.finer("Runner.initDoubleJumpSequence(): FALLING DOWN! Adjusting parameters of the jump for falling...");
721
722
723
724 double remainingDistance2D = distance2D - fallDistance;
725
726 debug("initFall(): distance2D = " + distance2D);
727 debug("initFall(): falling will get us = " + fallDistance + " further");
728 debug("initFall(): remainingDistance2D = " + remainingDistance2D);
729
730
731 boolean doubleJump = true;
732 double jumpZ = 705;
733
734
735
736
737
738 if (remainingDistance2D < velocity) {
739 debug("initFall(): single jump suffices (remainingDistance2D < velocity)");
740 doubleJump = false;
741 jumpZ = 340 * remainingDistance2D / 300;
742 } else
743 if (remainingDistance2D < 450) {
744 log.finer("initFall(): smaller double jump is needed (remainingDistance2D < 450)");
745 doubleJump = true;
746 jumpZ = 340 + 365 * (remainingDistance2D - 220) * 150;
747 } else {
748 log.finer("Runner.initDoubleJumpSequence(): full double jump is needed (remainingDistance2D > 450)");
749 doubleJump = true;
750 jumpZ = 705;
751 }
752
753 return jump(doubleJump, 0.39, jumpZ);
754 }
755
756
757
758
759
760
761 private boolean jump(boolean doubleJump, double delay, double force) {
762 if (doubleJump) {
763 debug("DOUBLE JUMPING (delay = " + delay + ", force = " + force + ")");
764 } else {
765 debug("JUMPING (delay = " + delay + ", force = " + force + ")");
766 }
767 body.jump(doubleJump, delay, force);
768
769 return true;
770 }
771
772 private void move(ILocated firstLocation, ILocated secondLocation, ILocated focus) {
773 Move move = new Move();
774 if (firstLocation != null) {
775 move.setFirstLocation(firstLocation.getLocation());
776 }
777 if (secondLocation != null) {
778 move.setSecondLocation(secondLocation.getLocation());
779 }
780
781 if (focus != null) {
782 if (focus instanceof Player) {
783 move.setFocusTarget((UnrealId)((IWorldObject)focus).getId());
784 } else {
785 move.setFocusLocation(focus.getLocation());
786 }
787 }
788
789 log.finer("MOVING: " + move);
790 bot.getAct().act(move);
791 }
792
793
794
795
796
797
798
799
800
801
802
803 private boolean resolveCollision()
804 {
805
806 if (
807
808 (collisionSpot == null)
809
810 || (memory.getLocation().getDistance2D(collisionSpot) > 120)
811 ) {
812
813 if (log != null && log.isLoggable(Level.FINER)) log.finer("Runner.resolveCollision(): collision");
814 collisionSpot = memory.getLocation();
815 collisionNum = 1;
816
817 move(firstLocation, secondLocation, focus);
818 return true;
819 }
820
821
822 else {
823 return initJump(true);
824 }
825 }
826
827
828
829
830
831
832
833 private boolean iterateJumpSequence()
834 {
835 debug("iterateJumpSequence(): called");
836
837 switch (jumpStep) {
838
839 case 1:
840
841 if (velocityZ > 100)
842 {
843 debug("iterateJumpSequence(): jumping in progress (velocityZ > 100), increasing jumpStep");
844 jumpStep++;
845 }
846
847 debug("iterateJumpSequence(): issuing move command to the target (just to be sure)");
848 move(firstLocation, secondLocation, focus);
849 return true;
850
851
852 default:
853
854 if (velocityZ <= 0.01)
855 {
856 debug("iterateJumpSequence(): jump ascension has ended (velocityZ < 0.01)");
857 jumpStep = 0;
858 }
859 debug("iterateJumpSequence(): continuing movement to the target");
860 move(firstLocation, secondLocation, focus);
861 return true;
862 }
863 }
864
865
866
867
868 protected UT2004Bot bot;
869
870 protected AgentInfo memory;
871
872 protected AdvancedLocomotion body;
873
874 protected Logger log;
875
876 protected Senses senses;
877
878
879
880
881
882
883
884
885 public KefikRunner (UT2004Bot bot, AgentInfo agentInfo, AdvancedLocomotion locomotion, Logger log) {
886
887 NullCheck.check(bot, "bot");
888 this.bot = bot;
889 NullCheck.check(agentInfo, "agentInfo");
890 this.memory = agentInfo;
891 NullCheck.check(locomotion, "locomotion");
892 this.body = new AdvancedLocomotion(bot, log);
893 this.senses = new Senses(bot, memory, new Players(bot), log);
894 this.log = log;
895 }
896
897 }