1 package cz.cuni.amis.pogamut.defcon.agent.module.sensor;
2
3 import java.security.InvalidParameterException;
4 import java.util.ArrayList;
5 import java.util.Collections;
6 import java.util.Hashtable;
7 import java.util.Iterator;
8 import java.util.LinkedList;
9 import java.util.List;
10 import java.util.SortedMap;
11 import java.util.TreeMap;
12 import java.util.concurrent.BlockingQueue;
13 import java.util.concurrent.LinkedBlockingQueue;
14
15 import javabot.JBot;
16 import javabot.JBotMethodsRepository;
17 import javabot.PogamutJBotSupport;
18 import javabot.events.IDefConBasicEvent;
19 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
20 import cz.cuni.amis.pogamut.defcon.base3d.worldview.object.DefConLocation;
21 import cz.cuni.amis.pogamut.defcon.communication.messages.infos.DebugIsReplayingGameChanged;
22 import cz.cuni.amis.pogamut.defcon.communication.messages.infos.DefConChanged;
23 import cz.cuni.amis.pogamut.defcon.communication.messages.infos.GameRunningChanged;
24 import cz.cuni.amis.pogamut.defcon.communication.messages.infos.GameSpeedChanged;
25 import cz.cuni.amis.pogamut.defcon.communication.messages.infos.VictoryTimerActiveChanged;
26 import cz.cuni.amis.pogamut.defcon.consts.GameSpeed;
27 import cz.cuni.amis.pogamut.defcon.consts.UnitType;
28 import cz.cuni.amis.pogamut.defcon.consts.state.IState;
29 import cz.cuni.amis.pogamut.defcon.utils.AdvancedFlagListener;
30 import cz.cuni.amis.pogamut.defcon.utils.SyncMethodExecContainer;
31 import cz.cuni.amis.pogamut.defcon.utils.SimpleFlag;
32
33
34
35
36
37
38
39
40 public class GameInfo {
41
42 private final static int MAX_FLEET_SIZE = 6;
43
44
45
46
47 private final int[] territoryOwners = new int[JBot.NumTerritories];
48
49
50
51 private final double[] fleetDiameters = new double[MAX_FLEET_SIZE];
52
53
54
55
56 private final Location[][] fleetMemberOffsets = new Location[MAX_FLEET_SIZE][];
57
58
59
60
61 private Float gameTime = 0f;
62
63
64
65
66 private Integer gameTick = 0;
67
68
69
70
71 private Float victoryTimer = 0f;
72
73
74
75
76 private int ownTeamId;
77
78
79
80
81 private final SortedMap<Integer, List<Integer>> enemiesCityIds = new TreeMap<Integer, List<Integer>>();
82
83
84
85
86 private final List<Integer> ownCityIds = new ArrayList<Integer>();
87
88
89
90
91 private final SortedMap<Integer, Location> cityLocations = new TreeMap<Integer, Location>();
92
93
94
95
96 private int[] enemyIds;
97
98
99
100
101 private final SimpleFlag<Integer> defcon = new SimpleFlag<Integer>(5);
102
103
104
105 private final AdvancedFlagListener<Integer> defconListener = new AdvancedFlagListener<Integer>() {
106
107 @Override
108 public void flagChanged(Integer oldValue, Integer changedValue) {
109 events.add(new DefConChanged(oldValue, changedValue, getGameTime()));
110 }
111
112 };
113
114
115
116
117 private final SimpleFlag<GameSpeed> gameSpeed = new SimpleFlag<GameSpeed>(
118 GameSpeed.PAUSED);
119
120
121
122 private final AdvancedFlagListener<GameSpeed> gameSpeedListener = new AdvancedFlagListener<GameSpeed>() {
123
124 @Override
125 public void flagChanged(GameSpeed oldValue, GameSpeed changedValue) {
126 events.add(new GameSpeedChanged(oldValue, changedValue,
127 getGameTime()));
128 }
129
130 };
131
132
133
134
135 private final SimpleFlag<Boolean> victoryTimerActive = new SimpleFlag<Boolean>(
136 false);
137
138
139
140 private AdvancedFlagListener<Boolean> victoryTimerActiveListener = new AdvancedFlagListener<Boolean>() {
141
142 @Override
143 public void flagChanged(Boolean oldValue, Boolean changedValue) {
144 events.add(new VictoryTimerActiveChanged(changedValue,
145 getGameTime()));
146 }
147
148 };
149
150
151
152
153 private final SimpleFlag<Boolean> debugIsReplayingGame = new SimpleFlag<Boolean>(false);
154
155
156
157 private final AdvancedFlagListener<Boolean> debugIsReplayingGameListener = new AdvancedFlagListener<Boolean>() {
158
159 @Override
160 public void flagChanged(Boolean oldValue, Boolean changedValue) {
161 events.add(new DebugIsReplayingGameChanged(changedValue,
162 getGameTime()));
163 }
164
165 };
166
167
168
169
170 private final SimpleFlag<Boolean> gameRunning = new SimpleFlag<Boolean>(
171 false);
172
173
174
175 private AdvancedFlagListener<Boolean> gameRunningListener = new AdvancedFlagListener<Boolean>() {
176
177 @Override
178 public void flagChanged(Boolean oldValue, Boolean changedValue) {
179 if (changedValue) {
180 cacheOwnTeamId();
181 populateTerritoryOwners();
182 populateCityLocations();
183 }
184 events.add(new GameRunningChanged(changedValue, getGameTime()));
185 }
186 };
187
188
189
190
191 private final BlockingQueue<IDefConBasicEvent> events = new LinkedBlockingQueue<IDefConBasicEvent>();
192
193
194
195
196 public GameInfo() {
197 gameTime = JBot.GetGameTime();
198 gameTick = JBot.GetGameTick();
199 victoryTimer = 0f;
200 gameRunning.addStrongListener(gameRunningListener);
201 defcon.addStrongListener(defconListener);
202 gameSpeed.addStrongListener(gameSpeedListener);
203 victoryTimerActive.addStrongListener(victoryTimerActiveListener);
204 debugIsReplayingGame.addStrongListener(debugIsReplayingGameListener);
205 populateFleetMemberOffsets();
206 populateFleetDiameters();
207 }
208
209
210
211
212 private void populateCityLocations() {
213
214
215 int[] cities = getCityIds();
216
217 for (int cityId : cities) {
218
219 Location location = getObjectLocation(cityId);
220
221 int territoryId = getTerritoryId(location);
222
223 int teamId = territoryOwners[territoryId];
224
225 cityLocations.put(cityId, location);
226
227 if (teamId == -1)
228 continue;
229
230 if (teamId == getOwnTeamId()) {
231 ownCityIds.add(cityId);
232 } else {
233 enemiesCityIds.get(teamId).add(cityId);
234 }
235 }
236 }
237
238
239
240
241 private final void populateTerritoryOwners() {
242
243 for (int i = 0; i < territoryOwners.length; ++i) {
244 territoryOwners[i] = -1;
245 }
246
247 ArrayList<Integer> enemies = new ArrayList<Integer>();
248 int own_id = getOwnTeamId();
249
250 for (int teamId : JBot.GetTeamIds()) {
251
252 if (teamId != own_id) {
253 enemies.add(teamId);
254 enemiesCityIds.put(teamId, new ArrayList<Integer>());
255 }
256
257 for (int territoryId : getTeamTerritories(teamId)) {
258 territoryOwners[territoryId] = teamId;
259 }
260 }
261
262 enemyIds = new int[enemies.size()];
263
264 int i = 0;
265 for (int enemyId : enemies) {
266 enemyIds[i++] = enemyId;
267 }
268 }
269
270
271
272
273 private final void populateFleetMemberOffsets() {
274 for (int i = 0; i < MAX_FLEET_SIZE; ++i) {
275 fleetMemberOffsets[i] = new Location[i + 1];
276 for (int j = 0; j <= i; ++j) {
277 fleetMemberOffsets[i][j] = getFleetMemberOffsetWorker(i + 1, j);
278 }
279 }
280 }
281
282
283
284
285 private final void populateFleetDiameters() {
286 for (int i = 0; i < MAX_FLEET_SIZE; ++i) {
287 fleetDiameters[i] = getFleetDiameterWorker(i + 1);
288 }
289 }
290
291
292
293
294 private void cacheOwnTeamId() {
295 ownTeamId = JBot.GetOwnTeamId();
296 }
297
298
299
300
301
302
303
304 public LinkedList<IDefConBasicEvent> getEvents() {
305 gameTime = JBot.GetGameTime();
306 gameTick = JBot.GetGameTick();
307
308 victoryTimerActive.setFlag(JBot.IsVictoryTimerActive());
309
310 if (victoryTimerActive.getFlag()) {
311 victoryTimer = JBot.GetVictoryTimer();
312 }
313
314 gameRunning.setFlag(true);
315 defcon.setFlag(JBot.GetDefcon());
316 gameSpeed.setFlag(GameSpeed.getEnum(JBot.GetGameSpeed()));
317 victoryTimerActive.setFlag(JBot.IsVictoryTimerActive());
318 debugIsReplayingGame.setFlag(JBot.DebugIsReplayingGame());
319
320 LinkedList<IDefConBasicEvent> output = new LinkedList<IDefConBasicEvent>();
321 events.drainTo(output);
322 return output;
323 }
324
325 private final LinkedList<Location> aiPlacementPoints = new LinkedList<Location>();
326 private final LinkedList<Location> targetCoords = new LinkedList<Location>();
327
328
329
330
331
332 private void populatePoints()
333 {
334
335
336
337 checkedAddToAIPlacementPoints(new Location(-177.890625f,34.736842f));
338 checkedAddToAIPlacementPoints(new Location(-177.187500f,46.666667f));
339 checkedAddToAIPlacementPoints(new Location(-156.093750f,45.964912f));
340 checkedAddToAIPlacementPoints(new Location(-151.875000f,35.438596f));
341 checkedAddToAIPlacementPoints(new Location(-146.953125f,22.807018f));
342 targetCoords.add(new Location(-142.031250f,45.964912f));
343 targetCoords.add(new Location(-136.406250f,28.421053f));
344 checkedAddToAIPlacementPoints(new Location(-133.593750f,20.701754f));
345 checkedAddToAIPlacementPoints(new Location(-123.046875f,26.315789f));
346 targetCoords.add(new Location(-118.828125f,9.473684f));
347 checkedAddToAIPlacementPoints(new Location(-113.203125f,-9.473684f));
348 checkedAddToAIPlacementPoints(new Location(-106.171875f,6.666667f));
349 checkedAddToAIPlacementPoints(new Location(-93.515625f,-6.666667f));
350 targetCoords.add(new Location(-93.515625f,-0.350877f));
351 checkedAddToAIPlacementPoints(new Location(-91.406250f,-18.596491f));
352 targetCoords.add(new Location(-88.593750f,-27.719298f));
353 targetCoords.add(new Location(-64.687500f,29.122807f));
354 checkedAddToAIPlacementPoints(new Location(-56.250000f,22.807018f));
355 checkedAddToAIPlacementPoints(new Location(-55.546875f,35.438596f));
356 targetCoords.add(new Location(-50.625000f,16.491228f));
357 targetCoords.add(new Location(-47.812500f,36.842105f));
358 checkedAddToAIPlacementPoints(new Location(-44.296875f,31.228070f));
359 targetCoords.add(new Location(-43.593750f,48.771930f));
360 checkedAddToAIPlacementPoints(new Location(-42.890625f,41.754386f));
361 checkedAddToAIPlacementPoints(new Location(-40.078125f,4.561404f));
362 checkedAddToAIPlacementPoints(new Location(-37.968750f,22.105263f));
363 checkedAddToAIPlacementPoints(new Location(-37.265625f,-30.526316f));
364 targetCoords.add(new Location(-31.640625f,-17.894737f));
365 checkedAddToAIPlacementPoints(new Location(-31.640625f,35.438596f));
366 targetCoords.add(new Location(-30.234375f,-35.438596f));
367 checkedAddToAIPlacementPoints(new Location(-29.531250f,45.263158f));
368 checkedAddToAIPlacementPoints(new Location(-28.828125f,9.473684f));
369 checkedAddToAIPlacementPoints(new Location(-28.125000f,24.912281f));
370 checkedAddToAIPlacementPoints(new Location(-26.718750f,0.350877f));
371 checkedAddToAIPlacementPoints(new Location(-25.312500f,-17.894737f));
372 targetCoords.add(new Location(-23.203125f,13.684211f));
373 targetCoords.add(new Location(-22.500000f,31.228070f));
374 checkedAddToAIPlacementPoints(new Location(-21.796875f,38.947368f));
375 checkedAddToAIPlacementPoints(new Location(-21.796875f,52.280702f));
376 targetCoords.add(new Location(-21.093750f,45.263158f));
377 checkedAddToAIPlacementPoints(new Location(-14.765625f,35.438596f));
378 checkedAddToAIPlacementPoints(new Location(-14.062500f,47.368421f));
379 checkedAddToAIPlacementPoints(new Location(-11.953125f,-5.964912f));
380 checkedAddToAIPlacementPoints(new Location(-10.546875f,60.000000f));
381 targetCoords.add(new Location(-9.140625f,68.421053f));
382 targetCoords.add(new Location(0.000000f,69.122807f));
383 targetCoords.add(new Location(1.406250f,-4.561404f));
384 checkedAddToAIPlacementPoints(new Location(2.812500f,73.333333f));
385 checkedAddToAIPlacementPoints(new Location(3.515625f,-19.298246f));
386 checkedAddToAIPlacementPoints(new Location(4.218750f,67.017544f));
387 targetCoords.add(new Location(6.328125f,-31.929825f));
388 checkedAddToAIPlacementPoints(new Location(12.656250f,71.929825f));
389 checkedAddToAIPlacementPoints(new Location(28.828125f,76.140351f));
390 targetCoords.add(new Location(35.859375f,75.438596f));
391 checkedAddToAIPlacementPoints(new Location(38.671875f,74.736842f));
392 checkedAddToAIPlacementPoints(new Location(48.515625f,75.438596f));
393 targetCoords.add(new Location(49.218750f,-5.263158f));
394 checkedAddToAIPlacementPoints(new Location(56.953125f,-10.175439f));
395 checkedAddToAIPlacementPoints(new Location(58.359375f,1.754386f));
396 targetCoords.add(new Location(64.687500f,8.771930f));
397 targetCoords.add(new Location(70.312500f,-6.666667f));
398 checkedAddToAIPlacementPoints(new Location(71.015625f,3.859649f));
399 checkedAddToAIPlacementPoints(new Location(82.968750f,-3.859649f));
400 targetCoords.add(new Location(90.000000f,-2.456140f));
401 checkedAddToAIPlacementPoints(new Location(94.921875f,-12.280702f));
402 targetCoords.add(new Location(132.890625f,21.403509f));
403 targetCoords.add(new Location(134.296875f,10.175439f));
404 checkedAddToAIPlacementPoints(new Location(144.843750f,27.017544f));
405 checkedAddToAIPlacementPoints(new Location(149.062500f,15.087719f));
406 targetCoords.add(new Location(150.468750f,31.228070f));
407 checkedAddToAIPlacementPoints(new Location(154.687500f,34.035088f));
408 checkedAddToAIPlacementPoints(new Location(157.500000f,21.403509f));
409 targetCoords.add(new Location(158.906250f,41.052632f));
410 checkedAddToAIPlacementPoints(new Location(163.828125f,46.666667f));
411 checkedAddToAIPlacementPoints(new Location(165.234375f,8.771930f));
412 checkedAddToAIPlacementPoints(new Location(167.343750f,32.631579f));
413 checkedAddToAIPlacementPoints(new Location(172.265625f,20.701754f));
414 checkedAddToAIPlacementPoints(new Location(172.968750f,45.964912f));
415 }
416
417 private final void checkedAddToAIPlacementPoints(Location location) {
418 if (JBot.IsValidTerritory(
419 JBot.GetOwnTeamId(),
420 (float) location.getX(),
421 (float) location.getY(),
422 true) ||
423 JBot.IsValidTerritory(
424 JBot.GetOwnTeamId(),
425 (float) location.getX(),
426 (float) location.getY(),
427 true))
428 aiPlacementPoints.add(location);
429 }
430
431
432
433
434
435 public final LinkedList<Location> getAIPlacementPoints() {
436 return aiPlacementPoints;
437 }
438
439
440
441
442
443 public final LinkedList<Location> getTargetCoords() {
444 return targetCoords;
445 }
446
447
448
449
450
451
452 public int getDefconLevel() {
453 return defcon.getFlag();
454 }
455
456
457
458
459
460
461
462 public float getGameTime() {
463 return gameTime;
464 }
465
466
467
468
469
470
471 public int getGameTick() {
472 return gameTick;
473 }
474
475
476
477
478
479
480
481
482 public GameSpeed getGameSpeed() {
483 return gameSpeed.getFlag();
484 }
485
486
487
488
489
490
491
492 public float getVictoryTimer() {
493 return victoryTimer;
494 }
495
496
497
498
499
500
501 public boolean isVictoryTimerActive() {
502 return victoryTimerActive.getFlag();
503 }
504
505
506
507
508
509
510
511
512
513
514
515 public int getOptionValue(String name) {
516 SyncMethodExecContainer container = new SyncMethodExecContainer(
517 JBotMethodsRepository.GetOptionValue(), new Object[] { name });
518 return (Integer) container.syncCallInMainThread();
519 }
520
521
522
523
524
525
526
527 public boolean debugIsReplayingGame() {
528 return debugIsReplayingGame.getFlag();
529 }
530
531
532
533
534
535
536
537 public int getTeamId(int id) {
538 SyncMethodExecContainer container = new SyncMethodExecContainer(
539 JBotMethodsRepository.GetTeamId(), new Object[] { id });
540 return (Integer) container.syncCallInMainThread();
541 }
542
543
544
545
546
547
548 public int[] getOwnFleets() {
549 SyncMethodExecContainer container = new SyncMethodExecContainer(
550 JBotMethodsRepository.GetOwnFleets(), null);
551 return (int[]) container.syncCallInMainThread();
552 }
553
554
555
556
557
558
559
560
561 public int[] getFleets(int teamId) {
562 SyncMethodExecContainer container = new SyncMethodExecContainer(
563 JBotMethodsRepository.GetFleets(), new Object[] { teamId });
564 return (int[]) container.syncCallInMainThread();
565 }
566
567
568
569
570
571
572
573 public int[] getFleetMembers(int fleetId) {
574 SyncMethodExecContainer container = new SyncMethodExecContainer(
575 JBotMethodsRepository.GetFleetMembers(),
576 new Object[] { fleetId });
577 return (int[]) container.syncCallInMainThread();
578 }
579
580
581
582
583
584
585
586 public int getFleetId(int unitId) {
587 SyncMethodExecContainer container = new SyncMethodExecContainer(
588 JBotMethodsRepository.GetFleetId(), new Object[] { unitId });
589 return (Integer) container.syncCallInMainThread();
590 }
591
592
593
594
595
596
597
598 public float getStateTimer(int unitId) {
599 SyncMethodExecContainer container = new SyncMethodExecContainer(
600 JBotMethodsRepository.GetStateTimer(),
601 new Object[] { unitId });
602 return (Float) container.syncCallInMainThread();
603 }
604
605
606
607
608
609
610
611
612 public int[] getActionQueue(int unitId) {
613 SyncMethodExecContainer container = new SyncMethodExecContainer(
614 JBotMethodsRepository.GetActionQueue(),
615 new Object[] { unitId });
616 return (int[]) container.syncCallInMainThread();
617 }
618
619
620
621
622
623
624
625 public boolean isRetaliating(int unitId) {
626 SyncMethodExecContainer container = new SyncMethodExecContainer(
627 JBotMethodsRepository.IsRetaliating(),
628 new Object[] { unitId });
629 return (Boolean) container.syncCallInMainThread();
630 }
631
632
633
634
635
636
637
638
639
640
641 public boolean isVisible(int unitId, int byTeamId) {
642 SyncMethodExecContainer container = new SyncMethodExecContainer(
643 JBotMethodsRepository.IsVisible(), new Object[] { unitId,
644 byTeamId });
645 return (Boolean) container.syncCallInMainThread();
646 }
647
648
649
650
651
652
653
654
655 public Location getVelocity(int unitId) {
656 SyncMethodExecContainer container = new SyncMethodExecContainer(
657 JBotMethodsRepository.GetVelocity(), new Object[] { unitId });
658 return new Location((float[]) container.syncCallInMainThread());
659 }
660
661
662
663
664
665
666
667 public float getRange(int unitId) {
668 SyncMethodExecContainer container = new SyncMethodExecContainer(
669 JBotMethodsRepository.GetRange(), new Object[] { unitId });
670 return (Float) container.syncCallInMainThread();
671 }
672
673
674
675
676
677
678
679 public int getRemainingUnits(UnitType typeId) {
680 SyncMethodExecContainer container = new SyncMethodExecContainer(
681 JBotMethodsRepository.GetRemainingUnits(),
682 new Object[] { typeId.id });
683 return (Integer) container.syncCallInMainThread();
684 }
685
686
687
688
689
690
691
692
693
694
695 public boolean isValidPlacementLocation(float longitude, float latitude,
696 UnitType typeId) {
697
698 SyncMethodExecContainer container = new SyncMethodExecContainer(
699 JBotMethodsRepository.IsValidPlacementLocation(),
700 new Object[] { longitude, latitude, typeId.id });
701
702 Object return_value = container.syncCallInMainThread();
703
704 return (Boolean) return_value;
705 }
706
707
708
709
710
711
712
713
714
715
716 public boolean isValidPlacementLocation(double longitude, double latitude,
717 UnitType typeId) {
718 return isValidPlacementLocation(
719 (float) longitude,
720 (float) latitude,
721 typeId);
722 }
723
724
725
726
727
728
729
730
731
732 public boolean isValidShipPlacementLocation(Location location) {
733 return isValidPlacementLocation(
734 location.getX(),
735 location.getY(),
736 UnitType.BATTLE_SHIP);
737 }
738
739
740
741
742
743
744
745
746
747 public boolean isValidShipPlacementLocation(double longitude,
748 double latitude) {
749 return isValidPlacementLocation(
750 longitude,
751 latitude,
752 UnitType.BATTLE_SHIP);
753 }
754
755
756
757
758
759
760
761
762 public boolean isValidBuildingPlacementLocation(Location location) {
763 return isValidBuildingPlacementLocation(
764 location.getX(),
765 location.getY());
766 }
767
768
769
770
771
772
773
774
775
776
777 public boolean isValidBuildingPlacementLocation(double longitude,
778 double latitude) {
779 return isValidPlacementLocation(
780 longitude,
781 latitude,
782 UnitType.RADAR);
783 }
784
785 public boolean isValidFleetPlacementLocation(float longitude, float latitude,
786 int fleetSize) {
787 for( int i = 0; i < fleetSize; ++i )
788 {
789 Location offset = getFleetMemberOffset(fleetSize, i);
790
791
792
793 if (!isValidShipPlacementLocation(longitude + offset.getX(),
794 latitude + offset.getY()))
795 return false;
796 }
797 return true;
798 }
799
800
801
802
803
804
805 public int getUnitCredits() {
806 SyncMethodExecContainer container = new SyncMethodExecContainer(
807 JBotMethodsRepository.GetUnitCredits(), null);
808 Object return_value = container.syncCallInMainThread();
809
810 return (Integer) return_value;
811 }
812
813
814
815
816
817
818
819 public int getUnitValue(UnitType typeId) {
820 SyncMethodExecContainer container = new SyncMethodExecContainer(
821 JBotMethodsRepository.GetUnitValue(),
822 new Object[] { typeId.id });
823 return (Integer) container.syncCallInMainThread();
824 }
825
826
827
828
829
830
831
832
833 public float getSailDistance(Location locationA, Location locationB) {
834
835 if (locationA == null)
836 throw new IllegalArgumentException(
837 "GetSailDistance requires non-null arguments. [locationA]");
838 if (locationB == null)
839 throw new IllegalArgumentException(
840 "GetSailDistance requires non-null arguments. [locationB]");
841
842 return getSailDistance(locationA.getX(),
843 locationA.getY(), locationB.getX(),
844 locationB.getY());
845 }
846
847
848
849
850
851
852
853
854 public float getSailDistance(double locationA_x, double locationA_y,
855 double locationB_x, double locationB_y) {
856 return getSailDistance(((float) locationA_x),
857 (float) locationA_y, (float) locationB_x,
858 (float) locationB_y);
859 }
860
861
862
863
864
865
866
867
868 public float getSailDistance(float locationA_x, float locationA_y,
869 float locationB_x, float locationB_y) {
870 SyncMethodExecContainer container = new SyncMethodExecContainer(
871 JBotMethodsRepository.GetSailDistance(),
872 new Object[] { locationA_x, locationA_y, locationB_x,
873 locationB_y });
874
875 Object return_value = container.syncCallInMainThread();
876
877 return (return_value instanceof Float) ? (Float) return_value : null;
878 }
879
880
881 private final static class LocationWithDistance {
882
883 private double distance;
884 private Location location;
885
886 public LocationWithDistance(double distance, Location location) {
887 this.distance = distance;
888 this.location = location;
889 }
890
891 public final double getDistance() {
892 return distance;
893 }
894
895 public final void setDistance(double distance) {
896 this.distance = distance;
897 }
898
899 public final Location getLocation() {
900 return location;
901 }
902
903 public final void setLocation(Location location) {
904 this.location = location;
905 }
906 }
907
908 private final float MIN_STEP = 5f;
909
910
911
912
913
914
915
916
917
918 public LocationWithDistance getClosestSailTarget(Location location,
919 List<Location> border) {
920 if (border == null || border.size() == 0)
921 return null;
922
923 if (border.size() == 1)
924 return new LocationWithDistance(getSailDistance(location, border.get(0)), border.get(0));
925
926 Iterator<Location> front = border.iterator();
927 Location last = null;
928 Location current = front.next();
929 Location best = null;
930 Location tmp = null;
931 Location tmp2 = null;
932 Location tmp3 = null;
933 double tmp_distance = 0, tmp_distance2 = 0, tmp_distance3 = 0;
934 double min_distance = Double.MAX_VALUE;
935
936 while (front.hasNext()) {
937 last = current;
938 current = front.next();
939
940 tmp = last;
941 tmp2 = current;
942
943 while (tmp.getDistance2D(tmp2) > MIN_STEP) {
944 tmp3 = tmp2.sub(tmp).scale(0.5f).add(tmp);
945
946 tmp_distance = getSailDistance(location, tmp);
947 tmp_distance2 = getSailDistance(location, tmp2);
948 tmp_distance3 = getSailDistance(location, tmp3);
949
950 if (tmp_distance2 < tmp_distance) {
951 tmp = tmp2;
952 tmp_distance = tmp_distance2;
953 }
954
955 if (tmp_distance3 > tmp_distance) {
956 break;
957 }
958
959 tmp2 = tmp3;
960 tmp_distance2 = tmp_distance3;
961 }
962
963 if (tmp_distance2 < tmp_distance) {
964 tmp_distance = tmp_distance2;
965 tmp = tmp2;
966 }
967
968 if (tmp_distance < min_distance) {
969 min_distance = tmp_distance;
970 best = tmp;
971 }
972 }
973
974 return new LocationWithDistance(min_distance, best);
975 }
976
977
978
979
980
981
982
983
984
985 public LocationPair getClosestSailDistance(List<Location> borderA,
986 List<Location> borderB) {
987
988 double min_distance = Double.MAX_VALUE;
989 LocationPair best = null;
990
991 if (borderA == null || borderA.size() == 0)
992 return null;
993
994 Iterator<Location> front = borderA.iterator();
995 Location current = front.next();
996 Location last = null;
997 LocationPair borderA_borderB = new LocationPair(current, borderB.get(0));
998 LocationPair borderA_borderB_2 = new LocationPair(current,
999 borderB.get(0));
1000 LocationPair borderA_borderB_candidate = null;
1001 double tmp_distance = 0, tmp_distance2 = 0, tmp_distance3 = 0;
1002
1003 while (front.hasNext()) {
1004 last = current;
1005 current = front.next();
1006
1007 borderA_borderB.A = last;
1008 borderA_borderB_2.A = current;
1009
1010 LocationWithDistance loc_with_dist;
1011
1012 loc_with_dist = getClosestSailTarget(borderA_borderB.A, borderB);;
1013 tmp_distance = loc_with_dist.getDistance();
1014 borderA_borderB.B = loc_with_dist.getLocation();
1015
1016
1017 loc_with_dist = getClosestSailTarget(borderA_borderB_2.A, borderB);
1018 tmp_distance2 = loc_with_dist.getDistance();
1019 borderA_borderB_2.B = loc_with_dist.getLocation();
1020
1021 while (borderA_borderB.A.getDistance2D(borderA_borderB_2.A) > MIN_STEP) {
1022
1023 Location half_way = borderA_borderB_2.A.sub(borderA_borderB.A).scale(0.5f).add(borderA_borderB.A);
1024 loc_with_dist = getClosestSailTarget(half_way, borderB);
1025 borderA_borderB_candidate = new LocationPair(half_way,
1026 loc_with_dist.getLocation());
1027
1028 tmp_distance3 = loc_with_dist.getDistance();
1029
1030 if (tmp_distance2 < tmp_distance) {
1031 borderA_borderB = borderA_borderB_2;
1032 tmp_distance = tmp_distance2;
1033 }
1034
1035 if (tmp_distance3 > tmp_distance) {
1036 break;
1037 }
1038
1039 borderA_borderB_2 = borderA_borderB_candidate;
1040 tmp_distance2 = tmp_distance3;
1041 }
1042
1043 if (tmp_distance2 < tmp_distance) {
1044 tmp_distance = tmp_distance2;
1045 borderA_borderB = borderA_borderB_2;
1046 }
1047
1048 if (tmp_distance < min_distance) {
1049 min_distance = tmp_distance;
1050 best = borderA_borderB;
1051 }
1052 }
1053 System.gc();
1054 return best;
1055 }
1056
1057 public class LocationPair {
1058 public Location A;
1059 public Location B;
1060
1061 public LocationPair(Location A, Location B) {
1062 this.A = A;
1063 this.B = B;
1064 }
1065 }
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 public boolean isValidTerritory(int teamId, float longitude,
1081 float latitude, boolean seaArea) {
1082
1083 SyncMethodExecContainer container = new SyncMethodExecContainer(
1084 JBotMethodsRepository.IsValidTerritory(),
1085 new Object[] { teamId, longitude, latitude, seaArea });
1086 return (Boolean) container.syncCallInMainThread();
1087 }
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102 public boolean isValidTerritory(int teamId, double longitude,
1103 double latitude, boolean seaArea) {
1104 return isValidTerritory(teamId, (float) longitude, (float) latitude,
1105 seaArea);
1106 }
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120 public boolean isValidTerritory(int teamId, Location location,
1121 boolean seaArea) {
1122 return isValidTerritory(teamId, (float) location.getX(),
1123 (float) location.getY(), seaArea);
1124 }
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134 public boolean isBorder(float longitude, float latitude) {
1135 SyncMethodExecContainer container = new SyncMethodExecContainer(
1136 JBotMethodsRepository.IsBorder(),
1137 new Object[] { longitude, latitude });
1138 return (Boolean) container.syncCallInMainThread();
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148 public int getTerritoryId(float longitude, float latitude) {
1149
1150 SyncMethodExecContainer container = new SyncMethodExecContainer(
1151 JBotMethodsRepository.GetTerritoryId(),
1152 new Object[] { longitude, latitude });
1153 return (Integer) container.syncCallInMainThread();
1154 }
1155
1156
1157
1158
1159
1160
1161
1162
1163 public int getTerritoryId(double longitude, double latitude) {
1164 return getTerritoryId((float) longitude, (float) latitude);
1165 }
1166
1167
1168
1169
1170
1171
1172 public int getOwnTeamId() {
1173 return ownTeamId;
1174 }
1175
1176
1177
1178
1179
1180
1181 public int[] getTeamIds() {
1182 SyncMethodExecContainer container = new SyncMethodExecContainer(
1183 JBotMethodsRepository.GetTeamIds(),
1184 null);
1185 return (int[]) container.syncCallInMainThread();
1186 }
1187
1188
1189
1190
1191
1192
1193
1194 public SortedMap<Integer, LinkedList<Integer>> getAlliancesWithTeamIds() {
1195 int[] teams = getTeamIds();
1196
1197 SortedMap<Integer, LinkedList<Integer>> alliances = new TreeMap<Integer, LinkedList<Integer>>();
1198 for (int i : teams) {
1199 int alliance = getAllianceId(i);
1200 LinkedList<Integer> list = alliances.get(alliance);
1201 if (list == null)
1202 list = new LinkedList<Integer>();
1203
1204 list.add(i);
1205 alliances.put(alliance, list);
1206 }
1207 return alliances;
1208 }
1209
1210
1211
1212
1213
1214
1215
1216 public int[] getEnemyTeamIds() {
1217 return enemyIds;
1218 }
1219
1220
1221
1222
1223
1224
1225
1226 public SortedMap<Integer, List<Integer>> getEnemiesCityIds() {
1227 return Collections.unmodifiableSortedMap(enemiesCityIds);
1228 }
1229
1230
1231
1232
1233
1234
1235
1236 public List<Integer> getEnemyCityIds() {
1237 ArrayList<Integer> enemyCityIds = new ArrayList<Integer>(20);
1238
1239 for (List<Integer> ids : enemiesCityIds.values()) {
1240 for (int id : ids) {
1241 enemyCityIds.add(id);
1242 }
1243 }
1244 return enemyCityIds;
1245 }
1246
1247
1248
1249
1250
1251
1252
1253 public List<Integer> getEnemyCityIds(int enemyId) {
1254 return Collections.unmodifiableList(enemiesCityIds.get(enemyId));
1255 }
1256
1257
1258
1259
1260
1261
1262 public int getTeamTerritoriesCount(int teamId) {
1263 SyncMethodExecContainer container = new SyncMethodExecContainer(
1264 JBotMethodsRepository.GetTeamTerritoriesCount(),
1265 new Object[] { teamId });
1266 return (Integer) container.syncCallInMainThread();
1267 }
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277 public int[] getTeamTerritories(int teamId) {
1278 SyncMethodExecContainer container = new SyncMethodExecContainer(
1279 JBotMethodsRepository.GetTeamTerritories(),
1280 new Object[] { teamId });
1281 return (int[]) container.syncCallInMainThread();
1282 }
1283
1284
1285
1286
1287
1288
1289
1290
1291 public int[] getOwnTeamTerritories() {
1292 return getTeamTerritories(getOwnTeamId());
1293 }
1294
1295
1296
1297
1298
1299
1300
1301 public int getAllianceId(int teamId) {
1302 SyncMethodExecContainer container = new SyncMethodExecContainer(
1303 JBotMethodsRepository.GetAllianceId(),
1304 new Object[] { teamId });
1305 return (Integer) container.syncCallInMainThread();
1306 }
1307
1308
1309
1310
1311
1312
1313
1314 public int getDesiredGameSpeed(int teamId) {
1315 SyncMethodExecContainer container = new SyncMethodExecContainer(
1316 JBotMethodsRepository.GetDesiredGameSpeed(),
1317 new Object[] { teamId });
1318 return (Integer) container.syncCallInMainThread();
1319 }
1320
1321
1322
1323
1324
1325
1326
1327 public int getEnemyKills(int teamId) {
1328 SyncMethodExecContainer container = new SyncMethodExecContainer(
1329 JBotMethodsRepository.GetEnemyKills(),
1330 new Object[] { teamId });
1331 return (Integer) container.syncCallInMainThread();
1332 }
1333
1334
1335
1336
1337
1338
1339
1340 public int getFriendlyDeaths(int teamId) {
1341 SyncMethodExecContainer container = new SyncMethodExecContainer(
1342 JBotMethodsRepository.GetFriendlyDeaths(),
1343 new Object[] { teamId });
1344 return (Integer) container.syncCallInMainThread();
1345 }
1346
1347
1348
1349
1350
1351
1352
1353
1354 public int getCollateralDamage(int teamId) {
1355 SyncMethodExecContainer container = new SyncMethodExecContainer(
1356 JBotMethodsRepository.GetCollateralDamage(),
1357 new Object[] { teamId });
1358 return (Integer) container.syncCallInMainThread();
1359 }
1360
1361
1362
1363
1364
1365
1366
1367 public String getTeamName(int teamId) {
1368 SyncMethodExecContainer container = new SyncMethodExecContainer(
1369 JBotMethodsRepository.GetTeamName(),
1370 new Object[] { teamId });
1371 return (String) container.syncCallInMainThread();
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381 public boolean isSharingRadar(int teamId1, int teamId2) {
1382 SyncMethodExecContainer container = new SyncMethodExecContainer(
1383 JBotMethodsRepository.IsSharingRadar(),
1384 new Object[] { teamId1, teamId2 });
1385 return (Boolean) container.syncCallInMainThread();
1386 }
1387
1388
1389
1390
1391
1392
1393
1394
1395 public boolean isCeaseFire(int teamId1, int teamId2) {
1396 SyncMethodExecContainer container = new SyncMethodExecContainer(
1397 JBotMethodsRepository.IsCeaseFire(),
1398 new Object[] { teamId1, teamId2 });
1399 return (Boolean) container.syncCallInMainThread();
1400 }
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 public Location getFleetMemberOffset(int memberCount, int memberId) {
1411 return fleetMemberOffsets[memberCount - 1][memberId];
1412 }
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422 private Location getFleetMemberOffsetWorker(int memberCount, int memberId) {
1423 if (memberCount <= 0 || memberId >= memberCount)
1424 throw new InvalidParameterException(
1425 "GetFleetMemberOffset requires memberCount > 0 && "
1426 + "memberId < membercount. memberCount: "
1427 + memberCount + " memberId: " + memberId);
1428
1429 return new Location((float[]) JBot.GetFleetMemberOffset(
1430 memberCount,
1431 memberId));
1432 }
1433
1434
1435
1436
1437
1438 public boolean getRunning() {
1439 return gameRunning.getFlag();
1440 }
1441
1442
1443
1444
1445
1446
1447
1448
1449 public boolean isValidFleetPlacement(Location placement, int fleetSize) {
1450 for (int i = 0; i < fleetSize; ++i) {
1451 Location offset = getFleetMemberOffset(fleetSize, i);
1452
1453
1454
1455 if (!isValidPlacementLocation(
1456 placement.getX() + offset.getX(),
1457 placement.getY() + offset.getY(),
1458 UnitType.BATTLE_SHIP)) {
1459 return false;
1460 }
1461 }
1462 return true;
1463 }
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473 private double getFleetDiameterWorker(int fleetSize) {
1474
1475 double max = 0;
1476 for (int i = 0; i < fleetSize; ++i) {
1477 Location offset = getFleetMemberOffset(fleetSize, i);
1478 double length = offset.getLength();
1479 if (max < length)
1480 max = length;
1481 }
1482
1483 return max + 1d;
1484 }
1485
1486
1487
1488
1489
1490
1491
1492 public double getFleetDiameter(int fleetSize) {
1493 return fleetDiameters[fleetSize - 1];
1494 }
1495
1496
1497
1498
1499
1500
1501 public LinkedList<Integer> getAllEnemyTerritories() {
1502
1503 LinkedList<Integer> territoryIds = new LinkedList<Integer>();
1504
1505 for (int enemyId : getEnemyTeamIds()) {
1506 for (int territoryId : getTeamTerritories(enemyId)) {
1507 territoryIds.add(territoryId);
1508 }
1509 }
1510
1511 return territoryIds;
1512 }
1513
1514
1515
1516
1517
1518
1519 public boolean isValidStructureLocation(Location placement) {
1520 return isValidPlacementLocation(placement.getX(),
1521 placement.getY(), UnitType.AIR_BASE);
1522 }
1523
1524
1525
1526
1527
1528
1529
1530 public int getNukeSupply(int unitId) {
1531 SyncMethodExecContainer container = new SyncMethodExecContainer(
1532 JBotMethodsRepository.GetNukeSupply(),
1533 new Object[] { unitId });
1534 return (Integer) container.syncCallInMainThread();
1535 }
1536
1537
1538
1539
1540
1541
1542
1543
1544 public UnitType getType(int unitId) {
1545 SyncMethodExecContainer container = new SyncMethodExecContainer(
1546 JBotMethodsRepository.GetType(),
1547 new Object[] { unitId });
1548 return UnitType.getEnum((Integer) container.syncCallInMainThread());
1549 }
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560 public int getStateCount(int unitId, IState state) {
1561 SyncMethodExecContainer container = new SyncMethodExecContainer(
1562 JBotMethodsRepository.GetStateCount(),
1563 new Object[] { unitId, state.getStateId() });
1564
1565 return (Integer) container.syncCallInMainThread();
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577 public int getStateCount(int unitId, int stateId) {
1578 SyncMethodExecContainer container = new SyncMethodExecContainer(
1579 JBotMethodsRepository.GetStateCount(),
1580 new Object[] { unitId, stateId });
1581
1582 return (Integer) container.syncCallInMainThread();
1583 }
1584
1585
1586
1587
1588
1589
1590 public int[] getTerritoryOwners() {
1591 return territoryOwners;
1592 }
1593
1594
1595
1596
1597
1598
1599
1600
1601 public int getTerritoryOwner(Location center) {
1602 return getTerritoryOwner(center.getX(), center.getY());
1603 }
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613 public int getTerritoryOwner(double longitude, double latitude) {
1614 return getTerritoryOwner(getTerritoryId(longitude, latitude));
1615 }
1616
1617
1618
1619
1620
1621
1622
1623 public int getTerritoryOwner(int territoryId) {
1624
1625 if (territoryId == -1)
1626 return -1;
1627
1628 return territoryOwners[territoryId];
1629 }
1630
1631
1632
1633
1634
1635
1636
1637 public int getTerritoryId(Location location) {
1638 return getTerritoryId(location.getX(), location.getY());
1639 }
1640
1641
1642
1643
1644
1645
1646 public int getTerritoriesCount() {
1647 return JBot.NumTerritories;
1648 }
1649
1650
1651
1652
1653
1654
1655 public int[] getCityIds() {
1656 SyncMethodExecContainer container = new SyncMethodExecContainer(
1657 JBotMethodsRepository.GetCityIds(),
1658 null);
1659 return (int[]) container.syncCallInMainThread();
1660 }
1661
1662
1663
1664
1665
1666
1667
1668 public Location getObjectLocation(int objectId) {
1669
1670 SyncMethodExecContainer container = new SyncMethodExecContainer(
1671 JBotMethodsRepository.GetLongitude(),
1672 new Object[] { objectId });
1673 float longitude = (Float) container.syncCallInMainThread();
1674
1675 container = new SyncMethodExecContainer(
1676 JBotMethodsRepository.GetLatitude(),
1677 new Object[] { objectId });
1678 float latitude = (Float) container.syncCallInMainThread();
1679
1680 return new Location(longitude, latitude);
1681 }
1682
1683
1684
1685
1686
1687
1688
1689
1690 public boolean canCreateFleet(UnitType[] ships) {
1691
1692 final Hashtable<Integer, Integer> table = new Hashtable<Integer, Integer>();
1693
1694 for (UnitType type : ships) {
1695
1696 if (table.containsKey(type.id)) {
1697 int newCount = table.get(type.id) + 1;
1698
1699 int remaining = getRemainingUnits(type);
1700
1701 if (newCount > remaining) {
1702 return false;
1703 }
1704
1705 table.put(type.id, newCount);
1706 } else {
1707 table.put(type.id, 1);
1708 }
1709 }
1710 table.clear();
1711
1712 return true;
1713 }
1714
1715
1716
1717
1718
1719
1720 public double getSubNukeRange() {
1721 return 45d;
1722 }
1723
1724
1725
1726
1727
1728
1729 public double getBomberRange() {
1730 return 180d;
1731 }
1732
1733
1734
1735
1736
1737
1738 public double getRadarRange() {
1739 return 30d;
1740 }
1741
1742
1743
1744
1745
1746
1747 public double getFighterRange() {
1748 return 40;
1749 }
1750
1751
1752
1753
1754
1755
1756 public double getSiloRange() {
1757 return 30d;
1758 }
1759
1760
1761
1762
1763
1764
1765
1766 public DefConLocation getCitiesGravityCenter(int teamId) {
1767
1768 double x = 0;
1769 double y = 0;
1770
1771
1772 List<Integer> cityList;
1773 if (teamId == getOwnTeamId())
1774 cityList = ownCityIds;
1775 else
1776 cityList = enemiesCityIds.get(teamId);
1777
1778 if (cityList == null) {
1779 PogamutJBotSupport.writeToConsole("cityList is empty: " + teamId
1780 + " " + enemiesCityIds);
1781 }
1782
1783 for (int cityId : cityList) {
1784 DefConLocation location = getCityLocation(cityId);
1785
1786 x += location.getX();
1787 y += location.getY();
1788 }
1789
1790 Location sum = new Location(x, y);
1791
1792 return new DefConLocation(sum.scale(1d / cityList.size()));
1793 }
1794
1795
1796
1797
1798
1799
1800
1801 public DefConLocation getCityLocation(int cityId) {
1802 return new DefConLocation(cityLocations.get(cityId));
1803 }
1804
1805 }