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
29
30
31
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
102
103
104
105
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
212
213
214
215 public List<BuildingWithAI<?>> getOwnBuildings() {
216 return Collections.unmodifiableList(ownBuildings);
217 }
218
219
220
221
222
223
224 public SortedMap<Integer, List<DefConUnitObject<?>>> getEnemyBuildings() {
225 return Collections.unmodifiableSortedMap(enemyBuildings);
226 }
227
228
229
230
231
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
250
251
252
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
265
266
267
268
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
289
290
291
292 public boolean isFinished() {
293 return placementQueue.isEmpty()
294 && placementsCounter == ownBuildings.size();
295 }
296 }