Main Page | Class Hierarchy | Class List | Directories | File List | Class Members | Related Pages

agentpolice.cpp

00001 /***************************************************************************
00002                         agentpolice.cpp  -  description
00003                             -------------------
00004     begin                : nov 29th 2005
00005     copyright            : (C) 2005-2006 by Duong-Khang NGUYEN
00006     email                : neoneurone @ users sourceforge net
00007     author               : Victor STINNER
00008     
00009     $Id: agentpolice.cpp 35 2006-08-16 20:50:25Z neoneurone $
00010  ***************************************************************************/
00011 
00012 /***************************************************************************
00013  *                                                                         *
00014  *   This program is free software; you can redistribute it and/or modify  *
00015  *   it under the terms of the GNU General Public License as published by  *
00016  *   the Free Software Foundation; either version 2 of the License, or     *
00017  *   any later version.                                                    *
00018  *                                                                         *
00019  ***************************************************************************/
00020 
00021 
00022 #include "agentpolice.h"
00023 #include "kernel.h"
00024 #include "environment.h"
00025 #include "message.h"
00026 #include "destination.h"
00027 
00028 #include <cstdlib>
00029 
00030 // The max square distance for collaboration
00031 #define MAX_DISTANCE 200
00032 #define MAX_PERCEPTION_RANGE 10
00033 
00034 
00035    /*=====================================================================*/
00036 AgentPolice::AgentPolice(Kernel& kernel, Environment& env, int x, int y):
00037 Agent(kernel, env, x, y, ROLE_POLICE),
00038 m_state( POLICE_LOOK )
00039 {
00040     m_sleep = 3;
00041     SetState( POLICE_LOOK );
00042 
00043     this->born();       // Warning: see superclass
00044 
00045 // OpenCity's specifics
00046     this->SetGraphicCode( OC_VEHICLE_POLICE );
00047 }
00048 
00049 
00050    /*=====================================================================*/
00051 AgentPolice::~AgentPolice()
00052 {
00053     if (m_agent_state != AGENT_DIE)
00054         this->die();        // Warning: see superclass
00055 }
00056 
00057 
00058 
00059    /*=====================================================================*/
00060 Agent* AgentPolice::SeeBadGuy(direction_t dir)
00061 {
00062     Agent* agent = lookForAgent(dir, MAX_PERCEPTION_RANGE);
00063     if (agent == NULL)
00064         return agent;
00065     if (agent->getRole() == ROLE_POLICE)
00066         return NULL;
00067     return agent;
00068 }
00069 
00070 
00071    /*=====================================================================*/
00072 void AgentPolice::SetState(police_state_t state)
00073 {
00074     m_index = 0;
00075     m_path.clear();
00076     
00077     if (state == m_state) return;
00078     
00079     m_state = state;
00080     switch(m_state)
00081     {
00082         case POLICE_COLLABORATE:
00083             break;
00084         case POLICE_PURSUE:
00085             m_pursue = 0;
00086             break;
00087         case POLICE_LOST_PURSUE:
00088             m_lost_pursue = 0;
00089             break;
00090         default:
00091             break;
00092     }
00093 }
00094 
00095 
00096    /*=====================================================================*/
00097 void AgentPolice::Look()
00098 {
00099     MAS_DEBUG( "(look)" );
00100 
00101     Agent* agent = FindBadGuy();
00102     if (agent == NULL)
00103     {
00104         randomMove();
00105         return;
00106     }
00107     MAS_DEBUG( "Look -> Pursue agent " << agent->getId() );
00108 
00109     moveDirection();
00110     NoticePursue(agent);
00111     SetState(POLICE_PURSUE);
00112 }
00113 
00114 
00115    /*=====================================================================*/
00116 void AgentPolice::NoticePursue(Agent *agent)
00117 {
00118 // Create a new alert message for other police agents
00119     Message::Message_t msgt;
00120     switch (agent->getRole()) {
00121         case ROLE_DEMONSTRATOR: msgt = Message::MSG_NEW_DEMONSTRATOR; break;
00122         case ROLE_ROBBER: msgt = Message::MSG_NEW_ROBBER; break;
00123         default:                    // Keep GCC happy
00124             break;
00125     }
00126     Message msg = Message(msgt, this) << agent->getX() << agent->getY();
00127     m_kernel.sendMessage( ROLE_POLICE, msg );
00128 }
00129 
00130 
00131 
00132    /*=====================================================================*/
00133 Agent* AgentPolice::IsNearBadGuy()
00134 {
00135     Agent *agent = m_environment.getAgentAt(m_x-1, m_y);
00136     if (agent != NULL) return agent;
00137     agent = m_environment.getAgentAt(m_x+1, m_y);
00138     if (agent != NULL) return agent;
00139     agent = m_environment.getAgentAt(m_x, m_y-1);
00140     if (agent != NULL) return agent;
00141     agent = m_environment.getAgentAt(m_x, m_y+1);
00142     if (agent != NULL) return agent;
00143     return NULL;
00144 }
00145 
00146    /*=====================================================================*/
00147 void AgentPolice::Pursue()
00148 {
00149     moveDirection();
00150     Agent *agent = SeeBadGuy(m_direction);
00151     if (agent != NULL) {
00152         MAS_DEBUG( *this << "(is pursuing agent " << agent->getId() << ")" );
00153         m_lost_pursue = 0;
00154     
00155         // Notice pursue if needed
00156         m_pursue++;
00157         if (1<m_pursue and (m_pursue % 5) == 0)
00158         {
00159             NoticePursue(agent);
00160         }
00161         return;
00162     }
00163     agent = FindBadGuy(false);
00164     if (agent == NULL) {
00165         MAS_DEBUG( "Pursue -> Lost pursue" );
00166 
00167         SetState(POLICE_LOST_PURSUE);
00168     }
00169 }
00170 
00171 
00172    /*=====================================================================*/
00173 Agent* AgentPolice::FindBadGuy(bool test_backward)
00174 {
00175     Agent *agent = SeeBadGuy(m_direction);
00176     if (agent != NULL) return agent;
00177 
00178     direction_t dir;
00179     unsigned char rotate = randomBool();
00180     if (rotate)
00181         dir = rotateLeft(m_direction);
00182     else
00183         dir = rotateRight(m_direction);
00184     agent = SeeBadGuy(dir);
00185 
00186     if (agent != NULL) {
00187         m_direction = dir;
00188         return agent;
00189     }
00190 
00191     if (rotate)
00192         dir = rotateRight(m_direction);
00193     else
00194         dir = rotateLeft(m_direction);
00195     agent = SeeBadGuy(dir);
00196 
00197     if (agent != NULL) {
00198         m_direction = dir;
00199         return agent;
00200     }
00201 
00202     if (test_backward) {
00203         dir = rotate180(m_direction);
00204         agent = SeeBadGuy(dir);
00205         if (agent != NULL) {
00206             m_direction = dir;
00207             return agent;
00208         }
00209     }
00210     return NULL;
00211 }
00212 
00213 
00214    /*=====================================================================*/
00215 void AgentPolice::LostPursue()
00216 {
00217     MAS_DEBUG( "(did lost agent)" );
00218 
00219     Agent *agent = FindBadGuy();
00220     if (agent != NULL) {
00221         MAS_DEBUG( "Lost pursue -> Pursue " << agent->getId() );
00222 
00223         moveDirection();
00224         NoticePursue(agent);
00225         SetState(POLICE_PURSUE);
00226         return;
00227     }
00228 
00229     m_lost_pursue++;
00230     if (7 < m_lost_pursue) {
00231         MAS_DEBUG( "Lost pursue -> Look" );
00232 
00233         SetState(POLICE_LOOK);
00234     }
00235     randomMove(30);
00236 
00237     agent = FindBadGuy();
00238     if (agent != NULL) {
00239         MAS_DEBUG( "Lost pursue -> Pursue (after moving)" << agent->getId() );
00240 
00241         NoticePursue(agent);
00242         SetState(POLICE_PURSUE);
00243         return;
00244     }
00245 }
00246 
00247 
00248    /*=====================================================================*/
00249 void AgentPolice::processMessage()
00250 {
00251     static Message msg;
00252 
00253 // Process all the messages
00254     while (!m_messages.empty()) {
00255         msg = m_messages.front();
00256         switch (msg.getType()) {
00257         case Message::MSG_NEW_DEMONSTRATOR:
00258         // IF this is not our own message THEN
00259             if ((msg.getSender() != this) and (m_state == POLICE_LOST_PURSUE || m_state == POLICE_LOOK)) {
00260             // Check the square distance of the target
00261                 unsigned int ax = msg[0].getUInt();
00262                 unsigned int ay = msg[1].getUInt();
00263                 if (Environment::toSquareDistance(m_x, m_y, ax, ay) <= MAX_DISTANCE) {
00264                     m_environment.findShortestPath(m_x, m_y, ax, ay, m_path);
00265                     if (m_path.size() > 1) {
00266                         MAS_DEBUG( "-> Collaborate (path size=" << m_path.size() << ")" );
00267 
00268                     // Avoid the first x, y which are equal to m_x, m_y
00269                         m_index = 1;
00270                         SetState(POLICE_COLLABORATE);
00271                     }
00272                     else {
00273                         m_path.clear();
00274                         m_index = 0;
00275 
00276                         Agent* agent = FindBadGuy();
00277                         if (agent != NULL) {
00278                             MAS_DEBUG( "(collaborate) Pursue agent " << agent->getId() );
00279 
00280                             NoticePursue(agent);
00281                             SetState(POLICE_PURSUE);
00282                         }
00283                     }
00284                 }
00285             }
00286             break;
00287 
00288         case Message::MSG_AGENT_DIE:
00289             m_agent_state = AGENT_DIE;
00290             break;
00291 
00292         default:
00293             MAS_DEBUG( "Received unknown message" );
00294         }
00295         m_messages.pop_front();
00296     }
00297 }
00298 
00299 
00300    /*=====================================================================*/
00301 void AgentPolice::born()
00302 {
00303     Agent::born();
00304     m_kernel.registerRole(this, ROLE_POLICE);
00305     m_agent_state = AGENT_LIVE;
00306 }
00307 
00308 
00309    /*=====================================================================*/
00310 void AgentPolice::Collaborate()
00311 {
00312     Agent *agent = IsNearBadGuy();
00313     if (agent != NULL)
00314     {
00315 //        NoticePursue(agent);
00316         randomMove(-1);      
00317         SetState(POLICE_PURSUE);
00318         return;
00319     }
00320     MAS_DEBUG( "(collaborate)" );
00321 
00322     followPath();
00323 }
00324 
00325 
00326    /*=====================================================================*/
00327 void AgentPolice::live()
00328 {
00329     if (m_agent_state != AGENT_LIVE)
00330         return;
00331 
00332     if (m_sleep != 0 and (m_kernel.getStep() % m_sleep) != 0)
00333         return;
00334 
00335     processMessage();
00336 
00337     switch (m_state) {
00338     case POLICE_LOOK:
00339         Look();
00340         break;
00341 
00342     case POLICE_PURSUE:
00343         Pursue();
00344         break;
00345 
00346     case POLICE_LOST_PURSUE:
00347         LostPursue();
00348         break;
00349 
00350     case POLICE_COLLABORATE:
00351         Collaborate();
00352         break;
00353     }
00354 }
00355 
00356 
00357    /*=====================================================================*/
00358 void AgentPolice::die()
00359 {
00360     processMessage();
00361     Agent::die();
00362     m_kernel.unregisterRole(this, this->getRole());
00363 }
00364 
00365 
00366    /*=====================================================================*/
00367 void AgentPolice::output (std::ostream& os) const
00368 {
00369     os << "AgentPolice " << getId();
00370 }
00371 
00372 
00373    /*=====================================================================*/
00374    /*                        PRIVATE     METHODS                          */
00375    /*=====================================================================*/
00376 void
00377 AgentPolice::followPath()
00378 {
00379     int x, y;
00380     bool ok = false;
00381 
00382    // move to the indicated direction
00383     if (m_path[m_index]._uiTime) {
00384         x = m_path[m_index]._uiW;
00385         y = m_path[m_index]._uiL;
00386         if (canMove(x, y) and move(x, y)) {
00387                 ok = true;
00388         }
00389         else {
00390             m_index = 0;
00391             m_path.clear();
00392 
00393             Agent *agent = m_environment.getAgentAt(x,y);
00394             if (agent != NULL and agent->getRole() != ROLE_POLICE) {
00395                 MAS_DEBUG( "Collaborate -> Pursue (blocked)" << agent->getId() );
00396 
00397                 NoticePursue(agent);
00398                 SetState (POLICE_PURSUE);
00399                 return;
00400             } else {
00401                 randomMove();
00402                 MAS_DEBUG( "Collaborate -> Look (abort)" << agent->getId() );
00403 
00404                 SetState (POLICE_LOOK);
00405                 return;
00406             }
00407         }
00408     }
00409 
00410     if (--m_path[m_index]._uiTime == 0) {
00411         if (++m_index >= m_path.size()) {
00412             Agent *agent = SeeBadGuy(m_direction);
00413             if (agent != NULL) {
00414                 MAS_DEBUG( "Collaborate -> Pursue (path ended)" << agent->getId() );
00415 
00416                 NoticePursue(agent);
00417                 SetState (POLICE_PURSUE);
00418             }
00419             else {
00420                 MAS_DEBUG( "Collaborate -> Look (path ended)" << agent->getId() );
00421 
00422                 SetState (POLICE_LOOK);
00423             }
00424         }
00425     }
00426 }
00427 
00428 
00429    /*=====================================================================*/
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445 
00446 
00447 
00448 
00449 
00450 
00451 
00452 
00453 
00454 
00455 
00456 
00457 
00458 
00459 

Generated on Sat Nov 11 10:21:09 2006 for OpenCity by  doxygen 1.4.2