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

city.cpp

00001 /***************************************************************************
00002                             city.cpp  -  description
00003                                 -------------------
00004     begin                : mer mai 28 2003
00005     copyright            : (C) 2003-2006 by Duong-Khang NGUYEN
00006     email                : neoneurone @ users sourceforge net
00007 
00008     $Id: city.cpp 78 2006-11-02 20:38:34Z 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 "city.h"
00021 #include "vehicle.h"
00022 #include "mainsim.h"                // simulator
00023 #include "structure.h"
00024 #include "buildinglayer.h"
00025 #include "guibutton.h"              // GUI management
00026 #include "guicontainer.h"
00027 #include "agentpolice.h"
00028 #include "agentdemonstrator.h"
00029 #include "agentrobber.h"
00030 
00031 #include "globalvar.h"
00032 extern GlobalVar gVars;
00033 
00034 #include <sstream>                  // For text output with data conversion
00035 
00036 #define OC_ACTION_FACTOR 10
00037 
00038 
00039    /*=====================================================================*/
00040 City::City(
00041     const uint width,
00042     const uint length,
00043     const OC_DATE foundedDate,
00044     const int difficulty ):
00045 strCityName("OpenCity"),
00046 iDifficulty( difficulty ),
00047 strFileName(""),
00048 cityFoundedDate( foundedDate ),
00049 _liCityFund( OC_FUND_START ),
00050 boolModified( false ),
00051 
00052 _uiDay( 1 ),
00053 _uiMonth( 1 ),
00054 _uiYear( 0 ),
00055 
00056 _cTool('N'),
00057 _uiWidth( width ),
00058 _uiLength( length ),
00059 
00060 boolLMBPressed( false ),
00061 enumCurrentLayer( BUILDING_LAYER ),
00062 enumCurrentSpeed( NORMAL_SPEED ),
00063 enumCurrentTool( OC_NONE )
00064 {
00065     OPENCITY_DEBUG( "City ctor - default parameters" );
00066 
00067 // set the windows's WH
00068     iWinWidth = SDL_GetVideoSurface()->w;
00069     iWinHeight = SDL_GetVideoSurface()->h;
00070 
00071 // registering our call-back interface for SDL events' treatment
00072     ocSetNewUI( this );
00073 
00074 // keyboard bool table's initialization
00075     for (int i = 0; i < KEY_NUMBER; i++)
00076         this->booltabKeyPressed[i] = false;
00077 
00078 // Layers' initialization
00079     ptabLayer[ BUILDING_LAYER ] = new BuildingLayer( *this );
00080     gVars.gpMapMgr->SetLayer( ptabLayer[BUILDING_LAYER] );
00081 
00082 // Pathfinder initialization
00083     gVars.gpPathFinder = new PathFinder(
00084         gVars.gpmutexSim,
00085         (BuildingLayer*)ptabLayer[ BUILDING_LAYER ],
00086         gVars.gpMapMgr,
00087         _uiWidth, _uiLength );
00088 
00089 // Debug toolcircle
00090     boolPathGo = false;
00091     uiPathStartW = 0; uiPathStartH = 0;
00092     uiPathStopW = 0; uiPathStopH = 0;
00093     pctrPath = new GUIContainer( 100, 100, 140, 140 );
00094     pbtnPathStart = new GUIButton( 20,  20,  30, 30, ocHomeDirPrefix( "graphism/gui/raise" ));
00095     pbtnPathStop1 = new GUIButton( 60,  0,   30, 30, ocHomeDirPrefix( "graphism/gui/lower" ));
00096     pbtnPathStop2 = new GUIButton( 100, 20,  30, 30, ocHomeDirPrefix( "graphism/gui/lower" ));
00097     pbtnTestBuilding = new GUIButton(  20,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/residential" ));
00098     pctrPath->Add( pbtnPathStart );
00099     pctrPath->Add( pbtnPathStop1 );
00100     pctrPath->Add( pbtnPathStop2 );
00101     pctrPath->Add( pbtnTestBuilding );
00102     pvehicle = NULL;
00103 //  pMoveMgr = new MovementManager( gVars.gpGraphicMgr, gVars.gpMapMgr );
00104 
00105 // Simulators' initialization
00106     _CreateSimulator();
00107 
00108 // create the GUI
00109     _CreateGUI();
00110 }
00111 
00112 
00113    /*=====================================================================*/
00114 City::~City(  ){
00115     OPENCITY_DEBUG( "City dtor" );
00116 
00117 // delete the GUI
00118     _DeleteGUI();
00119 
00120 // delete all the simulators
00121     _DeleteSimulator();
00122 
00123 // testing, delete the pathfinder
00124     delete pctrPath;
00125     delete pbtnTestBuilding;
00126     delete pbtnPathStart;
00127     delete pbtnPathStop1;
00128     delete pbtnPathStop2;
00129     delete gVars.gpPathFinder;
00130     gVars.gpPathFinder = NULL;
00131 //  delete pvehicle; // not needed, it is done automatically by deleting pMoveMgr
00132 //  delete pMoveMgr;
00133 
00134 // delete only the BUILDING_LAYER instead of delete [] ptabLayer
00135     delete ptabLayer[ BUILDING_LAYER ];
00136 // this must be done AFTER deleting the layers
00137 //  delete gVars.gpMapMgr;
00138 }
00139 
00140 
00141    /*=====================================================================*/
00142 void
00143 City::SaveTo( std::fstream& rfs )
00144 {
00145     OPENCITY_DEBUG( __PRETTY_FUNCTION__ << "saving" );
00146 
00147     rfs << _liCityFund << std::ends;
00148     rfs << _uiDay << std::ends;
00149     rfs << _uiMonth << std::ends;
00150     rfs << _uiYear << std::ends;
00151     rfs << _uiWidth << std::ends;
00152     rfs << _uiLength << std::ends;
00153 }
00154 
00155 
00156    /*=====================================================================*/
00157 void
00158 City::LoadFrom( std::fstream& rfs )
00159 {
00160     OPENCITY_DEBUG( __PRETTY_FUNCTION__ << "loading" );
00161 
00162     rfs >> _liCityFund; rfs.ignore();
00163     rfs >> _uiDay; rfs.ignore();
00164     rfs >> _uiMonth; rfs.ignore();
00165     rfs >> _uiYear; rfs.ignore();
00166     rfs >> _uiWidth; rfs.ignore();
00167     rfs >> _uiLength; rfs.ignore();
00168 }
00169 
00170 
00171    /*=====================================================================*/
00172 void City::SetCurrentLayer( OPENCITY_CITY_LAYER enumNewLayer )
00173 {}
00174 
00175 
00176    /*=====================================================================*/
00177 void City::Run( OPENCITY_CITY_SPEED enumSpeed )
00178 {
00179     static uint uiNumberFrame = 0;
00180     static ostringstream ossStatus;
00181     static bool boolKeyDown;
00182     static int iMouseX, iMouseY;
00183 
00184 // if another speed is requested, we switch to it
00185     if (enumSpeed != LAST_SPEED) {
00186         enumCurrentSpeed = enumSpeed;
00187     }
00188 
00189 // now treat keys such as: up, down, left, right etc..
00190     boolKeyDown = _HandleKeyPressed();
00191 
00192 // if the mouse reach the border of the screen, translate the map
00193     _HandleMouseXY();
00194 
00195 // NOTE:We can move the following part to City::uiMouseMotion
00196 // however, in this case City::uiMouseMotion is called each time
00197 // when the mouse moves, and this is no good
00198 // user is dragging
00199     if ((this->boolLMBPressed == true)
00200     && (enumCurrentTool != OC_NONE )) {
00201     // is the user dragging with the left mouse button ?
00202         if ( SDL_GetMouseState( &iMouseX, &iMouseY ) & SDL_BUTTON(1) ) {
00203             gVars.gpRenderer->GetSelectedWHFrom(
00204                 iMouseX, iMouseY,
00205                 this->uiMapW2, this->uiMapL2,
00206                 gVars.gpMapMgr, this->ptabLayer[ enumCurrentLayer ] );
00207 
00208         // draw the map with the highlighted area
00209             gVars.gpRenderer->DisplayHighlight(
00210                 gVars.gpMapMgr, ptabLayer[ enumCurrentLayer ],
00211                 this->uiMapW1, this->uiMapL1,
00212                 this->uiMapW2, this->uiMapL2,
00213                 enumCurrentTool );
00214 
00215             goto cityrun_swap;
00216         }
00217     }
00218 
00219 
00220 //cityrun_display:
00221 // Display the screen as usual
00222     gVars.gpRenderer->Display( gVars.gpMapMgr, ptabLayer[ enumCurrentLayer ] );
00223 
00224 
00225 cityrun_swap:
00226 // Display build preview
00227     _BuildPreview();
00228 
00229 // Display the city's funds
00230     ossStatus.str("");
00231     ossStatus << _liCityFund << " @";
00232     gVars.gpRenderer->DisplayText( 10, this->iWinHeight-15, OC_WHITE_COLOR, ossStatus.str() );
00233 // Display the R value
00234     ossStatus.str("");
00235     ossStatus << _pMSim->GetValue(MainSim::OC_MICROSIM_RES);
00236     gVars.gpRenderer->DisplayText( 120, this->iWinHeight-15, OC_GREEN_COLOR, ossStatus.str() );
00237 // display the C value
00238     ossStatus.str("");
00239     ossStatus << _pMSim->GetValue(MainSim::OC_MICROSIM_COM);
00240     gVars.gpRenderer->DisplayText( 180, this->iWinHeight-15, OC_BLUE_COLOR, ossStatus.str() );
00241 // display the I value
00242     ossStatus.str("");
00243     ossStatus << _pMSim->GetValue(MainSim::OC_MICROSIM_IND);
00244     gVars.gpRenderer->DisplayText( 240, this->iWinHeight-15, OC_YELLOW_COLOR, ossStatus.str() );
00245 // display the E value
00246     ossStatus.str("");
00247     ossStatus << _pMSim->GetValue(MainSim::OC_MICROSIM_ELE);
00248     gVars.gpRenderer->DisplayText( 300, this->iWinHeight-15, OC_PINK_COLOR, ossStatus.str() );
00249 
00250 // display the tool
00251     ossStatus.str("");
00252     ossStatus << "Tool: " << _cTool;
00253     gVars.gpRenderer->DisplayText( 550, this->iWinHeight-15, OC_WHITE_COLOR, ossStatus.str() );
00254 
00255 // display the date
00256     ossStatus.str("");
00257     ossStatus << _uiDay << "/" << _uiMonth << "/" << _uiYear;
00258     gVars.gpRenderer->DisplayText( 650, this->iWinHeight-15, OC_WHITE_COLOR, ossStatus.str() );
00259 
00260 // Send the movement manager the move order 
00261 // then display all the contained movements
00262     gVars.gpMoveMgr->Move();
00263     gVars.gpMoveMgr->Display();
00264 
00265 // FIXME: buggy MAS environment
00266 //  gVars.gpEnvironment->displayAgent();
00267 
00268 // display the current container
00269     pctr->Display();
00270 
00271 // display everything now
00272     SDL_GL_SwapBuffers();
00273 
00274 //cityrun_return:
00275     if ( ++uiNumberFrame*gVars.guiMsPerFrame > OC_MS_PER_DAY ) {
00276     // next day
00277         if ( ++_uiDay > 30 ) {
00278         // next month
00279             _uiDay = 1;
00280             if ( ++_uiMonth > 12 ) {
00281             // next year
00282                 _uiMonth = 1;
00283                 _uiYear++;
00284                 _DoBill( OC_INCOME );
00285             }
00286             else {
00287                 _DoBill( OC_MAINTENANCE_COST );
00288             }
00289         }
00290         uiNumberFrame = 0;
00291 
00292     // auto play background music
00293         if (gVars.gpAudioMgr->PlayingMusic() == false) {
00294             gVars.gpAudioMgr->PlayNextMusic();
00295         }
00296     }
00297 
00298 }
00299 
00300 
00301    /*=====================================================================*/
00302 Layer*
00303 City::GetLayer( OPENCITY_CITY_LAYER enumLayer ) const
00304 {
00305     return this->ptabLayer[ enumLayer ];
00306 }
00307 
00308 
00309    /*=====================================================================*/
00310 const void
00311 City::GetWL(
00312     uint & w, uint & l ) const
00313 {
00314     w = _uiWidth;
00315     l = _uiLength;
00316 }
00317 
00318 
00319    /*=====================================================================*/
00320    /*                    BASE CLASS 'UI' IMPLEMENTATION                   */
00321    /*=====================================================================*/
00322 
00323 
00324 
00325    /*=====================================================================*/
00326 void City::uiKeyboard(
00327     const SDL_KeyboardEvent & rcsSDLKeyboardEvent )
00328 {
00329 //  OPENCITY_DEBUG( "Keydown event received" );
00330 
00331 // SDL_KEYDOWN or SDL_PRESSED
00332     if (rcsSDLKeyboardEvent.type == SDL_KEYDOWN) {
00333     // test if ALT is pressed
00334         if (rcsSDLKeyboardEvent.keysym.mod & KMOD_ALT) {
00335             this->booltabKeyPressed[KEY_ALT] = true;
00336         }
00337 
00338     // key symbols treatment
00339         switch (rcsSDLKeyboardEvent.keysym.sym) {
00340         case SDLK_PAGEUP:
00341             this->booltabKeyPressed[KEY_PAGEUP] = true;
00342             break;
00343         case SDLK_PAGEDOWN:
00344             this->booltabKeyPressed[KEY_PAGEDOWN] = true;
00345             break;
00346 
00347         case SDLK_UP:
00348             this->booltabKeyPressed[KEY_UP] = true;
00349             break;
00350         case SDLK_DOWN:
00351             this->booltabKeyPressed[KEY_DOWN] = true;
00352             break;
00353         case SDLK_RIGHT:
00354             this->booltabKeyPressed[KEY_RIGHT] = true;
00355             break;
00356         case SDLK_LEFT:
00357             this->booltabKeyPressed[KEY_LEFT] = true;
00358             break;
00359 
00360     // test networking support, connect to the localhost
00361         case SDLK_t:
00362             OPENCITY_NET_CODE netCode;
00363             netCode = gVars.gpNetworking->Open( gVars.gsZenServer );
00364             switch (netCode) {
00365                 case OC_NET_CLIENT_CONNECTED:
00366                     OPENCITY_INFO( "OpenCity is already connected to a server." );
00367                     break;
00368                 case OC_NET_CLIENT_ACCEPTED:
00369                     OPENCITY_INFO( "The connection request has been accepted." );
00370                     break;
00371                 case OC_NET_CLIENT_REJECTED:
00372                     OPENCITY_INFO( "The connection request has been rejected. Is the server full ?" );
00373                     break;
00374                 default:
00375                     OPENCITY_INFO( "The connection to \"" << gVars.gsZenServer << "\" has failed." );
00376             }
00377             break;
00378 
00379         case SDLK_n:  // set the tool to "None"
00380             enumCurrentTool = OC_NONE;
00381             _cTool = 'N';
00382             break;
00383         case SDLK_r:  // set tool for "zone residential"
00384             enumCurrentTool = OC_ZONE_RES;
00385             _cTool = 'R';
00386             break;
00387         case SDLK_c:  // set tool for "zone commercial"
00388             enumCurrentTool = OC_ZONE_COM;
00389             _cTool = 'C';
00390             break;
00391         case SDLK_i:  // set tool for "zone industrial"
00392             enumCurrentTool = OC_ZONE_IND;
00393             _cTool = 'I';
00394             break;
00395 
00396         case SDLK_p:  // set tool for "building road"
00397             enumCurrentTool = OC_BUILD_ROAD;
00398             _cTool = 'P';
00399             break;
00400         case SDLK_l:  // set tool for building electric lines
00401             enumCurrentTool = OC_BUILD_ELINE;
00402             _cTool = 'L';
00403             break;
00404         case SDLK_e:  // set tool for building electric plants
00405             enumCurrentTool = OC_BUILD_EPLANT;
00406             _cTool = 'E';
00407             break;
00408 
00409         case SDLK_u:  // height up
00410             enumCurrentTool = OC_HEIGHT_UP;
00411             _cTool = 'U';
00412             break;
00413         case SDLK_d:  // height down
00414             enumCurrentTool = OC_HEIGHT_DOWN;
00415             _cTool = 'D';
00416             break;
00417         case SDLK_q:        //query tool
00418             enumCurrentTool = OC_QUERY;
00419             _cTool = 'Q';
00420             break;
00421 
00422 
00423         case SDLK_g:  // toggle grid on/off
00424             gVars.gpRenderer->ToggleGrid();
00425             break;
00426         case SDLK_k:  // toggle compass on/off
00427             gVars.gpRenderer->ToggleCompass();
00428             break;
00429         case SDLK_f:  // toggle wireframe on/off
00430             gVars.gpRenderer->ToggleWireFrame();
00431             break;
00432         case SDLK_o:  // toggle projection mode
00433             gVars.gpRenderer->ToggleProjection();
00434             break;
00435 
00436 
00437         case SDLK_INSERT: // zoom in
00438             this->booltabKeyPressed[KEY_INSERT] = true;
00439             break;
00440         case SDLK_DELETE: // zoom out
00441             this->booltabKeyPressed[KEY_DELETE] = true;
00442             break;
00443 
00444         case SDLK_x: // destroy
00445             enumCurrentTool = OC_DESTROY;
00446             _cTool = 'X';
00447             break;
00448 
00449 
00450     // manipulating the music player
00451         case SDLK_b:
00452             gVars.gpAudioMgr->PlayNextMusic();
00453             break;
00454 
00455         case SDLK_z:
00456             gVars.gpAudioMgr->PlayPreviousMusic();
00457             break;
00458 
00459         case SDLK_s:
00460             gVars.gpAudioMgr->ToggleSound();
00461             break;
00462 
00463         case SDLK_m:
00464             gVars.gpAudioMgr->ToggleMusic();
00465             break;
00466 
00467 
00468     // Save and load
00469         case SDLK_F2:
00470             _Save( ocSaveDirPrefix( "opencity.save" ) );
00471             break;
00472 
00473         case SDLK_F6:
00474             _Load( ocSaveDirPrefix( "opencity.save" ) );
00475             break;
00476 
00477 
00478         case SDLK_h:
00479             gVars.gpRenderer->Home();
00480             break;
00481         case SDLK_ESCAPE:
00482         // quit the program when ESCAPE is pressed
00483             ocQuit();
00484             break;
00485 
00486 #ifndef NDEBUG
00487     // Testing PathFinder
00488         case SDLK_a:
00489             pctr->ResetAttribute(
00490                 OC_GUIMAIN_CLICKED | OC_GUIMAIN_MOUSEOVER );
00491         // Avoid possible memory leak
00492             if ( pctr == pctrQ ) {
00493                 pctr = NULL;
00494                 delete pctrQ;
00495                 pctrQ = NULL;
00496             }
00497 
00498         // Toggle Main <-> Pathfinding toolcircle
00499             if ( pctr == pctrPath ) {
00500                 pctr = pctrMain;
00501             }
00502             else {
00503                 pctr = pctrPath;
00504             }
00505             if ( pctr->IsSet( OC_GUIMAIN_VISIBLE ) == false ) {
00506                 pctr->Set( OC_GUIMAIN_VISIBLE );
00507             }
00508             break;
00509 
00510     // MAS test toolcircle
00511         case SDLK_v:
00512             pctr->ResetAttribute(
00513                 OC_GUIMAIN_CLICKED | OC_GUIMAIN_MOUSEOVER );
00514         // Avoid possible memory leak
00515             if ( pctr == pctrQ ) {
00516                 pctr = NULL;
00517                 delete pctrQ;
00518                 pctrQ = NULL;
00519             }
00520 
00521         // Toggle Main <-> MAS toolcircle
00522             if ( pctr == pctrMAS ) {
00523                 pctr = pctrMain;
00524             }
00525             else {
00526                 pctr = pctrMAS;
00527             }
00528             if ( pctr->IsSet( OC_GUIMAIN_VISIBLE ) == false ) {
00529                 pctr->Set( OC_GUIMAIN_VISIBLE );
00530             }
00531             break;
00532 #endif
00533 
00534         default:
00535             break;
00536         }
00537     }
00538 // SDL_KEYUP or SDL_RELEASED
00539     else {
00540     // test if ALT is released
00541         if (!(rcsSDLKeyboardEvent.keysym.mod & KMOD_ALT)) {
00542             this->booltabKeyPressed[KEY_ALT] = false;
00543         }
00544 
00545     // other key symbols treatment
00546         switch (rcsSDLKeyboardEvent.keysym.sym) {
00547 
00548         case SDLK_PAGEUP:
00549             this->booltabKeyPressed[KEY_PAGEUP] = false;
00550             break;
00551         case SDLK_PAGEDOWN:
00552             this->booltabKeyPressed[KEY_PAGEDOWN] = false;
00553             break;
00554 
00555         case SDLK_UP:
00556             this->booltabKeyPressed[KEY_UP] = false;
00557             break;
00558         case SDLK_DOWN:
00559             this->booltabKeyPressed[KEY_DOWN] = false;
00560             break;
00561         case SDLK_RIGHT:
00562             this->booltabKeyPressed[KEY_RIGHT] = false;
00563             break;
00564         case SDLK_LEFT:
00565             this->booltabKeyPressed[KEY_LEFT] = false;
00566             break;
00567 
00568         case SDLK_INSERT: // zoom in
00569             this->booltabKeyPressed[KEY_INSERT] = false;
00570             break;
00571         case SDLK_DELETE: // zoom out
00572             this->booltabKeyPressed[KEY_DELETE] = false;
00573             break;
00574 
00575         default:
00576             break;
00577         } // switch
00578     } // key released
00579 
00580 }
00581 
00582 
00583    /*=====================================================================*/
00584 void
00585 City::uiMouseMotion(
00586     const SDL_MouseMotionEvent & rcsSDLMouseMotionEvent )
00587 {
00588 //  OPENCITY_DEBUG("Mouse moved");
00589     pctr->uiMouseMotion( rcsSDLMouseMotionEvent );
00590 }
00591 
00592 
00593    /*=====================================================================*/
00594 void
00595 City::uiMouseButton(
00596     const SDL_MouseButtonEvent & rcsMBE )
00597 {
00598 //  OPENCITY_DEBUG("Mouse button event received" );
00599 
00600 // Process the click concerning the GUI first
00601     pctr->uiMouseButton( rcsMBE );
00602     if ( pctr->GetClick() != 0 ) {
00603 //debug
00604 //cout << "clicked: " << pctr->GetClick() << endl;
00605         _HandleGUIClick();
00606         this->boolLMBPressed = false;
00607         return;
00608     }
00609 
00610 // The user didn't click on a GUI object so we look for clicks on the map
00611     switch (rcsMBE.state) {
00612         case SDL_PRESSED: {
00613             this->boolLMBPressed = false;
00614             if ((rcsMBE.button == SDL_BUTTON_LEFT)
00615                 && (gVars.gpRenderer->GetSelectedWHFrom(
00616                     rcsMBE.x, rcsMBE.y,
00617                     this->uiMapW1, this->uiMapL1,
00618                     gVars.gpMapMgr,
00619                     this->ptabLayer[ enumCurrentLayer ] ) == true ))
00620             {
00621                 this->boolLMBPressed = true;
00622 //debug begin
00623 //cout << "step one, coco " << endl;
00624 //cout << "W: " << uiMapW1 << "/" << "H: " << uiMapL1 << endl;
00625 //debug end
00626             } //if
00627 //debug begin
00628 //SDL_GL_SwapBuffers(); // uncomment this if you want to know how it works
00629 //SDL_Delay( 500 );
00630 //debug end
00631 
00632         // RMB (right mouse button) close/open the toolcircle
00633             if (rcsMBE.button == SDL_BUTTON_RIGHT) {
00634             // if the user has invoked "Query"
00635             // then we destroy it first
00636                 if (pctr == pctrQ) {
00637                     pctr = pctrMain;
00638                 // enable the visible bit
00639                 // since, it is disabled later, the main circletool
00640                 // won't be displayed
00641                     pctr->Set( OC_GUIMAIN_VISIBLE );
00642                     delete pctrQ;
00643                     pctrQ = NULL;       // YES, we need it
00644                 }
00645     
00646                 if (pctr->IsSet( OC_GUIMAIN_VISIBLE ) == true) {
00647                     pctr->Unset( OC_GUIMAIN_VISIBLE );
00648                 }
00649                 else {
00650                     pctr->SetLocation(
00651                         rcsMBE.x - 70,
00652                         iWinHeight - rcsMBE.y - 70 );
00653                     pctr->Set( OC_GUIMAIN_VISIBLE );
00654                 }
00655             }
00656     
00657         // Wheel button forward
00658             if (rcsMBE.button == 4) {
00659             // move right if CTRL pressed
00660                 if (SDL_GetModState() & KMOD_CTRL)
00661                     gVars.gpRenderer->MoveRight();
00662     
00663             // move up if SHIFT pressed
00664                 if (SDL_GetModState() & KMOD_SHIFT)
00665                     gVars.gpRenderer->MoveUp();
00666     
00667             // zoom in if nothing pressed
00668                 if (!(SDL_GetModState() & (KMOD_SHIFT | KMOD_CTRL)))
00669                     gVars.gpRenderer->ZoomIn();
00670             }
00671     
00672         // Wheel button backward
00673             if (rcsMBE.button == 5) {
00674             // move right if CTRL pressed
00675                 if (SDL_GetModState() & KMOD_CTRL)
00676                     gVars.gpRenderer->MoveLeft();
00677     
00678             // move up if SHIFT pressed
00679                 if (SDL_GetModState() & KMOD_SHIFT)
00680                     gVars.gpRenderer->MoveDown();
00681     
00682             // zoom in if nothing pressed
00683                 if (!(SDL_GetModState() & (KMOD_SHIFT | KMOD_CTRL)))
00684                     gVars.gpRenderer->ZoomOut();
00685             }
00686 
00687         break;
00688         } //case SDL_PRESSED
00689 
00690        //-------------------------------------------------------
00691         case SDL_RELEASED: {
00692             // If Ctrl not pressed, 
00693             // AND dragging enabled 
00694             // AND mouse button was correctly released in the map
00695             // THEN do tool
00696             if (!(SDL_GetModState() & KMOD_CTRL)
00697                 && (this->boolLMBPressed == true)
00698                 && gVars.gpRenderer->GetSelectedWHFrom(
00699                     rcsMBE.x, rcsMBE.y,
00700                     this->uiMapW2, this->uiMapL2,
00701                     gVars.gpMapMgr,
00702                     this->ptabLayer[ enumCurrentLayer ] ))
00703             {
00704 //debug
00705 //cout << "W2: " << uiMapW2 << "/" << "H2: "
00706 //     << uiMapL2 << endl;
00707 //test pathfinding
00708                 _TestPathfinding();
00709                 _DoTool( rcsMBE );
00710             } //if
00711             boolLMBPressed = false;
00712             break;
00713 
00714         } //case SDL_RELEASED
00715 
00716     } // switch
00717 }
00718 
00719 
00720    /*=====================================================================*/
00721 void
00722 City::uiExpose(
00723     const SDL_ExposeEvent & rcsSDLExposeEvent )
00724 {
00725     OPENCITY_DEBUG( "Expose event received" );
00726 
00727     gVars.gpRenderer->Display( gVars.gpMapMgr, ptabLayer[ enumCurrentLayer ] );
00728     pctr->uiExpose( rcsSDLExposeEvent );
00729 
00730     SDL_GL_SwapBuffers();
00731 }
00732 
00733 
00734    /*=====================================================================*/
00735 void City::uiResize( const SDL_ResizeEvent & rcsSDLResizeEvent )
00736 {
00737     OPENCITY_DEBUG( "Resize event received" );
00738 
00739     iWinWidth = rcsSDLResizeEvent.w;
00740     iWinHeight = rcsSDLResizeEvent.h;
00741 
00742 //---- set the new window's size ----
00743     gVars.gpRenderer->SetWinSize( iWinWidth, iWinHeight );
00744 
00745 // Not useful, since the screen is update on next frame
00746 //  gVars.gpRenderer->Display( gVars.gpMapMgr, ptabLayer[ enumCurrentLayer ] );
00747 //  SDL_GL_SwapBuffers();
00748 
00749 // tell the containers about the event
00750     pctrMain->uiResize( rcsSDLResizeEvent );
00751     pctrL->uiResize( rcsSDLResizeEvent );
00752     pctrT->uiResize( rcsSDLResizeEvent );
00753     pctrZ->uiResize( rcsSDLResizeEvent );
00754     pctrG->uiResize( rcsSDLResizeEvent );
00755     pctrN->uiResize( rcsSDLResizeEvent );
00756     pctrS->uiResize( rcsSDLResizeEvent );
00757     pctrPath->uiResize( rcsSDLResizeEvent );
00758     pctrMAS->uiResize( rcsSDLResizeEvent );
00759 }
00760 
00761 
00762 
00763 
00764 
00765 
00766 
00767 
00768 
00769 
00770 
00771 
00772 
00773 
00774    /*=====================================================================*/
00775    /*                        PRIVATE     METHODS                          */
00776    /*=====================================================================*/
00777 
00778 
00779 
00780 
00781 
00782 
00783 
00784 
00785 
00786 void City::_CreateSimulator()
00787 {
00788 // Simulators' initialization
00789     _pMSim = new MainSim( gVars.gpmutexSim, (BuildingLayer*)ptabLayer[ BUILDING_LAYER ], gVars.gpMapMgr );
00790 
00791 // now initialize simulators threads
00792     _pthreadMSim = SDL_CreateThread( Simulator::ThreadWrapper, _pMSim );
00793 
00794 //testing: how can I put funcTSim into the TrafficSim class ?
00795 //  int (*fn)(void*);
00796 //  fn = reinterpret_cast<int (*)(void*)>(&TrafficSim::Run);
00797 //  pthreadTSim = SDL_CreateThread( TrafficSim::Run, pTSim );
00798 
00799 // put all the simulators' threads into RUN state
00800     _pMSim->Run();
00801 }
00802 
00803 
00804    /*=====================================================================*/
00805 void
00806 City::_DeleteSimulator()
00807 {
00808     int iStatus;
00809 
00810 // put all the simulators' threads into RETURN state
00811     _pMSim->Return();
00812 
00813 // wait for simulator threads to end
00814     SDL_WaitThread( _pthreadMSim, &iStatus );
00815 
00816 // delete simulators at the end
00817     delete _pMSim;
00818 }
00819 
00820 
00821    /*=====================================================================*/
00822 void
00823 City::_CreateGUI()
00824 {
00825 // GUI main toolcircle
00826     pbtnZ = new GUIButton(  20,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/residential" ));
00827     pbtnS = new GUIButton( 100,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/save" ));
00828     pbtnL = new GUIButton(  20,  20, 30, 30, ocHomeDirPrefix( "graphism/gui/power" ));
00829     pbtnP = new GUIButton(  60,   0, 30, 30, ocHomeDirPrefix( "graphism/gui/road" ));
00830     pbtnX = new GUIButton(  100, 20, 30, 30, ocHomeDirPrefix( "graphism/gui/bulldozer" ));
00831     pbtnG = new GUIButton(  60, 100, 30, 30, ocHomeDirPrefix( "graphism/gui/government" ));
00832 
00833     pctrMain = new GUIContainer( 100, 100, 140, 140 );
00834     pctrMain->Add( pbtnZ );
00835     pctrMain->Add( pbtnS );
00836     pctrMain->Add( pbtnL );
00837     pctrMain->Add( pbtnP );
00838     pctrMain->Add( pbtnX );
00839     pctrMain->Add( pbtnG );
00840 
00841 
00842 // GUI Z toolcircle for RCI buttons
00843     pbtnZB = new GUIButton( 20,  80,  30, 30, ocHomeDirPrefix( "graphism/gui/back" ));
00844     pbtnZR = new GUIButton( 20,  20,  30, 30, ocHomeDirPrefix( "graphism/gui/residential" ));
00845     pbtnZC = new GUIButton( 60,  0,   30, 30, ocHomeDirPrefix( "graphism/gui/commercial" ));
00846     pbtnZI = new GUIButton( 100, 20,  30, 30, ocHomeDirPrefix( "graphism/gui/industrial" ));
00847 
00848     pctrZ = new GUIContainer( 100, 100, 140, 140 );
00849     pctrZ->Add( pbtnZB );
00850     pctrZ->Add( pbtnZR );
00851     pctrZ->Add( pbtnZC );
00852     pctrZ->Add( pbtnZI );
00853 
00854 
00855 // GUI L toolcircle ( electric lines, electric plants )
00856     pbtnLB = new GUIButton( 20,  20,  30, 30, ocHomeDirPrefix( "graphism/gui/back" ));
00857     pbtnLL = new GUIButton( 60,  0,   30, 30, ocHomeDirPrefix( "graphism/gui/power_line" ));
00858     pbtnLE = new GUIButton( 100, 20,  30, 30, ocHomeDirPrefix( "graphism/gui/power_plant" ));
00859 
00860     pctrL = new GUIContainer( 100, 100, 140, 140 );
00861     pctrL->Add( pbtnLB );
00862     pctrL->Add( pbtnLL );
00863     pctrL->Add( pbtnLE );
00864 
00865 
00866 // GUI T toolcircle ( raise, lower terrain )
00867     pbtnTU = new GUIButton( 20,  20,  30, 30, ocHomeDirPrefix( "graphism/gui/raise" ));
00868     pbtnTD = new GUIButton( 60,  0,   30, 30, ocHomeDirPrefix( "graphism/gui/lower" ));
00869     pbtnTB = new GUIButton( 100, 20,  30, 30, ocHomeDirPrefix( "graphism/gui/back" ));
00870     pbtnTX = new GUIButton( 20,  80,  30, 30, ocHomeDirPrefix( "graphism/gui/destroy" ));
00871     pbtnTQ = new GUIButton( 100,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/query" ));
00872 
00873     pctrT = new GUIContainer( 100, 100, 140, 140 );
00874     pctrT->Add( pbtnTB );
00875     pctrT->Add( pbtnTU );
00876     pctrT->Add( pbtnTD );
00877     pctrT->Add( pbtnTX );
00878     pctrT->Add( pbtnTQ );
00879 
00880 
00881 // GUI Gouvernement toolcircle ( park, education, hospital, police and fire )
00882     pbtnGB = new GUIButton(  60, 100, 30, 30, ocHomeDirPrefix( "graphism/gui/back" ));
00883     pbtnGP = new GUIButton(  20,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/park" ));
00884     pbtnGE = new GUIButton( 100,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/education" ));
00885     pbtnGH = new GUIButton(  20,  20, 30, 30, ocHomeDirPrefix( "graphism/gui/hospital" ));
00886     pbtnGL = new GUIButton(  60,   0, 30, 30, ocHomeDirPrefix( "graphism/gui/police" ));
00887     pbtnGF = new GUIButton(  100, 20, 30, 30, ocHomeDirPrefix( "graphism/gui/fire" ));
00888 
00889     pctrG = new GUIContainer( 100, 100, 140, 140 );
00890     pctrG->Add( pbtnGB );
00891     pctrG->Add( pbtnGP );
00892     pctrG->Add( pbtnGE );
00893     pctrG->Add( pbtnGH );
00894     pctrG->Add( pbtnGL );
00895     pctrG->Add( pbtnGF );
00896 
00897 
00898 // Create the nature container
00899     pbtnNB = new GUIButton(  20,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/back" ));
00900     pbtnNP = new GUIButton(  60, 100, 30, 30, ocHomeDirPrefix( "graphism/gui/park" ));
00901     pbtnNT = new GUIButton( 100,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/tree" ));
00902 
00903     pctrN = new GUIContainer( 100, 100, 140, 140 );
00904     pctrN->Add( pbtnNB );
00905     pctrN->Add( pbtnNP );
00906     pctrN->Add( pbtnNT );
00907 
00908 
00909 // Create save/load buttons and the container
00910     pbtnSL = new GUIButton(  20,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/save_load" ));
00911     pbtnSS = new GUIButton(  60, 100, 30, 30, ocHomeDirPrefix( "graphism/gui/save_save" ));
00912     pbtnSB = new GUIButton( 100,  80, 30, 30, ocHomeDirPrefix( "graphism/gui/back" ));
00913 
00914     pctrS = new GUIContainer( 100, 100, 140, 140 );
00915     pctrS->Add( pbtnSB );
00916     pctrS->Add( pbtnSS );
00917     pctrS->Add( pbtnSL );
00918 
00919 
00920 // MAS toolcircle
00921     pctrMAS = new GUIContainer( 100, 100, 140, 140 );
00922     pbtnMASPolice = new GUIButton( 20,  20,  30, 30, ocHomeDirPrefix( "graphism/gui/police" ));
00923     pbtnMASDemonstrator = new GUIButton( 60,  0,   30, 30, ocHomeDirPrefix( "graphism/gui/demonstrator" ));
00924     pbtnMASRobber = new GUIButton( 100, 20,  30, 30, ocHomeDirPrefix( "graphism/gui/robber" ));
00925     pctrMAS->Add( pbtnMASPolice );
00926     pctrMAS->Add( pbtnMASDemonstrator );
00927     pctrMAS->Add( pbtnMASRobber );
00928 
00929     pbtnMASRobber->Unset( OC_GUIMAIN_VISIBLE );
00930 
00931 // the current pctr points to the MAIN one
00932     pctr = pctrMain;
00933 
00934 // there isn't a query container
00935     pctrQ = NULL;
00936 }
00937 
00938 
00939    /*=====================================================================*/
00940 void
00941 City::_DeleteGUI()
00942 {
00943 // delete the Query container if needed
00944     if (pctrQ != NULL)
00945         delete pctrQ;
00946 
00947 // MAS toolcircle
00948     delete pctrMAS;
00949     delete pbtnMASRobber;
00950     delete pbtnMASDemonstrator;
00951     delete pbtnMASPolice;
00952 
00953 // Load/save toolcircle
00954     delete pctrS;
00955     delete pbtnSB;
00956     delete pbtnSS;
00957     delete pbtnSL;
00958 
00959 // Nature toolcircle
00960     delete pctrN;
00961     delete pbtnNB;
00962     delete pbtnNP;
00963     delete pbtnNT;
00964 
00965 // GUI G toolcircle ( park, education, hospital, police and fire )
00966     delete pctrG;
00967     delete pbtnGB;
00968     delete pbtnGP;
00969     delete pbtnGE;
00970     delete pbtnGH;
00971     delete pbtnGL;
00972     delete pbtnGF;
00973 
00974 // GUI T toolcircle ( raise, lower terrain )
00975     delete pctrT;
00976     delete pbtnTB;
00977     delete pbtnTU;
00978     delete pbtnTD;
00979     delete pbtnTX;
00980     delete pbtnTQ;
00981 
00982 // GUI L toolcircle ( electric lines, electric plants )
00983     delete pctrL;
00984     delete pbtnLB;
00985     delete pbtnLL;
00986     delete pbtnLE;
00987 
00988 // GUI Z toolcircle
00989     delete pctrZ;
00990     delete pbtnZB;
00991     delete pbtnZR;
00992     delete pbtnZC;
00993     delete pbtnZI;
00994 
00995 // GUI main toolcircle
00996     delete pctrMain;
00997     delete pbtnZ;
00998     delete pbtnS;
00999     delete pbtnL;
01000     delete pbtnP;
01001     delete pbtnX;
01002     delete pbtnG;
01003 }
01004 
01005 
01006    /*=====================================================================*/
01007 void
01008 City::_DoTool(
01009     const SDL_MouseButtonEvent & sdlMBEvent )
01010 {
01011     if ( enumCurrentTool == OC_NONE )
01012         return;
01013 
01014     static uint cost;
01015     static OPENCITY_ERR_CODE enumErrCode;
01016     static int w1, h1, w2, h2;
01017 
01018     Structure* pstruct = NULL;      // for MAS
01019 
01020     cost = 0;
01021     w1 = uiMapW1;
01022     h1 = uiMapL1;
01023     w2 = uiMapW2;
01024     h2 = uiMapL2;
01025     OPENCITY_SWAP( w1, w2, int );
01026     OPENCITY_SWAP( h1, h2, int );
01027 
01028 
01029 // we return if we don't have enough funds
01030     if (_liCityFund < 0)
01031         return;
01032 
01033 
01034 // block all the sim threads while modifying the game datas
01035     SDL_LockMutex( gVars.gpmutexSim );
01036 
01037     switch (this->enumCurrentTool) {
01038     case OC_ZONE_RES:
01039         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01040             BuildStructure(
01041                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01042                 OC_STRUCTURE_RES, cost )) == OC_ERR_FREE) {
01043             gVars.gpAudioMgr->PlaySound( OC_SOUND_RCI );
01044         }
01045         break;
01046 
01047     case OC_ZONE_COM:
01048         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01049             BuildStructure(
01050                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01051                 OC_STRUCTURE_COM, cost )) == OC_ERR_FREE) {
01052             gVars.gpAudioMgr->PlaySound( OC_SOUND_RCI );
01053         }
01054         break;
01055 
01056     case OC_ZONE_IND:
01057         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01058             BuildStructure(
01059                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01060                 OC_STRUCTURE_IND, cost )) == OC_ERR_FREE) {
01061             gVars.gpAudioMgr->PlaySound( OC_SOUND_RCI );
01062         }
01063         break;
01064 
01065     case OC_BUILD_ROAD:
01066         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01067             BuildStructure(
01068                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01069                 OC_STRUCTURE_ROAD, cost )) == OC_ERR_FREE) {
01070             gVars.gpAudioMgr->PlaySound( OC_SOUND_ROAD );
01071         }
01072         break;
01073 
01074     case OC_BUILD_ELINE:
01075         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01076             BuildStructure( 
01077                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01078                 OC_STRUCTURE_ELINE, cost )) == OC_ERR_FREE) {
01079             gVars.gpAudioMgr->PlaySound( OC_SOUND_ELINE );
01080         }
01081         break;
01082 
01083     case OC_BUILD_EPLANT:
01084         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01085             BuildStructure(
01086                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01087                 OC_STRUCTURE_EPLANT_COAL, cost )) == OC_ERR_FREE) {
01088             _pMSim->AddStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2, MainSim::OC_MICROSIM_ELE );
01089             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01090         }
01091         break;
01092 
01093     case OC_BUILD_PARK:
01094         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01095             BuildStructure(
01096                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01097                 OC_STRUCTURE_PARK, cost )) == OC_ERR_FREE) {
01098             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01099         }
01100         break;
01101 
01102     case OC_BUILD_FLORA:
01103         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01104             BuildStructure(
01105                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01106                 OC_STRUCTURE_FLORA, cost )) == OC_ERR_FREE) {
01107             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01108         }
01109         break;
01110 
01111     case OC_BUILD_FIRE:
01112         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01113             BuildStructure(
01114                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01115                 OC_STRUCTURE_FIREDEPT, cost )) == OC_ERR_FREE) {
01116 // not used         _pMSim->AddStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2, MainSim::OC_MICROSIM_ELE );
01117             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01118         }
01119         break;
01120 
01121     case OC_BUILD_POLICE:
01122         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01123             BuildStructure(
01124                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01125                 OC_STRUCTURE_POLICEDEPT, cost )) == OC_ERR_FREE) {
01126 // not used         _pMSim->AddStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2, MainSim::OC_MICROSIM_ELE );
01127             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01128         }
01129         break;
01130 
01131     case OC_BUILD_HOSPITAL:
01132         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01133             BuildStructure(
01134                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01135                 OC_STRUCTURE_HOSPITALDEPT, cost )) == OC_ERR_FREE) {
01136 // not used         _pMSim->AddStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2, MainSim::OC_MICROSIM_ELE );
01137             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01138         }
01139         break;
01140 
01141     case OC_BUILD_EDUCATION:
01142         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01143             BuildStructure(
01144                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01145                 OC_STRUCTURE_EDUCATIONDEPT, cost )) == OC_ERR_FREE) {
01146 // not used         _pMSim->AddStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2, MainSim::OC_MICROSIM_ELE );
01147             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01148         }
01149         break;
01150 
01151     case OC_BUILD_TEST_BUILDING:
01152         if ((enumErrCode = ptabLayer[ enumCurrentLayer ]->
01153             BuildStructure(
01154                 uiMapW1, uiMapL1, uiMapW2, uiMapL2,
01155                 OC_STRUCTURE_TEST, cost )) == OC_ERR_FREE) {
01156             gVars.gpAudioMgr->PlaySound( OC_SOUND_EPLANT );
01157         }
01158         break;
01159 
01160     case OC_BUILD_AGENT_POLICE:
01161         pstruct = ptabLayer[ BUILDING_LAYER ]->GetStructure( uiMapW1, uiMapL1 );
01162         if ((pstruct != NULL) && (pstruct->GetCode() == OC_STRUCTURE_ROAD))
01163         new AgentPolice(*gVars.gpKernel, *gVars.gpEnvironment, uiMapW1, uiMapL1);
01164         break;
01165 
01166     case OC_BUILD_AGENT_DEMONSTRATOR:
01167         pstruct = ptabLayer[ BUILDING_LAYER ]->GetStructure( uiMapW1, uiMapL1 );
01168         if ((pstruct != NULL) && (pstruct->GetCode() == OC_STRUCTURE_ROAD))
01169         new AgentDemonstrator(*gVars.gpKernel, *gVars.gpEnvironment, uiMapW1, uiMapL1);
01170         break;
01171 
01172     case OC_BUILD_AGENT_ROBBER:
01173         pstruct = ptabLayer[ BUILDING_LAYER ]->GetStructure( uiMapW1, uiMapL1 );
01174         if ((pstruct != NULL) && (pstruct->GetCode() == OC_STRUCTURE_ROAD))
01175         new AgentRobber(*gVars.gpKernel, *gVars.gpEnvironment, uiMapW1, uiMapL1);
01176         break;
01177 
01178 //FIXME: cost
01179     case OC_HEIGHT_UP:
01180         enumErrCode = gVars.gpMapMgr->ChangeHeight( uiMapW1, uiMapL1, OC_MAP_UP );
01181         if ( enumErrCode == OC_ERR_FREE ) {
01182             gVars.gpRenderer->boolHeightChange = true;
01183             cost = 5;       // Quick hack
01184         }
01185         break;
01186 
01187     case OC_HEIGHT_DOWN:
01188         enumErrCode = gVars.gpMapMgr->ChangeHeight( uiMapW1, uiMapL1, OC_MAP_DOWN );
01189         if ( enumErrCode == OC_ERR_FREE ) {
01190             gVars.gpRenderer->boolHeightChange = true;
01191             cost = 5;       // Quick hack
01192         }
01193         break;
01194 
01195     case OC_QUERY:
01196     // Delete the old query container
01197     // we don't need to assign it to NULL since
01198     // it will contain another value later
01199         if (pctrQ != NULL)
01200             delete pctrQ;
01201 
01202     // get the new query container
01203         pctrQ = ptabLayer[ enumCurrentLayer ]->
01204             QueryStructure( uiMapW1, uiMapL1 );
01205     // reset the old container
01206         pctr->ResetAttribute(
01207             OC_GUIMAIN_CLICKED | OC_GUIMAIN_MOUSEOVER );
01208         pctr->Unset( OC_GUIMAIN_VISIBLE );
01209     // show the informations queried
01210         pctr = pctrQ;
01211         pctr->SetLocation(
01212             sdlMBEvent.x - 70,
01213             iWinHeight - sdlMBEvent.y - 70 );
01214         pctr->Set( OC_GUIMAIN_VISIBLE );
01215         enumErrCode = OC_ERR_SOMETHING;     // avoid to calculate the cost
01216         break;
01217 
01218     case OC_DESTROY:
01219     // If it is a part of a bigger structure (an EPLANT for example),
01220     // the whole structure will be then destroyed
01221     // The following part tell the simulators to remove the collected data concerning
01222     // the structures which are going to be destroyed
01223         _pMSim->RemoveStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2 );
01224 
01225         enumErrCode = ptabLayer[ enumCurrentLayer ]->
01226             DestroyStructure( uiMapW1, uiMapL1, uiMapW2, uiMapL2, cost );
01227         break;
01228 
01229     default:
01230         enumErrCode = OC_ERR_SOMETHING;// which tool is this ?
01231     } // switch
01232 
01233 // now unlock the mutex and let the sims run
01234     SDL_UnlockMutex( gVars.gpmutexSim );
01235 
01236     if (enumErrCode == OC_ERR_FREE) {
01237         _liCityFund -= cost;
01238     }
01239 }
01240 
01241 
01242    /*=====================================================================*/
01243 bool
01244 City::_HandleKeyPressed()
01245 {
01246     static int actionFactor = 1;
01247     int key;
01248     bool boolKeyDown;
01249 
01250     if (this->booltabKeyPressed[KEY_ALT] == true) {
01251         actionFactor = OC_ACTION_FACTOR;
01252     }
01253     else {
01254         actionFactor = 1;
01255     }
01256 
01257 // there is no key pressed
01258     boolKeyDown = false;
01259 
01260 // look for pressed keys
01261     for (key = KEY_UP; key < KEY_NUMBER; key++) {
01262         if (this->booltabKeyPressed[key] == true) {
01263             switch (key) {
01264             case KEY_UP:
01265                 gVars.gpRenderer->MoveDown(actionFactor);
01266                 break;
01267             case KEY_DOWN:
01268                 gVars.gpRenderer->MoveUp(actionFactor);
01269                 break;
01270             case KEY_RIGHT:
01271                 gVars.gpRenderer->MoveLeft(actionFactor);
01272                 break;
01273             case KEY_LEFT:
01274                 gVars.gpRenderer->MoveRight(actionFactor);
01275                 break;
01276 
01277             case KEY_PAGEUP:
01278                 gVars.gpRenderer->RotateLeft(actionFactor);
01279                 break;
01280             case KEY_PAGEDOWN:
01281                 gVars.gpRenderer->RotateRight(actionFactor);
01282                 break;
01283 
01284             case KEY_INSERT: // zoom in
01285                 gVars.gpRenderer->ZoomIn();
01286                 break;
01287             case KEY_DELETE: // zoom out
01288                 gVars.gpRenderer->ZoomOut();
01289                 break;
01290             } // switch
01291 
01292         // there's at least one key pressed
01293             boolKeyDown = true;
01294         } // if
01295     } // for
01296 
01297 // tell the caller that there's whether at least a key pressed or not
01298     return boolKeyDown;
01299 }
01300 
01301 
01302    /*=====================================================================*/
01303 void
01304 City::_DoBill(
01305     const OPENCITY_PROPERTY_CODE & enumProperty )
01306 {
01307     uint maintenance;
01308     uint index, surface;
01309     Structure* pStruct;
01310     static uint income = 0;
01311 
01312     surface = _uiWidth * _uiLength;
01313     maintenance = 0;
01314     for (index = 0; index < surface; index++) {
01315         pStruct = ptabLayer[ BUILDING_LAYER ]->GetLinearStructure( index );
01316         if (pStruct != NULL)
01317             maintenance += gVars.gpPropertyMgr->Get( 
01318                 OC_MAINTENANCE_COST, pStruct->GetCode() );
01319     }
01320 
01321     _liCityFund -= maintenance;
01322 
01323 // accumulate the income each month
01324     income += (_pMSim->GetValue(MainSim::OC_MICROSIM_RES) * OC_R_INCOME_TAX / 100)
01325             + (_pMSim->GetValue(MainSim::OC_MICROSIM_COM) * OC_C_INCOME_TAX / 100)
01326             + (_pMSim->GetValue(MainSim::OC_MICROSIM_IND) * OC_I_INCOME_TAX / 100);
01327 
01328 // add the income only if we reach the end of the year
01329     if (enumProperty == OC_INCOME ) {
01330     // here is the gouvernment's help for this year :D
01331         income += income * OC_INCOME_HELP / 100;
01332 
01333         _liCityFund += income;
01334         income = 0;
01335     }
01336 }
01337 
01338 
01339    /*=====================================================================*/
01340 void
01341 City::_HandleGUIClick()
01342 {
01343     uint uiObject;
01344     GUIContainer* pctrOld;
01345     int iX, iY;
01346 
01347     pctrOld = pctr;
01348     uiObject = this->pctr->GetClick();
01349 
01350 // is this the main container ?
01351     if (pctr == pctrMain)
01352     switch (uiObject) {
01353         case 1: // switch to Z toolcircle
01354             pctr = pctrZ;
01355             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01356             break;
01357         case 2: // load/save toolcircle
01358             pctr = pctrS;
01359             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01360             break;
01361         case 3:  // L button, open the L toolcircle
01362             pctr = pctrL;
01363             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01364             break;
01365         case 4:  // P button, set tool for "building road"
01366             enumCurrentTool = OC_BUILD_ROAD;
01367             _cTool = 'P';
01368             break;
01369         case 5: // T button, open the T toolcircle
01370             pctr = pctrT;
01371             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01372             break;
01373         case 6: // G button, open the government toolcircle
01374             pctr = pctrG;
01375             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01376             break;
01377 
01378         default: // never reached
01379             OPENCITY_DEBUG( "WARNING: What's going wrong ?" );
01380             assert(0);
01381             break;
01382     }
01383 
01384 // the user clicked on the Zone toolcircle
01385     else if (pctr == pctrZ )
01386     switch (uiObject) {
01387         case 1: // back button, open the main toolcircle
01388             pctr = pctrMain;
01389             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01390             break;
01391         case 2: // R button
01392             enumCurrentTool = OC_ZONE_RES;
01393             _cTool = 'R';
01394             break;
01395         case 3:  // C button, set tool for "zone commercial"
01396             enumCurrentTool = OC_ZONE_COM;
01397             _cTool = 'C';
01398             break;
01399         case 4:  // I button, set tool for "zone industrial"
01400             enumCurrentTool = OC_ZONE_IND;
01401             _cTool = 'I';
01402             break;
01403 
01404         default:
01405             OPENCITY_DEBUG("Design error");
01406             assert( 0 );
01407             break;
01408     }
01409 
01410 // the user clicked on the eLectric toolcircle
01411     else if (pctr == pctrL)
01412     switch (uiObject) {
01413         case 1: // back button, open the main toolcircle
01414             pctr = pctrMain;
01415         // highlight the previous button under the mouse cursor
01416             pctr->Set( 3, OC_GUIMAIN_MOUSEOVER );
01417             break;
01418         case 2:  // L button, set tool for building electric lines
01419             enumCurrentTool = OC_BUILD_ELINE;
01420             _cTool = 'L';
01421             break;
01422         case 3:  // set tool for building electric plants
01423             enumCurrentTool = OC_BUILD_EPLANT;
01424             _cTool = 'E';
01425             break;
01426 
01427         default:
01428             OPENCITY_DEBUG( "WARNING: What's going wrong ?" );
01429             assert(0);
01430             break;
01431     }
01432 
01433 // the user clicked on the Terrain toolcircle
01434     else if (pctr == pctrT)
01435     switch (uiObject) {
01436         case 1: // back button, open the main toolcircle
01437             pctr = pctrMain;
01438             pctr->Set( 5, OC_GUIMAIN_MOUSEOVER );
01439             break;
01440         case 2:  // height up
01441             enumCurrentTool = OC_HEIGHT_UP;
01442             _cTool = 'U';
01443             break;
01444         case 3:  // height down
01445             enumCurrentTool = OC_HEIGHT_DOWN;
01446             _cTool = 'D';
01447             break;
01448         case 4:  // destroy tool
01449             enumCurrentTool = OC_DESTROY;
01450             _cTool = 'X';
01451             break;
01452         case 5: // query tool
01453             enumCurrentTool = OC_QUERY;
01454             _cTool = 'Q';
01455             break;
01456 
01457         default:
01458             OPENCITY_DEBUG( "WARNING: What's going wrong ?" );
01459             assert(0);
01460             break;
01461     }
01462 
01463 // the user clicked on the government toolcircle
01464     else if (pctr == pctrG)
01465     switch (uiObject) {
01466         case 1: // back button, open the main toolcircle
01467             pctr = pctrMain;
01468             pctr->Set( 6, OC_GUIMAIN_MOUSEOVER );
01469             break;
01470         case 2:  // nature toolcircle
01471             pctr = pctrN;
01472             pctr->Set( 1, OC_GUIMAIN_MOUSEOVER );
01473             break;
01474         case 3:
01475             enumCurrentTool = OC_BUILD_EDUCATION;
01476             _cTool = '?';
01477             break;
01478         case 4:
01479             enumCurrentTool = OC_BUILD_HOSPITAL;
01480             _cTool = '?';
01481             break;
01482         case 5:
01483             enumCurrentTool = OC_BUILD_POLICE;
01484             _cTool = '?';
01485             break;
01486         case 6:
01487             enumCurrentTool = OC_BUILD_FIRE;
01488             _cTool = '?';
01489             break;
01490 
01491         default:
01492             OPENCITY_DEBUG( "WARNING: Unknown command" );
01493             assert(0);
01494             break;
01495     }
01496 
01497 // the user clicked on the load/save toolcircle
01498     else if (pctr == pctrN)
01499     switch (uiObject) {
01500         case 1: // back button, open the government toolcircle
01501             pctr = pctrG;
01502             pctr->Set( 2, OC_GUIMAIN_MOUSEOVER );
01503             break;
01504         case 2:  // build park
01505             enumCurrentTool = OC_BUILD_PARK;
01506             _cTool = '?';
01507             break;
01508         case 3:  // build tree
01509             enumCurrentTool = OC_BUILD_FLORA;
01510             _cTool = '?';
01511             break;
01512 
01513         default:
01514             OPENCITY_DEBUG( "WARNING: Unknown tool" );
01515             assert(0);
01516             break;
01517     }
01518 
01519 // the user clicked on the load/save toolcircle
01520     else if (pctr == pctrS)
01521     switch (uiObject) {
01522         case 1: // back button, open the main toolcircle
01523             pctr = pctrMain;
01524             pctr->Set( 5, OC_GUIMAIN_MOUSEOVER );
01525             break;
01526         case 2:  // save
01527             _Save( ocSaveDirPrefix( "opencity.save" ) );
01528             break;
01529         case 3:  // load
01530             _Load( ocSaveDirPrefix( "opencity.save" ) );
01531             break;
01532 
01533         default:
01534             OPENCITY_DEBUG( "WARNING: Unknown command" );
01535             assert(0);
01536             break;
01537     }
01538 
01539 // the user clicked on the Path toolcircle
01540     else if (pctr == pctrPath)
01541     switch (uiObject) {
01542         case 1: // start button
01543             _cTool = 'N';
01544             enumCurrentTool = OC_NONE;
01545             boolPathGo = false;
01546 //debug cout << "changed to false" << endl;
01547             break;
01548         case 2: // stop button
01549             _cTool = 'N';
01550             enumCurrentTool = OC_NONE;
01551             boolPathGo = true;
01552             this->uiVehicleType = Vehicle::VEHICLE_BUS;
01553             break;
01554         case 3: // stop button
01555             _cTool = 'N';
01556             enumCurrentTool = OC_NONE;
01557             boolPathGo = true;
01558             this->uiVehicleType = Vehicle::VEHICLE_SPORT;
01559 //debug cout << "changed to true" << endl;
01560             break;
01561         case 4: // build test building
01562             enumCurrentTool = OC_BUILD_TEST_BUILDING;
01563             _cTool = '?';
01564             break;
01565         default:
01566             break;
01567     }
01568 
01569 // The user has clicked on the MAS toolcircle
01570     else if (pctr == pctrMAS)
01571     switch (uiObject) {
01572         case 1: // start button
01573             _cTool = 'N';
01574             enumCurrentTool = OC_BUILD_AGENT_POLICE;
01575             break;
01576         case 2: // stop button
01577             _cTool = 'N';
01578             enumCurrentTool = OC_BUILD_AGENT_DEMONSTRATOR;
01579             break;
01580         case 3: // stop button
01581             _cTool = 'N';
01582             enumCurrentTool = OC_BUILD_AGENT_ROBBER;
01583             break;
01584 
01585         default:
01586             break;
01587     }
01588 
01589 
01590 // if the container has been changed then we reset
01591 // the MouseOver & Clicked attributes
01592 // otherwise we reset only the Clicked attribute
01593     if (pctr != pctrOld) {
01594         pctrOld->ResetAttribute(
01595             OC_GUIMAIN_CLICKED | OC_GUIMAIN_MOUSEOVER );
01596         pctrOld->GetLocation( iX, iY );
01597         pctr->SetLocation( iX, iY );
01598         pctr->Set( OC_GUIMAIN_VISIBLE );
01599     }
01600     else {
01601         pctrOld->ResetAttribute(
01602             OC_GUIMAIN_CLICKED );
01603     }
01604     pctrOld->Unset( OC_GUIMAIN_VISIBLE );
01605 }
01606 
01607 
01608    /*=====================================================================*/
01609 void
01610 City::_HandleMouseXY()
01611 {
01612     #define OC_MOUSE_AUTOSCROLL 15
01613 
01614     static int mouseX, mouseY;
01615 
01616 // return immediately if the app doesn't have mouse focus
01617     if (!(SDL_GetAppState() & SDL_APPMOUSEFOCUS ))
01618         return;
01619 
01620     SDL_GetMouseState( &mouseX, &mouseY );
01621 
01622 // handle horizontal automatic map translation
01623     if ((mouseX < OC_MOUSE_AUTOSCROLL) && !(mouseY < OC_MOUSE_AUTOSCROLL))
01624         gVars.gpRenderer->MoveRight();
01625     if ((mouseX >= iWinWidth-OC_MOUSE_AUTOSCROLL) && !(mouseY < OC_MOUSE_AUTOSCROLL))
01626         gVars.gpRenderer->MoveLeft();
01627 
01628 // handle vertical automatic map translation
01629     if (!(mouseX < OC_MOUSE_AUTOSCROLL)
01630       &&!(mouseX >= iWinWidth-OC_MOUSE_AUTOSCROLL) && (mouseY < OC_MOUSE_AUTOSCROLL))
01631         gVars.gpRenderer->MoveDown();
01632     if ((mouseY >= iWinHeight-OC_MOUSE_AUTOSCROLL))
01633         gVars.gpRenderer->MoveUp();
01634 
01635 // handle map rotation
01636     if ((mouseX < OC_MOUSE_AUTOSCROLL) && (mouseY < OC_MOUSE_AUTOSCROLL))
01637         gVars.gpRenderer->RotateLeft();
01638 
01639     if ((mouseY < OC_MOUSE_AUTOSCROLL) && (mouseX >= iWinWidth-OC_MOUSE_AUTOSCROLL))
01640         gVars.gpRenderer->RotateRight();
01641 }
01642 
01643 
01644    /*=====================================================================*/
01645 void
01646 City::_TestPathfinding() {
01647     if (pctr == pctrPath)
01648         if (this->boolPathGo == false) {
01649             this->uiPathStartW = this->uiMapW2;
01650             this->uiPathStartH = this->uiMapL2;
01651         }
01652         else {
01653         //TODO: put this somewhere else
01654             vector<Destination> vdest;
01655     
01656             this->uiPathStopW = this->uiMapW2;
01657             this->uiPathStopH = this->uiMapL2;
01658     
01659         // Buses prefer short distance
01660             if (this->uiVehicleType == Vehicle::VEHICLE_BUS) {
01661                 gVars.gpPathFinder->findShortestPath(
01662                     uiPathStartW, uiPathStartH,
01663                     uiPathStopW, uiPathStopH,
01664                     vdest,
01665                     PathFinder::OC_DISTANCE );
01666             }
01667         // Sport vehicle prefer less traffic
01668             else if (this->uiVehicleType == Vehicle::VEHICLE_SPORT) {
01669                 gVars.gpPathFinder->findShortestPath(
01670                     uiPathStartW, uiPathStartH,
01671                     uiPathStopW, uiPathStopH,
01672                     vdest,
01673                     PathFinder::OC_TRAFFIC );
01674             }
01675     
01676         // Now create the new vehicle if a path was found
01677             if ( vdest.size() > 0 ) {
01678                 pvehicle = new Vehicle(
01679                     (Vehicle::VEHICLE_TYPE)this->uiVehicleType );
01680                 pvehicle->SetPath( vdest ); // path init
01681                 pvehicle->Start();      // vehicle init
01682                 if (gVars.gpMoveMgr->Add( pvehicle ) < 0) {
01683                     OPENCITY_DEBUG("MoveMgr full");
01684                     delete pvehicle;
01685                 }
01686             }
01687         }
01688 //debug: pathfinding
01689 /*
01690 cout << "StW: " << uiPathStartW << " / " << " StH: " << uiPathStartH
01691      << " SpW: " << uiPathStopW << " / " << "SpH: " << uiPathStopH << endl;
01692 */
01693 }
01694 
01695 
01696    /*=====================================================================*/
01697 void
01698 City::_BuildPreview()
01699 {
01700     static OPENCITY_STRUCTURE_CODE scode = OC_STRUCTURE_UNDEFINED;
01701     static OPENCITY_GRAPHIC_CODE gcode = OC_EMPTY;
01702     static OPENCITY_TOOL_CODE tcode = OC_NONE;
01703     static OPENCITY_ERR_CODE ecode = OC_ERR_FREE;
01704 
01705 
01706 // Get the corresponding structure code of the tool
01707     if (tcode != this->enumCurrentTool) {
01708         tcode = this->enumCurrentTool;
01709         switch (tcode) {
01710         /* not implemented yet
01711             case OC_ZONE_RES:
01712                 scode = OC_STRUCTURE_RES;
01713                 break;
01714             case OC_ZONE_COM:
01715                 scode = OC_STRUCTURE_COM;
01716                 break;
01717             case OC_ZONE_IND:
01718                 scode = OC_STRUCTURE_IND;
01719                 break;
01720             case OC_BUILD_ROAD:
01721                 scode = OC_STRUCTURE_ROAD;
01722                 break;  
01723             case OC_BUILD_ELINE:
01724                 scode = OC_STRUCTURE_ELINE;
01725                 break;
01726         */
01727     
01728             case OC_BUILD_EPLANT:
01729                 scode = OC_STRUCTURE_EPLANT_COAL;
01730                 break;
01731             case OC_BUILD_PARK:
01732                 scode = OC_STRUCTURE_PARK;
01733                 break;
01734             case OC_BUILD_FLORA:
01735                 scode = OC_STRUCTURE_FLORA;
01736                 break;
01737             case OC_BUILD_FIRE:
01738                 scode = OC_STRUCTURE_FIREDEPT;
01739                 break;
01740             case OC_BUILD_POLICE:
01741                 scode = OC_STRUCTURE_POLICEDEPT;
01742                 break;
01743             case OC_BUILD_HOSPITAL:
01744                 scode = OC_STRUCTURE_HOSPITALDEPT;
01745                 break;
01746             case OC_BUILD_EDUCATION:
01747                 scode = OC_STRUCTURE_EDUCATIONDEPT;
01748                 break;
01749         
01750             case OC_BUILD_TEST_BUILDING:
01751                 scode = OC_STRUCTURE_TEST;
01752                 break;
01753 
01754             default:
01755                 scode = OC_STRUCTURE_UNDEFINED;
01756                 break;
01757         } // switch
01758     } // if
01759 
01760 // Get the corresponding graphic code
01761     if ((scode != OC_STRUCTURE_UNDEFINED)
01762      && (this->boolLMBPressed == true)) {
01763         ecode = ptabLayer[ enumCurrentLayer ]->
01764             BuildPreview( uiMapW1, uiMapL1, scode, gcode );
01765 
01766         if (ecode == OC_ERR_FREE) {
01767             gVars.gpRenderer->DisplayBuildPreview(
01768                 uiMapW1, uiMapL1, OC_GREEN_COLOR, gcode );
01769         }
01770         else {
01771             gVars.gpRenderer->DisplayBuildPreview(
01772                 uiMapW1, uiMapL1, OC_RED_COLOR, gcode );
01773         }
01774     }
01775 }
01776 
01777 
01778    /*=====================================================================*/
01779 bool
01780 City::_Save( const string& strFilename )
01781 {
01782     fstream fs;
01783 
01784     fs.open( strFilename.c_str(), ios_base::out | ios_base::binary | ios_base::trunc );
01785     if (!fs.good()) {
01786         OPENCITY_DEBUG( "File opening error: " << strFilename );
01787         return false;
01788     }
01789 
01790 // Lock the simulator
01791     SDL_LockMutex( gVars.gpmutexSim );
01792 
01793 // Save city data
01794     this->SaveTo( fs );
01795 
01796 // Save map data
01797     gVars.gpMapMgr->SaveTo( fs );
01798 
01799 // Save layers's data
01800     ptabLayer[ BUILDING_LAYER ]->SaveTo( fs );
01801 
01802 // Save simulators data
01803     _pMSim->SaveTo( fs );
01804 
01805 // Unlock the simulator
01806     SDL_UnlockMutex( gVars.gpmutexSim );
01807 
01808     fs.close();
01809     return true;
01810 }
01811 
01812 
01813    /*=====================================================================*/
01814 bool
01815 City::_Load( const string& strFilename )
01816 {
01817     fstream fs;
01818     uint w, l;
01819 
01820     fs.open( strFilename.c_str(), ios_base::in | ios_base::binary );
01821     if (!fs.good()) {
01822         OPENCITY_DEBUG( "File opening error" << strFilename );
01823         return false;
01824     }
01825 
01826 // Lock the simulator
01827     SDL_LockMutex( gVars.gpmutexSim );
01828 
01829 // Remove all moving objects
01830     gVars.gpMoveMgr->Remove();
01831 
01832 // Load city data
01833     this->LoadFrom( fs );
01834 
01835 // Load map data
01836     gVars.gpMapMgr->LoadFrom( fs );
01837     gVars.gpRenderer->boolHeightChange = true;
01838 
01839 // Load layers' data
01840     ptabLayer[ BUILDING_LAYER ]->LoadFrom( fs );
01841 
01842 // Load simulators' data
01843     _pMSim->LoadFrom( fs );
01844 
01845 // Manually add the structures to the simulators
01846     for ( w = 0; w < _uiWidth; w++ ) {
01847         for ( l = 0; l < _uiLength; l++ ) {
01848             _pMSim->AddStructure( w, l, w, l );
01849         }
01850     }
01851 
01852 // Refresh/recalculate the simulators' value
01853     _pMSim->RefreshSimValue();
01854 
01855 // Unlock the simulator
01856     SDL_UnlockMutex( gVars.gpmutexSim );
01857 
01858     fs.close();
01859     return true;
01860 }
01861 
01862 
01863 
01864 
01865 
01866 
01867 
01868 
01869 
01870 
01871 
01872 
01873 
01874 
01875 
01876 
01877 
01878 
01879 
01880 
01881 
01882 
01883 
01884 
01885 
01886 
01887 
01888 
01889 
01890 
01891 
01892 
01893 
01894 
01895 
01896 

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