View Javadoc

1   package cz.cuni.amis.pogamut.ut2004.agent.module.sensor;
2   
3   import java.util.ArrayList;
4   import java.util.Collections;
5   import java.util.HashMap;
6   import java.util.HashSet;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Map;
10  import java.util.Random;
11  import java.util.Set;
12  import java.util.logging.Logger;
13  
14  import cz.cuni.amis.pogamut.base.agent.module.SensorModule;
15  import cz.cuni.amis.pogamut.base.agent.navigation.IPathPlanner;
16  import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
17  import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
18  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
19  import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
20  import cz.cuni.amis.pogamut.base.communication.worldview.object.event.WorldObjectUpdatedEvent;
21  import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils;
22  import cz.cuni.amis.pogamut.base.utils.math.DistanceUtils.IGetDistance;
23  import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
24  import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
25  import cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric.Weaponry;
26  import cz.cuni.amis.pogamut.ut2004.agent.module.utils.TabooSet;
27  import cz.cuni.amis.pogamut.ut2004.agent.navigation.floydwarshall.FloydWarshallMap;
28  import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
29  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
30  import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;
31  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
32  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.Item;
33  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ItemPickedUp;
34  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
35  import cz.cuni.amis.pogamut.ut2004.communication.translator.shared.events.MapPointListObtained;
36  import cz.cuni.amis.pogamut.ut2004.utils.UnrealUtils;
37  import cz.cuni.amis.utils.NullCheck;
38  import cz.cuni.amis.utils.collections.MyCollections;
39  import cz.cuni.amis.utils.maps.HashMapMap;
40  
41  /**
42   * Memory module specialized on items on the map.
43   * <p><p>
44   * Apart from providing useful getters based on {@link ItemType}, {@link ItemType.Group} and {@link ItemType.Category} it also
45   * provides an optimistic approach for guessing whether some item is spawned inside the map via getSpawnedXYZ methods
46   * such as {@link Items#getSpawnedItems()}.
47   * <p><p>
48   * <b>WARNING:</b>There are methods that contains "reachable" in its name but it is totally unclear what UT2004 means by reachable!!!
49   * These methods are for experimenting purposes only.
50   * <p><p>
51   * It is designed to be initialized inside {@link IUT2004BotController#prepareBot(UT2004Bot)} method call
52   * and may be used since {@link IUT2004BotController#botInitialized(cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo, cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.ConfigChange, cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.InitedMessage)}
53   * is called.
54   *
55   * @author Juraj 'Loque' Simlovic
56   * @author Jimmy
57   */
58  public abstract class Items extends SensorModule<UT2004Bot> {	
59  	
60  	private Random random = new Random(System.currentTimeMillis());
61  	
62  	private IPathPlanner<NavPoint> pathPlanner = null;
63  	
64  	private NavPoint obtainNavPoint(ILocated obj) {
65  		if (obj instanceof NavPoint) return (NavPoint)obj;
66  		if (obj instanceof Item) return ((Item)obj).getNavPoint();
67  		return null;
68  	}
69  	
70  	private IGetDistance<ILocated> pathPlannerGetDistance = new IGetDistance<ILocated>() {
71  
72  		@Override
73  		public double getDistance(ILocated object, ILocated target) {
74  			if (object == null || target == null) return Double.POSITIVE_INFINITY;
75  			if (pathPlanner == null) return target.getLocation().getDistance(object.getLocation());
76  			NavPoint objectNP = obtainNavPoint(object);
77  			NavPoint targetNP = obtainNavPoint(target);
78  			if (objectNP == null || targetNP == null) return Double.POSITIVE_INFINITY;
79  			return pathPlanner.getDistance(objectNP, targetNP);
80  		}
81  		
82  	};
83  	
84  	/**
85  	 * Sets {@link IPathPlanner} (typically {@link FloydWarshallMap}) to be used by the module in order to
86  	 * determine path-distance to items. 
87  	 * @param pathPlanner
88  	 */
89  	public void setPathPlanner(IPathPlanner<NavPoint> pathPlanner) {
90  		this.pathPlanner = pathPlanner;
91  	}
92  
93  	/**
94  	 * Method that determines whether 'item' is pickable in the current state of the bot.
95  	 * E.g., it asseses health for health items, ammo for weapons & ammo, etc.
96  	 * <p><p>
97  	 * Contributed by: David Holan
98  	 * 
99  	 * @param item
100 	 * @return
101 	 */
102 	public abstract boolean isPickable(Item item);
103 	
104 	/*========================================================================*/
105 	
106 	/**
107 	 * Retrieves list of all items, which includes all known pickups and all
108 	 * visible thrown items.
109 	 *
110 	 * <p>Note: The returned Map is unmodifiable and self updating throughout
111 	 * time. Once you obtain a specific Map of items from this module, the Map
112 	 * will get updated based on what happens within the map.
113 	 *
114 	 * @return List of all items. Note: Spawned items are included only.
115 	 */
116 	public Map<UnrealId, Item> getAllItems()
117 	{
118 		return Collections.unmodifiableMap(items.all);
119 	}
120 
121 	/**
122 	 * Retrieves list of all items <b>of specific type</b>.
123 	 *
124 	 * <p>Note: The returned Map is unmodifiable and self updating throughout
125 	 * time. Once you obtain a specific Map of items from this module, the Map
126 	 * will get updated based on what happens within the map.
127 	 *
128 	 * @return List of all items of specific type. Note: Spawned items are included only.
129 	 */
130 	public Map<UnrealId, Item> getAllItems(ItemType type)
131 	{
132 		return Collections.unmodifiableMap(items.allCategories.get(type));
133 	}
134 	
135 	/**
136 	 * Retrieves map of all items belonging to a <b>specific 'category'</b> of items, which
137 	 * includes all known pickups.
138 	 * 
139 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
140 	 * invocation of this method.
141 	 * 
142 	 * <p><p>WARNING: O(n) complexity!
143 	 * 
144 	 * @param category
145 	 * @return Map of all items of a specific category.
146 	 */
147 	public Map<UnrealId, Item> getAllItems(ItemType.Category category) {
148 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
149 		for (ItemType type : category.getTypes()) {
150 			result.putAll(getAllItems(type));
151 		}
152 		return result;
153 	}
154 	
155 	/**
156 	 * Retrieves map of all items belonging to a <b>specific 'group'</b> of items, which
157 	 * includes all known pickups.
158 	 * 
159 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
160 	 * invocation of this method.
161 	 * 
162 	 * <p><p>WARNING: O(n) complexity!
163 	 * 
164 	 * @param group
165 	 * @return Map of all items of a specific group.
166 	 */
167 	public Map<UnrealId, Item> getAllItems(ItemType.Group group) {
168 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
169 		for (ItemType type : group.getTypes()) {
170 			result.putAll(getAllItems(type));
171 		}
172 		return result;
173 	}
174 
175 	/**
176 	 * Retrieves a specific item from the all items in the map.
177 	 * <p><p>
178 	 * Once obtained it is self-updating based on what happens in the game.
179 	 *
180 	 * @param id
181 	 * @return A specific Item be it Spawned or Dropped (Dropped item must be visible though!).
182 	 */
183 	public Item getItem(UnrealId id) {
184 		Item item = items.all.get(id);
185 		if (item == null) item = items.visible.get(id);
186 		return item;
187 	}
188 
189 	/**
190 	 * Retrieves a specific item from the all items in the map.
191 	 * <p><p>
192 	 * Once obtained it is self-updating based on what happens in the game.
193 	 *
194 	 * @param stringUnrealId
195 	 * @return A specific Item be it Spawned or Dropped (Dropped item must be visible though!).
196 	 */
197 	public Item getItem(String stringUnrealId) {
198 		return getItem(UnrealId.get(stringUnrealId));
199 	}
200 	
201 	/**
202 	 * Returns random item from 'all' items.
203 	 * <p><p>
204 	 * Note that there is no need to provide all "getRandomXYZ(xyz)", just
205 	 * use {@link MyCollections#getRandom(java.util.Collection)}. 
206 	 * @return A specific Item be it Spawned or Dropped (Dropped item must be visible though!).
207 	 */
208 	public Item getRandomItem() {
209 		if (getAllItems().size() == 0) return null;
210 		int num = random.nextInt(getAllItems().size());
211 		Iterator<Item> iter = getAllItems().values().iterator();
212 		for (int i = 0; i < num-1; ++i) iter.next();
213 		return iter.next();
214 	}
215 	
216 	/**
217 	 * Returns nearest-by-air (Euclidean norm) item spawning point from 'all' items.
218 	 * Does not need to be necessarily spawned right now. 
219 	 * @return A nearest Item be it Spawned or Dropped (Dropped item must be visible though!).
220 	 */
221 	public Item getNearestItem() {
222 		return DistanceUtils.getNearest(getAllItems().values(), agentInfo.getLocation());
223 	}
224 	
225 	/**
226 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from 'all' items EXCEPT DROPPED ONES!
227 	 * Does not need to be necessarily spawned right now. 
228 	 * @return A nearest Item be it Spawned.
229 	 */
230 	public Item getPathNearestItem() {
231 		return DistanceUtils.getNearest(getAllItems().values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
232 	}
233 	
234 	/**
235 	 * Returns nearest-by-air (Euclidean norm) item spawning point from 'all' items of specific category.
236 	 * Does not need to be necessarily spawned right now. 
237 	 * @param category 
238 	 * @return A nearest Item be it Spawned or Dropped (Dropped item must be visible though!) of specific category.
239 	 */
240 	public Item getNearestItem(ItemType.Category category) {
241 		return DistanceUtils.getNearest(getAllItems(category).values(), agentInfo.getLocation());
242 	}
243 	
244 	/**
245 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from 'all' items EXCEPT DROPPED ONES!
246 	 * Does not need to be necessarily spawned right now. 
247 	 * @param category
248 	 * @return A nearest Item be it Spawned of specific category.
249 	 */
250 	public Item getPathNearestItem(ItemType.Category category) {
251 		return DistanceUtils.getNearest(getAllItems(category).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
252 	}
253 	
254 	/**
255 	 * Returns nearest-by-air (Euclidean norm) item spawning point from 'all' items of specific group.
256 	 * Does not need to be necessarily spawned right now. 
257 	 * @param group 
258 	 * @return A nearest Item be it Spawned or Dropped (Dropped item must be visible though!) of specific group.
259 	 */
260 	public Item getNearestItem(ItemType.Group group) {
261 		return DistanceUtils.getNearest(getAllItems(group).values(), agentInfo.getLocation());
262 	}
263 	
264 	/**
265 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from 'all' items EXCEPT DROPPED ONES!
266 	 * Does not need to be necessarily spawned right now. 
267 	 * @param group 
268 	 * @return A nearest Item be it Spawned of specific group.
269 	 */
270 	public Item getPathNearestItem(ItemType.Group group) {
271 		return DistanceUtils.getNearest(getAllItems(group).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
272 	}
273 	
274 	/**
275 	 * Returns nearest-by-air (Euclidean norm) item spawning point from 'all' items of specific type.
276 	 * Does not need to be necessarily spawned right now. 
277 	 * @param group 
278 	 * @return A nearest Item be it Spawned or Dropped (Dropped item must be visible though!) of specific category.
279 	 */
280 	public Item getNearestItem(ItemType type) {
281 		return DistanceUtils.getNearest(getAllItems(type).values(), agentInfo.getLocation());
282 	}
283 	
284 	/**
285 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from 'all' items EXCEPT DROPPED ONES!
286 	 * Does not need to be necessarily spawned right now. 
287 	 * @param type
288 	 * @return A nearest Item be it Spawned of specific type.
289 	 */
290 	public Item getPathNearestItem(ItemType type) {
291 		return DistanceUtils.getNearest(getAllItems(type).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
292 	}
293 
294 	/*========================================================================*/
295 
296 	/**
297 	 * Retreives list of all visible items, which includes all visible known
298 	 * pickups and all visible thrown items.
299 	 *
300 	 * <p>Note: The returned Map is unmodifiable and self updating throughout
301 	 * time. Once you obtain a specific Map of items from this module, the Map
302 	 * will get updated based on what happens within the map.
303 	 *
304 	 * @return List of all visible items. Note: Spawned items are included only.
305 	 */
306 	public Map<UnrealId, Item> getVisibleItems()
307 	{
308 		return Collections.unmodifiableMap(items.visible);
309 	}
310 
311 	/**
312 	 * Retreives list of all visible items <b> of specific type</b>, which includes all visible known
313 	 * pickups and all visible thrown items.
314 	 *
315 	 * <p>Note: The returned Map is unmodifiable and self updating throughout
316 	 * time. Once you obtain a specific Map of items from this module, the Map
317 	 * will get updated based on what happens within the map.
318 	 *
319 	 * @return List of all visible items of specific type. Note: Spawned items are included only.
320 	 */
321 	public Map<UnrealId, Item> getVisibleItems(ItemType type)
322 	{
323 		return Collections.unmodifiableMap(items.visibleCategories.get(type));
324 	}
325 	
326 	/**
327 	 * Retrieves map of visible items belonging to a <b>specific 'category'</b> of items, which
328 	 * includes all known pickups.
329 	 * 
330 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
331 	 * invocation of this method.
332 	 * 
333 	 * <p><p>WARNING: O(n) complexity!
334 	 * 
335 	 * @param category
336 	 * @return Map of visible items of a specific category.
337 	 */
338 	public Map<UnrealId, Item> getVisibleItems(ItemType.Category category) {
339 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
340 		for (ItemType type : category.getTypes()) {
341 			result.putAll(getVisibleItems(type));
342 		}
343 		return result;
344 	}
345 	
346 	/**
347 	 * Retrieves map of visible items belonging to a <b>specific 'group'</b> of items, which
348 	 * includes all known pickups.
349 	 * 
350 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
351 	 * invocation of this method.
352 	 * 
353 	 * <p><p>WARNING: O(n) complexity!
354 	 * 
355 	 * @param group
356 	 * @return Map of visible items of a specific group.
357 	 */
358 	public Map<UnrealId, Item> getVisibleItems(ItemType.Group group) {
359 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
360 		for (ItemType type : group.getTypes()) {
361 			result.putAll(getVisibleItems(type));
362 		}
363 		return result;
364 	}
365 
366 	/**
367 	 * Retrieves a specific item from the visible items in the map. If item of specified
368 	 * id is not visible returns null.
369 	 * <p><p>
370 	 * Once obtained it is self-updating based on what happens in the game.
371 	 *
372 	 * @param id
373 	 * @return A specific Item be it Spawned or Dropped.
374 	 */
375 	public Item getVisibleItem(UnrealId id) {
376 		Item item = items.visible.get(id);
377 		return item;
378 	}
379 
380 	/**
381 	 * Retrieves a specific item from the visible items in the map. If item of specified
382 	 * id is not visible returns null.
383 	 * <p><p>
384 	 * Once obtained it is self-updating based on what happens in the game.
385 	 *
386 	 * @param stringUnrealId
387 	 * @return A specific Item be it Spawned or Dropped.
388 	 */
389 	public Item getVisibleItem(String stringUnrealId) {
390 		return getVisibleItem(UnrealId.get(stringUnrealId));
391 	}
392 	
393 	/**
394 	 * Returns nearest-by-air (Euclidean norm) item spawning point from visible items.
395 	 * Does not need to be necessarily spawned right now. 
396 	 * @return A nearest visible Item be it Spawned or Dropped (Dropped item must be visible though!).
397 	 */
398 	public Item getNearestVisibleItem() {
399 		return DistanceUtils.getNearest(getVisibleItems().values(), agentInfo.getLocation());
400 	}
401 	
402 	/**
403 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from visible items EXCEPT DROPPED ONES!
404 	 * Does not need to be necessarily spawned right now. 
405 	 * @return A nearest visible Item be it Spawned.
406 	 */
407 	public Item getPathNearestVisibleItem() {
408 		return DistanceUtils.getNearest(getVisibleItems().values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
409 	}
410 	
411 	/**
412 	 * Returns nearest-by-air (Euclidean norm) item spawning point from visible items of specific category.
413 	 * Does not need to be necessarily spawned right now. 
414 	 * @param category 
415 	 * @return A nearest visible Item be it Spawned or Dropped (Dropped item must be visible though!) of specific category.
416 	 */
417 	public Item getNearestVisibleItem(ItemType.Category category) {
418 		return DistanceUtils.getNearest(getVisibleItems(category).values(), agentInfo.getLocation());
419 	}
420 	
421 	/**
422 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from visible items EXCEPT DROPPED ONES!
423 	 * Does not need to be necessarily spawned right now. 
424 	 * @param category
425 	 * @return A nearest visible Item be it Spawned of specific category.
426 	 */
427 	public Item getPathNearestVisibleItem(ItemType.Category category) {
428 		return DistanceUtils.getNearest(getVisibleItems(category).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
429 	}
430 	
431 	/**
432 	 * Returns nearest-by-air (Euclidean norm) item spawning point from visible items of specific group.
433 	 * Does not need to be necessarily spawned right now. 
434 	 * @param group 
435 	 * @return A nearest visible Item be it Spawned or Dropped (Dropped item must be visible though!) of specific group.
436 	 */
437 	public Item getNearestVisibleItem(ItemType.Group group) {
438 		return DistanceUtils.getNearest(getVisibleItems(group).values(), agentInfo.getLocation());
439 	}
440 	
441 	/**
442 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from visible items EXCEPT DROPPED ONES!
443 	 * Does not need to be necessarily spawned right now. 
444 	 * @param group 
445 	 * @return A nearest visible Item be it Spawned of specific group.
446 	 */
447 	public Item getPathNearestVisibleItem(ItemType.Group group) {
448 		return DistanceUtils.getNearest(getVisibleItems(group).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
449 	}
450 	
451 	/**
452 	 * Returns nearest-by-air (Euclidean norm) item spawning point from visible items of specific type.
453 	 * Does not need to be necessarily spawned right now. 
454 	 * @param group 
455 	 * @return A nearest visible Item be it Spawned or Dropped (Dropped item must be visible though!) of specific category.
456 	 */
457 	public Item getNearestVisibleItem(ItemType type) {
458 		return DistanceUtils.getNearest(getVisibleItems(type).values(), agentInfo.getLocation());
459 	}
460 	
461 	/**
462 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from visible items EXCEPT DROPPED ONES!
463 	 * Does not need to be necessarily spawned right now. 
464 	 * @param type
465 	 * @return A nearest visible Item be it Spawned of specific type.
466 	 */
467 	public Item getPathNearestVisibleItem(ItemType type) {
468 		return DistanceUtils.getNearest(getVisibleItems(type).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
469 	}
470 	
471 	/*========================================================================*/
472 
473 	/**
474 	 * Retrieves list of all known item pickup points.
475 	 *
476 	 * <p>Note: The returned Map is unmodifiable and self updating throughout
477 	 * time. Once you obtain a specific Map of items from this module, the Map
478 	 * will get updated based on what happens within the map.
479 	 *
480 	 * @return List of all items. Note: Empty pickups are included as well.
481 	 *
482 	 * @see isPickupSpawned(Item)
483 	 */
484 	public Map<UnrealId, Item> getKnownPickups()
485 	{
486 		return Collections.unmodifiableMap(items.known);
487 	}
488 
489 	/**
490 	 * Retrieves list of all known item pickup points <b>of specific type</b>.
491 	 *
492 	 * <p>Note: The returned Map is unmodifiable and self updating throughout
493 	 * time. Once you obtain a specific Map of items from this module, the Map
494 	 * will get updated based on what happens within the map.
495 	 *
496 	 * @return List of all items of specific type. Note: Empty pickups are included as well.
497 	 *
498 	 * @see isPickupSpawned(Item)
499 	 */
500 	public Map<UnrealId, Item> getKnownPickups(ItemType type)
501 	{
502 		return Collections.unmodifiableMap(items.knownCategories.get(type));
503 	}
504 	
505 	/**
506 	 * Retrieves map of all known pickups belonging to a <b>specific 'category'</b> of items, which
507 	 * includes all known pickups.
508 	 * 
509 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
510 	 * invocation of this method.
511 	 * 
512 	 * <p><p>WARNING: O(n) complexity!
513 	 * 
514 	 * @param category
515 	 * @return Map of known pickups of a specific category.
516 	 */
517 	public Map<UnrealId, Item> getKnownPickups(ItemType.Category category) {
518 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
519 		for (ItemType type : category.getTypes()) {
520 			result.putAll(getKnownPickups(type));
521 		}
522 		return result;
523 	}
524 	
525 	/**
526 	 * Retrieves map of all known pickups belonging to a <b>specific 'group'</b> of items, which
527 	 * includes all known pickups.
528 	 * 
529 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
530 	 * invocation of this method.
531 	 * 
532 	 * <p><p>WARNING: O(n) complexity!
533 	 * 
534 	 * @param group
535 	 * @return Map of known pickups of a specific group.
536 	 */
537 	public Map<UnrealId, Item> getKnownPickups(ItemType.Group group) {
538 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
539 		for (ItemType type : group.getTypes()) {
540 			result.putAll(getKnownPickups(type));
541 		}
542 		return result;
543 	}
544 
545 	/**
546 	 * Retrieves a specific pickup point.
547 	 * <p><p>
548 	 * Once obtained it is self-updating based on what happens in the game.
549 	 *
550 	 * @param id
551 	 * @return A specific Item be it Spawned or Dropped (Dropped item must be visible though!).
552 	 */
553 	public Item getKnownPickup(UnrealId id) {
554 		return items.known.get(id);
555 	}
556 
557 	/**
558 	 * Retrieves a specific pickup point.
559 	 * <p><p>
560 	 * Once obtained it is self-updating based on what happens in the game.
561 	 *
562 	 * @param stringUnrealId
563 	 * @return A specific Item be it Spawned or Dropped (Dropped item must be visible though!).
564 	 */
565 	public Item getKnownPickup(String stringUnrealId) {
566 		return getKnownPickup(UnrealId.get(stringUnrealId));
567 	}
568 
569 	/*========================================================================*/
570 	
571 	/**
572 	 * Uses {@link Items#isPickupSpawned(Item)} to return all items that are believed to 
573 	 * be currently spawned.
574 	 * 
575 	 * <p><p>WARNING: O(n) complexity!
576 	 * 
577 	 * @return collection of spawned items
578 	 */
579 	public Map<UnrealId, Item> getSpawnedItems() {
580 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
581 		for (Item item : getAllItems().values()) {
582 			if (isPickupSpawned(item)) result.put(item.getId(), item);
583 		}
584 		return result;
585 	}
586 	
587 	/**
588 	 * Uses {@link Items#isPickupSpawned(Item)} to return all items of 'type' that are believed to 
589 	 * be currently spawned.
590 	 * 
591 	 * <p><p>WARNING: O(n) complexity!
592 	 * 
593 	 * @return Map of spawned items of a specific type.
594 	 */
595 	public Map<UnrealId, Item> getSpawnedItems(ItemType type) {
596 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
597 		for (Item item : getAllItems(type).values()) {
598 			if (isPickupSpawned(item)) {
599 				result.put(item.getId(), item);
600 			}
601 		}
602 		return result;
603 	}
604 	
605 	/**
606 	 * Uses {@link Items#isPickupSpawned(Item)} to return all items belonging to a specific 'category' that are believed to 
607 	 * be currently spawned.
608 	 * 
609 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
610 	 * invocation of this method.
611 	 * 
612 	 * <p><p>WARNING: O(n) complexity!
613 	 * 
614 	 * @param category
615 	 * @return Map of spawned items of a specific category.
616 	 */
617 	public Map<UnrealId, Item> getSpawnedItems(ItemType.Category category) {
618 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
619 		for (ItemType type : category.getTypes()) {
620 			result.putAll(getSpawnedItems(type));
621 		}
622 		return result;
623 	}
624 	
625 	/**
626 	 * Uses {@link Items#isPickupSpawned(Item)} to return all items belonging to a specific 'group' that are believed to 
627 	 * be currently spawned.
628 	 * 
629 	 * <p>Note: The returned Map is modifiable and is always constructed upon every
630 	 * invocation of this method.
631 	 * 
632 	 * <p><p>WARNING: O(n) complexity!
633 	 * 
634 	 * @param group
635 	 * @return Map of spawned items of a specific group.
636 	 */
637 	public Map<UnrealId, Item> getSpawnedItems(ItemType.Group group) {
638 		Map<UnrealId, Item> result = new HashMap<UnrealId, Item>();
639 		for (ItemType type : group.getTypes()) {
640 			result.putAll(getSpawnedItems(type));
641 		}
642 		return result;
643 	}
644 	
645 	/**
646 	 * Returns nearest-by-air (Euclidean norm) item spawning point from spawned items.
647 	 * Does not need to be necessarily spawned right now. 
648 	 * @return A nearest spawned Item be it Spawned or Dropped (Dropped item must be visible though!).
649 	 */
650 	public Item getNearestSpawnedItem() {
651 		return DistanceUtils.getNearest(getSpawnedItems().values(), agentInfo.getLocation());
652 	}
653 	
654 	/**
655 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from spawned items EXCEPT DROPPED ONES!
656 	 * Does not need to be necessarily spawned right now. 
657 	 * @return A nearest spawned Item be it Spawned.
658 	 */
659 	public Item getPathNearestSpawnedItem() {
660 		return DistanceUtils.getNearest(getSpawnedItems().values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
661 	}
662 	
663 	/**
664 	 * Returns nearest-by-air (Euclidean norm) item spawning point from spawned items of specific category.
665 	 * Does not need to be necessarily spawned right now. 
666 	 * @param category 
667 	 * @return A nearest spawned Item be it Spawned or Dropped (Dropped item must be visible though!) of specific category.
668 	 */
669 	public Item getNearestSpawnedItem(ItemType.Category category) {
670 		return DistanceUtils.getNearest(getSpawnedItems(category).values(), agentInfo.getLocation());
671 	}
672 	
673 	/**
674 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from spawned items EXCEPT DROPPED ONES!
675 	 * Does not need to be necessarily spawned right now. 
676 	 * @param category
677 	 * @return A nearest spawned Item be it Spawned of specific category.
678 	 */
679 	public Item getPathNearestSpawnedItem(ItemType.Category category) {
680 		return DistanceUtils.getNearest(getSpawnedItems(category).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
681 	}
682 	
683 	/**
684 	 * Returns nearest-by-air (Euclidean norm) item spawning point from spawned items of specific group.
685 	 * Does not need to be necessarily spawned right now. 
686 	 * @param group 
687 	 * @return A nearest spawned Item be it Spawned or Dropped (Dropped item must be visible though!) of specific group.
688 	 */
689 	public Item getNearestSpawnedItem(ItemType.Group group) {
690 		return DistanceUtils.getNearest(getSpawnedItems(group).values(), agentInfo.getLocation());
691 	}
692 	
693 	/**
694 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from spawned items EXCEPT DROPPED ONES!
695 	 * Does not need to be necessarily spawned right now. 
696 	 * @param group 
697 	 * @return A nearest spawned Item be it Spawned of specific group.
698 	 */
699 	public Item getPathNearestSpawnedItem(ItemType.Group group) {
700 		return DistanceUtils.getNearest(getSpawnedItems(group).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
701 	}
702 	
703 	/**
704 	 * Returns nearest-by-air (Euclidean norm) item spawning point from spawned items of specific type.
705 	 * Does not need to be necessarily spawned right now. 
706 	 * @param group 
707 	 * @return A nearest spawned Item be it Spawned or Dropped (Dropped item must be visible though!) of specific category.
708 	 */
709 	public Item getNearestSpawnedItem(ItemType type) {
710 		return DistanceUtils.getNearest(getSpawnedItems(type).values(), agentInfo.getLocation());
711 	}
712 	
713 	/**
714 	 * Returns nearest-by-path (using {@link #pathPlanner} previously injected via {@link #setPathPlanner(IPathPlanner)}) item spawning point from spawned items EXCEPT DROPPED ONES!
715 	 * Does not need to be necessarily spawned right now. 
716 	 * @param type
717 	 * @return A nearest spawned Item be it Spawned of specific type.
718 	 */
719 	public Item getPathNearestSpawnedItem(ItemType type) {
720 		return DistanceUtils.getNearest(getSpawnedItems(type).values(), agentInfo.getNearestNavPoint(), pathPlannerGetDistance);
721 	}
722 	
723 	/**
724 	 * Returns how fast are the items respawning based on their item type (in UT Time == UT seconds == {@link UnrealUtils#UT2004_TIME_SPEED} * 1 seconds).
725 	 * @param item
726 	 * @return
727 	 */
728 	public double getItemRespawnUT2004Time(Item item) {
729 		return getItemRespawnTime(item.getType()) * UnrealUtils.UT2004_TIME_SPEED;
730 	}
731 	
732 	/**
733 	 * Returns how fast are the items respawning based on their item type (in UT Time == UT seconds == {@link UnrealUtils#UT2004_TIME_SPEED} * 1 seconds).
734 	 * @param itemType
735 	 * @return
736 	 */
737 	public double getItemRespawnUT2004Time(ItemType itemType) {
738 		return getItemRespawnTime(itemType) * UnrealUtils.UT2004_TIME_SPEED;
739 	}
740 	
741 	/**
742 	 * Returns how fast are the items respawning based on their item type (in real seconds according to {@link System#currentTimeMillis()}.
743 	 * @param item
744 	 * @return
745 	 */
746 	public double getItemRespawnTime(Item item) {
747 		return getItemRespawnTime(item.getType());
748 	}
749 	
750 	/**
751 	 * Returns how fast are the items respawning based on their item type (in real seconds according to {@link System#currentTimeMillis()}.
752 	 * @param itemType
753 	 * @return
754 	 */
755 	public abstract double getItemRespawnTime(ItemType itemType);
756 	
757 	/**
758 	 * Tells, whether the given pickup point contains a spawned item.
759 	 * 
760 	 * <p><p>This implementation is guessing (optimistically) whether the item is spawned based on
761 	 * the last time we have seen it missing (bot has seen its spawning-navpoint but the item was not laying there).
762 	 * 
763 	 * <p><p>Note that the guessing is not perfect, experiment with it or check the source code
764 	 * and possibly reimplement (probably copy-paste) to suit your needs.
765 	 * 
766 	 * <p><p>Note that this method is working correctly only if items are respawning.
767 	 *
768 	 * @param item Item, for which its pickup point is to be examined.
769 	 * @return True, if the item is spawned; false if the pickup is empty.
770 	 *
771 	 * @see getKnownPickups(boolean,boolean)
772 	 */
773 	public boolean isPickupSpawned(Item item) {
774 		if (item == null) return false;
775 		if (item.isVisible()) {
776 			// if the item is visible it is truly spawned
777 			return true;
778 		}
779 		NavPoint np = item.getNavPoint();
780 		if (np == null) {
781 			np = navPoints.get(item.getNavPointId());
782 		}		
783 		if (np != null) { 
784 			if (np.isVisible()) {
785 				// we can see the spawning-navpoint but the item is not visible!
786 				return np.isItemSpawned();
787 			} else {
788 				return !items.itemMissing.isTaboo(item);
789 			}			
790 		} else {
791 			// we do not have item's navpoint, just check times
792 			return !items.itemMissing.isTaboo(item);			
793 		}
794 	}
795 	
796 	/**
797 	 * Tells, whether the given pickup will be thought to be spawned in "millis"
798 	 * 
799 	 * <p><p>This implementation is guessing (optimistically) whether the item is spawned based on
800 	 * the last time we have seen it missing (bot has seen its spawning-navpoint but the item was not laying there).
801 	 * 
802 	 * <p><p>Note that the guessing is not perfect, experiment with it or check the source code
803 	 * and possibly reimplement (probably copy-paste) to suit your needs.
804 	 * 
805 	 * <p><p>Note that this method is working correctly only if items are respawning.
806 	 *
807 	 * @param item Item, for which its pickup point is to be examined.
808 	 * @param long seconds, lookahead time, does not count with "picking up"
809 	 * @return True, if the item is spawned; false if the pickup is empty.
810 	 *
811 	 * @see getKnownPickups(boolean,boolean)
812 	 */
813 	public boolean willPickupBeSpawnedIn(Item item, double seconds) {
814 		if (isPickupSpawned(item)) return true;
815 		return !items.itemMissing.willBeTaboo(item, seconds);
816 	}
817 	
818 	/**
819 	 * Tells, whether the given pickup point contains a spawned item.
820 	 * 
821 	 * <p><p>This implementation is guessing (optimistically) whether the item is spawned based on
822 	 * the last time we have seen it missing (saw its navpoint but the item was not laying there).
823 	 * 
824 	 * <p><p>Note that the guessing is not perfect, experiment with it or check the source code
825 	 * and possibly reimplement to suit your needs.
826 	 * 
827 	 * <p><p>Note that this method is working only if items are respawning.
828 	 *
829 	 * @param itemId Id of the item, for which its pickup point is to be examined.
830 	 * @return True, if the item is spawned; false if the pickup is empty.
831 	 *
832 	 * @see getKnownPickups(boolean,boolean)
833 	 */
834 	public boolean isPickupSpawned(UnrealId itemId) {	
835 		return isPickupSpawned(items.all.get(itemId));
836 	}
837 
838 	/*========================================================================*/
839 
840 	/**
841 	 * Maps of items of specific type.
842 	 */
843 	private class ItemMaps
844 	{
845 		/** Map of all items (known and thrown). */
846 		private HashMap<UnrealId, Item> all = new HashMap<UnrealId, Item> ();
847 		/** Map of visible items of the specific type. */
848 		private HashMap<UnrealId, Item> visible = new HashMap<UnrealId, Item> ();
849 		/** Map of visible items of the specific type. */
850 		private HashMap<UnrealId, Item> reachable = new HashMap<UnrealId, Item> ();
851 		/** Map of all known items of the specific type. */
852 		private HashMap<UnrealId, Item> known = new HashMap<UnrealId, Item> ();
853 		/** Map of all items (known and thrown) of specific categories. */
854 		private HashMapMap<ItemType, UnrealId, Item> allCategories = new HashMapMap<ItemType, UnrealId, Item>();
855 		/** Map of visible items of the specific type. */
856 		private HashMapMap<ItemType, UnrealId, Item> visibleCategories = new HashMapMap<ItemType, UnrealId, Item> ();
857 		/** Map of visible items of the specific type. */
858 		private HashMapMap<ItemType, UnrealId, Item> reachableCategories = new HashMapMap<ItemType, UnrealId, Item> ();
859 		/** Map of all known items of the specific type. */
860 		private HashMapMap<ItemType, UnrealId, Item> knownCategories = new HashMapMap<ItemType, UnrealId, Item> ();
861 		/**Map of all items and the time when they were last seen as 'missing' (== picked up == they were not on their navpoint). */		
862 		private TabooSet<Item> itemMissing;	
863 		/** Set of items that were picked up in this sync-batch. */
864 		private Set<Item> justPickedUp = new HashSet<Item>();
865 		
866 		private HashMap<UnrealId, Boolean> itemSpawned = new HashMap<UnrealId, Boolean>();
867 		
868 		public ItemMaps(UT2004Bot bot) {
869 			itemMissing = new TabooSet<Item>(bot);		
870 		}
871 
872 		private void notify(NavPoint navPoint) {
873 			if (navPoint.getItem() == null) return; // NOT AN INVENTORY SPOT
874 			Item item = getItem(navPoint.getItem());
875 			if (item == null) return; // MISSING ITEM? ... should not happen...
876 			// we have an inventory spot
877 			if (navPoint.isItemSpawned()) {
878 				// item is spawned...
879 				itemMissing.remove(item);
880 			} else {
881 				if (itemMissing.isTaboo(item)) {
882 					// item is already a taboo
883 					return;
884 				}
885 				itemMissing.add(item, getItemRespawnUT2004Time(item));
886 			}
887 		}
888 		
889 		/**
890 		 * Processes events.
891 		 * @param item Item to process.
892 		 */
893 		private void notify(Item item)
894 		{
895 			UnrealId uid = item.getId();
896 
897 			// be sure to be within all
898 			if (!all.containsKey(uid)) {
899 				all.put(uid, item);
900 				allCategories.put(item.getType(), item.getId(), item);
901 			}
902 
903 			// previous visibility
904 			boolean wasVisible = visible.containsKey(uid);
905 			boolean isVisible = item.isVisible();
906 
907 			// refresh visible
908 			if (isVisible && !wasVisible)
909 			{
910 				// add to visible(s)
911 				visible.put(uid, item);
912 				visibleCategories.put(item.getType(), item.getId(), item);
913 			}
914 			else if (!isVisible && wasVisible)
915 			{
916 				// remove from visible(s)
917 				visible.remove(uid);
918 				visibleCategories.remove(item.getType(), item.getId());
919 			}
920 
921 			// remove non-visible thrown items
922 			if (!isVisible && item.isDropped()) {
923 				all.remove(uid);
924 				allCategories.remove(item.getType(), item.getId());
925 			}
926 	
927 		}
928 		
929 		/**
930 		 * Processes events.
931 		 * @param items Map of known items to process.
932 		 */
933 		private void notify(Map<UnrealId, Item> items)
934 		{
935 			// register all known items
936 			known.putAll(items);
937 			for (Item item : items.values()) {
938 				knownCategories.put(item.getType(), item.getId(), item);
939 				notify(item);
940 			}
941 		}
942 		
943 		/**
944 		 * Handles 'itemMissingTimes', called from the {@link EndMessageListener}.
945 		 * @param navPoints
946 		 */
947 		private void notifyBatchEnd(List<NavPoint> navPoints) {
948 			justPickedUp.clear();
949 		}
950 
951 		/**
952 		 * Handles 'itemMissingTimes' for picked up item.
953 		 * @param event
954 		 */
955 		private void notify(ItemPickedUp event) {
956 			Item item = all.get(event.getId());
957 			if (item == null) return;
958 			justPickedUp.add(item);
959 			itemMissing.add(item, getItemRespawnUT2004Time(item));
960 		}
961 
962 		private void clear() {
963 			all.clear();
964 			allCategories.clear();
965 			itemMissing.clear();
966 			justPickedUp.clear();
967 			known.clear();
968 			knownCategories.clear();
969 			reachable.clear();
970 			reachableCategories.clear();
971 			visible.clear();
972 			visibleCategories.clear();			
973 		}
974 	}
975 
976 	/** Maps of all items. */
977 	private ItemMaps items;
978 
979 	/*========================================================================*/
980 
981 	protected class ItemsListener implements IWorldObjectEventListener<Item, IWorldObjectEvent<Item>> {
982 
983 		public ItemsListener(IWorldView worldView) {
984 			worldView.addObjectListener(Item.class, IWorldObjectEvent.class, this);
985 		}
986 
987         public void notify(IWorldObjectEvent<Item> event) {
988             items.notify(event.getObject());
989         }
990 
991     }
992 
993 	protected ItemsListener itemsListener;
994 
995 	/**
996 	 *  This method is called from the constructor to hook a listener that updated the items field.
997 	 *  <p><p>
998 	 *  It must:
999 	 *  <ol>
1000 	 *  <li>initialize itemsListener field</li>
1001 	 *  <li>hook the listener to the world view</li>
1002 	 *  </ol>
1003 	 *  <p><p>
1004 	 *  By overriding this method you may provide your own listener that may wrap Items with your class
1005 	 *  adding new fields into them.
1006 	 *
1007 	 *  @param worldView
1008 	 **/
1009 	protected ItemsListener createItemsListener(IWorldView worldView) {
1010 		return new ItemsListener(worldView);
1011 	}
1012 
1013 	/*========================================================================*/
1014 
1015 	/**
1016 	 * MapPointsListObtained listener.
1017 	 */
1018 	protected class MapPointsListener implements IWorldEventListener<MapPointListObtained>
1019 	{
1020 		/**
1021 		 * Constructor. Registers itself on the given WorldView object.
1022 		 * @param worldView WorldView object to listen to.
1023 		 */
1024 		public MapPointsListener(IWorldView worldView)
1025 		{
1026 			worldView.addEventListener(MapPointListObtained.class, this);
1027 		}
1028 
1029 		@Override
1030 		public void notify(MapPointListObtained event)
1031 		{
1032 			navPoints = event.getNavPoints();
1033 			items.notify(event.getItems());			
1034 		}
1035 
1036 	}
1037 
1038 	/** MapPointsListObtained listener */
1039 	protected MapPointsListener mapPointsListener;
1040 	protected Map<UnrealId, NavPoint> navPoints = new HashMap<UnrealId, NavPoint>();
1041 
1042 	/**
1043 	 *  This method is called from the constructor to create a listener that initialize items field from
1044 	 *  the MapPointListObtained event.
1045 	 *  <p><p>
1046 	 *  By overriding this method you may provide your own listener that may wrap Items with your class
1047 	 *  adding new fields into them.
1048 	 *
1049 	 *  @param worldView
1050 	 * @return
1051 	 **/
1052 	protected MapPointsListener createMapPointsListener(IWorldView worldView) {
1053 		return new MapPointsListener(worldView);
1054 	}
1055 
1056 	/*========================================================================*/
1057 	
1058 	/**
1059 	 * MapPointsListObtained listener.
1060 	 */
1061 	protected class NavPointListener implements IWorldObjectEventListener<NavPoint, WorldObjectUpdatedEvent<NavPoint>>
1062 	{
1063 		/**
1064 		 * Constructor. Registers itself on the given WorldView object.
1065 		 * @param worldView WorldView object to listen to.
1066 		 */
1067 		public NavPointListener(IWorldView worldView) {
1068 			worldView.addObjectListener(NavPoint.class, WorldObjectUpdatedEvent.class, this);
1069 		}
1070 
1071 		@Override
1072 		public void notify(WorldObjectUpdatedEvent<NavPoint> event) {
1073 			items.notify(event.getObject());
1074 			if (event.getObject().isVisible()) {
1075 				navPointsToProcess.add(event.getObject());
1076 			} else {
1077 				navPointsToProcess.remove(event.getObject());
1078 			}
1079 		}
1080 
1081 	}
1082 	
1083 	/**
1084 	 * Contains only navpoints that are visible so we can check whether they are spawning-points,
1085 	 * if so - we may check whether the item is laying there or not to handle spawning times.
1086 	 */
1087 	protected List<NavPoint> navPointsToProcess = new ArrayList<NavPoint>();
1088 	
1089 	protected NavPointListener navPointListener;
1090 	
1091 	/*========================================================================*/
1092 	
1093 	/**
1094 	 * {@link EndMessage} listener.
1095 	 */
1096 	protected class EndMessageListener implements IWorldEventListener<EndMessage>
1097 	{
1098 		/**
1099 		 * Constructor. Registers itself on the given WorldView object.
1100 		 * @param worldView WorldView object to listen to.
1101 		 */
1102 		public EndMessageListener(IWorldView worldView)
1103 		{
1104 			worldView.addEventListener(EndMessage.class, this);
1105 		}
1106 
1107 		@Override
1108 		public void notify(EndMessage event)
1109 		{
1110 			items.notifyBatchEnd(navPointsToProcess);
1111 		}
1112 
1113 	}
1114 	
1115 	protected EndMessageListener endMessageListener;
1116 	
1117 	/*========================================================================*/
1118 	
1119 	/**
1120 	 * {@link ItemPickedUp} listener.
1121 	 */
1122 	protected class ItemPickedUpListener implements IWorldEventListener<ItemPickedUp>
1123 	{
1124 		/**
1125 		 * Constructor. Registers itself on the given WorldView object.
1126 		 * @param worldView WorldView object to listen to.
1127 		 */
1128 		public ItemPickedUpListener(IWorldView worldView)
1129 		{
1130 			worldView.addEventListener(ItemPickedUp.class, this);
1131 		}
1132 
1133 		@Override
1134 		public void notify(ItemPickedUp event)
1135 		{
1136 			items.notify(event);
1137 		}
1138 
1139 	}
1140 	
1141 	protected ItemPickedUpListener itemPickedUpListener;
1142 
1143 	/*========================================================================*/
1144 
1145 	/** AgentInfo memory module. */
1146 	protected AgentInfo agentInfo;
1147 	
1148 	/** Weaponry memory module. */
1149 	protected Weaponry weaponry;
1150 	
1151 	/** Game memory module. */
1152 	protected Game game;
1153 
1154 	
1155 	/**
1156 	 * Constructor. Setups the memory module based on bot's world view.
1157 	 * @param bot owner of the module that is using it
1158 	 * @param agentInfo AgentInfo memory module
1159 	 * @param log Logger to be used for logging runtime/debug info, if null is provided the module creates its own logger
1160 	 */
1161 	public Items(UT2004Bot bot, AgentInfo agentInfo, Game game, Weaponry weaponry, Logger log)
1162 	{
1163 		super(bot, log);
1164 
1165 		// save reference
1166 		this.agentInfo = agentInfo;
1167 		NullCheck.check(this.agentInfo, "agentInfo");
1168 		
1169 		this.weaponry = weaponry;
1170 		NullCheck.check(this.weaponry, "weaponry");
1171 		
1172 		this.game = game;
1173 		NullCheck.check(this.game, "game");
1174 
1175 		items = new ItemMaps(bot);
1176 		
1177 		// create listeners
1178 		itemsListener =        createItemsListener(worldView);
1179 		mapPointsListener =    createMapPointsListener(worldView);
1180 		navPointListener =     new NavPointListener(worldView);
1181 		endMessageListener =   new EndMessageListener(worldView);
1182 		itemPickedUpListener = new ItemPickedUpListener(worldView);
1183 		
1184 		cleanUp();
1185 	}
1186 
1187 	@Override
1188 	protected void cleanUp() {
1189 		super.cleanUp();
1190 		navPoints.clear();
1191 		items.clear();
1192 	}
1193 	
1194 }