turncontrol.cpp

Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00009     Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00010 
00011     This program is free software; you can redistribute it and/or modify
00012     it under the terms of the GNU General Public License as published by
00013     the Free Software Foundation; either version 2 of the License, or
00014     (at your option) any later version.
00015 
00016     This program is distributed in the hope that it will be useful,
00017     but WITHOUT ANY WARRANTY; without even the implied warranty of
00018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019     GNU General Public License for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with this program; see the file COPYING. If not, write to the 
00023     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00024     Boston, MA  02111-1307  USA
00025 */
00026 
00027 
00028 #include "turncontrol.h"
00029 #include "gamemap.h"
00030 #include "mapdisplay.h"
00031 #include "gameoptions.h"
00032 #include "dialogs/pwd_dlg.h"
00033 #include "controls.h"
00034 #include "spfst.h"
00035 #include "dlg_box.h"
00036 #include "ai/ai.h"
00037 #include "dialog.h"
00038 #include "strtmesg.h"
00039 #include "loaders.h"
00040 #include "cannedmessages.h"
00041 #include "viewcalculation.h"
00042 #include "network/simple_file_transfer.h"
00043 #include "dialogs/fileselector.h"
00044 #include "researchexecution.h"
00045 #include "gameeventsystem.h"
00046 
00047 bool authenticateUser ( GameMap* actmap, bool allowCancel = true, bool lockView = true, bool throwOnFailure = false  )
00048 {
00049    for ( int p = 0; p < 8; p++ )
00050       actmap->player[p].existanceAtBeginOfTurn = actmap->player[p].exist() && actmap->player[p].stat != Player::off;
00051 
00052    int humannum = 0;
00053    for ( int i = 0; i < 8; i++ )
00054       if ( actmap->player[i].exist() )
00055          if ( actmap->player[i].isHuman() )
00056             humannum++;
00057 
00058    if ( humannum > 1  ) {
00059       MapDisplayPG::LockDisplay ld ( !lockView );
00060 
00061       bool firstRound = actmap->time.turn() == 1;
00062       bool specifyPassword = firstRound && actmap->player[actmap->actplayer].passwordcrc.empty();
00063       // bool askForPassword = false;
00064 
00065       if ( (!actmap->player[actmap->actplayer].passwordcrc.empty() && actmap->player[actmap->actplayer].passwordcrc != CGameOptions::Instance()->getDefaultPassword() )
00066          || firstRound  ) {
00067             bool stat;
00068             actmap->setPlayerView ( actmap->actplayer );  // the idle handler of enterpassword starts generating the overview map, so we need to have the correct view prior to enterpassword
00069             do {
00070                stat = enterpassword ( actmap->player[actmap->actplayer].passwordcrc, specifyPassword, allowCancel, true, actmap->player[actmap->actplayer].getName() );
00071                if ( !stat ) {
00072                   if ( throwOnFailure ) {
00073                      delete actmap;
00074                      throw NoMapLoaded();
00075                   } else
00076                      return false;
00077                }
00078             } while ( actmap->player[actmap->actplayer].passwordcrc.empty() && stat && viewtextquery ( 910, "warning", "~e~nter password", "~c~ontinue without password" ) == 0 ); /* enddo */
00079       } else {
00080          infoMessage("next player is " + actmap->player[actmap->actplayer].getName() );
00081          actmap->setPlayerView ( actmap->actplayer );
00082       }
00083       actmap->overviewMapHolder.clear( true );
00084    } else
00085       actmap->overviewMapHolder.clear( true );
00086 
00087    actmap->setPlayerView ( actmap->actplayer );
00088 
00089    return true;
00090    
00091 }
00092 
00093 
00094 
00095 
00096 void runai( GameMap* actmap, int playerView, MapDisplayInterface* display )
00097 {
00098    MapDisplayPG::CursorHiding cusorHiding;
00099    actmap->setPlayerView ( playerView );
00100 
00101    computeview( actmap );
00102 
00103    if ( !actmap->player[ actmap->actplayer ].ai )
00104       actmap->player[ actmap->actplayer ].ai = new AI ( actmap, actmap->actplayer );
00105 
00106    actmap->player[ actmap->actplayer ].ai->run( display );
00107    updateFieldInfo();
00108 }
00109 
00110 
00111 int findNextPlayer( GameMap* actmap, AbstractPlayerProcessing* playerProcessor )
00112 {
00113    int p = actmap->actplayer;
00114    bool found = false;
00115    int loop = 0;
00116    do {
00117       ++p;
00118       if ( p >= actmap->getPlayerCount())  {
00119          p = 0;
00120          ++loop;
00121          if ( loop >= 3 )
00122             throw ShutDownMap();
00123       }
00124 
00125       
00126       if ( actmap->player[p].exist() ) 
00127          if ( actmap->player[p].stat != Player::off )
00128             found = true;
00129       
00130       if ( !found && playerProcessor )
00131          playerProcessor->playerSkipped( actmap->player[p] );
00132       
00133    } while ( !found );
00134    return p;
00135 }
00136 
00137 
00138 class ReplayClearer : public AbstractPlayerProcessing {
00139    
00140    virtual void playerSkipped( Player& player ) {
00141       if ( !player.exist() || player.stat == Player::off || player.stat == Player::suspended ) {
00142          int i = player.getPosition();
00143          if ( player.getParentMap()->replayinfo )
00144             if ( player.getParentMap()->replayinfo->map[i] && player.getParentMap()->replayinfo->guidata[i] ) {
00145                delete player.getParentMap()->replayinfo->map[i];
00146                player.getParentMap()->replayinfo->map[i] = NULL;
00147       
00148                delete player.getParentMap()->replayinfo->guidata[i];
00149                player.getParentMap()->replayinfo->guidata[i] = NULL;
00150             }
00151       }
00152    };
00153    
00154 };
00155 
00156 void iterateToNextPlayer( GameMap* actmap, bool saveNetwork, int lastPlayer, int lastTurn, MapDisplayInterface* display  )
00157 {
00158    int loop = 0;
00159    bool closeLoop = false;
00160 
00161    ReplayClearer replayClearing;
00162    
00163    do {
00164 
00165       int currentPlayer= actmap->actplayer;
00166       
00167       int nextPlayer = findNextPlayer( actmap, &replayClearing );
00168       
00169       if ( nextPlayer <= currentPlayer ) {
00170          actmap->endRound();
00171          ++loop;
00172       }
00173       
00174       if ( loop > 2 ) {
00175          displaymessage("no human players found !", 1 );
00176          delete actmap;
00177          actmap = NULL;
00178          throw NoMapLoaded();
00179       }
00180 
00181                
00182       actmap->actplayer = nextPlayer;
00183       
00184       if ( actmap->player[nextPlayer].stat == Player::computer ) {
00185          actmap->beginTurn();
00186          runai( actmap, lastPlayer, display );
00187          actmap->endTurn();
00188       }
00189       
00190       if ( actmap->player[nextPlayer].stat == Player::suspended ) {
00191          actmap->beginTurn();
00192          actmap->endTurn();
00193       }
00194 
00195       if ( actmap->player[nextPlayer].stat == Player::human || actmap->player[nextPlayer].stat == Player::supervisor ) {
00196          if ( actmap->network && lastPlayer >= 0 && saveNetwork ) {
00197             actmap->network->send( actmap, lastPlayer, lastTurn );
00198             delete actmap;
00199             actmap = NULL;
00200             throw NoMapLoaded();
00201          } else
00202             closeLoop = true;
00203          }
00204    } while ( !closeLoop ); /* enddo */
00205 
00206 }
00207 
00208 bool NextTurnStrategy_AskUser::continueWhenLastPlayer() const
00209 {
00210    viewtext2(904);
00211    if ( choice_dlg("Do you want to continue playing ?","~y~es","~n~o") == 2) 
00212       return false;
00213    else
00214       return true;
00215 }
00216 
00217 bool NextTurnStrategy_AskUser::authenticate( GameMap* actmap ) const
00218 {
00219    return authenticateUser( actmap );
00220 }
00221 
00222 bool NextTurnStrategy_Abort::continueWhenLastPlayer() const { 
00223    return false;
00224 };  
00225 
00226 bool NextTurnStrategy_Abort::authenticate( GameMap* actmap) const
00227 {
00228    return true;  
00229 }
00230 
00231 
00232 void next_turn ( GameMap* gamemap, const NextTurnStrategy& nextTurnStrategy, MapDisplayInterface* display, int playerView  )
00233 {
00234    int lastPlayer = gamemap->actplayer;
00235    int lastTurn = gamemap->time.turn();
00236 
00237    if  ( lastPlayer >= 0 )
00238       gamemap->endTurn();
00239    
00240    int pv;
00241    if ( playerView == -2 ) {
00242       if ( gamemap->time.turn() <= 0 || gamemap->actplayer < 0 )
00243          pv = -1;
00244       else
00245          if ( gamemap->player[gamemap->actplayer].stat != Player::human )
00246             pv = -1;
00247          else
00248             pv = gamemap->actplayer;
00249    } else
00250       pv = playerView;
00251 
00252       
00253    if ( findNextPlayer( gamemap ) == lastPlayer ) {
00254       if ( !gamemap->continueplaying ) {
00255          
00256          
00257          if ( !nextTurnStrategy.continueWhenLastPlayer() ) {
00258             delete gamemap;
00259             gamemap = NULL;
00260             throw NoMapLoaded();
00261          } else {
00262             gamemap->continueplaying = true;
00263             if ( gamemap->replayinfo ) {
00264                delete gamemap->replayinfo;
00265                gamemap->replayinfo = NULL;
00266             }
00267          }
00268       }   
00269    }
00270       
00271  
00272    iterateToNextPlayer( gamemap, true, lastPlayer, lastTurn, display );
00273    
00274    gamemap->setPlayerView ( -1 );
00275    
00276    if ( ! nextTurnStrategy.authenticate(gamemap) ) {
00277       delete gamemap;
00278       throw NoMapLoaded();
00279    }
00280    
00281    gamemap->beginTurn();
00282    gamemap->setPlayerView ( gamemap->actplayer );
00283    gamemap->overviewMapHolder.clear();
00284    
00285    gamemap->sigPlayerUserInteractionBegins( gamemap->player[gamemap->actplayer] );
00286    
00287    checktimedevents( gamemap, display );
00288    checkevents( gamemap, display );
00289 }
00290 
00291 
00292 void skipTurn( GameMap* gamemap )
00293 {
00294    if ( gamemap->actplayer >= 0 ) {
00295       SuppressTechPresentation stp;
00296             
00297       gamemap->beginTurn();
00298       gamemap->endTurn();
00299    }
00300    iterateToNextPlayer( gamemap, false, -1, -1, NULL );
00301 }
00302 
00303 void checkUsedASCVersions ( Player& currentPlayer )
00304 {
00305    for ( int i = 0; i < 8; i++ )
00306       if  ( currentPlayer.getParentMap()->player[i].exist() )
00307          if ( currentPlayer.getParentMap()->actplayer != i )
00308             if ( currentPlayer.getParentMap()->player[i].ASCversion > 0 )
00309                if ( (currentPlayer.getParentMap()->player[i].ASCversion & 0xffffff00) > getNumericVersion() ) {
00310                   new Message ( ASCString("Player ") + currentPlayer.getParentMap()->player[i].getName()
00311                            + " is using a newer version of ASC. \n"
00312                            "Please check www.asc-hq.org for updates.\n\n"
00313                            "Please do NOT report any problems with this version of ASC until "
00314                            "you have confirmed that they are also present in the latest "
00315                            "version of ASC.", currentPlayer.getParentMap(), 1<<currentPlayer.getParentMap()->actplayer );
00316                   return;
00317                }
00318 
00319 }
00320 
00321 
00322 
00323 
00324 GameMap* continueNetworkGame ( bool mostRecent )
00325 {
00326    ASCString filename;
00327    if ( !mostRecent ) {
00328       filename = selectFile( ASCString("*") + tournamentextension + ";*.asc", true );
00329    } else {
00330       int datefound = 0;
00331 
00332       for ( int w = 0; w < 2; ++w) {
00333 
00334          ASCString wildcard;
00335          if ( w == 0 )
00336             wildcard = ASCString("*") + tournamentextension;
00337          else
00338             wildcard = "*.asc";
00339 
00340          tfindfile ff ( wildcard );
00341 
00342          tfindfile::FileInfo fi;
00343          while ( ff.getnextname( fi ))
00344             if ( fi.date > datefound ) {
00345                datefound = fi.date;
00346                filename = fi.name;
00347             }
00348       }
00349    }
00350 
00351    if ( filename.empty() )
00352       return NULL;
00353 
00354    StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "loading " + filename );
00355 
00356    return continueNetworkGame( filename );
00357 }
00358 
00359 GameMap* continueNetworkGame ( const ASCString& filename )
00360 {
00361    FileTransfer ft;
00362    auto_ptr<GameMap> newMap ( mapLoadingExceptionChecker( filename, MapLoadingFunction( &ft, &FileTransfer::loadPBEMFile )));
00363    if ( !newMap.get() )
00364       return NULL;
00365 
00366    if ( !authenticateUser( newMap.get(), true, false ))
00367       return NULL;
00368    
00369    computeview( newMap.get() );
00370    newMap->beginTurn();
00371    newMap->setPlayerView ( newMap->actplayer );
00372    return newMap.release();
00373 }
00374 
00375 
00376 
00377 void  checkforvictory ( GameMap* gamemap, bool hasTurnControl )
00378 {
00379    if ( !gamemap->continueplaying ) {
00380       int plnum = 0;
00381       for ( int i = 0; i < 8; i++ )
00382          if ( !gamemap->player[i].exist() && gamemap->player[i].existanceAtBeginOfTurn ) {
00383             int to = 0;
00384             for ( int j = 0; j < 8; j++ )
00385                if ( j != i )
00386                   to |= 1 << j;
00387 
00388 
00389             if ( !gamemap->campaign.avail ) {
00390                char txt[1000];
00391                const char* sp = getmessage( 10010 ); // Message "player has been terminated"
00392    
00393                sprintf ( txt, sp, gamemap->player[i].getName().c_str() );
00394                new Message ( txt, gamemap, to  );
00395             } 
00396 
00397             gamemap->player[i].existanceAtBeginOfTurn = false;
00398 
00399             if ( i == gamemap->actplayer ) {
00400                if ( gamemap->getPlayerView() == i && gamemap->getPlayer(i).stat == Player::human )
00401                   displaymessage ( getmessage ( 10011 ),1 );
00402 
00403                int humannum=0;
00404                for ( int j = 0; j < 8; j++ )
00405                   if (gamemap->player[j].exist() && gamemap->player[j].stat == Player::human )
00406                      humannum++;
00407 
00408                if ( hasTurnControl ) {
00409                   if ( humannum )
00410                      next_turn(gamemap, NextTurnStrategy_AskUser(), &getDefaultMapDisplay() );
00411                   else {
00412                      delete gamemap;
00413                      gamemap = NULL;
00414                      throw NoMapLoaded();
00415                   }
00416                }
00417             }
00418          } else
00419             plnum++;
00420 
00421       if ( plnum <= 1 ) {
00422          if ( gamemap->player[gamemap->actplayer].ai &&  gamemap->player[gamemap->actplayer].ai->isRunning() ) {
00423             displaymessage("You lost!",1);
00424          } else {
00425             displaymessage("Congratulations!\nYou won!",1);
00426             if (choice_dlg("Do you want to continue playing ?","~y~es","~n~o") == 2) {
00427                delete gamemap;
00428                gamemap = NULL;
00429                throw NoMapLoaded();
00430             } else {
00431                gamemap->continueplaying = 1;
00432                if ( gamemap->replayinfo ) {
00433                   delete gamemap->replayinfo;
00434                   gamemap->replayinfo = 0;
00435                }
00436             }
00437          }
00438       }
00439    }
00440 }
00441 

Generated on Mon May 21 01:26:38 2012 for Advanced Strategic Command by  doxygen 1.5.1