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

electricitysim.cpp

00001 /***************************************************************************
00002                         electricitysim.cpp  -  description
00003                             -------------------
00004     begin                : mar 2nd, 2004
00005     copyright            : (C) 2004-2006 by Duong-Khang NGUYEN
00006     email                : neoneurone @ users sourceforge net
00007 
00008     $Id: electricitysim.cpp 79 2006-11-02 21:26:35Z neoneurone $
00009  ***************************************************************************/
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU General Public License as published by  *
00015  *   the Free Software Foundation; either version 2 of the License, or     *
00016  *   any later version.                                                    *
00017  *                                                                         *
00018  ***************************************************************************/
00019 
00020 #include "electricitysim.h"
00021 #include "buildinglayer.h"
00022 #include "structure.h"
00023 
00024 #include "globalvar.h"
00025 extern GlobalVar gVars;
00026 
00027    /*=====================================================================*/
00028 ElectricitySim::ElectricitySim(
00029     SDL_mutex* mutex,
00030     BuildingLayer* pblayer,
00031     Map* pmap ):
00032 Simulator( mutex, pblayer, pmap ),
00033 _uiNumberEPlant( 0 ),
00034 _iValueMax( 0 )
00035 {
00036     OPENCITY_DEBUG( "ESim param ctor" );
00037 }
00038 
00039 
00040    /*=====================================================================*/
00041 ElectricitySim::~ElectricitySim()
00042 {
00043     OPENCITY_DEBUG( "ESim dtor" );
00044 }
00045 
00046 
00047    /*=====================================================================*/
00048 void
00049 ElectricitySim::SaveTo( std::fstream& rfs )
00050 {
00051 // Call the base class method
00052     Simulator::SaveTo( rfs );
00053 }
00054 
00055 
00056    /*=====================================================================*/
00057 void
00058 ElectricitySim::LoadFrom( std::fstream& rfs )
00059 {
00060 // Call the base class method
00061     Simulator::LoadFrom( rfs );
00062 
00063 // Member variable reinitialization
00064     _uiNumberEPlant = 0;
00065     _iValueMax = 0;
00066     vectorpairuiEPlant.clear();
00067 }
00068 
00069 
00070    //========================================================================
00071    // int simulatorMain()
00072    //
00073    // description: simulate the transmission of the electricity
00074    //
00075    // algorithm  : it is inpired by my GRAPH knownledge
00076    //              (which is quite limited). In few words, it is
00077    //              breadth-first search algorithm
00078    //
00079    // note       : (28 jun 04) Currently, RCISims unset the Electricity bit
00080    //              then set it again if there's an electric structure around
00081    //              the under processing structure. I don't think that is a
00082    //              good idea. We should let the electricity sim do its job.
00083    //========================================================================
00084 int
00085 ElectricitySim::Main()
00086 {
00087     static Structure* pstruct;
00088     static vector< pair<uint, uint> >::iterator iter;
00089     static pair<uint, uint> pairstructWH;
00090     static uint nW, nH;
00091 
00092 
00093     if (this->enumSimState == SIMULATOR_RUNNING) {
00094         SDL_LockMutex( this->mutexMain );
00095         // See MainSim::RefreshSimValue(), 16 sep 2006
00096         //_iValue = _iValueMax;
00097 
00098         // clear the mark and E bit of ALL structure
00099         pbuildlayer->StructureUnset( OC_STRUCTURE_MARK | OC_STRUCTURE_E );
00100 
00101         // for each EPLANT do
00102         iter = vectorpairuiEPlant.begin();
00103         while ( iter != vectorpairuiEPlant.end() ) {
00104             pairstructWH = *iter;
00105             pstruct = pbuildlayer->GetStructure( pairstructWH.first, pairstructWH.second );
00106 
00107             // only process the EPLANT if it is not marked yet
00108             if (pstruct != NULL)
00109             if (pstruct->IsSet( OC_STRUCTURE_MARK ) == false )
00110                 dequepairui.push_back( pairstructWH );
00111 
00112             // now process the deque
00113             while ( !dequepairui.empty() ) {
00114                 pairstructWH = dequepairui.front();
00115                 dequepairui.pop_front();
00116                 // process the front structure
00117                 pstruct = pbuildlayer->GetStructure(
00118                     pairstructWH.first, pairstructWH.second );
00119                 // WARNING: pstruct is never NULL here !
00120                 switch (pstruct->GetCode()) {
00121                     // turn the E bit of the following structures on
00122                     case OC_STRUCTURE_EPLANT_COAL:
00123                         pstruct->Set(OC_STRUCTURE_E);
00124                         break;
00125 
00126                     // the RCI zones need nearby electric zone
00127                     // in order to be connected to the E system
00128                     case OC_STRUCTURE_RES:
00129                     case OC_STRUCTURE_COM:
00130                     case OC_STRUCTURE_IND:
00131                     case OC_STRUCTURE_PART:
00132                     case OC_STRUCTURE_FIREDEPT:
00133                     case OC_STRUCTURE_POLICEDEPT:
00134                     case OC_STRUCTURE_EDUCATIONDEPT:
00135                     case OC_STRUCTURE_HOSPITALDEPT:
00136                         if (CheckRange(
00137                             pairstructWH.first,
00138                             pairstructWH.second,
00139                             OC_E_RCI_RANGE,
00140                             OC_STRUCTURE_ELECTRIC )
00141                             == true) {
00142                             pstruct->Set(OC_STRUCTURE_E);
00143                             // See MainSim::RefreshSimValue(), 16 sep 2006
00144                             //_iValue--;
00145                         }
00146                         break;
00147 
00148                     // the ELINE structure have a shorter range
00149                     case OC_STRUCTURE_ELINE:
00150                         if (CheckRange(
00151                             pairstructWH.first,
00152                             pairstructWH.second,
00153                             OC_E_E_RANGE,
00154                             OC_STRUCTURE_ELECTRIC )
00155                             == true) {
00156                             pstruct->Set(OC_STRUCTURE_E);
00157                             // See MainSim::RefreshSimValue(), 16 sep 2006
00158                             //_iValue--;
00159                         }
00160                         break;
00161 
00162                 // Ignored structures
00163                     case OC_STRUCTURE_PARK:
00164                     case OC_STRUCTURE_FLORA:
00165                     case OC_STRUCTURE_ROAD:
00166                     case OC_STRUCTURE_TEST:         // Development test feature
00167                         break;
00168 
00169                 // What's the heck ?
00170                     case OC_STRUCTURE_UNDEFINED:
00171                     case OC_STRUCTURE_ANY:
00172                     case OC_STRUCTURE_ELECTRIC:
00173 
00174                 // Future asserts
00175                     case OC_STRUCTURE_MILITARYDEPT:
00176 
00177                 // What's the heck ?
00178                     default:
00179                         OPENCITY_DEBUG( "What's the heck ?" );
00180                         assert( 0 );
00181                         break;
00182                 } // switch
00183 
00184                 // mark the structure we have just processed
00185                 pstruct->Set( OC_STRUCTURE_MARK );
00186 
00187                 // put all the neighbour into the deque
00188                 // if they are not yet marked (processed)
00189                 // look for the neighour in the NORTH
00190                 if ((pmapOfCity->GetNeighbourWH(
00191                     pairstructWH.first, pairstructWH.second,
00192                     nW, nH, OC_DIR_N ) == true )
00193                     &&(pstruct = pbuildlayer->GetStructure( nW, nH ))
00194                     &&(pstruct->IsSet(OC_STRUCTURE_MARK) == false )
00195                     &&(dequeContain(make_pair(nW, nH)) == false))
00196                     dequepairui.push_back(
00197                         pair<uint,uint>( nW, nH) );
00198 
00199                 // look for the neighour in the EAST
00200                 if ((pmapOfCity->GetNeighbourWH(
00201                     pairstructWH.first, pairstructWH.second,
00202                     nW, nH, OC_DIR_E ) == true )
00203                     &&(pstruct = pbuildlayer->GetStructure( nW, nH ))
00204                     &&(pstruct->IsSet(OC_STRUCTURE_MARK) == false )
00205                     &&(dequeContain(make_pair(nW, nH)) == false))
00206                     dequepairui.push_back(
00207                         pair<uint,uint>( nW, nH) );
00208 
00209                 // look for the neighour in the SOUTH
00210                 if ((pmapOfCity->GetNeighbourWH(
00211                     pairstructWH.first, pairstructWH.second,
00212                     nW, nH, OC_DIR_S ) == true )
00213                     &&(pstruct = pbuildlayer->GetStructure( nW, nH ))
00214                     &&(pstruct->IsSet(OC_STRUCTURE_MARK) == false )
00215                     &&(dequeContain(make_pair(nW, nH)) == false))
00216                     dequepairui.push_back(
00217                         pair<uint,uint>( nW, nH) );
00218 
00219                 // look for the neighour in the WEST
00220                 if ((pmapOfCity->GetNeighbourWH(
00221                     pairstructWH.first, pairstructWH.second,
00222                     nW, nH, OC_DIR_W ) == true )
00223                     &&(pstruct = pbuildlayer->GetStructure( nW, nH ))
00224                     &&(pstruct->IsSet(OC_STRUCTURE_MARK) == false )
00225                     &&(dequeContain(make_pair(nW, nH)) == false))
00226                     dequepairui.push_back(
00227                         pair<uint,uint>( nW, nH) );
00228             } // while
00229 
00230             // next EPLANT
00231             iter++;
00232         } // while vectorpairuiEPlant
00233 
00234         SDL_UnlockMutex( this->mutexMain );
00235     } // if run
00236 
00237 
00238     return 0;
00239 }
00240 
00241 
00242 
00243    /*=====================================================================*/
00244 void
00245 ElectricitySim::AddStructure(
00246     const uint & w1,
00247     const uint & h1,
00248     const uint & w2,
00249     const uint & h2 )
00250 {
00251     Structure* pstruct;
00252 
00253     pstruct = pbuildlayer->GetStructure( w1, h1 );
00254     if ( pstruct != NULL )
00255         switch( pstruct->GetCode() ) {
00256             case OC_STRUCTURE_EPLANT_COAL:
00257                 _iValueMax += OC_EPLANT_COAL_POWER;
00258                 _uiNumberEPlant++;
00259                 vectorpairuiEPlant.push_back( pair<uint, uint>( w1, h1 ) );
00260                 break;
00261             default: // keep gcc happy
00262                 break;
00263         }
00264 }
00265 
00266 
00267    /*=====================================================================*/
00268 void
00269 ElectricitySim::RemoveStructure(
00270     const uint & w1,
00271     const uint & h1,
00272     const uint & w2,
00273     const uint & h2 )
00274 {
00275     Structure* pstruct;
00276     OPENCITY_STRUCTURE_CODE enumStructCode;
00277     uint mainW1 = w1, mainH1 = h1, mainW2 = w1, mainH2 = h1;
00278     uint mainW = w1, mainH = h1;
00279     bool boolFound = false;
00280     uint sw, sl, sh;                // Structure's width, length and height
00281 
00282    // remove the w, h of the main structure
00283     vector< pair<uint, uint> >::iterator iter;
00284 
00285     pstruct = pbuildlayer->GetStructure( mainW, mainH );
00286     if ( pstruct != NULL ) {
00287         enumStructCode = pstruct->GetCode();
00288         switch ( enumStructCode ) {
00289             case OC_STRUCTURE_PART:
00290                // get the main structure pointer, and code
00291                 pstruct = pstruct->GetMain();
00292                 enumStructCode = pstruct->GetCode();
00293 
00294                // Calculate the structure's range
00295                 gVars.gpPropertyMgr->GetWLH( pstruct->GetGraphicCode(), sw, 4, sl, 4, sh, 1 );
00296                 sw--; sl--;
00297                // now look for the main w, h
00298                 this->pmapOfCity->GetPossibleWH( mainW1, mainH1, -sw, -sl );
00299                 this->pmapOfCity->GetPossibleWH( mainW2, mainH2,  sw,  sl );
00300                 mainH = mainH1;
00301                 while ( (boolFound == false)
00302                      && (mainH <= mainH2) ) {
00303                     mainW = mainW1;
00304                     while ( (boolFound == false)
00305                          && (mainW <= mainW2) ) {
00306                        // if the current structure at mainW, mainH
00307                        // is the main structure then we found it
00308                         if ( pbuildlayer->GetStructure( mainW, mainH )
00309                           == pstruct )
00310                             boolFound = true;
00311                         else
00312                             mainW++;
00313                     }
00314                     mainH++;
00315                 }
00316                 break;
00317 
00318             case OC_STRUCTURE_RES:
00319             case OC_STRUCTURE_COM:
00320             case OC_STRUCTURE_IND:
00321             case OC_STRUCTURE_FIREDEPT:
00322             case OC_STRUCTURE_POLICEDEPT:
00323             case OC_STRUCTURE_EDUCATIONDEPT:
00324                 // See MainSim::RefreshSimValue(), 16 sep 2006
00325                 //if (pstruct->IsSet( OC_STRUCTURE_E ) == true)
00326                 //  _iValue++;
00327                 break;
00328 
00329             default: // keep gcc happy
00330                 break;
00331         }
00332 
00333         switch ( enumStructCode ) {
00334             case OC_STRUCTURE_EPLANT_COAL:
00335                 _iValueMax -= OC_EPLANT_COAL_POWER;
00336                 _uiNumberEPlant--;
00337 
00338                // search for the pair of mainW, mainH in
00339                // the "vectorpairuiEPlant"
00340                // and delete it if found
00341 
00342                 iter = std::find( vectorpairuiEPlant.begin(),
00343                           vectorpairuiEPlant.end(),
00344                           make_pair( mainW, mainH ) );
00345                 if ( iter != vectorpairuiEPlant.end() )
00346                     vectorpairuiEPlant.erase( iter );
00347                 break;
00348 
00349             default: // keep gcc happy
00350                 break;
00351         }
00352     }
00353 }
00354 
00355 
00356    /*=====================================================================*/
00357 bool
00358 ElectricitySim::dequeContain( const pair<uint, uint> & pairui )
00359 {
00360     if (find( this->dequepairui.begin(),  this->dequepairui.end(), pairui )
00361         != this->dequepairui.end())
00362         return true;
00363     else
00364         return false;
00365 }
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 

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