00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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 );
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 );
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 );
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 );
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