View Javadoc

1   package cz.cuni.amis.pogamut.defcon.communication.worldview.modules.managers.buildings;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.Iterator;
6   import java.util.LinkedList;
7   import java.util.List;
8   import java.util.SortedMap;
9   import java.util.TreeMap;
10  
11  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
12  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectListener;
13  import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectDestroyedEvent;
14  import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectFirstEncounteredEvent;
15  import cz.cuni.amis.pogamut.defcon.agent.impl.DefConAgentLogicController;
16  import cz.cuni.amis.pogamut.defcon.agent.impl.ILogicUpdateListener;
17  import cz.cuni.amis.pogamut.defcon.ai.buildingai.IBuildingAI;
18  import cz.cuni.amis.pogamut.defcon.base3d.worldview.object.DefConLocation;
19  import cz.cuni.amis.pogamut.defcon.communication.messages.commands.DefConCommand;
20  import cz.cuni.amis.pogamut.defcon.communication.messages.commands.PlaceStructure;
21  import cz.cuni.amis.pogamut.defcon.communication.messages.infos.AirBase;
22  import cz.cuni.amis.pogamut.defcon.communication.messages.infos.DefConUnitObject;
23  import cz.cuni.amis.pogamut.defcon.communication.messages.infos.Radar;
24  import cz.cuni.amis.pogamut.defcon.communication.messages.infos.Silo;
25  import cz.cuni.amis.pogamut.defcon.consts.UnitType;
26  
27  /**
28   * Manages all known buildings. Be they either own or enemies. Also takes care
29   * of updating of all you buildings AIs.
30   * 
31   * @author Radek 'Black_Hand' Pibil
32   * 
33   */
34  public class BuildingsManager {
35  
36  	protected final ArrayList<BuildingWithAI<?>> ownBuildings = new ArrayList<BuildingWithAI<?>>();
37  	protected final SortedMap<Integer, List<DefConUnitObject<?>>> enemyBuildings = new TreeMap<Integer, List<DefConUnitObject<?>>>();
38  	protected final LinkedList<PlaceStructure> placementQueue = new LinkedList<PlaceStructure>();
39  
40  	protected int placementsCounter = 0;
41  
42  	protected static final int PLACEMENT_PER_TICK = 2;
43  
44  	protected static final long PLACEMENT_TIMEOUT = 1000;
45  
46  	protected long lastPlacement;
47  
48  	protected final ILogicUpdateListener logicListener = new ILogicUpdateListener() {
49  
50  		@Override
51  		public void update() {
52  			int counter = 0;
53  
54  			if (!placementQueue.isEmpty()) {
55  
56  				do {
57  
58  					if (counter > PLACEMENT_PER_TICK)
59  						break;
60  
61  					PlaceStructure placement = placementQueue.pollFirst();
62  
63  					act(placement);
64  
65  					++counter;
66  				} while (!placementQueue.isEmpty());
67  			}
68  
69  			if (placementsCounter != ownBuildings.size()
70  					&& System.currentTimeMillis() - lastPlacement > PLACEMENT_TIMEOUT) {
71  				placementsCounter = ownBuildings.size();
72  			}
73  
74  			for (BuildingWithAI<?> building : ownBuildings) {
75  				IBuildingAI ai = building.getAI();
76  
77  				if (ai != null && !building.getBuilding().getDestroyed()) {
78  					ai.update();
79  				}
80  			}
81  		}
82  	};
83  
84  	protected DefConAgentLogicController<?> logic;
85  
86  	protected IWorldObjectListener<DefConUnitObject<?>> buildingListener =
87  			new IWorldObjectListener<DefConUnitObject<?>>() {
88  
89  				@Override
90  				public void notify(IWorldObjectEvent<DefConUnitObject<?>> event) {
91  					if (event instanceof WorldObjectFirstEncounteredEvent<?>) {
92  						addBuilding(event.getObject());
93  					}
94  					if (event instanceof WorldObjectDestroyedEvent<?>) {
95  						removeBuilding(event.getObject());
96  					}
97  				}
98  			};
99  
100 	/**
101 	 * Building and AI pair.
102 	 * 
103 	 * @author Radek 'Black_Hand' Pibil
104 	 * 
105 	 * @param <T>
106 	 */
107 	public class BuildingWithAI<T extends DefConUnitObject<?>> {
108 		T building;
109 		IBuildingAI ai;
110 
111 		public BuildingWithAI(T building, IBuildingAI ai) {
112 			this.building = building;
113 			this.ai = ai;
114 		}
115 
116 		public final IBuildingAI getAI() {
117 			return ai;
118 		}
119 
120 		public final void setAI(IBuildingAI ai) {
121 			this.ai = ai;
122 		}
123 
124 		public final T getBuilding() {
125 			return building;
126 		}
127 	}
128 
129 	public BuildingsManager(DefConAgentLogicController<?> logic) {
130 
131 		this.logic = logic;
132 
133 		for (int teamId : logic.getGameInfo().getEnemyTeamIds()) {
134 			enemyBuildings.put(teamId, new ArrayList<DefConUnitObject<?>>());
135 		}
136 
137 		logic.getWorldView().addObjectListener(AirBase.class, buildingListener);
138 		logic.getWorldView().addObjectListener(Silo.class, buildingListener);
139 		logic.getWorldView().addObjectListener(Radar.class, buildingListener);
140 		logic.addGameLogicListener(logicListener);
141 
142 	}
143 
144 	protected void addBuilding(DefConUnitObject<?> building) {
145 		if (building.getTeamId() == logic.getGameInfo().getOwnTeamId()) {
146 			addOwnBuilding(building);
147 		} else {
148 			addEnemyBuilding(building);
149 		}
150 	}
151 
152 	protected void removeBuilding(DefConUnitObject<?> building) {
153 		if (building.getTeamId() == logic.getGameInfo().getOwnTeamId()) {
154 			removeOwnBuilding(building);
155 		} else {
156 			removeEnemyBuilding(building);
157 		}
158 	}
159 
160 	protected void addOwnBuilding(DefConUnitObject<?> building) {
161 		if (!ownBuildings.contains(building)) {
162 			ownBuildings.add(new BuildingWithAI<DefConUnitObject<?>>(building,
163 					null));
164 			lastPlacement = System.currentTimeMillis();
165 		}
166 	}
167 
168 	protected void removeOwnBuilding(DefConUnitObject<?> building) {
169 		Iterator<BuildingWithAI<?>> ownBuildingsIterator = ownBuildings
170 				.iterator();
171 
172 		while (ownBuildingsIterator.hasNext()) {
173 			BuildingWithAI<?> ownBuilding = ownBuildingsIterator.next();
174 
175 			if (ownBuilding.building != building)
176 				continue;
177 
178 			ownBuildingsIterator.remove();
179 
180 			if (ownBuilding.getAI() != null) {
181 				ownBuilding.getAI().dispose();
182 				ownBuilding.setAI(null);
183 				return;
184 			}
185 
186 		}
187 	}
188 
189 	protected void addEnemyBuilding(DefConUnitObject<?> building) {
190 
191 		int enemyId = building.getTeamId();
192 		List<DefConUnitObject<?>> singleEnemyBuildings = enemyBuildings
193 				.get(enemyId);
194 
195 		if (!singleEnemyBuildings.contains(building))
196 			singleEnemyBuildings.add(building);
197 	}
198 
199 	protected void removeEnemyBuilding(DefConUnitObject<?> building) {
200 
201 		int enemyId = building.getTeamId();
202 		List<DefConUnitObject<?>> singleEnemyBuildings = enemyBuildings
203 				.get(enemyId);
204 
205 		if (singleEnemyBuildings.contains(building))
206 			singleEnemyBuildings.remove(building);
207 
208 	}
209 
210 	/**
211 	 * Returns a list of all own buildings with their AIs.
212 	 * 
213 	 * @return
214 	 */
215 	public List<BuildingWithAI<?>> getOwnBuildings() {
216 		return Collections.unmodifiableList(ownBuildings);
217 	}
218 
219 	/**
220 	 * Returns a list of all enemy buildings.
221 	 * 
222 	 * @return
223 	 */
224 	public SortedMap<Integer, List<DefConUnitObject<?>>> getEnemyBuildings() {
225 		return Collections.unmodifiableSortedMap(enemyBuildings);
226 	}
227 
228 	/**
229 	 * Returns the list of enemy buildings of the enemy of given id.
230 	 * 
231 	 * @return
232 	 */
233 	public List<DefConUnitObject<?>> getSingleEnemyBuildings(int enemyId) {
234 		return Collections.unmodifiableList(enemyBuildings.get(enemyId));
235 	}
236 
237 	public static boolean isBuilding(DefConUnitObject<?> unitObject) {
238 		return unitObject instanceof AirBase ||
239 				unitObject instanceof Radar ||
240 				unitObject instanceof Silo;
241 	}
242 
243 	public static boolean isBuilding(UnitType type) {
244 		return type == UnitType.AIR_BASE || type == UnitType.RADAR
245 				|| type == UnitType.SILO;
246 	}
247 
248 	/**
249 	 * Tries to place buildings on all given buildings location.
250 	 * 
251 	 * @param locations
252 	 * @param type
253 	 */
254 	public void placeBuildings(List<DefConLocation> locations, UnitType type) {
255 		if (!BuildingsManager.isBuilding(type))
256 			return;
257 
258 		for (DefConLocation location : locations) {
259 			placementQueue.add(new PlaceStructure(type.id, location));
260 		}
261 	}
262 
263 	/**
264 	 * Assigns AI to the given building.
265 	 * 
266 	 * @param building
267 	 * @param ai
268 	 * @return
269 	 */
270 	public boolean assignAI(DefConUnitObject<?> building, IBuildingAI ai) {
271 		for (BuildingWithAI<?> buildingWithAI : ownBuildings) {
272 			if (buildingWithAI.equals(building)) {
273 				buildingWithAI.setAI(ai);
274 				return true;
275 			}
276 		}
277 
278 		return false;
279 	}
280 
281 	protected void act(DefConCommand command) {
282 		++placementsCounter;
283 		lastPlacement = System.currentTimeMillis();
284 		logic.act(command);
285 	}
286 
287 	/**
288 	 * Returns true if all attempts to place buildings were processed.
289 	 * 
290 	 * @return
291 	 */
292 	public boolean isFinished() {
293 		return placementQueue.isEmpty()
294 				&& placementsCounter == ownBuildings.size();
295 	}
296 }