Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

sg.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                            sg.cpp  -  description
00003                              -------------------
00004     begin                : a long time ago...
00005     copyright            : (C) 1994-2003 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00014 /***************************************************************************
00015  *                                                                         *
00016  *   This program is free software; you can redistribute it and/or modify  *
00017  *   it under the terms of the GNU General Public License as published by  *
00018  *   the Free Software Foundation; either version 2 of the License, or     *
00019  *   (at your option) any later version.                                   *
00020  *                                                                         *
00021  ***************************************************************************/
00022 
00023 
00070 #include "global.h"
00071 
00072 #include <stdio.h>
00073 #include <stdlib.h>
00074 #include <new>
00075 #include <cstdlib>
00076 #include <ctype.h>
00077 #include <algorithm>
00078 #include <memory>
00079 
00080 #include <boost/regex.hpp>
00081 
00082 #include "paradialog.h"
00083 
00084 #include "vehicletype.h"
00085 #include "buildingtype.h"
00086 #include "ai/ai.h"
00087 #include "misc.h"
00088 #include "events.h"
00089 #include "typen.h"
00090 #include "spfst.h"
00091 #include "loaders.h"
00092 #include "dlg_box.h"
00093 #include "controls.h"
00094 #include "dlg_box.h"
00095 #include "dialog.h"
00096 #include "strtmesg.h"
00097 #include "gamedlg.h"
00098 #include "sg.h"
00099 #include "gameoptions.h"
00100 #include "loadimage.h"
00101 #include "astar2.h"
00102 #include "errors.h"
00103 #include "dialogs/pwd_dlg.h"
00104 #include "viewcalculation.h"
00105 #include "replay.h"
00106 #include "graphicset.h"
00107 #include "loadbi3.h"
00108 #include "itemrepository.h"
00109 #include "music.h"
00110 #include "messagedlg.h"
00111 #include "statisticdialog.h"
00112 #include "clipboard.h"
00113 #include "guifunctions.h"
00114 #include "iconrepository.h"
00115 #include "dashboard.h"
00116 #include "gamedialog.h"
00117 #include "unitset.h"
00118 
00119 #ifdef WEATHERGENERATOR
00120 # include "weathercast.h"
00121 #endif
00122 
00123 #include "asc-mainscreen.h"
00124 #include "dialogs/unitinfodialog.h"
00125 #include "messaginghub.h"
00126 #include "cannedmessages.h"
00127 #include "memorycheck.cpp"
00128 #include "networkinterface.h"
00129 #include "resourcenet.h"
00130 #include "mapimageexport.h"
00131 #include "loadpcx.h"
00132 #include "gameeventsystem.h"
00133 #include "sdl/sound.h"
00134 #include "soundList.h"
00135 #include "turncontrol.h"
00136 #include "networksupervisor.h"
00137 
00138 #include "dialogs/newgame.h"
00139 #include "dialogs/soundsettings.h"
00140 #include "dialogs/alliancesetup.h"
00141 #include "dialogs/unitcounting.h"
00142 #include "dialogs/editgameoptions.h"
00143 #include "dialogs/nextcampaignmap.h"
00144 #include "dialogs/terraininfo.h"
00145 #include "dialogs/editplayerdata.h"
00146 #include "dialogs/locatefile.h"
00147 #include "stdio-errorhandler.h"
00148 #include "widgets/textrenderer.h"
00149 #include "dialogs/productionanalysis.h"
00150 #include "dialogs/fileselector.h"
00151 #include "containerbase-functions.h"
00152 #include "memory-measurement.h"
00153 #include "dialogs/mailoptionseditor.h"
00154 
00155 #ifdef WIN32
00156 # include "win32/win32-errormsg.h"
00157 # include  "win32/msvc/mdump.h"
00158  MiniDumper miniDumper( "main" );
00159 # include <direct.h>
00160 # include <stdlib.h>
00161 # include <stdio.h>
00162 #endif
00163 
00164 tfield*        getSelectedField(void)
00165 {
00166    return actmap->getField( actmap->getCursor() ); 
00167 } 
00168 
00169 
00170 #define mmaintainence
00171 
00172 bool maintainencecheck( void )
00173 {
00174    int res = 0;
00175    if ( res )
00176       return true;
00177 
00178 #ifdef maintainence
00179    int num = 0;
00180 
00181    for ( int i = 0; i < 8; i++ )
00182       if ( actmap->player[i].stat == Player::human  && actmap->player[i].exist())
00183          num++;
00184 
00185    if ( actmap->campaign )
00186       num++;
00187 
00188    if ( actmap->network )
00189       num++;
00190 
00191    if ( num <= 1 )
00192       return 1;
00193    else
00194       return 0;
00195 
00196 #else
00197    return false;
00198 #endif
00199 }
00200 
00201 void positionCursor( Player& player )
00202 {
00203    getDefaultMapDisplay().displayPosition( player.getParentMap()->getCursor() );
00204 }
00205 
00206 void viewcomp( Player& player )
00207 {
00208    computeview( player.getParentMap() );
00209 }
00210 
00211 void hookGuiToMap( GameMap* map )
00212 {
00213    if ( !map->getGuiHooked() ) {
00214 
00215       map->sigPlayerUserInteractionBegins.connect( SigC::slot( &viewcomp ) );
00216       map->sigPlayerUserInteractionBegins.connect( SigC::hide<Player&>( repaintMap.slot() ));
00217       
00218       map->sigPlayerUserInteractionBegins.connect( SigC::slot( &positionCursor ));
00219       map->sigPlayerUserInteractionBegins.connect( SigC::hide<Player&>( SigC::slot( &checkforreplay )));
00220       map->sigPlayerUserInteractionBegins.connect( SigC::slot( &researchCheck ));
00221       map->sigPlayerUserInteractionBegins.connect( SigC::slot( &viewunreadmessages ));
00222       map->sigPlayerUserInteractionBegins.connect( SigC::slot( &checkJournal ));
00223       map->sigPlayerUserInteractionBegins.connect( SigC::slot( &checkUsedASCVersions ));
00224       map->sigPlayerUserInteractionBegins.connect( SigC::hide<Player&>( updateFieldInfo.slot() ));
00225       
00226       map->sigPlayerTurnHasEnded.connect( SigC::slot( viewOwnReplay));
00227 
00228       
00229       map->guiHooked();
00230    }
00231 }
00232 
00233 
00234 bool loadGame( const ASCString& filename )
00235 {
00236    GameMap* m = mapLoadingExceptionChecker( filename, MapLoadingFunction( tsavegameloaders::loadGameFromFile ));
00237    if ( !m )
00238       return false;
00239 
00240    delete actmap;
00241    actmap = m;
00242    actmap->levelfinished = false;
00243 
00244    if ( actmap->replayinfo ) {
00245       if ( actmap->replayinfo->actmemstream )
00246          displaymessage2( "actmemstream already open at begin of turn ",2 );
00247 
00248       if ( actmap->replayinfo->guidata[actmap->actplayer] )
00249          actmap->replayinfo->actmemstream = new tmemorystream ( actmap->replayinfo->guidata[actmap->actplayer], tnstream::appending );
00250       else {
00251          actmap->replayinfo->guidata[actmap->actplayer] = new tmemorystreambuf;
00252          actmap->replayinfo->actmemstream = new tmemorystream ( actmap->replayinfo->guidata[actmap->actplayer], tnstream::writing );
00253       }
00254    }
00255    
00256    computeview( actmap );
00257    hookGuiToMap ( actmap );
00258    return true;
00259 }
00260 
00261 
00262 bool loadGame( bool mostRecent )
00263 {
00264    ASCString s1;
00265    if ( mostRecent ) {
00266       int datefound = 0;
00267 
00268       tfindfile ff ( savegameextension );
00269       tfindfile::FileInfo fi;
00270       while ( ff.getnextname( fi ))
00271          if ( fi.date > datefound ) {
00272             datefound = fi.date;
00273             s1 = fi.name;
00274          }
00275    } else {
00276       s1 = selectFile( savegameextension, true );
00277    }
00278 
00279    if ( !s1.empty() ) {
00280       StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "loading " + s1 );
00281 
00282       loadGame( s1 );
00283       
00284       updateFieldInfo();
00285       positionCursor( actmap->getCurrentPlayer() );
00286       getDefaultMapDisplay().displayPosition( actmap->getCursor() );
00287       displaymap();
00288 
00289       moveparams.movestatus = 0;
00290       return true;
00291    } else
00292       return false;
00293 }
00294 
00295 
00296 void saveGame( bool as )
00297 {
00298    if ( !actmap )
00299       return;
00300 
00301    ASCString s1;
00302 
00303    int nameavail = 0;
00304    if ( !actmap->preferredFileNames.savegame[actmap->actplayer].empty() )
00305       nameavail = 1;
00306 
00307    if ( as || !nameavail ) {
00308       s1 = selectFile( savegameextension, false);
00309    } else
00310       s1 = actmap->preferredFileNames.savegame[actmap->actplayer];
00311 
00312    if ( !s1.empty() ) {
00313       actmap->preferredFileNames.savegame[actmap->actplayer] = s1;
00314 
00315       StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "saving " + s1 );
00316       savegame( s1 );
00317    }
00318 }
00319 
00320 
00321 
00322 
00323 
00324 
00325 void loadmap( const ASCString& name, bool campaign )
00326 {
00327    GameMap* m = mapLoadingExceptionChecker( name, MapLoadingFunction( tmaploaders::loadmap ));
00328    delete actmap;
00329    actmap = m;
00330    computeview( actmap );
00331    hookGuiToMap( actmap );
00332    if ( !campaign )
00333       actmap->campaign.avail = false;
00334 }
00335 
00336 
00337 enum MapTypeLoaded { None, Map, Savegame, Mailfile };
00338 
00339 MapTypeLoaded loadStartupMap ( const char *gameToLoad=NULL )
00340 {
00341    if ( gameToLoad && gameToLoad[0] ) {
00342       try {
00343          if ( patimat ( ASCString("*")+tournamentextension, gameToLoad )) {
00344 
00345             if( validateemlfile( gameToLoad ) == 0 )
00346                fatalError( "Email gamefile %s is invalid. Aborting.", gameToLoad );
00347 
00348             try {
00349 
00350                if ( continuenetworkgame( ASCString(gameToLoad) )) 
00351                   hookGuiToMap(actmap);
00352 
00353                return Mailfile;
00354             } catch ( tfileerror ) {
00355                fatalError ( "%s is not a legal email game.", gameToLoad );
00356             }
00357          } else if( patimat ( savegameextension, gameToLoad )) {
00358             if( validatesavfile( gameToLoad ) == 0 )
00359                fatalError ( "The savegame %s is invalid. Aborting.", gameToLoad );
00360 
00361             try {
00362                loadGame( gameToLoad );
00363                computeview( actmap );
00364                return Savegame;
00365             } catch ( tfileerror ) {
00366                fatalError ( "%s is not a legal savegame. ", gameToLoad );
00367             }
00368 
00369          } else if( patimat ( mapextension, gameToLoad )) {
00370             if( validatemapfile( gameToLoad ) == 0 )
00371                fatalError ( "Mapfile %s is invalid. Aborting.", gameToLoad );
00372 
00373             try {
00374                loadmap( gameToLoad, false );
00375             } catch ( tfileerror ) {
00376                fatalError ( "%s is not a legal map. ", gameToLoad );
00377             }
00378          } else
00379             fatalError ( "Don't know how to handle the file %s ", gameToLoad );
00380 
00381       }
00382       catch ( InvalidID err ) {
00383          displaymessage( err.getMessage(), 2 );
00384       } /* endcatch */
00385       catch ( tinvalidversion err ) {
00386          if ( err.expected < err.found )
00387             displaymessage( "File/module %s has invalid version.\nExpected version %d\nFound version %d\nPlease install the latest version from www.asc-hq.org", 2, err.getFileName().c_str(), err.expected, err.found );
00388          else
00389             displaymessage( "File/module %s has invalid version.\nExpected version %d\nFound version %d\nThis is a bug, please report it!", 2, err.getFileName().c_str(), err.expected, err.found );
00390       }
00391    } else {  // resort to loading defaults
00392 
00393       ASCString s = CGameOptions::Instance()->startupMap; 
00394 
00395       if ( s.empty() )
00396          s = "asc001.map";
00397 
00398 
00399       int maploadable;
00400       {
00401          tfindfile ff ( s );
00402          string filename = ff.getnextname();
00403          maploadable = validatemapfile ( filename );
00404       }
00405 
00406       if ( !maploadable ) {
00407 
00408          tfindfile ff ( mapextension );
00409          string filename = ff.getnextname();
00410 
00411          if ( filename.empty() )
00412             displaymessage( "unable to load startup-map",2);
00413 
00414          while ( !validatemapfile ( filename ) ) {
00415             filename = ff.getnextname();
00416             if ( filename.empty() )
00417                displaymessage( "unable to load startup-map",2);
00418 
00419          }
00420          s = filename;
00421       }
00422 
00423       loadmap( s, true );
00424       return Map;
00425       displayLogMessage ( 6, "done\n" );
00426    }
00427 
00428    return None;
00429 }
00430 
00431 
00432 void         startnextcampaignmap( int id)
00433 {
00434    GameMap* map = nextCampaignMap( id );
00435    delete actmap;
00436    actmap = map;
00437 
00438    if ( actmap ) {
00439       computeview( actmap );
00440       hookGuiToMap( actmap );
00441       repaintMap();
00442    }
00443 }
00444 
00445 
00446 void benchgame ( bool withViewCalc )
00447 {
00448    int t2;
00449    int t = ticker;
00450    int n = 0;
00451    do {
00452       if ( withViewCalc ) 
00453          computeview( actmap );
00454 
00455       repaintMap();
00456             
00457       n++;
00458       t2 = ticker;
00459    } while ( t + 1000 > t2 ); /* enddo */
00460    double d = 100 * n;
00461    d /= (t2-t);
00462    char buf[100];
00463    sprintf ( buf, "%3.1f fps", d );
00464    infoMessage ( buf );
00465 }
00466 
00467 
00468 void showSearchPath()
00469 {
00470 
00471    ASCString s = "#fontsize=17#ASC search path#fontsize=13#\n";
00472       for ( int i = 0; i < getSearchPathNum(); ++i )
00473          s += getSearchPath ( i ) + "\n"; 
00474 
00475       s += "\n";
00476       s += "Configuration file used: \n";
00477       s += getConfigFileName();
00478 
00479 #ifdef WIN32
00480      char buffer[_MAX_PATH];
00481 
00482      if( _getcwd( buffer, _MAX_PATH ) ) {
00483         s += "\n#fontsize=17#Current working directory#fontsize=13#\n";
00484          s += buffer;
00485      }
00486 #endif
00487 
00488      s += "\n\n#fontsize=17#Mounted archive files#fontsize=13#\n";
00489      s += listContainer();
00490 
00491 
00492      ViewFormattedText vft("ASC directories", s, PG_Rect( -1, -1, 400, 400 ));
00493      vft.Show();
00494      vft.RunModal();
00495 }
00496 
00497 
00498 
00499 void changePassword( GameMap* gamemap )
00500 {
00501    if ( Player::getHumanPlayerNum( gamemap) < 2 ) {
00502       infoMessage ("Passwords are only used for multiplayer games");
00503       return;
00504    }
00505 
00506    bool success;
00507    do {
00508       Password oldpwd = gamemap->player[gamemap->actplayer].passwordcrc;
00509       gamemap->player[gamemap->actplayer].passwordcrc.reset();
00510       success = enterpassword ( gamemap->player[gamemap->actplayer].passwordcrc, true, true );
00511       if ( !success )
00512          gamemap->player[gamemap->actplayer].passwordcrc = oldpwd;
00513    } while ( gamemap->player[gamemap->actplayer].passwordcrc.empty() && success && viewtextquery ( 910, "warning", "~e~nter password", "~c~ontinue without password" ) == 0 ); /* enddo */
00514 }
00515 
00516 void showSDLInfo()
00517 {
00518 #ifdef _SDL_
00519    ASCString s;
00520    s += "#fontsize=18#SDL versions#fontsize=14#\n";
00521    char buf[1000];
00522    SDL_version compiled;
00523    SDL_VERSION(&compiled);
00524    sprintf(buf, "\nCompiled with SDL version: %d.%d.%d\n", compiled.major, compiled.minor, compiled.patch);
00525    s += buf;
00526 
00527    sprintf(buf, "Linked with SDL version: %d.%d.%d\n", SDL_Linked_Version()->major, SDL_Linked_Version()->minor, SDL_Linked_Version()->patch);
00528    s += buf;
00529 
00530    s += "Byte order is ";
00531 #if SDL_BYTEORDER==SDL_LIL_ENDIAN
00532    s += "little endian\n";
00533 #else
00534 #if SDL_BYTEORDER==SDL_BIG_ENDIAN
00535    s += "big endian\n";
00536 #else
00537    s += "undefined\n";
00538 #endif
00539 #endif
00540   
00541    s += "Graphics backend: ";
00542    s += SDL_VideoDriverName( buf, 1000 );
00543    s += "\n";
00544 
00545 
00546    const SDL_VideoInfo* videoInfo = SDL_GetVideoInfo();
00547    s += "VideoInfo: \n";
00548 
00549    s += "Hardware surfaces available: ";
00550    s += videoInfo->hw_available ? "yes" : "no";
00551 
00552 
00553    s += "\nScreen uses hardware surface: ";
00554    s += PG_Application::GetScreen()->flags & SDL_HWSURFACE ? "yes" : "no";
00555 
00556    s += "\nWindow manager available: ";
00557    s += videoInfo->wm_available ? "yes" : "no";
00558 
00559    s += "\nhardware to hardware blits accelerated: ";
00560    s += videoInfo->blit_hw ? "yes" : "no";
00561 
00562    s += "\nhardware to hardware colorkey blits accelerated: ";
00563    s += videoInfo->blit_hw_CC ? "yes" : "no";
00564 
00565    s += "\nhardware to hardware alpha blits accelerated: ";
00566    s += videoInfo->blit_hw_A ? "yes" : "no";
00567 
00568    s += "\nsoftware to hardware blits accelerated: ";
00569    s += videoInfo->blit_sw ? "yes" : "no";
00570 
00571    s += "\nsoftware to hardware colorkey blits accelerated: ";
00572    s += videoInfo->blit_sw_CC ? "yes" : "no";
00573 
00574    s += "\nsoftware to hardware alpha blits accelerated: ";
00575    s += videoInfo->blit_sw_A ? "yes" : "no";
00576 
00577    s += "\ncolor fills accelerated: ";
00578    s += videoInfo->blit_fill ? "yes" : "no";
00579 
00580    s += "\nVideo memory: ";
00581    s += ASCString::toString( int(videoInfo->video_mem ));
00582 
00583    ViewFormattedText vft( "SDL Settings", s, PG_Rect(-1,-1,450,550));
00584    vft.Show();
00585    vft.RunModal();
00586 #endif
00587 }
00588 
00589 void helpAbout()
00590 {
00591    ASCString s = "#fontsize=22#Advanced Strategic Command#fontsize=14#\n";
00592    s += getVersionAndCompilation();
00593 
00594    s += "\n#fontsize=18#Credits#fontsize=14#\n";
00595 
00596    s += readtextmessage( 30 );
00597                      
00598    ViewFormattedText vft( "About", s, PG_Rect(-1,-1,450,550));
00599    vft.Show();
00600    vft.RunModal();
00601 }
00602 
00603 
00604 // user actions using the old event system
00605 void execuseraction ( tuseractions action )
00606 {
00607    switch ( action ) {
00608       case ua_repainthard  :
00609       case ua_repaint      :
00610          repaintDisplay();
00611          break;
00612 
00613       case ua_help         :
00614          help(20);
00615          break;
00616 
00617       case ua_howtostartpbem :
00618          help(21);
00619          break;
00620 
00621       case ua_howtocontinuepbem :
00622          help(22);
00623          break;
00624 
00625 /*
00626       case ua_mntnc_morefog:
00627          if (actmap->weather.fog < 255   && maintainencecheck() ) {
00628             actmap->weather.fog++;
00629             computeview( actmap );
00630             displaymessage2("fog intensity set to %d ", actmap->weather.fog);
00631             displaymap();
00632          }
00633          break;
00634 
00635       case ua_mntnc_lessfog:
00636          if (actmap->weather.fog  && maintainencecheck()) {
00637             actmap->weather.fog--;
00638             computeview( actmap );
00639             displaymessage2("fog intensity set to %d ", actmap->weather.fog);
00640             displaymap();
00641          }
00642          break;
00643 
00644       case ua_mntnc_morewind:
00645          if ((actmap->weather.windSpeed < 254) &&  maintainencecheck()) {
00646             actmap->weather.windSpeed+=2;
00647             displaywindspeed (  );
00648             updateFieldInfo();
00649          }
00650          break;
00651 
00652       case ua_mntnc_lesswind:
00653          if ((actmap->weather.windSpeed > 1)  && maintainencecheck() ) {
00654             actmap->weather.windSpeed-=2;
00655             displaywindspeed (  );
00656             updateFieldInfo();
00657          }
00658          break;
00659 
00660       case ua_mntnc_rotatewind:
00661          if ( maintainencecheck() ) {
00662             if (actmap->weather.windDirection < sidenum-1 )
00663                actmap->weather.windDirection++;
00664             else
00665                actmap->weather.windDirection = 0;
00666             displaymessage2("wind dir set to %d ", actmap->weather.windDirection);
00667             updateFieldInfo();
00668             displaymap();
00669          }
00670          break;
00671 */
00672       case ua_changeresourceview:
00673          if ( mainScreenWidget ) 
00674             mainScreenWidget->toggleMapLayer( "resources");
00675          displaymap();
00676          break;
00677 
00678       case ua_visibilityInfo:
00679          if ( mainScreenWidget ) 
00680             mainScreenWidget->toggleMapLayer( "visibilityvalue");
00681          displaymap();
00682          break;
00683 
00684       case ua_showCargoLayer:
00685          if ( mainScreenWidget ) 
00686             mainScreenWidget->toggleMapLayer( "container");
00687          displaymap();
00688          break;
00689 
00690       case ua_benchgamewov:
00691          benchgame( false );
00692          break;
00693 
00694       case ua_benchgamewv :
00695          benchgame( true );
00696          break;
00697 
00698       case ua_writescreentopcx:
00699          {
00700             ASCString name = getnextfilenumname ( "screen", "pcx", 0 );
00701             Surface s ( PG_Application::GetScreen() );
00702             writepcx ( name, s);
00703             displaymessage2( "screen saved to %s", name.c_str() );
00704          }
00705          break;
00706 
00707       case ua_bi3preferences:
00708          bi3preferences();
00709          break;
00710 
00711       case ua_settribute :
00712          settributepayments ();
00713          break;
00714 
00715       case ua_giveunitaway:
00716          if ( actmap && actmap->getgameparameter( cgp_disableUnitTransfer ) == 0 )
00717             giveunitaway ( actmap->getField( actmap->getCursor() ));
00718          else
00719             infoMessage("Sorry, this function has been disabled when starting the map!");
00720          break;
00721 
00722       case ua_newmessage:
00723          newmessage();
00724          break;
00725 
00726       case ua_viewqueuedmessages:
00727          viewmessages( "queued messages", actmap->unsentmessage, 1 );
00728          break;
00729 
00730       case ua_viewsentmessages:
00731          viewmessages( "sent messages", actmap->player[ actmap->actplayer ].sentmessage, 0);
00732          break;
00733 
00734       case ua_viewreceivedmessages:
00735          viewmessages( "received messages", actmap->player[ actmap->actplayer ].oldmessage, 0 );
00736          break;
00737 
00738       case ua_viewjournal:
00739          viewjournal( true );
00740          break;
00741 
00742       case ua_editjournal:
00743          editjournal();
00744          break;
00745 
00746       case ua_viewaboutmessage:
00747          helpAbout();
00748          break;
00749 
00750       case ua_viewlayerhelp:
00751          help(49);
00752          break;
00753 
00754       case ua_SDLinfo:
00755          showSDLInfo();
00756          break;
00757 
00758       case ua_toggleunitshading: 
00759          {
00760             CGameOptions::Instance()->units_gray_after_move = !CGameOptions::Instance()->units_gray_after_move;
00761             CGameOptions::Instance()->setChanged();
00762             displaymap();
00763             while ( mouseparams.taste )
00764                releasetimeslice();
00765 
00766             ASCString condition;
00767             if ( CGameOptions::Instance()->units_gray_after_move )
00768                condition = "- thay can't move";
00769             else
00770                condition = "- thay can't move AND\n- thay can't shoot";
00771 
00772             infoMessage ("units that now displayed shaded when:\n" + condition);
00773          }
00774 
00775          break;
00776 
00777       case ua_computerturn:
00778          if ( maintainencecheck() ) {
00779             displaymessage("This function is under development and for programmers only\n"
00780                            "unpredictable things may happen ...",3 ) ;
00781 
00782             if (choice_dlg("do you really want to start the AI?","~y~es","~n~o") == 1) {
00783 
00784                if ( !actmap->player[ actmap->actplayer ].ai )
00785                   actmap->player[ actmap->actplayer ].ai = new AI ( actmap, actmap->actplayer );
00786 
00787                savegame ( "aistart.sav" );
00788                actmap->player[ actmap->actplayer ].ai->run();
00789             }
00790          }
00791          break;
00792       case ua_setupnetwork:
00793       /*
00794          if ( actmap->network )
00795             setupnetwork ( actmap->network );
00796          else
00797             displaymessage("This map is not played across a network",3 );
00798             */
00799             displaymessage("Not implemented yet",3 );
00800          break;
00801       case ua_UnitSetInfo:
00802          viewUnitSetinfo();
00803          break;
00804       case ua_GameParameterInfo:
00805          showGameParameters();
00806          break;
00807       case ua_viewunitweaponrange:
00808          mainScreenWidget->showWeaponRange( actmap, actmap->getCursor() );
00809          break;
00810 
00811       case ua_viewunitmovementrange:
00812          mainScreenWidget->showMovementRange( actmap, actmap->getCursor() );
00813          break;
00814 
00815       case ua_aibench:
00816          if ( maintainencecheck() && 0 ) {
00817             if ( !actmap->player[ actmap->actplayer ].ai )
00818                actmap->player[ actmap->actplayer ].ai = new AI ( actmap, actmap->actplayer );
00819 
00820             if ( AI* ai = dynamic_cast<AI*>( actmap->player[ actmap->actplayer ].ai )) {
00821                savegame ( "ai-bench-start.sav" );
00822                ai->run( true );
00823             }
00824          }
00825          break;
00826 
00827       case ua_selectPlayList:
00828          selectPlayList();
00829          break;
00830       case ua_statisticdialog:
00831          statisticDialog();
00832          break;
00833 
00834       case ua_togglesound:
00835          if ( !SoundSystem::getInstance()->isOff() ) {
00836             bool on = !SoundSystem::getInstance()->areEffectsMuted();
00837             SoundSystem::getInstance()->setEffectsMute( on );
00838             if ( on )
00839                SoundSystem::getInstance()->pauseMusic();
00840             else
00841                SoundSystem::getInstance()->resumeMusic();
00842          }
00843          break;
00844       case ua_showPlayerSpeed:
00845          showPlayerTime();
00846          break;
00847       case  ua_cancelResearch:
00848          if ( actmap->player[actmap->actplayer].research.activetechnology ) {
00849             ASCString s = "do you really want to cancel the current research project ?\n";
00850             // s += strrr ( actmap->player[actmap->actplayer].research.progress );
00851             // s += " research points will be lost.";
00852             if (choice_dlg(s.c_str(),"~y~es","~n~o") == 1) {
00853                actmap->player[actmap->actplayer].research.cancel();
00854                logtoreplayinfo( rpl_cancelResearch );
00855             }
00856             
00857          } else
00858             displaymessage("you are not researching anything", 3);
00859          break;
00860       case ua_showResearchStatus: {
00861             ASCString s;
00862             s += "Current technology:\n";
00863             if ( actmap->player[actmap->actplayer].research.activetechnology )
00864                s += actmap->player[actmap->actplayer].research.activetechnology->name;
00865             else
00866                s += " - none - ";
00867             s += "\n\n";
00868 
00869             s += "Research Points: \n";
00870             s += strrr( actmap->player[actmap->actplayer].research.progress );
00871             if ( actmap->player[actmap->actplayer].research.activetechnology )
00872                s += ASCString(" / ") + strrr ( actmap->player[actmap->actplayer].research.activetechnology->researchpoints );
00873             s += "\n\n";
00874 
00875             s+= "Research Points Plus \n";
00876 
00877             s += strrr ( actmap->player[actmap->actplayer].research.getResearchPerTurn() );
00878 
00879             s += "\n\n";
00880 
00881             s+= "Developed Technologies: \n";
00882             for ( vector<int>::iterator i = actmap->player[actmap->actplayer].research.developedTechnologies.begin(); i != actmap->player[actmap->actplayer].research.developedTechnologies.end(); ++i ) {
00883                Technology* t = technologyRepository.getObject_byID( *i );
00884                if ( t )
00885                   s += t->name + "\n";
00886             }
00887 
00888             tviewanytext vat ;
00889             vat.init ( "Research Status", s.c_str(), 20, -1 , 450, 480 );
00890             vat.run();
00891             vat.done();
00892          }
00893          break;
00894       case ua_exportUnitToFile:
00895          if ( getSelectedField()->vehicle && getSelectedField()->vehicle->getOwner() == actmap->actplayer ){
00896             if (choice_dlg( "do you really want to cut this unit from the game?", "~y~es","~n~o") == 1) {
00897                Vehicle* veh = getSelectedField()->vehicle;
00898                ClipBoard::Instance().clear();
00899                ClipBoard::Instance().addUnit( veh );
00900 
00901                ASCString filename = selectFile( clipboardFileExtension, false );
00902                if ( !filename.empty() ) {
00903                   tnfilestream stream ( filename, tnstream::writing );
00904                   ClipBoard::Instance().write( stream );
00905                   logtoreplayinfo ( rpl_cutFromGame, veh->networkid );
00906                   veh->prepareForCleanRemove();
00907                   delete veh;
00908                   computeview( actmap );
00909                   displaymap();
00910                }
00911             }
00912          }
00913          break;
00914 
00915       default:;
00916       };
00917 }
00918 
00919 bool continueAndStartMultiplayerGame( bool mostRecent = false )
00920 {
00921    if ( continuenetworkgame( mostRecent )) {
00922       hookGuiToMap(actmap);
00923       actmap->sigPlayerUserInteractionBegins( actmap->player[actmap->actplayer] );
00924       displaymap();
00925       return true;
00926    } else
00927       return false;
00928 }
00929 
00930 
00931 void ammoCounter( const ContainerBase* c, map<int,int>& amount )
00932 {
00933    for ( int i = 0; i < cwaffentypennum; ++i )
00934       if ( weaponAmmo[i] )
00935          amount[i] += c->getAmmo(i,maxint );
00936 
00937    for ( int i = 1000; i < 1003; ++i )
00938       amount[i] += c->getAvailableResource( maxint, i-1000, 0 );
00939 
00940    for ( ContainerBase::Cargo::const_iterator i = c->getCargo().begin(); i != c->getCargo().end(); ++i )
00941       if ( *i )
00942          ammoCounter( *i, amount );
00943 }
00944 
00945 
00946 void showCargoSummary( tfield* fld )
00947 {
00948    if ( !fld->vehicle ) {
00949       infoMessage( "Please select a unit");
00950       return;
00951    }
00952 
00953    if ( actmap->getCurrentPlayer().diplomacy.isAllied( fld->vehicle  )) {
00954       showUnitCargoSummary( fld->vehicle );
00955       map<int,int> ammo;
00956       ammoCounter( fld->vehicle, ammo );
00957       ASCString s;
00958       for ( int i = 0; i < cwaffentypennum; ++i )
00959          if ( weaponAmmo[i] )
00960             s += ASCString(cwaffentypen[i]) + ": " + ASCString::toString( ammo[i] ) + "\n";
00961 
00962       s += "\n";
00963       for ( int i = 1000; i < 1003; ++i )
00964          s += ASCString(Resources::name(i-1000)) + ": " + ASCString::toString( ammo[i] ) + "\n";
00965 
00966       ViewFormattedText vft("Ammo summary", s, PG_Rect( -1, -1, 300, 300 ));
00967       vft.Show();
00968       vft.RunModal();
00969    } else
00970       infoMessage( "The unit is not yours");
00971    
00972 }
00973 
00974 
00975  class GotoPosition: public ASC_PG_Dialog {
00976       PG_LineEdit* xfield;
00977       PG_LineEdit* yfield;
00978       GameMap* gamemap;
00979 
00980       
00981 
00982       bool ok()
00983       {
00984          static boost::regex numercial("\\d+");
00985 
00986          if( boost::regex_match( xfield->GetText(), numercial)  &&
00987              boost::regex_match( yfield->GetText(), numercial)) {
00988                int xx = atoi( xfield->GetText() );
00989                int yy = atoi( yfield->GetText() );
00990                if ( xx >= 0 && yy >= 0 && xx < gamemap->xsize && yy < gamemap->ysize ) {
00991                   Hide();
00992                   MapDisplayPG* md = getMainScreenWidget()->getMapDisplay();
00993                   md->cursor.goTo( MapCoordinate( xx, yy) );
00994                   QuitModal();
00995                   return true;
00996                }
00997          }
00998          return false;
00999       }
01000       
01001       bool cancel()
01002       {
01003          QuitModal();
01004          return true;
01005       }
01006 
01007       static const int border  = 20;
01008 
01009       bool line1completed()
01010       {
01011          if ( yfield ) {
01012             yfield->EditBegin();
01013             return true;
01014          } else
01015             return false;
01016       }
01017       
01018    public:
01019       GotoPosition ( GameMap* gamemap ) : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 300, 120), "Enter Coordinates")
01020       {
01021          this->gamemap = gamemap;
01022          int fieldwidth = (Width()-3*border)/2;
01023          xfield = new PG_LineEdit( this, PG_Rect( border, 40, fieldwidth, 20));
01024          // xfield->SetText( ASCString::toString( gamemap->getCursor().x ));
01025          xfield->sigEditReturn.connect( SigC::slot( *this, &GotoPosition::line1completed ));
01026 
01027          yfield = new PG_LineEdit( this, PG_Rect( (Width()+border)/2, 40, fieldwidth, 20));
01028          // yfield->SetText( ASCString::toString( gamemap->getCursor().y ));
01029          yfield->sigEditReturn.connect( SigC::slot( *this, &GotoPosition::ok ));
01030 
01031          AddStandardButton( "~O~k" )->sigClick.connect( SigC::slot( *this, &GotoPosition::ok ));
01032       };
01033 
01034       int RunModal()
01035       {
01036          xfield->EditBegin();
01037          return ASC_PG_Dialog::RunModal();
01038       }
01039    };
01040 
01041 
01042 
01043 class FontViewer : public ASC_PG_Dialog {
01044       static const int spacing = 30;
01045    public:
01046       FontViewer() : ASC_PG_Dialog( NULL, PG_Rect( -1, -1, 18 * spacing, 19 * spacing ), "view character set" ) 
01047       {
01048          for ( int i = 32; i < 255; ++i ) {
01049             ASCString s;
01050             s += char(i);
01051             new PG_Label ( this, PG_Rect( (i % 16 + 1) * spacing, (i / 16 + 2) * spacing, spacing, spacing ), s );
01052          }
01053       };
01054 };
01055 
01056 void viewFont()
01057 {
01058    FontViewer fv;
01059    fv.Show();
01060    fv.RunModal();
01061 }
01062 
01063 
01064 void resourceAnalysis()
01065 {
01066    ASCString s;
01067    Resources total;
01068    for ( Player::BuildingList::iterator j = actmap->player[actmap->actplayer].buildingList.begin(); j != actmap->player[actmap->actplayer].buildingList.end() ; j++ ) {
01069       Resources res = (*j)->getResource( Resources(maxint,maxint,maxint), true, 0 );
01070       MapCoordinate pos = (*j)->getPosition();
01071       s += (*j)->getName() + " #pos150#(" + ASCString::toString( pos.x ) + "/" + ASCString::toString( pos.y) + pos.toString() + ") : #pos300#" + ASCString::toString(res.energy) + "#pos400#" + ASCString::toString(res.material) + "#pos500#" + ASCString::toString(res.fuel) + "\n";
01072       total += res;
01073    }
01074    s += "\nTotal:\n";
01075 
01076    for ( int r = 0; r < 3; ++r)
01077       if ( actmap->isResourceGlobal(r))
01078          total.resource(r) = actmap->bi_resource[actmap->actplayer].resource(r);
01079    s += total.toString();
01080 
01081    ViewFormattedText vft("Resource Analysis", s, PG_Rect( -1, -1, 600, 550 ));
01082    vft.Show();
01083    vft.RunModal();
01084 }
01085 
01086 void showUnitEndurance()
01087 {
01088    
01089    vector<Vehicletype*> units;
01090    for ( int i = 0; i < vehicleTypeRepository.getNum(); ++i ) {
01091       Vehicletype* vt = vehicleTypeRepository.getObject_byPos(i);
01092       if ( vt && (vt->movemalustyp == MoveMalusType::medium_aircraft || 
01093                   vt->movemalustyp == MoveMalusType::light_aircraft  ||
01094                   vt->movemalustyp == MoveMalusType::heavy_aircraft  ||
01095                   vt->movemalustyp == MoveMalusType::helicopter))
01096          units.push_back( vt );
01097    }
01098    sort( units.begin(), units.end(), vehicleComp );
01099    
01100    ASCString s;
01101    for ( vector<Vehicletype*>::iterator i = units.begin(); i != units.end(); ++i )
01102    {
01103       ASCString u;
01104       ASCString range;
01105       if ( (*i)->fuelConsumption )
01106          range = ASCString::toString( (*i)->getStorageCapacity(0).fuel / (*i)->fuelConsumption);
01107       else
01108          range = "-";
01109       
01110       u.format( "#vehicletype=%d# %s : %d fuel ; %s fields range ; %d turns endurance \n", (*i)->id, (*i)->getName().c_str(), (*i)->getStorageCapacity(0).fuel, range.c_str(), UnitHooveringLogic::getEndurance(*i) );
01111       s += u;
01112    }
01113    
01114    ViewFormattedText vft("Unit Endurance", s, PG_Rect( -1, -1, 650, 550 ));
01115    vft.Show();
01116    vft.RunModal();
01117 }
01118 
01119 
01120 void showMemoryFootprint()
01121 {
01122    MemoryMeasurement mm;
01123    mm.measureTypes();
01124    mm.measure( actmap );
01125    mm.measureIcons();
01126    
01127    ViewFormattedText vft("Memory Usage", mm.getResult(), PG_Rect( -1, -1, 750, 550 ));
01128    vft.Show();
01129    vft.RunModal();
01130 }
01131 
01132 
01133 void viewMiningPower()
01134 {
01135    typedef map<const ContainerBaseType*,ASCString> InfoMap;
01136    InfoMap info;
01137 
01138    for ( Player::BuildingList::iterator i = actmap->getCurrentPlayer().buildingList.begin(); i != actmap->getCurrentPlayer().buildingList.end(); ++i )
01139       if ( (*i)->baseType->hasFunction( ContainerBaseType::MiningStation )) {
01140          int power;
01141          int output;
01142          MiningStation miningStation ( *i, true );
01143          for ( int r = 0; r < 3; ++r )
01144             if ( (*i)->maxplus.resource(r) ) {
01145                power = 100 * (*i)->plus.resource(r) / (*i)->maxplus.resource(r) ;
01146                break;
01147             }
01148             
01149          for ( int r = 0; r < 3; ++r )
01150             if ( miningStation.getPlus().resource(r) ) {
01151                output = miningStation.getPlus().resource(r);
01152                break;
01153             }
01154             
01155          ASCString txt = ASCString::toString(output) + " (" + ASCString::toString(power) + "%) " + (*i)->getPosition().toString() + " " + (*i)->baseType->name + "\n";
01156          info[(*i)->baseType] += txt;
01157       }
01158 
01159    ASCString fullText = "Mining Station Statistics\n\n";
01160    for ( InfoMap::iterator i = info.begin(); i != info.end(); ++i )
01161       fullText += i->second;
01162 
01163 
01164    ViewFormattedText vft("Mining Stations", fullText, PG_Rect( -1, -1, 750, 550 ));
01165    vft.Show();
01166    vft.RunModal();
01167 
01168 }
01169 
01170 
01171 
01172 
01173 // user actions using the new event system
01174 void execuseraction2 ( tuseractions action )
01175 {
01176    switch ( action ) {
01177    
01178       case ua_unitweightinfo:
01179          if ( fieldvisiblenow  ( getSelectedField() )) {
01180             Vehicle* eht = getSelectedField()->vehicle;
01181             if ( eht && actmap->player[actmap->actplayer].diplomacy.getState( eht->getOwner()) >= PEACE_SV )
01182                infoMessage(" weight of unit: \n basic: " + ASCString::toString(eht->typ->weight) + "\n+cargo: " + ASCString::toString(eht->cargoWeight()) + "\n= " + ASCString::toString( eht->weight() ));
01183          }
01184          break;
01185       case ua_GameStatus:
01186          infoMessage ( "Current game time is:\n turn " + ASCString::toString( actmap->time.turn() ) + " , move " + ASCString::toString( actmap->time.move() ));
01187          break;
01188       case ua_soundDialog:
01189           soundSettings( NULL );
01190          break;
01191       case ua_reloadDlgTheme:
01192              getPGApplication().reloadTheme();
01193              MessagingHub::Instance().message( MessagingHubBase::InfoMessage, "Theme reloaded" );
01194              // soundSettings( NULL );
01195          break;
01196       case ua_viewButtonPanel:  mainScreenWidget->spawnPanel( ASC_MainScreenWidget::ButtonPanel );
01197          break;
01198       case ua_viewWindPanel:     mainScreenWidget->spawnPanel( ASC_MainScreenWidget::WindInfo );
01199          break;
01200       case ua_clearImageCache:  IconRepository::clear();
01201          break;
01202       case ua_viewUnitInfoPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::UnitInfo );
01203          break;
01204       case ua_viewOverviewMapPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::OverviewMap );
01205          break;
01206       case ua_viewMapControlPanel: mainScreenWidget->spawnPanel( ASC_MainScreenWidget::MapControl );
01207          break;
01208       case ua_vehicleinfo: unitInfoDialog();
01209          break;
01210 #ifdef WEATHERGENERATOR
01211       case ua_weathercast: weathercast();
01212          break;
01213 #endif
01214       case ua_newGame: 
01215          startMultiplayerGame();
01216          break;
01217 
01218       case ua_continuerecentnetworkgame:
01219          continueAndStartMultiplayerGame( true );
01220          break;
01221 
01222       case ua_continuenetworkgame:
01223          continueAndStartMultiplayerGame();
01224          break;
01225       case ua_loadgame: loadGame( false);
01226          break;
01227       case ua_loadrecentgame: loadGame ( true );
01228          break;
01229       case ua_savegame: saveGame( true );
01230          break;
01231       case ua_setupalliances:
01232          if ( setupalliances( actmap, actmap->getCurrentPlayer().stat == Player::supervisor ) ) {
01233             if ( computeview( actmap ))
01234                displaymap();
01235          }
01236          updateFieldInfo();
01237          break;
01238       case ua_mainmenu:
01239          /*
01240          if (choice_dlg("do you really want to close the current game ?","~y~es","~n~o") == 1) {
01241             delete actmap;
01242             actmap = NULL;
01243             throw NoMapLoaded();
01244          }
01245          */
01246          GameDialog::gameDialog();
01247          break;
01248       case ua_viewterraininfo:
01249          if ( fieldvisiblenow( actmap->getField( actmap->getCursor())))
01250             viewterraininfo( actmap, actmap->getCursor(), fieldVisibility( actmap->getField( actmap->getCursor())) == visible_all );
01251          break;
01252       case ua_testMessages:
01253          MessagingHub::Instance().message( MessagingHubBase::InfoMessage, "This is an informational message" );
01254          MessagingHub::Instance().message( MessagingHubBase::Warning,     "This is an warning message" );
01255          MessagingHub::Instance().message( MessagingHubBase::Error,       "This is an error message" );
01256          MessagingHub::Instance().message( MessagingHubBase::FatalError,  "This is an fatal error message. Game will be exited." );
01257          break;
01258       case ua_writemaptopcx :
01259          writemaptopcx ( actmap, choice_dlg("Include View ?","~y~es","~n~o")==1  );
01260          break;
01261       case ua_exitgame:
01262          if (choice_dlg("do you really want to quit ?","~y~es","~n~o") == 1)
01263             getPGApplication().Quit();
01264          break;
01265       case ua_cargosummary: 
01266          showCargoSummary( getSelectedField() );
01267          break;
01268       case ua_unitsummary: showUnitSummary( actmap );
01269          break;
01270       case ua_gamepreferences:
01271          editGameOptions();
01272          break;
01273       case ua_increase_zoom:
01274          if ( mainScreenWidget && mainScreenWidget->getMapDisplay() ) {
01275             mainScreenWidget->getMapDisplay()->changeZoom( 10 );
01276             viewChanged();
01277             repaintMap();
01278          }
01279          break;
01280       case ua_decrease_zoom:
01281          if ( mainScreenWidget && mainScreenWidget->getMapDisplay() ) {
01282             mainScreenWidget->getMapDisplay()->changeZoom( -10 );
01283             viewChanged();
01284             repaintMap();
01285          }
01286          break;
01287       case ua_selectgraphicset:
01288          selectgraphicset();
01289          break;
01290       case ua_networksupervisor:
01291          networksupervisor();
01292          displaymap();
01293          break;
01294       case ua_researchinfo:
01295          researchinfo ();
01296          break;
01297       case ua_viewPipeNet:
01298          mainScreenWidget->getMapDisplay()->toggleMapLayer("pipes");
01299          repaintMap();
01300          break;
01301       case ua_showsearchdirs: showSearchPath();
01302          break;
01303       case ua_changepassword:
01304          changePassword( actmap );
01305          break;
01306       case ua_editPlayerData:
01307          editPlayerData( actmap );
01308          break;
01309       case ua_locatefile:
01310          locateFile();
01311          break;
01312       case ua_viewfont:
01313          viewFont();
01314          break;
01315       case ua_resourceAnalysis:
01316          resourceAnalysis();
01317          break;
01318       case ua_unitproductionanalysis:
01319          unitProductionAnalysis( actmap );
01320          break;
01321       case ua_gotoPosition: { 
01322          GotoPosition gp( actmap );
01323          gp.Show();
01324          gp.RunModal();
01325           break;
01326       };
01327       case ua_showTechAdapter: {
01328                ViewFormattedText vft("TechAdapter", actmap->getCurrentPlayer().research.listTriggeredTechAdapter(), PG_Rect( -1,-1,300,500));
01329                vft.Show();
01330                vft.RunModal();
01331                                };
01332          break;
01333       case ua_showUnitEndurance:  showUnitEndurance(); 
01334          break;
01335          
01336       case ua_getMemoryFootprint: showMemoryFootprint();
01337          break;
01338 
01339       case ua_showMiningPower: viewMiningPower();
01340          break;
01341 
01342       case ua_emailOptions: editEmailOptions();
01343          break;
01344       
01345       case ua_createReminder: newreminder(); 
01346          break;
01347          
01348       default:
01349          break;
01350    }
01351 
01352 }
01353 
01354 
01355 
01356 
01357 void execUserAction_ev( tuseractions action )
01358 {
01359    execuseraction( action );
01360    execuseraction2( action );
01361 }
01362 
01363 
01364 
01365 
01366 bool mainloopidle( PG_MessageObject* msgObj )
01367 {
01368    if ( msgObj != PG_Application::GetApp())
01369       return false;
01370 
01371    if ( actmap ) {
01372       while ( actmap->player[ actmap->actplayer ].queuedEvents )
01373          if ( !checkevents( &getDefaultMapDisplay() ))
01374             return false;
01375 
01376       checktimedevents( &getDefaultMapDisplay() );
01377 
01378       checkforvictory( true );
01379    }
01380    return false;
01381 }
01382 
01383 
01384 
01385 pfont load_font ( const char* name )
01386 {
01387    tnfilestream stream ( name , tnstream::reading );
01388    return loadfont ( &stream );
01389 }
01390 
01391 
01392 void resetActions( GameMap& map )
01393 {
01394    moveparams.reset();
01395    pendingVehicleActions.reset();
01396 }
01397 
01398 
01399 void