001 package student; 002 003 004 import jade.core.AID; 005 import jade.domain.DFService; 006 import jade.domain.FIPAException; 007 import jade.domain.FIPANames; 008 import jade.domain.FIPAAgentManagement.DFAgentDescription; 009 import jade.domain.FIPAAgentManagement.ServiceDescription; 010 import jade.lang.acl.ACLMessage; 011 012 import java.util.Iterator; 013 014 import es.upv.dsic.gti_ia.jgomas.CMedic; 015 import es.upv.dsic.gti_ia.jgomas.CPack; 016 import es.upv.dsic.gti_ia.jgomas.CSight; 017 import es.upv.dsic.gti_ia.jgomas.CTask; 018 import es.upv.dsic.gti_ia.jgomas.Vector3D; 019 020 public class MyMedic extends CMedic { 021 022 023 /** 024 * 025 */ 026 private static final long serialVersionUID = 1L; 027 028 029 protected void setup() { 030 031 super.setup(); 032 SetUpPriorities(); 033 034 } 035 036 ///////////////////////////////////////////////////////////////////////////////////////////////////// 037 // Methods to overload inhereted from CTroop class 038 // 039 040 ///////////////////////////////////////////////////////////////////////////////////////////////////// 041 042 /** 043 * Request for medicine. 044 * 045 * This method sends a <b> FIPA REQUEST </b> message to all agents who offers the <tt> m_sMedicService </tt> service. 046 * 047 * The content of message is: <tt> ( x , y , z ) ( health ) </tt>. 048 * 049 * Variable <tt> m_iMedicsCount </tt> is updated. 050 * 051 * <em> It's very useful to overload this method. </em> 052 * 053 */ 054 055 protected void CallForMedic() { 056 057 try { 058 059 DFAgentDescription dfd = new DFAgentDescription(); 060 ServiceDescription sd = new ServiceDescription(); 061 sd.setType(m_sMedicService); 062 dfd.addServices(sd); 063 DFAgentDescription[] result = DFService.search(this, dfd); 064 065 if ( result.length > 0 ) { 066 067 m_iMedicsCount = result.length; 068 069 // Fill the REQUEST message 070 ACLMessage msg = new ACLMessage(ACLMessage.REQUEST); 071 072 for ( int i = 0; i < result.length; i++ ) { 073 074 DFAgentDescription dfdMedic = result[i]; 075 AID Medic = dfdMedic.getName(); 076 if ( ! Medic.equals(getName()) ) 077 msg.addReceiver(dfdMedic.getName()); 078 else 079 m_iMedicsCount--; 080 } 081 msg.setProtocol(FIPANames.InteractionProtocol.FIPA_REQUEST); 082 msg.setConversationId("CFM"); 083 msg.setContent(" ( " + m_Movement.getPosition().x + " , " + m_Movement.getPosition().y + " , " + m_Movement.getPosition().z + " ) ( " + GetHealth() + " ) "); 084 send(msg); 085 System.out.println(getLocalName()+ ": Need a Medic! (v21)"); 086 087 } else { 088 m_iMedicsCount = 0; 089 } 090 } catch (FIPAException fe) { 091 fe.printStackTrace(); 092 } 093 } 094 ///////////////////////////////////////////////////////////////////////////////////////////////////// 095 096 ///////////////////////////////////////////////////////////////////////////////////////////////////// 097 /** 098 * Request for ammunition. 099 * 100 * This method sends a <b> FIPA REQUEST </b> message to all agents who offers the <tt> m_sAmmoService </tt> service. 101 * 102 * The content of message is: <tt> ( x , y , z ) ( ammo ) </tt>. 103 * 104 * Variable <tt> m_iFieldOpsCount </tt> is updated. 105 * 106 * <em> It's very useful to overload this method. </em> 107 * 108 */ 109 protected void CallForAmmo() { 110 111 super.CallForAmmo(); 112 113 } 114 ///////////////////////////////////////////////////////////////////////////////////////////////////// 115 116 117 ///////////////////////////////////////////////////////////////////////////////////////////////////// 118 /** 119 * Request for backup. 120 * 121 * This method sends a <b> FIPA REQUEST </b> message to all agents who offers the <tt> m_sBackupService</tt> service. 122 * 123 * The content of message is: <tt> ( x , y , z ) ( SoldiersCount ) </tt>. 124 * 125 * Variable <tt> m_iSoldiersCount </tt> is updated. 126 * 127 * <em> It's very useful to overload this method. </em> 128 * 129 */ 130 protected void CallForBackup() { 131 132 133 super.CallForBackup(); 134 135 } 136 ///////////////////////////////////////////////////////////////////////////////////////////////////// 137 138 139 140 ///////////////////////////////////////////////////////////////////////////////////////////////////// 141 /** 142 * Update priority of all 'prepared (to execute)' tasks. 143 * 144 * This method is invoked in the state <em>STANDING</em>, and it's used to re-calculate the priority of all tasks (targets) int the task list 145 * of the agent. The reason is because JGOMAS Kernel always execute the maximum priority task. 146 * 147 * <em> It's very useful to overload this method. </em> 148 * 149 */ 150 protected void UpdateTargets() {} 151 ///////////////////////////////////////////////////////////////////////////////////////////////////// 152 153 ///////////////////////////////////////////////////////////////////////////////////////////////////// 154 /** 155 * Should we update now all 'prepared (to execute)' tasks? 156 * 157 * This method is a decision function invoked in the state <em>GOTO_TARGET</em>. A value of <tt> TRUE</tt> break out the inner loop, 158 * making possible to JGOMAS Kernel extract a more priority task, or update some attributes of the current task. 159 * By default, the return value is <tt> FALSE</tt>, so we execute the current task until it finalizes. 160 * 161 * <em> It's very useful to overload this method. </em> 162 * 163 * @return <tt> FALSE</tt> 164 * 165 */ 166 protected boolean ShouldUpdateTargets() { return false; } 167 ///////////////////////////////////////////////////////////////////////////////////////////////////// 168 169 ///////////////////////////////////////////////////////////////////////////////////////////////////// 170 /** 171 * The agent has got the objective pack. 172 * 173 * This method is called when this agent walks on the objective pack, getting it. 174 * 175 * <em> It's very useful to overload this method. </em> 176 * 177 */ 178 protected void ObjectivePackTaken() {} // Should we do anything when we take the objective pack? 179 ///////////////////////////////////////////////////////////////////////////////////////////////////// 180 181 ///////////////////////////////////////////////////////////////////////////////////////////////////// 182 /** 183 * Definition of priorities for each kind of task. 184 * 185 * This method can be implemented in CTroop's derived classes to define the task's priorities in agreement to 186 * the role of the new class. Priorities must be defined in the array <tt> m_TaskPriority</tt>. 187 * 188 * <em> It's very useful to overload this method. </em> 189 * 190 */ 191 protected void SetUpPriorities() { 192 193 m_TaskPriority[CTask.TASK_NONE] = 0; 194 m_TaskPriority[CTask.TASK_GIVE_MEDICPAKS] = 2000; 195 m_TaskPriority[CTask.TASK_GIVE_AMMOPACKS] = 0; 196 m_TaskPriority[CTask.TASK_GIVE_BACKUP] = 0; 197 m_TaskPriority[CTask.TASK_GET_OBJECTIVE] = 1000; 198 m_TaskPriority[CTask.TASK_ATTACK] = 1000; 199 m_TaskPriority[CTask.TASK_RUN_AWAY] = 1500; 200 m_TaskPriority[CTask.TASK_GOTO_POSITION] = 750; 201 m_TaskPriority[CTask.TASK_PATROLLING] = 500; 202 m_TaskPriority[CTask.TASK_WALKING_PATH] = 750; 203 204 } 205 ///////////////////////////////////////////////////////////////////////////////////////////////////// 206 207 ///////////////////////////////////////////////////////////////////////////////////////////////////// 208 /** 209 * Action to do if this agent cannot shoot. 210 * 211 * This method is called when the agent try to shoot, but has no ammo. The agent will spit enemies out. :-) 212 * 213 * <em> It's very useful to overload this method. </em> 214 * 215 */ 216 protected void PerformNoAmmoAction() {} 217 ///////////////////////////////////////////////////////////////////////////////////////////////////// 218 219 ///////////////////////////////////////////////////////////////////////////////////////////////////// 220 /** 221 * Calculates a new destiny position to escape. 222 * 223 * This method is called before the agent creates a task for escaping. It generates a valid random point in a radius of 50 units. 224 * Once position is calculated, agent updates its destiny to the new position, and automatically calculates the new direction. 225 * 226 * <em> It's very useful to overload this method. </em> 227 * 228 */ 229 protected void GenerateEscapePosition() { 230 231 while (true) { 232 m_Movement.CalculateNewDestination(50, 50); 233 if ( CheckStaticPosition(m_Movement.getDestination().x, m_Movement.getDestination().z) == true ) { 234 m_Movement.CalculateNewOrientation(); 235 return; 236 } 237 } 238 } 239 ///////////////////////////////////////////////////////////////////////////////////////////////////// 240 241 ///////////////////////////////////////////////////////////////////////////////////////////////////// 242 /** 243 * Calculates a new destiny position to walk. 244 * 245 * This method is called before the agent creates a <tt> TASK_GOTO_POSITION</tt> task. It will try (for 5 attempts) to generate a 246 * valid random point in a radius of 20 units. If it doesn't generate a valid position in this cycle, it will try it in next cycle. 247 * Once a position is calculated, agent updates its destination to the new position, and automatically calculates the new direction. 248 * 249 * <em> It's very useful to overload this method. </em> 250 * 251 * @return <tt> TRUE</tt>: valid position generated / <tt> FALSE</tt> cannot generate a valid position 252 * 253 */ 254 protected boolean GeneratePath() { 255 256 for (int iAttempts = 0; iAttempts < 5; iAttempts++) { 257 m_Movement.CalculateNewDestination(20,20); 258 if ( CheckStaticPosition(m_Movement.getDestination().x, m_Movement.getDestination().z) == true ) { 259 // we must insert a task to go to a new position, so agent will follow previous path 260 String sNewPosition = " ( " + m_Movement.getDestination().x + " , " + m_Movement.getDestination().y + " , " + m_Movement.getDestination().z + " ) "; 261 AddTask(CTask.TASK_GOTO_POSITION, getAID(), sNewPosition, m_CurrentTask.getPriority() + 1); 262 return true; 263 } 264 } 265 266 return false; 267 } 268 ///////////////////////////////////////////////////////////////////////////////////////////////////// 269 270 ///////////////////////////////////////////////////////////////////////////////////////////////////// 271 /** 272 * Calculates an array of positions for patrolling. 273 * 274 * When this method is called, it creates an array of <tt> n</tt> random positions. For medics and fieldops, the rank of <tt> n</tt> is 275 * [1..1]. For soldiers, the rank of <tt> n</tt> is [5..10]. 276 * 277 * <em> It's very useful to overload this method. </em> 278 * 279 */ 280 protected void CreateControlPoints() { 281 282 int iMaxCP = 0; 283 284 switch ( m_eClass ) { 285 case CLASS_MEDIC: 286 case CLASS_FIELDOPS: 287 super.CreateControlPoints(); 288 break; 289 290 case CLASS_SOLDIER: 291 iMaxCP = (int) (Math.random() * 5) + 5; 292 m_ControlPoints = new Vector3D [iMaxCP]; 293 for (int i = 0; i < iMaxCP; i++ ) { 294 Vector3D ControlPoints = new Vector3D(); 295 while (true) { 296 297 double x = m_Map.GetTargetX() + (25 - (Math.random() * 50)); 298 double z = m_Map.GetTargetZ() + (25 - (Math.random() * 50)); 299 300 if ( CheckStaticPosition(x, z) == true ) { 301 ControlPoints.x = x; 302 ControlPoints.z = z; 303 m_ControlPoints[i] = ControlPoints; 304 break; 305 } 306 } 307 } 308 break; 309 310 case CLASS_ENGINEER: 311 case CLASS_NONE: 312 default: 313 break; 314 } 315 } 316 ///////////////////////////////////////////////////////////////////////////////////////////////////// 317 318 ///////////////////////////////////////////////////////////////////////////////////////////////////// 319 /** 320 * Action to do when an agent is being shot. 321 * 322 * This method is called every time this agent receives a messager from agent Manager informing it is being shot. 323 * 324 * <em> It's very useful to overload this method. </em> 325 * 326 */ 327 protected void PerformInjuryAction() { 328 } 329 ///////////////////////////////////////////////////////////////////////////////////////////////////// 330 331 ///////////////////////////////////////////////////////////////////////////////////////////////////// 332 /** 333 * Action to do when ammo or health values exceed the threshold allowed. 334 * 335 * This method is called when current values of ammo and health exceed the threshold allowed. These values are checked 336 * by <tt> Launch_MedicAmmo_RequestBehaviour</tt> behaviour, every ten seconds. Perhaps it is convenient to create a 337 * <tt> TASK_RUN_AWAY</tt> task. 338 * 339 * <em> It's very useful to overload this method. </em> 340 * 341 */ 342 protected void PerformThresholdAction() { 343 344 GenerateEscapePosition(); 345 String sNewPosition = " ( " + m_Movement.getDestination().x + " , " + m_Movement.getDestination().y + " , " + m_Movement.getDestination().z + " ) "; 346 AddTask(CTask.TASK_RUN_AWAY, getAID(), sNewPosition, m_CurrentTask.getPriority() + 1); 347 348 } 349 ///////////////////////////////////////////////////////////////////////////////////////////////////// 350 351 ///////////////////////////////////////////////////////////////////////////////////////////////////// 352 /** 353 * Calculates if there is an enemy at sight. 354 * 355 * This method scans the list <tt> m_FOVObjects</tt> (objects in the Field Of View of the agent) looking for an enemy. 356 * If an enemy agent is found, a value of <tt> TRUE</tt> is returned and variable <tt> m_AimedAgent</tt> is updated. 357 * Note that there is no criterion (proximity, etc.) for the enemy found. 358 * Otherwise, the return value is <tt> FALSE</tt>. 359 * 360 * <em> It's very useful to overload this method. </em> 361 * 362 * @return <tt> TRUE</tt>: enemy found / <tt> FALSE</tt> enemy not found 363 * 364 */ 365 protected boolean GetAgentToAim() { 366 367 if ( m_FOVObjects.isEmpty() ) { 368 m_AimedAgent = null; 369 return false; 370 } 371 372 Iterator it = m_FOVObjects.iterator(); 373 while ( it.hasNext() ) { 374 CSight s = (CSight) it.next(); 375 if ( s.getType() >= CPack.PACK_NONE ) { 376 continue; 377 } 378 379 int eTeam = s.getTeam(); 380 381 if ( m_eTeam == eTeam ) 382 continue; 383 384 m_AimedAgent = s; 385 return true; 386 } 387 m_AimedAgent = null; 388 return false; 389 } 390 ///////////////////////////////////////////////////////////////////////////////////////////////////// 391 392 ///////////////////////////////////////////////////////////////////////////////////////////////////// 393 /** 394 * Action to do when the agent is looking at. 395 * 396 * This method is called just after Look method has ended. 397 * 398 * <em> It's very useful to overload this method. </em> 399 * 400 */ 401 protected void PerformLookAction() { 402 } 403 ///////////////////////////////////////////////////////////////////////////////////////////////////// 404 405 // End of Methods to overload inhereted from CTroop class 406 ///////////////////////////////////////////////////////////////////////////////////////////////////// 407 408 409 410 ///////////////////////////////////////////////////////////////////////////////////////////////////// 411 // Methods to overload inhereted from CMedic class 412 // 413 414 ///////////////////////////////////////////////////////////////////////////////////////////////////// 415 /** 416 * Decides if agent accepts the CFM request 417 * 418 * This method is a decision function invoked when a CALL FOR MEDIC request has arrived. 419 * Parameter <tt> sContent</tt> is the content of message received in <tt> CFM</tt> responder behaviour as 420 * result of a <tt> CallForMedic</tt> request, so it must be: <tt> ( x , y , z ) ( health ) </tt>. 421 * By default, the return value is <tt> TRUE</tt>, so agents always accept all CFM requests. 422 * 423 * <em> It's very useful to overload this method. </em> 424 * 425 * @param _sContent 426 * @return <tt> TRUE</tt> 427 * 428 */ 429 protected boolean checkMedicAction(String _sContent) { 430 // We always go to help 431 return ( true ); 432 } 433 ///////////////////////////////////////////////////////////////////////////////////////////////////// 434 435 436 ///////////////////////////////////////////////////////////////////////////////////////////////////// 437 /** 438 * Action to do when this agent reaches the target of current task. 439 * 440 * This method is called when this agent goes to state <em>TARGET_REACHED</em>. If current task is <tt> TASK_GIVE_MEDICPAKS</tt>, 441 * agent must give medic packs, but in other case, it calls to parent's method. 442 * 443 * <em> It's very useful to overload this method. </em> 444 * 445 * @param _CurrentTask 446 * 447 */ 448 protected void PerformTargetReached(CTask _CurrentTask) { 449 450 switch ( _CurrentTask.getType() ) { 451 case CTask.TASK_NONE: 452 break; 453 454 case CTask.TASK_GIVE_MEDICPAKS: 455 int iPacks = _CurrentTask.getPacksDelivered(); 456 super.PerformTargetReached(_CurrentTask); 457 if ( iPacks != _CurrentTask.getPacksDelivered() ) 458 System.out.println(getLocalName()+ ": Medic has left " + (_CurrentTask.getPacksDelivered() - iPacks) + " Medic Packs"); 459 else 460 System.out.println(getLocalName()+ ": Medic cannot leave Medic Packs"); 461 break; 462 463 default: 464 super.PerformTargetReached(_CurrentTask); 465 break; 466 } 467 } 468 ///////////////////////////////////////////////////////////////////////////////////////////////////// 469 470 // End of Methods to overload inhereted from CMedic class 471 ///////////////////////////////////////////////////////////////////////////////////////////////////// 472 473 474 } 475 476 477