1 package cz.cuni.amis.pogamut.defcon.communication.worldview;
2
3 import java.io.BufferedWriter;
4 import java.io.FileNotFoundException;
5 import java.io.FileWriter;
6 import java.io.IOException;
7 import java.util.BitSet;
8 import java.util.SortedMap;
9 import java.util.TreeMap;
10 import java.util.logging.Logger;
11
12 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
13 import cz.cuni.amis.pogamut.defcon.agent.module.sensor.GameInfo;
14 import cz.cuni.amis.pogamut.defcon.communication.worldview.modules.grid.flags.BasicFlag;
15 import cz.cuni.amis.pogamut.defcon.consts.UnitType;
16 import cz.cuni.amis.pogamut.defcon.utils.Pair;
17
18
19
20
21
22
23
24 public class NativeMapSource extends AbstractMapSource {
25
26 private final SortedMap<Integer, Pair<BitSet, BitSet>> unifiedTerritories = new TreeMap<Integer, Pair<BitSet, BitSet>>();
27 private final BitSet sailable;
28 private final Pair<BitSet, BitSet> ownTerritories =
29 new Pair<BitSet, BitSet>();
30 private final SortedMap<Integer, Pair<BitSet, BitSet>> enemyTerritories =
31 new TreeMap<Integer, Pair<BitSet, BitSet>>();
32 private final Logger log;
33
34 private final double X_SPAN = 180d;
35 private final double Y_SPAN = 100d;
36
37 private GameInfo gameInfo;
38
39 public NativeMapSource(GameInfo gameInfo) {
40 this(gameInfo, null);
41 }
42
43 public NativeMapSource(GameInfo gameInfo, Logger log) {
44 this.gameInfo = gameInfo;
45
46 this.log = log;
47
48 this.sailable = cache(BasicFlag.SEA);
49
50 testOutput("sailable", sailable);
51
52
53 int[] teamIds = gameInfo.getTeamIds();
54
55 for (int teamId : teamIds) {
56 if (teamId == gameInfo.getOwnTeamId()) {
57 ownTerritories.first = cache(BasicFlag.OWN_PLACEABLE_SEA);
58 ownTerritories.second = cache(BasicFlag.OWN_PLACEABLE_LAND);
59
60 testOutput("own_sea", ownTerritories.first);
61 testOutput("own_land", ownTerritories.second);
62
63 unifiedTerritories.put(teamId, ownTerritories);
64 }
65 else {
66 Pair<BitSet, BitSet> pair = new Pair<BitSet, BitSet>();
67 pair.first = cacheEnemy(BasicFlag.ENEMY_PLACEABLE_SEA, teamId);
68 pair.second = cacheEnemy(BasicFlag.ENEMY_PLACEABLE_LAND, teamId);
69
70 unifiedTerritories.put(teamId, pair);
71 enemyTerritories.put(teamId, pair);
72
73 testOutput("enemy_sea", pair.first);
74 testOutput("enemy_land", pair.second);
75 }
76 }
77 }
78
79 private void testOutput(String filename, BitSet flags) {
80 try {
81 BufferedWriter ostream = new BufferedWriter(new FileWriter(
82 filename + ".def"));
83
84 for (double i = -X_SPAN; i < X_SPAN; ++i) {
85 for (double j = -Y_SPAN; j < Y_SPAN; ++j) {
86 int index = convert2dIndicesTo1d(i, j);
87 ostream.write((flags.get(index) ? "X" : " "));
88 }
89 ostream.write("\n");
90 }
91 ostream.close();
92 } catch (FileNotFoundException e) {
93
94 e.printStackTrace();
95 } catch (IOException e) {
96
97 e.printStackTrace();
98 }
99 }
100
101
102
103
104
105
106
107 private BitSet cache(BasicFlag flag) {
108 BitSet bit_set = new BitSet(360 * 200);
109 for (double i = -X_SPAN; i < X_SPAN; ++i) {
110 for (double j = -Y_SPAN; j < Y_SPAN; ++j) {
111 int index = convert2dIndicesTo1d(i, j);
112 boolean isPresent = hasFlagWorker(
113 i,
114 j,
115 flag);
116 bit_set.set(index, isPresent);
117 }
118 }
119 return bit_set;
120 }
121
122
123
124
125
126
127
128
129 private BitSet cacheEnemy(BasicFlag flag, int teamId) {
130
131 boolean sea;
132
133 switch (flag) {
134 case ENEMY_PLACEABLE_LAND:
135 sea = false;
136 break;
137 case ENEMY_PLACEABLE_SEA:
138 sea = true;
139 break;
140 default:
141 return null;
142 }
143
144 BitSet bit_set = new BitSet(360 * 200);
145 for (double i = -X_SPAN; i < X_SPAN; ++i) {
146 for (double j = -Y_SPAN; j < Y_SPAN; ++j) {
147 int index = convert2dIndicesTo1d(i, j);
148 boolean isPresent = hasEnemyTerritoryFlagWorker(
149 i,
150 j,
151 teamId,
152 sea);
153 bit_set.set(index, isPresent);
154 }
155 }
156 return bit_set;
157 }
158
159
160
161
162
163
164
165
166 private final int convert2dIndicesTo1d(double x, double y) {
167 return (int) ((x + X_SPAN) * X_SPAN) + (int) (y + Y_SPAN);
168 }
169
170
171
172
173
174
175
176
177
178
179 private boolean hasFlagWorker(double x, double y, BasicFlag flag) {
180 if (x < -X_SPAN || x > X_SPAN || y < -Y_SPAN || y > Y_SPAN)
181 return false;
182
183 switch (flag) {
184 case SEA:
185 return gameInfo.isValidTerritory(-1, x, y, true);
186 case LAND:
187 return gameInfo.isValidTerritory(-1, x, y, false);
188 case OWN_TERRITORY: {
189 int id = gameInfo.getOwnTeamId();
190 return gameInfo.isValidTerritory(id, x, y, false)
191 || gameInfo.isValidTerritory(id, x, y, true);
192 }
193 case ENEMY_TERRITORY: {
194 Boolean ok = false;
195 for (int id : gameInfo.getEnemyTeamIds()) {
196 if (ok = hasEnemyTerritoryFlagWorker(x, y, id))
197 break;
198 }
199 return ok;
200 }
201 case OWN_PLACEABLE_LAND: {
202 return gameInfo.isValidPlacementLocation(x, y, UnitType.RADAR);
203 }
204 case OWN_PLACEABLE_SEA:
205 return gameInfo.isValidPlacementLocation(
206 x, y, UnitType.BATTLE_SHIP);
207 case ENEMY_PLACEABLE_LAND: {
208 for (int id : gameInfo.getEnemyTeamIds()) {
209 if (hasEnemyTerritoryFlagWorker(x, y, id, false))
210 return true;
211 }
212 return false;
213 }
214 case ENEMY_PLACEABLE_SEA: {
215 for (int id : gameInfo.getEnemyTeamIds()) {
216 if (hasEnemyTerritoryFlagWorker(x, y, id, true))
217 return true;
218 }
219 return false;
220
221 }
222 }
223 return false;
224 }
225
226
227
228
229
230
231
232
233
234
235 private boolean hasEnemyTerritoryFlagWorker(double x, double y, int enemyId) {
236 return gameInfo.isValidTerritory(enemyId, x, y, false) ||
237 gameInfo.isValidTerritory(enemyId, x, y, true);
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251 private boolean hasEnemyTerritoryFlagWorker(double x, double y,
252 int enemyId,
253 boolean seaArea) {
254 return gameInfo.isValidTerritory(enemyId, x, y, seaArea);
255 }
256
257 @Override
258 public boolean hasFlag(Location location, BasicFlag flag) {
259 return hasFlag(location.getX(), location.getY(), flag);
260 }
261
262 @Override
263 public boolean hasFlag(double x, double y, BasicFlag flag) {
264 if (x < -X_SPAN || x > X_SPAN || y < -Y_SPAN || y > Y_SPAN)
265 return false;
266
267 int index = convert2dIndicesTo1d(x, y);
268 switch (flag) {
269 case SEA: {
270 return sailable.get(index);
271 }
272 case LAND: {
273 return !sailable.get(index);
274 }
275 case OWN_TERRITORY: {
276 return ownTerritories.first.get(index)
277 || ownTerritories.second.get(index);
278 }
279 case OWN_PLACEABLE_SEA: {
280 return ownTerritories.first.get(index);
281 }
282 case OWN_PLACEABLE_LAND: {
283 return ownTerritories.second.get(index);
284 }
285 case ENEMY_TERRITORY: {
286 for (Pair<BitSet, BitSet> enemyArea : enemyTerritories.values()) {
287 if (enemyArea.first.get(index)
288 || enemyArea.second.get(index))
289 return true;
290 }
291 return false;
292 }
293 case ENEMY_PLACEABLE_SEA: {
294 for (Pair<BitSet, BitSet> enemyArea : enemyTerritories.values()) {
295 if (enemyArea.first.get(index))
296 return true;
297 }
298 return false;
299 }
300 case ENEMY_PLACEABLE_LAND: {
301 for (Pair<BitSet, BitSet> enemyArea : enemyTerritories.values()) {
302 if (enemyArea.second.get(index))
303 return true;
304 }
305 return false;
306 }
307
308 }
309 return false;
310 }
311
312 @Override
313 public boolean hasEnemyTerritoryFlag(Location location, int enemyId) {
314 return hasEnemyTerritoryFlag(location.getX(), location.getY(), enemyId);
315 }
316
317 @Override
318 public boolean hasEnemyTerritoryFlag(double x, double y, int enemyId) {
319 int index = convert2dIndicesTo1d(x, y);
320 if (enemyTerritories.get(enemyId).first.get(index)
321 || enemyTerritories.get(enemyId).second.get(index))
322 return true;
323 else
324 return false;
325 }
326
327 @Override
328 public boolean hasEnemyTerritoryFlag(Location location, int enemyId,
329 boolean seaArea) {
330 return hasEnemyTerritoryFlag(
331 location.getX(),
332 location.getY(),
333 enemyId,
334 seaArea);
335 }
336
337 @Override
338 public boolean hasEnemyTerritoryFlag(double x, double y, int enemyId,
339 boolean seaArea) {
340 int index = convert2dIndicesTo1d(x, y);
341
342 if (seaArea) {
343 return enemyTerritories.get(enemyId).first.get(index);
344 } else {
345 return enemyTerritories.get(enemyId).second.get(index);
346 }
347 }
348 }