1 package cz.cuni.amis.pogamut.ut2004.agent.module.sensor;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.logging.Level;
10 import java.util.logging.Logger;
11
12 import cz.cuni.amis.pogamut.base.agent.module.SensorModule;
13 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
14 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
15 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
16 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
17 import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
18 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
19 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
20 import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
21 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
22 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.BeginMessage;
23 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.FlagInfo;
24 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo;
25 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.InitedMessage;
26 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Mutator;
27 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
28 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.PlayerScore;
29 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Self;
30 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.TeamScore;
31 import cz.cuni.amis.pogamut.ut2004.communication.translator.shared.events.MutatorListObtained;
32 import cz.cuni.amis.utils.exception.PogamutException;
33
34
35
36
37
38
39
40
41
42
43
44 public class Game extends SensorModule<UT2004Bot>
45 {
46
47
48
49
50
51 public enum GameType
52 {
53
54 BotDeathMatch,
55
56 BotTeamGame,
57
58 BotCTFGame,
59
60 BotBombingRun,
61
62 BotDoubleDomination,
63
64 Unknown;
65
66
67
68
69
70
71
72 public static GameType getType(String type)
73 {
74 if (type.equalsIgnoreCase("BotDeathMatch")) return BotDeathMatch;
75 if (type.equalsIgnoreCase("BotTeamGame")) return BotTeamGame;
76 if (type.equalsIgnoreCase("BotCTFGame")) return BotCTFGame;
77 if (type.equalsIgnoreCase("BotBombingRun")) return BotBombingRun;
78 if (type.equalsIgnoreCase("BotDoubleDomination")) return BotDoubleDomination;
79 return Unknown;
80 }
81 }
82
83
84
85
86
87
88 public GameInfo getGameInfo() {
89 return lastGameInfo;
90 }
91
92
93
94
95
96
97 public GameType getGameType()
98 {
99
100 if (lastGameInfo == null) return null;
101 return GameType.getType(lastGameInfo.getGametype());
102 }
103
104
105
106
107
108
109
110
111 public String getMapName()
112 {
113
114 if (lastGameInfo == null) return null;
115 return lastGameInfo.getLevel();
116 }
117
118
119
120
121
122
123 public boolean isMapName(String name) {
124 if (lastGameInfo == null) return false;
125 if (name == null) return false;
126 return lastGameInfo.getLevel().toLowerCase().equals(name.toLowerCase());
127 }
128
129
130
131
132
133
134
135
136
137
138
139 public String getPrefixed(String objectId) {
140
141 if (getMapName() == null) {
142 throw new PogamutException("GameInfo was not received yet, can't prefix '" + objectId + "'.", this);
143 }
144 if (objectId.toLowerCase().startsWith(mapNameLowerChar + ".")) {
145
146 if (!objectId.startsWith(getMapName())) {
147
148 objectId = getMapName() + objectId.substring(mapNameLowerChar.length());
149 }
150
151 return objectId;
152 } else {
153
154 if (objectId.contains(".")) {
155
156 throw new PogamutException("id '" + objectId + "' is already prefixed with '" + objectId.substring(0, objectId.indexOf(".")) + "' which is different from current map name '" + getMapName() + "', map name validation fails!", this);
157 }
158
159 return getMapName() + "." + objectId;
160 }
161 }
162
163
164
165
166
167
168
169
170
171
172
173 public UnrealId getPrefixedId(String objectId) {
174
175 if (getMapName() == null) {
176 throw new PogamutException("GameInfo was not received yet, can't prefix '" + objectId + "'.", this);
177 }
178 if (objectId.toLowerCase().startsWith(mapNameLowerChar + ".")) {
179
180 if (!objectId.startsWith(getMapName())) {
181
182 objectId = getMapName() + objectId.substring(mapNameLowerChar.length());
183 }
184
185 return UnrealId.get(objectId);
186 } else {
187
188 if (objectId.contains(".")) {
189
190 throw new PogamutException("id '" + objectId + "' is already prefixed with '" + objectId.substring(0, objectId.indexOf(".")) + "' which is different from current map name '" + getMapName() + "', map name validation fails!", this);
191 }
192
193 return UnrealId.get(getMapName() + "." + objectId);
194 }
195 }
196
197
198
199
200
201
202
203
204
205
206 public double getTime()
207 {
208
209 if (lastBeginMessage == null) return 0;
210 return lastBeginMessage.getTime();
211 }
212
213
214
215
216
217
218
219
220
221
222
223
224 public Double getTimeLimit()
225 {
226
227 if (lastGameInfo == null) return null;
228 return lastGameInfo.getTimeLimit();
229 }
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 public Double getRemainingTime()
246 {
247
248 if (getTimeLimit() == null) return null;
249 return getTimeLimit() - getTime();
250 }
251
252
253
254
255
256
257
258
259
260
261
262 public Integer getFragLimit()
263 {
264
265 if (lastGameInfo == null) return null;
266 return lastGameInfo.getFragLimit();
267 }
268
269
270
271
272
273
274
275
276
277 public Integer getTeamScoreLimit()
278 {
279
280
281 if (lastGameInfo == null) return null;
282 return (int)lastGameInfo.getGoalTeamScore();
283 }
284
285
286
287
288
289
290
291
292
293
294 public FlagInfo getCTFFlag(int team) {
295 Collection<FlagInfo> flags = worldView.getAll(FlagInfo.class).values();
296 for (FlagInfo flag : flags) {
297 if (flag.getTeam() == team) {
298 return flag;
299 }
300 }
301 return null;
302 }
303
304
305
306
307
308
309
310 public Collection<FlagInfo> getCTFFlags() {
311 return worldView.getAll(FlagInfo.class).values();
312 }
313
314
315
316
317
318
319
320
321
322 public Collection<NavPoint> getDominationPoints() {
323 Collection<NavPoint> domPoints = new ArrayList();
324 Collection<NavPoint> navPoints = worldView.getAll(NavPoint.class).values();
325 for (NavPoint nav : navPoints) {
326 if (nav.isDomPoint()) {
327 domPoints.add(nav);
328 }
329 }
330 return domPoints;
331 }
332
333
334
335
336
337
338
339
340
341
342 public Map<Integer, TeamScore> getTeamScores() {
343 return Collections.unmodifiableMap(lastTeamScore);
344 }
345
346
347
348
349
350
351
352
353
354
355
356
357 public int getTeamScore(int team) {
358 TeamScore teamScore = lastTeamScore.get(team);
359 if (teamScore == null) {
360 return Integer.MIN_VALUE;
361 }
362
363 return teamScore.getScore();
364 }
365
366
367
368
369
370
371
372 public boolean isTeamScoreKnown(int team) {
373 return lastTeamScore.containsKey(team);
374 }
375
376
377
378
379
380
381
382
383 public Map<UnrealId, PlayerScore> getPlayerScores() {
384 return Collections.unmodifiableMap(lastPlayerScore);
385 }
386
387
388
389
390
391
392
393
394
395
396
397
398 public int getPlayerScore(UnrealId id) {
399 PlayerScore score = lastPlayerScore.get(id);
400 if (score != null) {
401 return score.getScore();
402 }
403 return Integer.MIN_VALUE;
404 }
405
406
407
408
409
410
411
412 public boolean isPlayerScoreKnown(UnrealId player) {
413 return lastPlayerScore.containsKey(player);
414 }
415
416
417
418
419
420
421
422
423
424
425
426
427 public int getPlayerDeaths(UnrealId id) {
428
429 PlayerScore score = lastPlayerScore.get(id);
430 if (score == null) {
431 return Integer.MIN_VALUE;
432 }
433 return score.getDeaths();
434 }
435
436
437
438
439
440
441
442 public boolean isPlayerDeathsKnown(UnrealId player) {
443 return lastPlayerScore.containsKey(player);
444 }
445
446
447
448
449
450
451
452
453
454
455
456 public Integer getMaxTeams()
457 {
458
459 if (lastGameInfo == null) return null;
460 return lastGameInfo.getMaxTeams();
461 }
462
463
464
465
466
467
468
469 public Integer getMaxTeamSize()
470 {
471
472 if (lastGameInfo == null) return null;
473 return lastGameInfo.getMaxTeamSize();
474 }
475
476
477
478
479
480
481
482
483
484
485
486
487 public Integer getStartHealth()
488 {
489
490 if (lastInitedMessage == null) return null;
491 return lastInitedMessage.getHealthStart();
492 }
493
494
495
496
497
498
499
500
501
502
503 public Integer getFullHealth()
504 {
505
506 if (lastInitedMessage == null) return null;
507 return lastInitedMessage.getHealthFull();
508 }
509
510
511
512
513
514
515
516
517
518
519
520 public Integer getMaxHealth()
521 {
522
523 if (lastInitedMessage == null) return null;
524 return lastInitedMessage.getHealthMax();
525 }
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540 public Integer getMaxArmor()
541 {
542
543 if (lastInitedMessage == null) return null;
544 return lastInitedMessage.getShieldStrengthMax();
545 }
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560 public int getMaxLowArmor()
561 {
562
563 return 50;
564 }
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579 public int getMaxHighArmor()
580 {
581
582 return 100;
583 }
584
585
586
587
588
589
590
591
592
593 public Integer getStartAdrenaline()
594 {
595
596
597 if (lastInitedMessage == null) return null;
598 return (int)lastInitedMessage.getAdrenalineStart();
599 }
600
601
602
603
604
605
606
607
608
609
610
611
612 public Integer getTargetAdrenaline()
613 {
614
615
616 if (lastInitedMessage == null) return null;
617 return (int)lastInitedMessage.getAdrenalineMax();
618 }
619
620
621
622
623
624
625 public Integer getMaxAdrenaline()
626 {
627
628
629 if (lastInitedMessage == null) return null;
630 return (int)lastInitedMessage.getAdrenalineMax();
631 }
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652 public Boolean getWeaponsStay()
653 {
654
655 if (lastGameInfo == null) return null;
656 return lastGameInfo.isWeaponStay();
657 }
658
659
660
661
662
663
664
665
666
667
668
669 public Integer getMaxMultiJump()
670 {
671
672 if (lastInitedMessage == null) return null;
673 return lastInitedMessage.getMaxMultiJump();
674 }
675
676
677
678
679
680
681
682
683 public List<Mutator> getMutators()
684 {
685 if (lastMutatorListObtained == null) return null;
686 return lastMutatorListObtained.getMutators();
687 }
688
689
690
691
692
693
694
695
696
697
698
699 public Boolean isPaused()
700 {
701
702 if (lastGameInfo == null) return null;
703 return lastGameInfo.isGamePaused();
704 }
705
706
707
708
709
710
711
712
713
714
715
716 public Boolean isBotsPaused()
717 {
718
719 if (lastGameInfo == null) return null;
720 return lastGameInfo.isBotsPaused();
721 }
722
723
724
725
726
727
728
729
730
731
732
733 public Map<Integer, FlagInfo> getAllCTFFlags()
734 {
735 return allCTFFlags;
736 }
737
738
739
740
741
742
743
744 public Collection<FlagInfo> getAllCTFFlagsCollection()
745 {
746 return allCTFFlags.values();
747 }
748
749
750
751
752
753
754 public FlagInfo getFlag(int team) {
755 return allCTFFlags.get(team);
756 }
757
758
759
760
761
762 public FlagInfo getMyFlag() {
763 if (self == null) return null;
764 return allCTFFlags.get(self.getTeam());
765 }
766
767
768
769
770
771 public FlagInfo getEnemyFlag() {
772 if (self == null) return null;
773 return getFlag(self.getTeam() == 0 ? 1 : 0);
774 }
775
776
777
778
779
780
781 public Location getFlagBase(int team) {
782 if (lastGameInfo == null) return null;
783 if (team == 0) return lastGameInfo.getRedBaseLocation();
784 else return lastGameInfo.getBlueBaseLocation();
785 }
786
787
788
789
790
791 public Location getMyFlagBase() {
792 if (self == null) return null;
793 return getFlagBase(self.getTeam());
794 }
795
796
797
798
799
800 public Location getEnemyFlagBase() {
801 if (self == null) return null;
802 return getFlagBase(self.getTeam() == 0 ? 1 : 0);
803 }
804
805
806
807
808 GameInfo lastGameInfo = null;
809
810
811 InitedMessage lastInitedMessage = null;
812
813
814 BeginMessage lastBeginMessage = null;
815
816
817 MutatorListObtained lastMutatorListObtained = null;
818
819
820 Map<Integer, FlagInfo> allCTFFlags = new HashMap();
821
822
823 Map<UnrealId, PlayerScore> lastPlayerScore = null;
824
825
826 Map<Integer, TeamScore> lastTeamScore = null;
827
828
829 Self self;
830
831
832
833
834
835
836 private class SelfListener implements IWorldObjectEventListener<Self, WorldObjectUpdatedEvent<Self>>
837 {
838 private IWorldView worldView;
839
840
841
842
843
844 public SelfListener(IWorldView worldView)
845 {
846 this.worldView = worldView;
847 worldView.addObjectListener(Self.class, WorldObjectUpdatedEvent.class, this);
848 }
849
850 @Override
851 public void notify(WorldObjectUpdatedEvent<Self> event) {
852 self = event.getObject();
853 }
854 }
855
856
857 private SelfListener selfListener;
858
859
860
861
862
863
864
865 private class GameInfoListener implements IWorldObjectEventListener<GameInfo, IWorldObjectEvent<GameInfo>>
866 {
867 @Override
868 public void notify(IWorldObjectEvent<GameInfo> event)
869 {
870 lastGameInfo = event.getObject();
871 mapNameLowerChar = lastGameInfo.getLevel().toLowerCase();
872 }
873
874
875
876
877
878 public GameInfoListener(IWorldView worldView)
879 {
880 worldView.addObjectListener(GameInfo.class, this);
881 }
882 }
883
884
885 GameInfoListener gameInfoListener;
886
887 String mapNameLowerChar = "";
888
889
890
891
892
893
894 private class InitedMessageListener implements IWorldObjectEventListener<InitedMessage, WorldObjectUpdatedEvent<InitedMessage>>
895 {
896 @Override
897 public void notify(WorldObjectUpdatedEvent<InitedMessage> event)
898 {
899 lastInitedMessage = event.getObject();
900 }
901
902
903
904
905
906 public InitedMessageListener(IWorldView worldView)
907 {
908 worldView.addObjectListener(InitedMessage.class, WorldObjectUpdatedEvent.class, this);
909 }
910 }
911
912
913 InitedMessageListener initedMessageListener;
914
915
916
917
918
919
920 private class BeginMessageListener implements IWorldEventListener<BeginMessage>
921 {
922 @Override
923 public void notify(BeginMessage event)
924 {
925 lastBeginMessage = event;
926 }
927
928
929
930
931
932 public BeginMessageListener(IWorldView worldView)
933 {
934 worldView.addEventListener(BeginMessage.class, this);
935 }
936 }
937
938
939 BeginMessageListener beginMessageListener;
940
941
942
943
944
945
946 private class MutatorListObtainedListener implements IWorldEventListener<MutatorListObtained>
947 {
948 @Override
949 public void notify(MutatorListObtained event)
950 {
951 lastMutatorListObtained = event;
952 }
953
954
955
956
957
958 public MutatorListObtainedListener(IWorldView worldView)
959 {
960 worldView.addEventListener(MutatorListObtained.class, this);
961 }
962 }
963
964
965 MutatorListObtainedListener mutatorListObtainedListener;
966
967
968
969
970
971
972 private class FlagInfoObjectListener implements IWorldObjectEventListener<FlagInfo,WorldObjectUpdatedEvent<FlagInfo>>
973 {
974
975
976
977
978
979 public void notify(WorldObjectUpdatedEvent<FlagInfo> event)
980 {
981 allCTFFlags.put(event.getObject().getTeam(), event.getObject());
982 }
983
984
985
986
987
988 public FlagInfoObjectListener(IWorldView worldView)
989 {
990 worldView.addObjectListener(FlagInfo.class, WorldObjectUpdatedEvent.class, this);
991 }
992 }
993
994
995 FlagInfoObjectListener flagInfoObjectListener;
996
997
998
999
1000
1001
1002 private class PlayerScoreListener implements IWorldEventListener<PlayerScore>
1003 {
1004 @Override
1005 public void notify(PlayerScore event)
1006 {
1007 synchronized(lastPlayerScore) {
1008 lastPlayerScore.put(event.getId(), event);
1009 }
1010 }
1011
1012
1013
1014
1015
1016 public PlayerScoreListener(IWorldView worldView)
1017 {
1018 worldView.addEventListener(PlayerScore.class, this);
1019 }
1020 }
1021
1022
1023 private PlayerScoreListener playerScoreListener;
1024
1025
1026
1027
1028
1029
1030 private class TeamScoreListener implements IWorldObjectEventListener<TeamScore, WorldObjectUpdatedEvent<TeamScore>>
1031 {
1032
1033
1034
1035
1036 public TeamScoreListener(IWorldView worldView)
1037 {
1038 worldView.addObjectListener(TeamScore.class, WorldObjectUpdatedEvent.class, this);
1039 }
1040
1041 @Override
1042 public void notify(WorldObjectUpdatedEvent<TeamScore> event) {
1043 synchronized(lastTeamScore) {
1044 lastTeamScore.put(event.getObject().getTeam(), event.getObject());
1045 }
1046 }
1047 }
1048
1049
1050 private TeamScoreListener teamScoreListener;
1051
1052
1053
1054
1055
1056
1057
1058 public Game(UT2004Bot bot) {
1059 this(bot, null);
1060 }
1061
1062
1063
1064
1065
1066
1067 public Game(UT2004Bot bot, Logger log)
1068 {
1069 super(bot, log);
1070
1071
1072 gameInfoListener = new GameInfoListener(worldView);
1073 beginMessageListener = new BeginMessageListener(worldView);
1074 initedMessageListener = new InitedMessageListener(worldView);
1075 mutatorListObtainedListener = new MutatorListObtainedListener(worldView);
1076 flagInfoObjectListener = new FlagInfoObjectListener(worldView);
1077 playerScoreListener = new PlayerScoreListener(worldView);
1078 teamScoreListener = new TeamScoreListener(worldView);
1079 lastPlayerScore = new HashMap<UnrealId, PlayerScore>();
1080 lastTeamScore = new HashMap<Integer, TeamScore>();
1081 selfListener = new SelfListener(worldView);
1082 mapNameLowerChar = "";
1083
1084 cleanUp();
1085 }
1086
1087 @Override
1088 protected void cleanUp() {
1089 super.cleanUp();
1090 lastGameInfo = null;
1091 lastInitedMessage = null;
1092 lastBeginMessage = null;
1093 lastMutatorListObtained = null;
1094 synchronized(lastPlayerScore) {
1095 lastPlayerScore.clear();
1096 }
1097 synchronized(lastTeamScore) {
1098 lastTeamScore.clear();
1099 }
1100 }
1101
1102 }