Advanced Strategic Command
turncontrol.cpp
Go to the documentation of this file.
1 
7 /*
8  This file is part of Advanced Strategic Command; http://www.asc-hq.de
9  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
10 
11  This program is free software; you can redistribute it and/or modify
12  it under the terms of the GNU General Public License as published by
13  the Free Software Foundation; either version 2 of the License, or
14  (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; see the file COPYING. If not, write to the
23  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24  Boston, MA 02111-1307 USA
25 */
26 
27 
28 #include "turncontrol.h"
29 #include "gamemap.h"
30 #include "mapdisplay.h"
31 #include "gameoptions.h"
32 #include "dialogs/pwd_dlg.h"
33 #include "controls.h"
34 #include "spfst.h"
35 #include "dlg_box.h"
36 #include "ai/ai.h"
37 #include "dialog.h"
38 #include "strtmesg.h"
39 #include "loaders.h"
40 #include "cannedmessages.h"
41 #include "viewcalculation.h"
43 #include "dialogs/fileselector.h"
44 #include "researchexecution.h"
45 #include "gameeventsystem.h"
46 
47 bool authenticateUser ( GameMap* actmap, bool allowCancel = true, bool lockView = true, bool throwOnFailure = false )
48 {
49  for ( int p = 0; p < 8; p++ )
50  actmap->player[p].existanceAtBeginOfTurn = actmap->player[p].exist() && actmap->player[p].stat != Player::off;
51 
52  int humannum = 0;
53  for ( int i = 0; i < 8; i++ )
54  if ( actmap->player[i].exist() )
55  if ( actmap->player[i].isHuman() )
56  humannum++;
57 
58  if ( humannum > 1 ) {
59  MapDisplayPG::LockDisplay ld ( !lockView );
60 
61  bool firstRound = actmap->time.turn() == 1;
62  bool specifyPassword = firstRound && actmap->player[actmap->actplayer].passwordcrc.empty();
63  // bool askForPassword = false;
64 
65  if ( (!actmap->player[actmap->actplayer].passwordcrc.empty() && actmap->player[actmap->actplayer].passwordcrc != CGameOptions::Instance()->getDefaultPassword() )
66  || firstRound ) {
67  bool stat;
68  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
69  do {
70  stat = enterpassword ( actmap->player[actmap->actplayer].passwordcrc, specifyPassword, allowCancel, true, actmap->player[actmap->actplayer].getName() );
71  if ( !stat ) {
72  if ( throwOnFailure ) {
73  delete actmap;
74  throw NoMapLoaded();
75  } else
76  return false;
77  }
78  } while ( actmap->player[actmap->actplayer].passwordcrc.empty() && stat && viewtextquery ( 910, "warning", "~e~nter password", "~c~ontinue without password" ) == 0 ); /* enddo */
79  } else {
80  infoMessage("next player is " + actmap->player[actmap->actplayer].getName() );
81  actmap->setPlayerView ( actmap->actplayer );
82  }
83  actmap->overviewMapHolder.clear( true );
84  } else
85  actmap->overviewMapHolder.clear( true );
86 
87  actmap->setPlayerView ( actmap->actplayer );
88 
89  return true;
90 
91 }
92 
93 
94 
95 
96 void runai( GameMap* actmap, int playerView, MapDisplayInterface* display )
97 {
98  MapDisplayPG::CursorHiding cusorHiding;
99  actmap->setPlayerView ( playerView );
100 
101  computeview( actmap );
102 
103  if ( !actmap->player[ actmap->actplayer ].ai )
104  actmap->player[ actmap->actplayer ].ai = new AI ( actmap, actmap->actplayer );
105 
106  actmap->player[ actmap->actplayer ].ai->run( display );
107  updateFieldInfo();
108 }
109 
110 
112 {
113  int p = actmap->actplayer;
114  bool found = false;
115  int loop = 0;
116  do {
117  ++p;
118  if ( p >= actmap->getPlayerCount()) {
119  p = 0;
120  ++loop;
121  if ( loop >= 3 )
122  throw ShutDownMap();
123  }
124 
125 
126  if ( actmap->player[p].exist() )
127  if ( actmap->player[p].stat != Player::off )
128  found = true;
129 
130  if ( !found && playerProcessor )
131  playerProcessor->playerSkipped( actmap->player[p] );
132 
133  } while ( !found );
134  return p;
135 }
136 
137 
139 
140  virtual void playerSkipped( Player& player ) {
141  if ( !player.exist() || player.stat == Player::off || player.stat == Player::suspended ) {
142  int i = player.getPosition();
143  if ( player.getParentMap()->replayinfo )
144  if ( player.getParentMap()->replayinfo->map[i] && player.getParentMap()->replayinfo->guidata[i] ) {
145  delete player.getParentMap()->replayinfo->map[i];
146  player.getParentMap()->replayinfo->map[i] = NULL;
147 
148  delete player.getParentMap()->replayinfo->guidata[i];
149  player.getParentMap()->replayinfo->guidata[i] = NULL;
150  }
151  }
152  };
153 
154 };
155 
156 void iterateToNextPlayer( GameMap* actmap, bool saveNetwork, int lastPlayer, int lastTurn, MapDisplayInterface* display )
157 {
158  int loop = 0;
159  bool closeLoop = false;
160 
161  ReplayClearer replayClearing;
162 
163  do {
164 
165  int currentPlayer= actmap->actplayer;
166 
167  int nextPlayer = findNextPlayer( actmap, &replayClearing );
168 
169  if ( nextPlayer <= currentPlayer ) {
170  actmap->endRound();
171  ++loop;
172  }
173 
174  if ( loop > 2 ) {
175  displaymessage("no human players found !", 1 );
176  delete actmap;
177  actmap = NULL;
178  throw NoMapLoaded();
179  }
180 
181 
182  actmap->actplayer = nextPlayer;
183 
184  if ( actmap->player[nextPlayer].stat == Player::computer ) {
185  actmap->beginTurn();
186  runai( actmap, lastPlayer, display );
187  actmap->endTurn();
188  }
189 
190  if ( actmap->player[nextPlayer].stat == Player::suspended ) {
191  actmap->beginTurn();
192  actmap->endTurn();
193  }
194 
195  if ( actmap->player[nextPlayer].stat == Player::human || actmap->player[nextPlayer].stat == Player::supervisor ) {
196  if ( actmap->network && lastPlayer >= 0 && saveNetwork ) {
197  actmap->network->send( actmap, lastPlayer, lastTurn );
198  delete actmap;
199  actmap = NULL;
200  throw NoMapLoaded();
201  } else
202  closeLoop = true;
203  }
204  } while ( !closeLoop ); /* enddo */
205 
206 }
207 
209 {
210  viewtext2(904);
211  if ( choice_dlg("Do you want to continue playing ?","~y~es","~n~o") == 2)
212  return false;
213  else
214  return true;
215 }
216 
218 {
219  return authenticateUser( actmap );
220 }
221 
223  return false;
224 };
225 
227 {
228  return true;
229 }
230 
231 
232 void next_turn ( GameMap* gamemap, const NextTurnStrategy& nextTurnStrategy, MapDisplayInterface* display, int playerView )
233 {
234  int lastPlayer = gamemap->actplayer;
235  int lastTurn = gamemap->time.turn();
236 
237  if ( lastPlayer >= 0 )
238  gamemap->endTurn();
239 
240  /*
241  int pv;
242  if ( playerView == -2 ) {
243  if ( gamemap->time.turn() <= 0 || gamemap->actplayer < 0 )
244  pv = -1;
245  else
246  if ( gamemap->player[gamemap->actplayer].stat != Player::human )
247  pv = -1;
248  else
249  pv = gamemap->actplayer;
250  } else
251  pv = playerView;
252  */
253 
254 
255  if ( findNextPlayer( gamemap ) == lastPlayer ) {
256  if ( !gamemap->continueplaying ) {
257  if ( !nextTurnStrategy.continueWhenLastPlayer() ) {
258  delete gamemap;
259  gamemap = NULL;
260  throw NoMapLoaded();
261  } else {
262  gamemap->continueplaying = true;
263  if ( gamemap->replayinfo ) {
264  delete gamemap->replayinfo;
265  gamemap->replayinfo = NULL;
266  }
267  }
268  }
269  }
270 
271 
272  iterateToNextPlayer( gamemap, true, lastPlayer, lastTurn, display );
273 
274  gamemap->setPlayerView ( -1 );
275 
276  if ( ! nextTurnStrategy.authenticate(gamemap) ) {
277  delete gamemap;
278  throw NoMapLoaded();
279  }
280 
281  gamemap->beginTurn();
282  gamemap->setPlayerView ( gamemap->actplayer );
283  gamemap->overviewMapHolder.clear();
284 
285  gamemap->sigPlayerUserInteractionBegins( gamemap->player[gamemap->actplayer] );
286 
287  checktimedevents( gamemap, display );
288  checkevents( gamemap, display );
289 }
290 
291 
292 void skipTurn( GameMap* gamemap )
293 {
294  if ( gamemap->actplayer >= 0 ) {
296 
297  gamemap->beginTurn();
298  gamemap->endTurn();
299  }
300  iterateToNextPlayer( gamemap, false, -1, -1, NULL );
301 }
302 
303 void checkUsedASCVersions ( Player& currentPlayer )
304 {
305  for ( int i = 0; i < 8; i++ )
306  if ( currentPlayer.getParentMap()->player[i].exist() )
307  if ( currentPlayer.getParentMap()->actplayer != i )
308  if ( currentPlayer.getParentMap()->player[i].ASCversion > 0 )
309  if ( (currentPlayer.getParentMap()->player[i].ASCversion & 0xffffff00) > getNumericVersion() ) {
310  new Message ( ASCString("Player ") + currentPlayer.getParentMap()->player[i].getName()
311  + " is using a newer version of ASC. \n"
312  "Please check www.asc-hq.org for updates.\n\n"
313  "Please do NOT report any problems with this version of ASC until "
314  "you have confirmed that they are also present in the latest "
315  "version of ASC.", currentPlayer.getParentMap(), 1<<currentPlayer.getParentMap()->actplayer );
316  return;
317  }
318 
319 }
320 
321 
322 
323 
324 GameMap* continueNetworkGame ( bool mostRecent )
325 {
326  ASCString filename;
327  if ( !mostRecent ) {
328  filename = selectFile( ASCString("*") + tournamentextension + ";*.asc", true );
329  } else {
330  int datefound = 0;
331 
332  for ( int w = 0; w < 2; ++w) {
333 
334  ASCString wildcard;
335  if ( w == 0 )
336  wildcard = ASCString("*") + tournamentextension;
337  else
338  wildcard = "*.asc";
339 
340  tfindfile ff ( wildcard );
341 
343  while ( ff.getnextname( fi ))
344  if ( fi.date > datefound ) {
345  datefound = fi.date;
346  filename = fi.name;
347  }
348  }
349  }
350 
351  if ( filename.empty() )
352  return NULL;
353 
354  StatusMessageWindowHolder smw = MessagingHub::Instance().infoMessageWindow( "loading " + filename );
355 
356  return continueNetworkGame( filename );
357 }
358 
360 {
361  FileTransfer ft;
362  auto_ptr<GameMap> newMap ( mapLoadingExceptionChecker( filename, MapLoadingFunction( &ft, &FileTransfer::loadPBEMFile )));
363  if ( !newMap.get() )
364  return NULL;
365 
366  if ( !authenticateUser( newMap.get(), true, false ))
367  return NULL;
368 
369  computeview( newMap.get() );
370  newMap->beginTurn();
371  newMap->setPlayerView ( newMap->actplayer );
372  return newMap.release();
373 }
374 
375 
376 
377 void checkforvictory ( GameMap* gamemap, bool hasTurnControl )
378 {
379  if ( !gamemap->continueplaying ) {
380  int plnum = 0;
381  for ( int i = 0; i < 8; i++ )
382  if ( !gamemap->player[i].exist() && gamemap->player[i].existanceAtBeginOfTurn ) {
383  int to = 0;
384  for ( int j = 0; j < 8; j++ )
385  if ( j != i )
386  to |= 1 << j;
387 
388 
389  if ( !gamemap->campaign.avail ) {
390  const char* sp = getmessage( 10010 ); // Message "player has been terminated"
391  ASCString txt;
392  txt.format( sp, gamemap->player[i].getName().c_str() );
393  new Message ( txt, gamemap, to );
394  }
395 
396  gamemap->player[i].existanceAtBeginOfTurn = false;
397 
398  if ( i == gamemap->actplayer ) {
399  if ( gamemap->getPlayerView() == i && gamemap->getPlayer(i).stat == Player::human )
400  displaymessage ( getmessage ( 10011 ),1 );
401 
402  int humannum=0;
403  for ( int j = 0; j < 8; j++ )
404  if (gamemap->player[j].exist() && gamemap->player[j].stat == Player::human )
405  humannum++;
406 
407  if ( hasTurnControl ) {
408  if ( humannum )
410  else {
411  delete gamemap;
412  gamemap = NULL;
413  throw NoMapLoaded();
414  }
415  }
416  }
417  } else
418  plnum++;
419 
420  if ( plnum <= 1 ) {
421  if ( gamemap->player[gamemap->actplayer].ai && gamemap->player[gamemap->actplayer].ai->isRunning() ) {
422  displaymessage("You lost!",1);
423  } else {
424  displaymessage("Congratulations!\nYou won!",1);
425  if (choice_dlg("Do you want to continue playing ?","~y~es","~n~o") == 2) {
426  delete gamemap;
427  gamemap = NULL;
428  throw NoMapLoaded();
429  } else {
430  gamemap->continueplaying = 1;
431  if ( gamemap->replayinfo ) {
432  delete gamemap->replayinfo;
433  gamemap->replayinfo = 0;
434  }
435  }
436  }
437  }
438  }
439 }
440 
virtual bool isRunning(void)=0
virtual bool continueWhenLastPlayer() const =0
Player & getPlayer(PlayerID p)
Definition: gamemap.h:257
MapDisplayInterface & getDefaultMapDisplay()
describes the behavier that next_turn() shall do when it finds out that the current player is the las...
Definition: turncontrol.h:42
bool authenticateUser(GameMap *actmap, bool allowCancel=true, bool lockView=true, bool throwOnFailure=false)
Definition: turncontrol.cpp:47
int getNumericVersion()
Definition: strtmesg.cpp:37
void clear(bool allImages=false)
Definition: gamemap.cpp:201
int computeview(GameMap *gamemap, int player_fieldcount_mask, bool disableShareView, const Context *context)
completely computes the view
map accessing and usage routines used by ASC and the mapeditor
void checkUsedASCVersions(Player &currentPlayer)
this checks if one player has been using a new ASC version than the current player. If this is the case, the current player is notified and asked to upgrade
GameMap * loadPBEMFile(const ASCString &filename)
int findNextPlayer(GameMap *actmap, AbstractPlayerProcessing *playerProcessor)
BaseAI * ai
if the player is run by an AI, this is the pointer to it
Definition: player.h:144
int getPosition() const
Definition: player.h:112
ASCString getnextname(int *loc=NULL, bool *inContainer=NULL, ASCString *location=NULL)
Returns the next entry of the internal file list.
Definition: basestrm.cpp:2211
const GameMap * getParentMap() const
Definition: player.h:114
ASCString getName() const
returns the name of the player
Definition: player.cpp:274
virtual void playerSkipped(Player &player)=0
int turn() const
Definition: typen.h:181
MemoryStreamStorage * guidata[8]
Definition: gamemap.h:374
Loki::Functor< GameMap *, LOKI_TYPELIST_1(const ASCString &) > MapLoadingFunction
Definition: loaders.h:57
void iterateToNextPlayer(GameMap *actmap, bool saveNetwork, int lastPlayer, int lastTurn, MapDisplayInterface *display)
void beginTurn()
called when a player starts his turn
Definition: gamemap.cpp:1263
bool isHuman() const
Definition: player.h:152
virtual bool authenticate(GameMap *actmap) const =0
Interface for some basic classes from which all of ASC's dialogs are derived.
GameMap * continueNetworkGame(bool mostRecent)
continues a PBeM game; the current map is deleted
bool enterpassword(Password &pwd, bool firstTime, bool cancelAllowed, bool defaultAllowed, const ASCString &username)
Definition: pwd_dlg.cpp:158
Definition: ai.h:44
ASCString & format(const charT *pFormat,...)
Definition: ascstring.cpp:78
A class that hols a MessageWindow. This class ensures that the window is removed if the last copy of ...
Definition: messaginghub.h:34
The ASCString class provides an abstract way to manipulate strings.
Definition: ascstring.h:14
const char * getmessage(int id)
returns a pointer to the message id. The messages must have been loaded with loadmessages ...
void checktimedevents(GameMap *gamemap, MapDisplayInterface *md)
bool checkevents(GameMap *gamemap, MapDisplayInterface *md)
int getPlayerView() const
the player which is currently viewing the map.
Definition: gamemap.cpp:1007
void next_turn(GameMap *gamemap, const NextTurnStrategy &nextTurnStrategy, MapDisplayInterface *display, int playerView)
bool empty() const
Definition: password.cpp:89
void endRound()
called between endTurn() of player 7 and the next turn of player 0
Definition: gamemap.cpp:1357
GameMap * mapLoadingExceptionChecker(const ASCString &filename, MapLoadingFunction loader)
Definition: loaders.cpp:1539
enum Player::PlayerStatus stat
Password getDefaultPassword()
Definition of THE central asc class: GameMap.
void displaymessage(const char *formatstring, int num,...)
displays a dialog box with a message
Definition: dlg_box.cpp:1849
virtual void run(MapDisplayInterface *mapDisplay)=0
Searching for files.
Definition: basestrm.h:484
ASCString name
Definition: basestrm.h:489
bool avail
is this a campaign map?
Definition: gamemap.h:221
sigc::signal< void > updateFieldInfo
Definition: spfst.cpp:47
int viewtextquery(int id, const char *title, const char *s1, const char *s2)
Definition: dlg_box.cpp:3394
signed char actplayer
the player who is currently making his moves (may be human or AI)
Definition: gamemap.h:232
MemoryStreamStorage * map[8]
Definition: gamemap.h:375
Player player[9]
Definition: gamemap.h:253
static CGameOptions * Instance()
returns the only Instance
Definition: gameoptions.cpp:38
OverviewMapHolder overviewMapHolder
Definition: gamemap.h:532
ASCString selectFile(const ASCString &ext, bool load, bool overwriteMessage)
void skipTurn(GameMap *gamemap)
skips the next player. This is for administrative use, for example if a player does not react ...
bool continueWhenLastPlayer() const
A Message to a player. It may either be send by another player or by the system.
Definition: messages.h:30
Interface for all the dialog boxes used by the game and the mapeditor.
void checkforvictory(GameMap *gamemap, bool hasTurnControl)
checks if the current player has terminated another player or even won
bool continueWhenLastPlayer() const
The interface for the artificial intelligence of ASC.
virtual void send(const GameMap *map, int lastPlayer, int lastturn)=0
procedure for loading and writing savegames, maps etc.
bool existanceAtBeginOfTurn
did the player exist when the turn started? Required for checking if a player has been terminated ...
Definition: player.h:131
GameMap * actmap
Definition: spfst.cpp:64
Interface to the event handling of ASC.
GameTransferMechanism * network
Definition: gamemap.h:576
void viewtext2(int id)
displays a dialogbog with the given message
Definition: dlg_box.cpp:3296
the different players in ASC. There may be 8 players (0..7) and neutral units (8) ...
Definition: player.h:99
void setPlayerView(int player)
Definition: gamemap.cpp:1017
Password passwordcrc
the Password required for playing this player
Definition: player.h:160
sigc::signal< void, Player & > sigPlayerUserInteractionBegins
Definition: gamemap.h:494
bool authenticate(GameMap *actmap) const
int choice_dlg(const ASCString &title, const ASCString &leftButton, const ASCString &rightButton)
Definition: dialog.cpp:616
bool authenticate(GameMap *actmap) const
void runai(GameMap *actmap, int playerView, MapDisplayInterface *display)
Definition: turncontrol.cpp:96
int getPlayerCount() const
Definition: gamemap.h:255
int ASCversion
the version of ASC that this player has used to make his last turn
Definition: player.h:196
void endTurn()
called after a player ends his turn
Definition: gamemap.cpp:1281
bool exist() const
does the player exist at all
Definition: player.cpp:313
ReplayInfo * replayinfo
Definition: gamemap.h:396
GameTime time
the time in the game, mesured in a turns and moves
Definition: gamemap.h:235
const char * tournamentextension
Definition: loaders.cpp:80
void infoMessage(const ASCString &string)
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
bool continueplaying
if a player has won a singleplayer map, but wants to continue playing without any enemies...
Definition: gamemap.h:512
struct GameMap::Campaign campaign