View Javadoc

1   package nl.tudelft.pogamut.ut2004.agent.module.shooting;
2   
3   import java.util.HashMap;
4   import java.util.Map;
5   
6   import nl.tudelft.pogamut.ut2004.agent.module.shooting.util.FocusProvider;
7   import nl.tudelft.pogamut.ut2004.agent.module.shooting.weapon.GenericWeaponShooting;
8   import cz.cuni.amis.pogamut.base.agent.module.SensorModule;
9   import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
10  import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
11  import cz.cuni.amis.pogamut.base3d.worldview.object.ILocated;
12  import cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric.Weapon;
13  import cz.cuni.amis.pogamut.ut2004.agent.module.sensomotoric.Weaponry;
14  import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.AgentInfo;
15  import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.WeaponPref;
16  import cz.cuni.amis.pogamut.ut2004.agent.module.sensor.WeaponPrefs;
17  import cz.cuni.amis.pogamut.ut2004.agent.navigation.UT2004Navigation;
18  import cz.cuni.amis.pogamut.ut2004.bot.command.ImprovedShooting;
19  import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
20  import cz.cuni.amis.pogamut.ut2004.communication.messages.ItemType;
21  import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.EndMessage;
22  import cz.cuni.amis.utils.SafeEquals;
23  
24  /**
25   * <p>
26   * Module that handles shooting other players in an intelligent manner.
27   * </p>
28   * 
29   * <p>
30   * Will utilize {@link WeaponPrefs} to determine which weapon to use for the
31   * target its {@link WeaponShooting} modules to effectively use the weapon.
32   * </p>
33   * 
34   * <p>
35   * The targets for shooting can be set on the logic thread, but the actual
36   * shooting is evaluated by listening to the {@link EndMessage}.
37   * </p>
38   * 
39   * <p>
40   * This module obeys the restrictions set by
41   * {@link ImprovedShooting#setChangeWeaponCooldown(long)} and uses
42   * {@link WeaponPrefs#getWeaponPreference(ILocated)} to determine which weapon
43   * to use.
44   * </p>
45   * 
46   * <p>
47   * The {@link UT2004Navigation#setFocus(ILocated)} is used to indicate where the
48   * bot wants to look. It should be honored for best results.
49   * </p>
50   * 
51   * @author mpkorstanje
52   * 
53   */
54  @SuppressWarnings("rawtypes")
55  public class WeaponryShooting extends SensorModule<UT2004Bot> {
56  
57  	/**
58  	 * {@link EndMessage} listener.
59  	 */
60  	private class EndMessageListener implements IWorldEventListener<EndMessage> {
61  		/**
62  		 * Constructor. Registers itself on the given WorldView object.
63  		 * 
64  		 * @param worldView
65  		 *            WorldView object to listen to.
66  		 */
67  		public EndMessageListener(IWorldView worldView) {
68  			worldView.addEventListener(EndMessage.class, this);
69  		}
70  
71  		@Override
72  		public void notify(EndMessage event) {
73  			shoot();
74  		}
75  	}
76  
77  	/**
78  	 * Current target. Null if none.
79  	 */
80  	protected ILocated currentTarget = null;
81  
82  	/**
83  	 * Current weapon pref to use.
84  	 */
85  	protected WeaponPref currentWeaponPref = null;
86  	/**
87  	 * Currently active shooting.
88  	 */
89  	protected WeaponShooting currentWeaponShooting = null;
90  	/** {@link EndMessage} listener */
91  	@SuppressWarnings("unused")
92  	private EndMessageListener endMessageListener;
93  
94  	/**
95  	 * Focus provider, use to set where you want to look.
96  	 */
97  	protected FocusProvider focus = new FocusProvider();
98  	/**
99  	 * Info about the agent.
100 	 */
101 	protected AgentInfo info;
102 
103 	/**
104 	 * Previous target.
105 	 */
106 	protected ILocated lastTarget = null;
107 
108 	/**
109 	 * Weapon pref used in the previous evaluation of
110 	 * {@link WeaponryShooting#shoot()}.
111 	 */
112 	protected WeaponPref lastWeaponPref = null;
113 	/**
114 	 * Shooting active in the previous evaluation of
115 	 * {@link WeaponryShooting#shoot()}.
116 	 */
117 	protected WeaponShooting lastWeaponShooting = null;
118 
119 	/**
120 	 * Reference to shooting module to shoot stuff.
121 	 */
122 	protected ImprovedShooting shoot;
123 	/**
124 	 * Reference to {@link WeaponPrefs}
125 	 */
126 	protected WeaponPrefs weaponPrefs;
127 
128 	/**
129 	 * Reference to all the weapons we have.
130 	 */
131 	protected Weaponry weaponry;
132 	/**
133 	 * Map of weapon shooting and associated weapons.
134 	 */
135 	protected Map<ItemType, WeaponShooting> weaponShootings = new HashMap<ItemType, WeaponShooting>();
136 
137 	/**
138 	 * Creates a new WeaponryShooting module.
139 	 * 
140 	 * @param bot
141 	 * @param info
142 	 * @param weaponry
143 	 * @param weaponPrefs
144 	 * @param shoot
145 	 */
146 	public WeaponryShooting(UT2004Bot bot, AgentInfo info, Weaponry weaponry, WeaponPrefs weaponPrefs,
147 			ImprovedShooting shoot) {
148 		super(bot);
149 		this.info = info;
150 		this.weaponry = weaponry;
151 		this.weaponPrefs = weaponPrefs;
152 		this.shoot = shoot;
153 
154 		endMessageListener = new EndMessageListener(worldView);
155 
156 	}
157 
158 	/**
159 	 * Adds a new WeaponShooting. The module will be used as soon as the bot
160 	 * changes weapons to the weapon associated with the shooting.
161 	 * 
162 	 * @param weaponShooting
163 	 * @return the previous {@link WeaponShooting} for the associated weapon.
164 	 */
165 	public WeaponShooting addWeaponShooting(WeaponShooting weaponShooting) {
166 		return weaponShootings.put(weaponShooting.getWeaponType(), weaponShooting);
167 	}
168 
169 	/**
170 	 * Removes the WeaponShooting for the given weapon.
171 	 * 
172 	 * @param weapon
173 	 *            the weapon for which the WeaponShooting should be removed.
174 	 * @return the removed WeaponShooting or null if none.
175 	 * 
176 	 */
177 	public WeaponShooting removeWeaponShooting(ItemType weapon) {
178 		return weaponShootings.remove(weapon);
179 	}
180 
181 	/**
182 	 * @return location bot wants to look.
183 	 */
184 
185 	public ILocated getFocus() {
186 		return focus;
187 	}
188 
189 	/**
190 	 * @return the previous target.
191 	 */
192 	public ILocated getLastTarget() {
193 		return lastTarget;
194 
195 	}
196 
197 	/**
198 	 * @return the target
199 	 */
200 	public ILocated getTarget() {
201 		return currentTarget;
202 	}
203 
204 	/**
205 	 * @return the current weaponPref
206 	 */
207 	public WeaponPref getWeaponPref() {
208 		return currentWeaponPref;
209 	}
210 
211 	/**
212 	 * @return the currently active shooting.
213 	 */
214 	public WeaponShooting getWeaponShooting() {
215 		return currentWeaponShooting;
216 	}
217 
218 	/**
219 	 * Selects a WeaponShooting appropriate for the type of the Weapon. If
220 	 * WeaponShooting is available for the weapon type a
221 	 * {@link GenericWeaponShooting} will be created instead.
222 	 * 
223 	 * @param weapon
224 	 * @return
225 	 */
226 	private WeaponShooting selectWeaponShooting(Weapon weapon) {
227 		if (weapon == null) {
228 			return null;
229 		}
230 
231 		if (!weaponShootings.containsKey(weapon.getType())) {
232 			GenericWeaponShooting genericWeaponShooting = new GenericWeaponShooting(agent, info, shoot, weaponry,
233 					weapon.getType());
234 			weaponShootings.put(weapon.getType(), genericWeaponShooting);
235 			return genericWeaponShooting;
236 		}
237 
238 		return weaponShootings.get(weapon.getType());
239 	}
240 
241 	/**
242 	 * The actual shooting happens here. Called by {@link EndMessageListener}.
243 	 */
244 	private void shoot() {
245 		lastWeaponShooting = currentWeaponShooting;
246 
247 		WeaponPref suggested = weaponPrefs.getWeaponPreference(currentTarget);
248 
249 		if (shoot.mayChangeWeapon()) {
250 			lastWeaponPref = currentWeaponPref;
251 			currentWeaponPref = suggested;
252 		}
253 
254 		// The shooting module is selected based on the weapon preference.
255 		// Should none be available, the current weapon will be used to select
256 		// the shooting.
257 		if (currentWeaponPref != null) {
258 			currentWeaponShooting = selectWeaponShooting(weaponry.getWeapon(currentWeaponPref.getWeapon()));
259 		} else {
260 			currentWeaponShooting = selectWeaponShooting(weaponry.getCurrentWeapon());
261 			currentWeaponPref = new WeaponPref(weaponry.getCurrentWeapon().getType());
262 		}
263 
264 		// New shooting, stop the old one.
265 		if (lastWeaponShooting != null && lastWeaponShooting != currentWeaponShooting) {
266 			lastWeaponShooting.stopShoot();
267 			focus.clearFocus();
268 		}
269 		// Unable to make selection.
270 		if (currentWeaponShooting == null) {
271 			return;
272 		}
273 		// New shooting, start new one.
274 		if (lastWeaponShooting != currentWeaponShooting) {
275 			currentWeaponShooting.shoot(currentWeaponPref, currentTarget);
276 			focus.setFocus(currentWeaponShooting.getFocus());
277 		}
278 		// Target or preference changed. Update.
279 		else if (!currentWeaponPref.equals(lastWeaponPref) || !SafeEquals.equals(lastTarget, currentTarget)) {
280 			currentWeaponShooting.shoot(currentWeaponPref, currentTarget);
281 		}
282 
283 	}
284 
285 	/**
286 	 * Sets the target to be shot at. When set to null the bot will continue to
287 	 * charge up any weapons it has, but not actually shoot.
288 	 * 
289 	 * @param target
290 	 */
291 	public void shoot(ILocated target) {
292 		if (this.currentTarget != target) {
293 			this.lastTarget = this.currentTarget;
294 			this.currentTarget = target;
295 		}
296 	}
297 
298 	/**
299 	 * Clears the target and stops the shooting.
300 	 * 
301 	 */
302 	public void stopShoot() {
303 		if (this.currentTarget != null) {
304 			this.lastTarget = this.currentTarget;
305 			this.currentTarget = null;
306 		}
307 		this.currentWeaponShooting.stopShoot();
308 	}
309 }