View Javadoc

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   * Uses ingame representation of to provide info about it.
20   * 
21   * @author Radek 'Black_Hand' Pibil
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  			// TODO Auto-generated catch block
94  			e.printStackTrace();
95  		} catch (IOException e) {
96  			// TODO Auto-generated catch block
97  			e.printStackTrace();
98  		}
99  	}
100 
101 	/**
102 	 * Caches the map for a given flag.
103 	 * 
104 	 * @param flag
105 	 * @return
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 	 * Caches the map for a given flag and given teamId.
124 	 * 
125 	 * @param flag
126 	 * @param teamId
127 	 * @return
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 	 * Converts 2d indices to an index into linearized 2D array.
161 	 * 
162 	 * @param x
163 	 * @param y
164 	 * @return
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 	 * Used during caching. Returns true if the flag is present on the given
172 	 * location.
173 	 * 
174 	 * @param x
175 	 * @param y
176 	 * @param flag
177 	 * @return
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 	 * Used during caching. Returns true if the given location is a valid
228 	 * territory for the given teamId.
229 	 * 
230 	 * @param x
231 	 * @param y
232 	 * @param enemyId
233 	 * @return
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 	 * Used during caching. Returns true if the given location is a valid
242 	 * territory for the given teamId.
243 	 * 
244 	 * @param x
245 	 * @param y
246 	 * @param enemyId
247 	 * @param seaArea
248 	 *            if true then checks, whether [x, y] is a sea territory
249 	 * @return
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 }