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

replay.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           replay.cpp  -  description
00003                              -------------------
00004     begin                : Sun Jan 21 2001
00005     copyright            : (C) 2001 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00016 /***************************************************************************
00017  *                                                                         *
00018  *   This program is free software; you can redistribute it and/or modify  *
00019  *   it under the terms of the GNU General Public License as published by  *
00020  *   the Free Software Foundation; either version 2 of the License, or     *
00021  *   (at your option) any later version.                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #include <stdarg.h>
00026 #include "replay.h"
00027 #include "typen.h"
00028 #include "buildingtype.h"
00029 #include "vehicletype.h"
00030 #include "spfst.h"
00031 #include "controls.h"
00032 #include "dialog.h"
00033 #include "gameoptions.h"
00034 #include "viewcalculation.h"
00035 #include "itemrepository.h"
00036 #include "containercontrols.h"
00037 #include "resourcenet.h"
00038 #include "guiiconhandler.h"
00039 #include "guifunctions.h"
00040 #include "cannedmessages.h"
00041 #include "unitctrl.h"
00042 #include "replaymapdisplay.h"
00043 #include "asc-mainscreen.h"
00044 #include "loaders.h"
00045 #include "turncontrol.h"
00046 #include "widgets/textrenderer.h"
00047 #include "actions/jumpdrive.h"
00048 #include "actions/selfdestruct.h"
00049 #include "reactionfire.h"
00050 #include "gameeventsystem.h"
00051 #include "sdl/graphicsqueue.h"
00052 #include "video/videorecorder.h"
00053 #include "iconrepository.h"
00054 #include "dialogs/replayrecorder.h"
00055 
00056 trunreplay runreplay;
00057 
00058 int startreplaylate = 0;
00059 
00060 
00061 class ReplayRecorder;
00062 
00063 class ReplayRecorderWatcherGlobal {
00064       ReplayRecorder* recorder;
00065    public:
00066       ReplayRecorderWatcherGlobal()  : recorder( NULL ) {};
00067       void set(  ReplayRecorder* rec  ) {
00068          recorder = rec;
00069       }
00070       
00071       ~ReplayRecorderWatcherGlobal() ;
00072 } replayRecorderWatcherGlobal;
00073 
00074 
00075  class ReplayRecorder : public SigC::Object {
00076    
00077    VideoRecorder* rec;
00078    SigC::Connection connection;
00079    bool movieModeStorage;
00080    ASCString lastFilename;
00081    
00082    public:
00083       ReplayRecorder() : rec (NULL)
00084       {
00085          movieModeStorage = CGameOptions::Instance()->replayMovieMode;
00086          replayRecorderWatcherGlobal.set( this );
00087       }
00088       
00089       void start( const ASCString& filename, bool append, int framerate, int quality )
00090       {
00091          lastFilename = filename;
00092          movieModeStorage = CGameOptions::Instance()->replayMovieMode;
00093          CGameOptions::Instance()->replayMovieMode = true;
00094          ASCString newFilename = constructFileName( 0, "", filename );
00095          if ( !rec || !append || newFilename != rec->getFilename()  ) {
00096             delete rec;
00097             rec = new VideoRecorder( newFilename, PG_Application::GetScreen(), framerate, quality );
00098          }
00099          
00100          if ( !connection.connected() )
00101             connection = postScreenUpdate.connect( SigC::slot( *this, &ReplayRecorder::screenUpdate ));
00102       }
00103       
00104       void pause()
00105       {
00106          if ( connection.connected() )
00107             connection.disconnect();
00108          CGameOptions::Instance()->replayMovieMode = movieModeStorage;
00109       }
00110       
00111       void close()
00112       {
00113          pause();
00114          delete rec;
00115          rec = NULL;
00116       }
00117       
00118       bool isRunning()
00119       {
00120          return connection.connected() && rec;
00121       }
00122       
00123       bool isOpen()
00124       {
00125          return rec != NULL;  
00126       }
00127       
00128       ASCString getLastFilename()
00129       {
00130          return lastFilename;
00131       }
00132    
00133    private:
00134       void screenUpdate( const SDL_Surface* surf )
00135       {
00136          if ( rec )
00137             rec->storeFrame( surf );
00138       }
00139 };
00140 
00141 class ReplayRecorderWatcherLocal {
00142       ReplayRecorder* recorder;
00143    public:
00144       ReplayRecorderWatcherLocal( ReplayRecorder* rec )  : recorder( rec ) {};
00145       ~ReplayRecorderWatcherLocal() 
00146       { 
00147          if ( recorder ) 
00148             recorder->pause();
00149       }
00150 };
00151 
00152 
00153 ReplayRecorderWatcherGlobal::~ReplayRecorderWatcherGlobal() 
00154 { 
00155    if ( recorder ) 
00156       recorder->pause();
00157 }
00158 
00159 
00160 ReplayRecorder* replayRecorder = NULL;
00161 
00162  
00163 
00164 namespace ReplayGuiFunctions {
00165 
00166 class ReplayPlay : public GuiFunction
00167 {
00168    public:
00169       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00170       {
00171          if ( runreplay.status == 1 )
00172             return true;
00173 
00174          return false;
00175       };
00176 
00177       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00178       {
00179         runreplay.status = 2;
00180         updateFieldInfo();
00181       }
00182 
00183       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00184       {
00185          return IconRepository::getIcon("replay-play.png");
00186       };
00187 
00188       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00189       {
00190          return "start re~p~lay";
00191       };
00192 
00193       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00194       {
00195          return ( key->keysym.unicode == 'p' );
00196       };
00197       
00198 };
00199 
00200 
00201 class ReplayPause : public GuiFunction
00202 {
00203    public:
00204       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00205       {
00206          if ( runreplay.status == 2 )
00207             return true;
00208 
00209          return false;
00210       };
00211 
00212       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00213       {
00214         runreplay.status = 1;
00215         updateFieldInfo();
00216       }
00217 
00218       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00219       {
00220          return IconRepository::getIcon("replay-pause.png");
00221       };
00222 
00223       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00224       {
00225          return "~p~ause replay";
00226       };
00227       
00228       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00229       {
00230          return ( key->keysym.unicode == 'p' );
00231       };
00232       
00233 };
00234 
00235 
00236 
00237 class ReplayFaster : public GuiFunction
00238 {
00239    public:
00240       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00241       {
00242          if ( runreplay.status == 2 )
00243             if ( CGameOptions::Instance()->replayspeed > 0 )
00244               return true;
00245 
00246          return false;
00247       };
00248 
00249       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00250       {
00251          if ( CGameOptions::Instance()->replayspeed > 20 )
00252             CGameOptions::Instance()->replayspeed -= 20;
00253          else
00254             CGameOptions::Instance()->replayspeed = 0;
00255 
00256          CGameOptions::Instance()->setChanged ( 1 );
00257          displaymessage2 ( "delay set to %d / 100 sec", CGameOptions::Instance()->replayspeed );
00258          updateFieldInfo();
00259       }
00260 
00261       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00262       {
00263          return IconRepository::getIcon("replay-faster.png");
00264       };
00265 
00266       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00267       {
00268          return "increase replay speed (~+~)";
00269       };
00270 
00271       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00272       {
00273          return ( key->keysym.unicode == '+' || key->keysym.sym == SDLK_KP_PLUS);
00274       };
00275       
00276 };
00277 
00278 
00279 class ReplaySlower : public GuiFunction
00280 {
00281    public:
00282       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00283       {
00284          if ( runreplay.status == 2 )
00285             return true;
00286 
00287          return false;
00288       };
00289 
00290       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00291       {
00292          CGameOptions::Instance()->replayspeed += 20;
00293          CGameOptions::Instance()->setChanged ( 1 );
00294          displaymessage2 ( "delay set to %d / 100 sec", CGameOptions::Instance()->replayspeed );
00295          updateFieldInfo();
00296       }
00297 
00298       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00299       {
00300          return IconRepository::getIcon("replay-slow.png");
00301       };
00302 
00303       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00304       {
00305          return "decrease replay speed (~-~)";
00306       };
00307 
00308       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00309       {
00310          return ( key->keysym.unicode == '-' || key->keysym.sym == SDLK_KP_MINUS);
00311       };
00312       
00313 };
00314 
00315 
00316 class ReplayRewind : public GuiFunction
00317 {
00318    public:
00319       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00320       {
00321          if ( runreplay.status == 1  ||  runreplay.status == 10 )
00322               return true;
00323 
00324          return false;
00325       };
00326 
00327       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00328       {
00329          runreplay.status = 101;
00330          updateFieldInfo();
00331       }
00332 
00333       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00334       {
00335          return IconRepository::getIcon("replay-back.png");
00336       };
00337 
00338       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00339       {
00340          return "~r~estart replay";
00341       };
00342 
00343       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00344       {
00345          return ( key->keysym.unicode == 'r' );
00346       };
00347       
00348 };
00349 
00350 
00351 class ReplayExit : public GuiFunction
00352 {
00353    public:
00354       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00355       {
00356          if ( runreplay.status == 1 || runreplay.status == 10 || runreplay.status == 11 )
00357               return true;
00358 
00359          return false;
00360       };
00361 
00362       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00363       {
00364          runreplay.status = 100;
00365          updateFieldInfo();
00366       }
00367 
00368       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00369       {
00370          return IconRepository::getIcon("replay-exit.png");
00371       };
00372 
00373       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00374       {
00375          return "e~x~it replay";
00376       };
00377 
00378       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00379       {
00380          return ( key->keysym.unicode == 'x' );
00381       };
00382       
00383 };
00384 
00385 class ReplayRecord : public GuiFunction
00386 {
00387    public:
00388       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00389       {
00390          if ( runreplay.status == 1 )
00391             return true;
00392 
00393          return false;
00394       };
00395 
00396       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00397       {
00398         ASCString filename;
00399         bool open = false;
00400         if ( replayRecorder ) {
00401            filename = replayRecorder->getLastFilename();
00402            open = replayRecorder->isOpen();
00403         }
00404         
00405         ReplayRecorderDialog rrd( filename, open );
00406         rrd.Show();
00407         rrd.RunModal();
00408         rrd.Hide();
00409          
00410         if ( !replayRecorder )
00411            replayRecorder = new ReplayRecorder();
00412         replayRecorder->start( rrd.getFilename(), rrd.getAppend(), rrd.getFramerate(), rrd.getQuality() );
00413         
00414         runreplay.status = 2;
00415         updateFieldInfo();
00416       }
00417 
00418       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00419       {
00420          return IconRepository::getIcon("replay-record.png");
00421       };
00422 
00423       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00424       {
00425          return "record to ~v~ideo";
00426       };
00427 
00428       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00429       {
00430          return ( key->keysym.unicode == 'v' );
00431       };
00432       
00433 };
00434 
00435 class ReplayRecordExit : public GuiFunction
00436 {
00437    public:
00438       bool available( const MapCoordinate& pos, ContainerBase* subject, int num )
00439       {
00440          if ( replayRecorder && replayRecorder->isOpen() && (runreplay.status == 1 || runreplay.status == 10 || runreplay.status == 11) )
00441               return true;
00442 
00443          return false;
00444       };
00445 
00446       void execute( const MapCoordinate& pos, ContainerBase* subject, int num )
00447       {
00448          replayRecorder->close();
00449          runreplay.status = 100;
00450          updateFieldInfo();
00451       }
00452 
00453       Surface& getImage( const MapCoordinate& pos, ContainerBase* subject, int num )
00454       {
00455          return IconRepository::getIcon("replay-record-stop.png");
00456       };
00457 
00458       ASCString getName( const MapCoordinate& pos, ContainerBase* subject, int num )
00459       {
00460          return "exit replay and ~c~lose recording";
00461       };
00462 
00463       bool checkForKey( const SDL_KeyboardEvent* key, int modifier, int num )
00464       {
00465          return ( key->keysym.unicode == 'c' );
00466       };
00467       
00468 };
00469 
00470 
00471 }
00472 
00473 void registerReplayGuiFunctions( GuiIconHandler& handler )
00474 {
00475    handler.registerUserFunction( new ReplayGuiFunctions::ReplayPlay() );
00476 #ifdef XVIDEXPORT   
00477    handler.registerUserFunction( new ReplayGuiFunctions::ReplayRecord() );
00478 #endif   
00479    handler.registerUserFunction( new ReplayGuiFunctions::ReplayPause() );
00480    handler.registerUserFunction( new ReplayGuiFunctions::ReplayFaster() );
00481    handler.registerUserFunction( new ReplayGuiFunctions::ReplaySlower() );
00482    handler.registerUserFunction( new ReplayGuiFunctions::ReplayRewind() );
00483 #ifdef XVIDEXPORT   
00484    handler.registerUserFunction( new ReplayGuiFunctions::ReplayRecordExit() );
00485 #endif
00486    handler.registerUserFunction( new ReplayGuiFunctions::ReplayExit() );
00487 }
00488 
00489 
00490 
00491 class ReplayGuiIconHandleHandler {
00492    static GuiIconHandler* replayIconHandler;
00493    bool active;
00494    public:
00495       ReplayGuiIconHandleHandler()
00496       {
00497          if ( !replayIconHandler ) {
00498             replayIconHandler = new GuiIconHandler();
00499             registerReplayGuiFunctions( *replayIconHandler );
00500          }
00501          
00502          if ( NewGuiHost::getIconHandler() != replayIconHandler ) {
00503             active = true;
00504             NewGuiHost::pushIconHandler( replayIconHandler );
00505          } else
00506             active = false;
00507       };
00508 
00509       ~ReplayGuiIconHandleHandler()
00510       {
00511          if ( active )
00512             NewGuiHost::popIconHandler();
00513       };
00514 };
00515 GuiIconHandler* ReplayGuiIconHandleHandler::replayIconHandler = NULL;
00516 
00517 
00518 
00519 
00520 
00521 void runSpecificReplay( int player, int viewingplayer, bool performEndTurnOperations )
00522 {
00523     if ( actmap->replayinfo->map[player] && actmap->replayinfo->guidata[player] ) {
00524        try {
00525          int t;
00526          do {
00527             t = runreplay.run ( player, viewingplayer, performEndTurnOperations );
00528          } while ( t ); /* enddo */
00529        }
00530 
00531 #ifndef _DEBUG
00532        catch ( ... ) {     // this will catch NullPointer-Exceptions and stuff like that, which we want to pass to the debugger  in debug mode
00533 #else
00534        catch ( GameMap ) {  // will never be thrown, but we need catch statement for the try block
00535 #endif
00536           errorMessage("An unrecognized error occured during the replay");
00537           delete actmap;
00538           actmap = NULL;
00539           throw NoMapLoaded();
00540        }
00541     }
00542 }
00543 
00544 void viewOwnReplay( Player& player )
00545 {
00546    if ( player.stat == Player::human || player.stat == Player::supervisor )
00547       if ( CGameOptions::Instance()->debugReplay && player.getParentMap()->replayinfo )
00548          if (choice_dlg("run replay of your turn ?","~y~es","~n~o") == 1) {
00549             // cursor.gotoxy( actmap->cursorpos.position[oldplayer].cx, actmap->cursorpos.position[oldplayer].cy );
00550             runSpecificReplay ( player.getPosition(), player.getPosition(), false );
00551          }
00552 }
00553 
00554 
00555 void checkforreplay ( void )
00556 {
00557    if ( !actmap->replayinfo )
00558       return;
00559 
00560    int rpnum  = 0;
00561    int s = actmap->actplayer + 1;
00562    if ( s >= 8 )
00563        s = 0;
00564    while ( s != actmap->actplayer ) {
00565        if ( actmap->replayinfo->map[s] && actmap->replayinfo->guidata[s] )
00566           rpnum++;
00567 
00568        if ( s < 7 )
00569           s++;
00570        else
00571           s = 0;
00572    }
00573 
00574 
00575    if ( actmap->replayinfo  &&  rpnum  &&  (actmap->player[ actmap->actplayer ].stat == Player::human || actmap->player[ actmap->actplayer ].stat == Player::supervisor) )
00576       if (choice_dlg("run replay of last turn ?","~y~es","~n~o") == 1) {
00577       
00578          MainScreenWidget::StandardActionLocker locker( mainScreenWidget, MainScreenWidget::LockOptions::Menu );
00579          ReplayGuiIconHandleHandler guiIconHandler;
00580          
00581          int s = actmap->actplayer + 1;
00582          if ( s >= 8 )
00583             s = 0;
00584          while ( s != actmap->actplayer ) {
00585             if ( s >= 8 )
00586                s = 0;
00587 
00588              runSpecificReplay(s, actmap->actplayer );
00589 
00590              if ( s < 7 )
00591                  s++;
00592               else
00593                  s = 0;
00594           }
00595 
00596 
00597       }
00598 }
00599 
00600 
00601 void initReplayLogging( Player& player )
00602 {
00603    GameMap* gamemap = player.getParentMap();
00604    
00605    if ( startreplaylate ) {
00606       gamemap->replayinfo = new GameMap::ReplayInfo;
00607       startreplaylate = 0;
00608    }
00609 
00610    if ( gamemap->replayinfo && player.stat != Player::off ) {
00611       if ( gamemap->replayinfo->actmemstream )
00612          fatalError( "actmemstream already open at begin of turn " );
00613 
00614       if ( gamemap->replayinfo->guidata[ player.getPosition() ] ) {
00615          delete gamemap->replayinfo->guidata[ player.getPosition() ];
00616          gamemap->replayinfo->guidata[ player.getPosition() ] = NULL;
00617       }
00618 
00619       savereplay ( gamemap, player.getPosition() );
00620 
00621       gamemap->replayinfo->guidata[ player.getPosition() ] = new tmemorystreambuf;
00622       gamemap->replayinfo->actmemstream = new tmemorystream ( gamemap->replayinfo->guidata[ player.getPosition() ], tnstream::writing );
00623    }
00624 }
00625 
00626 
00627 LockReplayRecording::LockReplayRecording( GameMap::ReplayInfo& _ri )
00628                     : ri ( _ri )
00629 {
00630    ri.stopRecordingActions++;
00631 }
00632 
00633 LockReplayRecording::~LockReplayRecording()
00634 {
00635    ri.stopRecordingActions--;
00636 }
00637 
00638 
00639 Resources getUnitResourceCargo ( Vehicle* veh )
00640 {
00641    Resources res = veh->getTank();
00642    for ( ContainerBase::Cargo::const_iterator i = veh->getCargo().begin(); i != veh->getCargo().end(); ++i )
00643       if ( *i )
00644          res += getUnitResourceCargo ( *i );
00645    return res;
00646 }
00647 
00648 void logtoreplayinfo ( trpl_actions _action, ... )
00649 {
00650    char action = _action;
00651    if ( actmap->replayinfo && actmap->replayinfo->actmemstream && !actmap->replayinfo->stopRecordingActions) {
00652       pnstream stream = actmap->replayinfo->actmemstream;
00653 
00654       va_list paramlist;
00655       va_start ( paramlist, _action );
00656 
00657       if ( action == rpl_attack || action == rpl_reactionfire ) {
00658          int x1 =  va_arg ( paramlist, int );
00659          int y1 =  va_arg ( paramlist, int );
00660          int x2 =  va_arg ( paramlist, int );
00661          int y2 =  va_arg ( paramlist, int );
00662          int ad1 =  va_arg ( paramlist, int );
00663          int ad2 =  va_arg ( paramlist, int );
00664          int dd1 =  va_arg ( paramlist, int );
00665          int dd2 =  va_arg ( paramlist, int );
00666          int wpnum =  va_arg ( paramlist, int );
00667          int size = 9;
00668          stream->writeChar ( action );
00669          stream->writeInt ( size );
00670          stream->writeInt ( x1 );
00671          stream->writeInt ( y1 );
00672          stream->writeInt ( x2 );
00673          stream->writeInt ( y2 );
00674          stream->writeInt ( ad1 );
00675          stream->writeInt ( ad2 );
00676          stream->writeInt ( dd1 );
00677          stream->writeInt ( dd2 );
00678          stream->writeInt ( wpnum );
00679       }
00680 
00681       if ( action == rpl_move ) {
00682          int x1 =  va_arg ( paramlist, int );
00683          int y1 =  va_arg ( paramlist, int );
00684          int x2 =  va_arg ( paramlist, int );
00685          int y2 =  va_arg ( paramlist, int );
00686          int nwid = va_arg ( paramlist, int );
00687          stream->writeChar ( action );
00688          int size = 5;
00689          stream->writeInt ( size );
00690          stream->writeInt ( x1 );
00691          stream->writeInt ( y1 );
00692          stream->writeInt ( x2 );
00693          stream->writeInt ( y2 );
00694          stream->writeInt ( nwid );
00695       }
00696       if ( action == rpl_move2 || action == rpl_move3 || action == rpl_move4 || action==rpl_move5) {
00697          int x1 =  va_arg ( paramlist, int );
00698          int y1 =  va_arg ( paramlist, int );
00699          int x2 =  va_arg ( paramlist, int );
00700          int y2 =  va_arg ( paramlist, int );
00701          int nwid = va_arg ( paramlist, int );
00702          int height = va_arg ( paramlist, int );
00703 
00704          stream->writeChar ( action );
00705          if ( action == rpl_move5 ) {
00706             int size = 8;
00707             stream->writeInt( size );
00708          } else 
00709             if ( action == rpl_move2 ) {
00710                int size = 6;
00711                stream->writeInt ( size );
00712             } else {
00713                int size = 7;
00714                stream->writeInt ( size );
00715             }
00716          stream->writeInt ( x1 );
00717          stream->writeInt ( y1 );
00718          stream->writeInt ( x2 );
00719          stream->writeInt ( y2 );
00720          stream->writeInt ( nwid );
00721          stream->writeInt ( height );
00722          if ( action == rpl_move3 || action == rpl_move4 || action==rpl_move5) {
00723             int nointerrupt = va_arg ( paramlist, int );
00724             stream->writeInt ( nointerrupt );
00725             if ( action==rpl_move5 ) {
00726                int destDamage = va_arg( paramlist, int );
00727                stream->writeInt( destDamage );
00728             }
00729          }
00730       }
00731 
00732       if ( action == rpl_changeheight || action == rpl_changeheight2 ) {
00733          int x1 =  va_arg ( paramlist, int );
00734          int y1 =  va_arg ( paramlist, int );
00735          int x2 =  va_arg ( paramlist, int );
00736          int y2 =  va_arg ( paramlist, int );
00737          int nwid = va_arg ( paramlist, int );
00738          int oldheight = va_arg ( paramlist, int );
00739          int newheight = va_arg ( paramlist, int );
00740          stream->writeChar ( action );
00741          if ( action == rpl_changeheight ) {
00742             int size = 7;
00743             stream->writeInt ( size );
00744          } else {
00745             int size = 8;
00746             stream->writeInt ( size );
00747          }
00748          stream->writeInt ( x1 );
00749          stream->writeInt ( y1 );
00750          stream->writeInt ( x2 );
00751          stream->writeInt ( y2 );
00752          stream->writeInt ( nwid );
00753          stream->writeInt ( oldheight );
00754          stream->writeInt ( newheight );
00755          if ( action == rpl_changeheight2 ) {
00756             int noInterrupt = va_arg ( paramlist, int );
00757             stream->writeInt ( noInterrupt );
00758          }
00759       }
00760       if ( action == rpl_convert  ) {
00761          int x =  va_arg ( paramlist, int );
00762          int y =  va_arg ( paramlist, int );
00763          int col =  va_arg ( paramlist, int );
00764          stream->writeChar ( action );
00765          int size = 3;
00766          stream->writeInt ( size );
00767          stream->writeInt ( x );
00768          stream->writeInt ( y );
00769          stream->writeInt ( col );
00770       }
00771       if ( action == rpl_convert2  ) {
00772          int x =  va_arg ( paramlist, int );
00773          int y =  va_arg ( paramlist, int );
00774          int col =  va_arg ( paramlist, int );
00775          int nwid =  va_arg ( paramlist, int );
00776          stream->writeChar ( action );
00777          int size = 4;
00778          stream->writeInt ( size );
00779          stream->writeInt ( x );
00780          stream->writeInt ( y );
00781          stream->writeInt ( col );
00782          stream->writeInt ( nwid );
00783       }
00784       if ( action == rpl_buildobj || action == rpl_remobj ) {
00785          int x =  va_arg ( paramlist, int );
00786          int y =  va_arg ( paramlist, int );
00787          int id =  va_arg ( paramlist, int );
00788          stream->writeChar ( action );
00789          int size = 3;
00790          stream->writeInt ( size );
00791          stream->writeInt ( x );
00792          stream->writeInt ( y );
00793          stream->writeInt ( id );
00794       }
00795       if ( action == rpl_buildobj2 || action == rpl_remobj2 ) {
00796          int x =  va_arg ( paramlist, int );
00797          int y =  va_arg ( paramlist, int );
00798          int id =  va_arg ( paramlist, int );
00799          int unit = va_arg ( paramlist, int );
00800          stream->writeChar ( action );
00801          int size = 4;
00802          stream->writeInt ( size );
00803          stream->writeInt ( x );
00804          stream->writeInt ( y );
00805          stream->writeInt ( id );
00806          stream->writeInt ( unit );
00807       }
00808       if ( action == rpl_buildtnk || action == rpl_buildtnk3 || action == rpl_buildtnk4 ) {
00809          int x =  va_arg ( paramlist, int );
00810          int y =  va_arg ( paramlist, int );
00811          int id =  va_arg ( paramlist, int );
00812          int col =  va_arg ( paramlist, int );
00813          stream->writeChar ( action );
00814          int size;
00815          if ( action == rpl_buildtnk )
00816             size = 4;
00817          else
00818             if ( action == rpl_buildtnk4 )
00819                size = 7;
00820             else
00821                size = 6;
00822 
00823          stream->writeInt ( size );
00824          stream->writeInt ( x );
00825          stream->writeInt ( y );
00826          stream->writeInt ( id );
00827          stream->writeInt ( col );
00828          if ( action == rpl_buildtnk3 || action == rpl_buildtnk4 ) {
00829             stream->writeInt ( va_arg ( paramlist, int ) ); // constructor x
00830             stream->writeInt ( va_arg ( paramlist, int ) ); // constructor x
00831             if ( action == rpl_buildtnk4  )
00832                stream->writeInt ( va_arg ( paramlist, int ) ); // unit height
00833          }
00834       }
00835       if ( action == rpl_buildtnk2 ) {
00836          stream->writeChar ( action );
00837          int size = 5;
00838          stream->writeInt ( size );
00839          stream->writeInt ( va_arg ( paramlist, int ) );
00840          stream->writeInt ( va_arg ( paramlist, int ) );
00841          stream->writeInt ( va_arg ( paramlist, int ) );
00842          stream->writeInt ( va_arg ( paramlist, int ) );
00843          stream->writeInt ( va_arg ( paramlist, int ) );
00844       }
00845       if ( action == rpl_putbuilding || action == rpl_putbuilding2 ) {
00846          int x =  va_arg ( paramlist, int );
00847          int y =  va_arg ( paramlist, int );
00848          int id = va_arg ( paramlist, int );
00849          int col =  va_arg ( paramlist, int );
00850          stream->writeChar ( action );
00851          if ( action == rpl_putbuilding )
00852             stream->writeInt ( 4 );
00853          else
00854             stream->writeInt ( 5 );
00855 
00856          stream->writeInt ( x );
00857          stream->writeInt ( y );
00858          stream->writeInt ( id );
00859          stream->writeInt ( col );
00860          if ( action == rpl_putbuilding2 )
00861             stream->writeInt ( va_arg ( paramlist, int ));
00862       }
00863       if ( action == rpl_putmine || action == rpl_putmine2 ) {
00864          int x =  va_arg ( paramlist, int );
00865          int y =  va_arg ( paramlist, int );
00866          int col =  va_arg ( paramlist, int );
00867          int typ = va_arg ( paramlist, int );
00868          int strength = va_arg ( paramlist, int );
00869          int nwid = -1; 
00870 
00871          stream->writeChar ( action );
00872          int size;
00873          if ( action == rpl_putmine ) {
00874             size = 5;
00875          } else {
00876             nwid = va_arg ( paramlist, int );
00877             size = 6;
00878          }
00879          stream->writeInt ( size );
00880          stream->writeInt ( x );
00881          stream->writeInt ( y );
00882          stream->writeInt ( col );
00883          stream->writeInt ( typ );
00884          stream->writeInt ( strength );
00885 
00886          if ( action == rpl_putmine2 ) 
00887             stream->writeInt ( nwid );
00888          
00889       }
00890       if ( action == rpl_removemine ) {
00891          int x =  va_arg ( paramlist, int );
00892          int y =  va_arg ( paramlist, int );
00893          stream->writeChar ( action );
00894          int size = 2;
00895          stream->writeInt ( size );
00896          stream->writeInt ( x );
00897          stream->writeInt ( y );
00898       }
00899       if ( action == rpl_removebuilding ) {
00900          int x =  va_arg ( paramlist, int );
00901          int y =  va_arg ( paramlist, int );
00902          stream->writeChar ( action );
00903          int size = 2;
00904          stream->writeInt ( size );
00905          stream->writeInt ( x );
00906          stream->writeInt ( y );
00907       }
00908       if ( action == rpl_removebuilding2 || action == rpl_removebuilding3) {
00909          int x =  va_arg ( paramlist, int );
00910          int y =  va_arg ( paramlist, int );
00911          int nwid = va_arg ( paramlist, int );
00912          stream->writeChar ( action );
00913          if ( action == rpl_removebuilding2 ) {
00914             int size = 3;
00915             stream->writeInt ( size );
00916             stream->writeInt ( x );
00917             stream->writeInt ( y );
00918             stream->writeInt( nwid );
00919          } else {
00920             int size = 6;
00921             stream->writeInt ( size );
00922             stream->writeInt ( x );
00923             stream->writeInt ( y );
00924             stream->writeInt( nwid );
00925             int e =  va_arg ( paramlist, int );
00926             int m =  va_arg ( paramlist, int );
00927             int f =  va_arg ( paramlist, int );
00928             stream->writeInt( e );
00929             stream->writeInt( m );
00930             stream->writeInt( f );
00931          }
00932       }
00933 
00934       if ( action == rpl_produceunit ) {
00935          int id = va_arg ( paramlist, int );
00936          int col = va_arg ( paramlist, int );
00937          int x =  va_arg ( paramlist, int );
00938          int y =  va_arg ( paramlist, int );
00939          int cl = va_arg ( paramlist, int );
00940          int nwid = va_arg ( paramlist, int );
00941          stream->writeChar ( action );
00942          int size = 6;
00943          stream->writeInt ( size );
00944          stream->writeInt ( id );
00945          stream->writeInt ( col );
00946          stream->writeInt ( x );
00947          stream->writeInt ( y );
00948          stream->writeInt ( cl );
00949          stream->writeInt ( nwid );
00950       }
00951       if ( action == rpl_removeunit ) {
00952          int x =  va_arg ( paramlist, int );
00953          int y =  va_arg ( paramlist, int );
00954          int nwid = va_arg ( paramlist, int );
00955          stream->writeChar ( action );
00956          int size = 3;
00957          stream->writeInt ( size );
00958          stream->writeInt ( x );
00959          stream->writeInt ( y );
00960          stream->writeInt ( nwid );
00961       }
00962       if ( action == rpl_trainunit ) {
00963          int x =  va_arg ( paramlist, int );
00964          int y =  va_arg ( paramlist, int );
00965          int exp =  va_arg ( paramlist, int );
00966          int nwid = va_arg ( paramlist, int );
00967          stream->writeChar ( action );
00968          int size = 4;
00969          stream->writeInt ( size );
00970          stream->writeInt ( x );
00971          stream->writeInt ( y );
00972          stream->writeInt ( exp );
00973          stream->writeInt ( nwid );
00974       }
00975       /*
00976       not supported any more because of new diplomatic model
00977       if ( action == rpl_shareviewchange ) {
00978          stream->writeChar ( action );
00979          if ( actmap->shareview ) {
00980             int size = 8*8/4+1;
00981             stream->writeInt ( size );
00982             for ( int a = 0; a < 8; a++ )
00983                for ( int b = 0; b < 8; b++ )
00984                    stream->writeChar ( actmap->shareview->mode[a][b] );
00985             stream->writeInt ( actmap->shareview->recalculateview );
00986          } else {
00987             int size = 0;
00988             stream->writeInt ( size );
00989          }
00990       }
00991       */
00992       if ( action == rpl_alliancechange2 ) {
00993          stream->writeChar ( action );
00994          stream->writeInt( 3 ); // size
00995 
00996          int actingPlayer =  va_arg ( paramlist, int );
00997          int targetPlayer =  va_arg ( paramlist, int );
00998          int state = va_arg ( paramlist, int );
00999          stream->writeInt( actingPlayer );
01000          stream->writeInt( targetPlayer );
01001          stream->writeInt( state );
01002       }
01003       if ( action == rpl_refuel || action == rpl_refuel2 ) {
01004          int x =  va_arg ( paramlist, int );
01005          int y =  va_arg ( paramlist, int );
01006          int nwid = va_arg ( paramlist, int );
01007          int pos = va_arg ( paramlist, int );
01008          int amnt = va_arg ( paramlist, int );
01009          stream->writeChar ( action );
01010          stream->writeInt ( action==rpl_refuel ? 5 : 6 );
01011          stream->writeInt ( x );
01012          stream->writeInt ( y );
01013          stream->writeInt ( nwid );
01014          stream->writeInt ( pos );
01015          stream->writeInt ( amnt );
01016          if ( action == rpl_refuel2 ) {
01017              int old = va_arg ( paramlist, int );
01018              stream->writeInt( old );
01019          }
01020       }
01021       if ( action == rpl_refuel3 ) {
01022          int id =  va_arg ( paramlist, int );
01023          int resource = va_arg ( paramlist, int );
01024          int delta = va_arg ( paramlist, int );
01025          stream->writeChar ( action );
01026          stream->writeInt ( 3 );
01027          stream->writeInt ( id );
01028          stream->writeInt ( resource );
01029          stream->writeInt ( delta );
01030       }
01031       if ( action == rpl_bldrefuel ) {
01032          int x =  va_arg ( paramlist, int );
01033          int y =  va_arg ( paramlist, int );
01034          int pos = va_arg ( paramlist, int );
01035          int amnt = va_arg ( paramlist, int );
01036          stream->writeChar ( action );
01037          int size = 4;
01038          stream->writeInt ( size );
01039          stream->writeInt ( x );
01040          stream->writeInt ( y );
01041          stream->writeInt ( pos );
01042          stream->writeInt ( amnt );
01043       }
01044       if ( action == rpl_moveUnitUpDown ) {
01045          int x =  va_arg ( paramlist, int );
01046          int y =  va_arg ( paramlist, int );
01047          int nwid_from = va_arg ( paramlist, int );
01048          int nwid_to = va_arg ( paramlist, int );
01049          int nwid_moving = va_arg ( paramlist, int );
01050          stream->writeChar ( action );
01051          int size = 5;
01052          stream->writeInt ( size );
01053          stream->writeInt ( x );
01054          stream->writeInt ( y );
01055          stream->writeInt ( nwid_from );
01056          stream->writeInt ( nwid_to );
01057          stream->writeInt ( nwid_moving );
01058       }
01059       if ( action == rpl_moveUnitUp ) {
01060          int x =  va_arg ( paramlist, int );
01061          int y =  va_arg ( paramlist, int );
01062          int nwid = va_arg ( paramlist, int );
01063          stream->writeChar ( action );
01064          int size = 3;
01065          stream->writeInt ( size );
01066          stream->writeInt ( x );
01067          stream->writeInt ( y );
01068          stream->writeInt ( nwid );
01069       }
01070       if ( action == rpl_productionResourceUsage ) {
01071          int en = va_arg ( paramlist, int );
01072          int ma = va_arg ( paramlist, int );
01073          int fu = va_arg ( paramlist, int );
01074          int x = va_arg ( paramlist, int );
01075          int y = va_arg ( paramlist, int );
01076          stream->writeChar ( action );
01077          int size = 5;
01078          stream->writeInt ( size );
01079          stream->writeInt ( en );
01080          stream->writeInt ( ma );
01081          stream->writeInt ( fu );
01082          stream->writeInt ( x );
01083          stream->writeInt ( y );
01084       }
01085       if ( action == rpl_repairUnit ) {
01086          int nwid = va_arg ( paramlist, int );
01087          int destnwid = va_arg ( paramlist, int );
01088          int amount = va_arg ( paramlist, int );
01089          int matremain = va_arg ( paramlist, int );
01090          int fuelremain = va_arg ( paramlist, int );
01091 
01092          stream->writeChar ( action );
01093          int size = 5;
01094          stream->writeInt ( size );
01095          stream->writeInt ( nwid );
01096          stream->writeInt ( destnwid );
01097          stream->writeInt ( amount );
01098          stream->writeInt ( matremain );
01099          stream->writeInt ( fuelremain );
01100       }
01101       if ( action == rpl_repairUnit2 || action == rpl_repairBuilding ) {
01102          int x = va_arg ( paramlist, int );
01103          int y = va_arg ( paramlist, int );
01104          int destnwid = va_arg ( paramlist, int );
01105          int amount = va_arg ( paramlist, int );
01106 
01107          stream->writeChar ( action );
01108          int size = 4;
01109          stream->writeInt ( size );
01110          stream->writeInt ( x );
01111          stream->writeInt ( y );
01112          stream->writeInt ( destnwid );
01113          stream->writeInt ( amount );
01114       }
01115       if ( action == rpl_repairUnit3  ) {
01116          int serviceNWID = va_arg ( paramlist, int );
01117          int destnwid = va_arg ( paramlist, int );
01118          int amount = va_arg ( paramlist, int );
01119 
01120          stream->writeChar ( action );
01121          int size = 3;
01122          stream->writeInt ( size );
01123          stream->writeInt ( serviceNWID );
01124          stream->writeInt ( destnwid );
01125          stream->writeInt ( amount );
01126       }
01127       if ( action == rpl_produceAmmo ) {
01128          int x = va_arg ( paramlist, int );
01129          int y = va_arg ( paramlist, int );
01130          int type = va_arg ( paramlist, int );
01131          int amount = va_arg ( paramlist, int );
01132          stream->writeChar ( action );
01133          int size = 4;
01134          stream->writeInt ( size );
01135          stream->writeInt ( x );
01136          stream->writeInt ( y );
01137          stream->writeInt ( type );
01138          stream->writeInt ( amount );
01139       }
01140       if ( action == rpl_buildProdLine || action == rpl_removeProdLine) {
01141          int building = va_arg ( paramlist, int );
01142          int id = va_arg ( paramlist, int );
01143          stream->writeChar ( action );
01144          int size = 2;
01145          stream->writeInt ( size );
01146          stream->writeInt ( building );
01147          stream->writeInt ( id );
01148       }
01149 
01150       if ( action == rpl_recycleUnit ) {
01151          int building = va_arg ( paramlist, int );
01152          int id = va_arg ( paramlist, int );
01153          stream->writeChar ( action );
01154          int size = 2;
01155          stream->writeInt ( size );
01156          stream->writeInt ( building );
01157          stream->writeInt ( id );
01158       }
01159 
01160       if ( action == rpl_techResearched ) {
01161          int tech = va_arg ( paramlist, int );
01162          int player = va_arg ( paramlist, int );
01163          stream->writeChar ( action );
01164          int size = 2;
01165          stream->writeInt ( size );
01166          stream->writeInt ( tech );
01167          stream->writeInt ( player );
01168       }
01169       if ( action == rpl_setGeneratorStatus ) {
01170          int vehid = va_arg ( paramlist, int );
01171          int status = va_arg ( paramlist, int );
01172          stream->writeChar ( action );
01173          int size = 2;
01174          stream->writeInt ( size );
01175          stream->writeInt ( vehid );
01176          stream->writeInt ( status );
01177       }
01178       if ( action == rpl_cutFromGame ) {
01179          int vehid = va_arg( paramlist, int );
01180          Resources res = getUnitResourceCargo ( actmap->getUnit ( vehid ));
01181          stream->writeChar ( action );
01182          int size = 4;
01183          stream->writeInt ( size );
01184          stream->writeInt ( vehid );
01185          stream->writeInt ( res.energy );
01186          stream->writeInt ( res.material );
01187          stream->writeInt ( res.fuel );
01188       }
01189       if ( action == rpl_setResearch ) {
01190          int bldid = va_arg ( paramlist, int );
01191          int amount = va_arg ( paramlist, int );
01192          stream->writeChar ( action );
01193          int size = 2;
01194          stream->writeInt ( size );
01195          stream->writeInt ( bldid );
01196          stream->writeInt ( amount );
01197       }
01198       if ( action == rpl_setResourceProcessingAmount ) {
01199          int x = va_arg ( paramlist, int );
01200          int y = va_arg ( paramlist, int );
01201          int e = va_arg ( paramlist, int );
01202          int m = va_arg ( paramlist, int );
01203          int f = va_arg ( paramlist, int );
01204          stream->writeChar ( action );
01205          int size = 5;
01206          stream->writeInt ( size );
01207          stream->writeInt ( x );
01208          stream->writeInt ( y );
01209          stream->writeInt ( e );
01210          stream->writeInt ( m );
01211          stream->writeInt ( f );
01212       }
01213       if ( action == rpl_netcontrol ) {
01214          int x = va_arg ( paramlist, int );
01215          int y = va_arg ( paramlist, int );
01216          int cat = va_arg ( paramlist, int );
01217          int stat = va_arg ( paramlist, int );
01218          stream->writeChar ( action );
01219          int size = 4;
01220          stream->writeInt ( size );
01221          stream->writeInt ( x );
01222          stream->writeInt ( y );
01223          stream->writeInt ( cat );
01224          stream->writeInt ( stat );
01225       }
01226       if ( action == rpl_jump ) {
01227          int nwid = va_arg ( paramlist, int );
01228          int x = va_arg ( paramlist, int );
01229          int y = va_arg ( paramlist, int );
01230          stream->writeChar ( action );
01231          int size = 3;
01232          stream->writeInt ( size );
01233          stream->writeInt ( nwid );
01234          stream->writeInt ( x );
01235          stream->writeInt ( y );
01236       }
01237       if ( action == rpl_transferTribute ) {
01238          stream->writeChar( action );
01239          stream->writeInt( 1 );
01240          int player = va_arg( paramlist, int );
01241          stream->writeInt( player );
01242       }
01243 
01244       if ( action == rpl_reactionFireOn || action == rpl_reactionFireOff ) {
01245          stream->writeChar( action );
01246          stream->writeInt( 1 );
01247          int nwid = va_arg( paramlist, int );
01248          stream->writeInt( nwid );
01249       }
01250 
01251       if ( action == rpl_selfdestruct ) {
01252          stream->writeChar( action );
01253          stream->writeInt( 1 );
01254          int nwid = va_arg( paramlist, int );
01255          stream->writeInt( nwid );
01256       }
01257 
01258       if ( action == rpl_cancelResearch ) {
01259          stream->writeChar( action );
01260          stream->writeInt( 0 );
01261       }
01262 
01263 
01264       va_end ( paramlist );
01265    }
01266 }
01267 
01268 
01269 trunreplay :: trunreplay ( void )  
01270 {
01271    status = -1;
01272    movenum = 0;
01273 }
01274 
01275 void trunreplay::error( const MapCoordinate& pos, const ASCString& message )
01276 {
01277    error( message );
01278 }
01279 
01280 
01281 void trunreplay::error( const MapCoordinate& pos, const char* message, ... )
01282 {
01283    va_list paramlist;
01284    va_start ( paramlist, message );
01285    char tempbuf[1000];
01286    int lng = vsprintf( tempbuf, message, paramlist );
01287 
01288    assert(lng < 1000);
01289    error( tempbuf );
01290    // error( message + "\nPosition: " + pos.toString() );
01291 }
01292 
01293 void trunreplay::error( const char* message, ... )
01294 {
01295    if ( message != lastErrorMessage ) {
01296       va_list paramlist;
01297       va_start ( paramlist, message );
01298 
01299       char tempbuf[1000];
01300 
01301       int lng = vsprintf( tempbuf, message, paramlist );
01302       if ( lng >= 1000 )
01303          displaymessage ( "trunreplay::error: String to long !\nPlease report this error", 1 );
01304 
01305       va_end ( paramlist );
01306       
01307       displaymessage(tempbuf, 1 );
01308       lastErrorMessage = message;
01309    }
01310 }
01311 
01312 void trunreplay::error( const ASCString& message )
01313 {
01314    if ( CGameOptions::Instance()->replayMovieMode )
01315       return;
01316 
01317    if ( message != lastErrorMessage ) {
01318       displaymessage(message.c_str(), 1 );
01319       lastErrorMessage = message;
01320    }
01321 }
01322 
01323 
01324 
01325 
01326 void trunreplay :: wait ( int t )
01327 {
01328 //   if ( fieldvisiblenow ( getactfield(), actmap->playerView ))
01329     while ( ticker < t + CGameOptions::Instance()->replayspeed  && !keypress()) {
01330        /*
01331        tkey input;
01332        while (keypress ()) {
01333            input = r_key ( );
01334            if ( input == ct_'+' )
01335        }
01336        */
01337        releasetimeslice();
01338     }
01339 }
01340 
01341 void trunreplay :: wait ( MapCoordinate pos, int t )
01342 {
01343