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

loaders.cpp

Go to the documentation of this file.
00001 
00008 /*
00009     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00010     Copyright (C) 1994-2005  Martin Bickel  and  Marc Schellenberger
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; see the file COPYING. If not, write to the 
00024     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00025     Boston, MA  02111-1307  USA
00026 */
00027 
00028 #include <algorithm>
00029 #include <cstring>
00030 #include <stdlib.h>
00031 #include <stdio.h>
00032 
00033 #include "typen.h"
00034 #include "misc.h"
00035 #include "newfont.h"
00036 #include "buildingtype.h"
00037 #include "vehicletype.h"
00038 #include "spfst.h"
00039 #include "loaders.h"
00040 #include "dlg_box.h"
00041 #include "dlg_box.h"
00042 #include "dialog.h"
00043 #include "sgstream.h"
00044 #include "attack.h"
00045 #include "errors.h"
00046 #include "strtmesg.h"
00047 #include "textfileparser.h"
00048 #include "itemrepository.h"
00049 #include "prehistoricevents.h"
00050 #include "gamemap.h"
00051 #include "gameeventsystem.h"
00052 
00053 #ifdef sgmain
00054 # include "ai/ai.h"
00055 #endif
00056 
00057 
00058 
00059 const int actsavegameversion  = 0xff61;
00060 const int minsavegameversion  = 0xff31;
00061 const int actmapversion       = 0xfe51;
00062 const int minmapversion       = 0xfe24;
00063 const int actnetworkversion   = 0x0032;
00064 const int minnetworkversion   = 0x0004;
00065 const int actreplayversion    = 0x0003;
00066 const int minreplayversion    = 0x0001;
00067 
00068 
00069 const int fileterminator = 0xa01a;
00070 
00071 
00072  const char* savegameextension = "*.sav";
00073  const char* mapextension = "*.map";
00074  const char* tournamentextension = ".ascpbm";
00075 
00076 
00077 
00078 void         seteventtriggers( GameMap* actmap )
00079 {
00080    #ifdef sgmain
00081    for ( GameMap::Events::iterator i = actmap->events.begin(); i != actmap->events.end(); ++i )
00082        (*i)->arm();
00083 
00084    #endif
00085    
00086    for ( int i = 0; i < 8; i++ )
00087       actmap->player[i].queuedEvents = 1;
00088 } 
00089 
00090 
00091 
00092   #define csm_typid32 1      /*  b1  */
00093   #define csm_direction 2    /*  b1  */ 
00094   #define csm_vehicle 4      /*  b1  */
00095   #define csm_building 8     /*  b1  */
00096   #define csm_height 32      /*  b1  */
00097   #define csm_cnt2 64        /*  b1  */
00098   #define csm_b3 128         /*  b1  */
00099 
00100   #define csm_material 1     /*  b3  */
00101   #define csm_fuel 2         /*  b3  */
00102   #define csm_visible 4      /*  b3  */
00103 //  #define csm_mine 8         /*  b3  */
00104   #define csm_weather 16     /*  b3  */
00105 //  #define csm_fahrspur 32    /*  b3  */
00106   #define csm_object 64      /*  b3  */
00107   #define csm_b4 128         /* b3 */ 
00108 
00109   #define csm_resources  1     /* b4 */
00110   #define csm_connection 2     // b4
00111   #define csm_newobject  4     // b4
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 /**************************************************************/
00120 /*     sezierungen schreiben / lesen                         */
00121 /**************************************************************/
00122 
00123 
00124 void   tspfldloaders::readdissections ( void )
00125 {
00126    for (int i = 0; i < 8; i ++ ) {
00127       if ( spfld->player[ i ].__dissectionsToLoad ) {
00128          int k;
00129          do {
00130             Player::Dissection du;
00131             stream->readInt(); // dummy;
00132             stream->readInt(); // dummy;
00133 
00134             du.orgpoints = stream->readInt();
00135             du.points    = stream->readInt();
00136             du.num       = stream->readInt();
00137 
00138             k = stream->readInt();
00139 
00140             int j = stream->readInt();
00141             du.fzt = vehicleTypeRepository.getObject_byID ( j );
00142             if ( !du.fzt )
00143                throw InvalidID ( "vehicle", j );
00144 
00145             j = stream->readInt();
00146             du.tech = technologyRepository.getObject_byID  ( j );
00147             if ( !du.tech )
00148                throw InvalidID ( "technology", j );
00149 
00150             spfld->player[ i ].dissections.push_back ( du );
00151          } while ( k );
00152       }
00153    } /* endfor */
00154 }
00155 
00156 void   tspfldloaders::writedissections ( void )
00157 {
00158    for (int i = 0; i < 8; i ++ ) {
00159       Player::DissectionContainer::iterator di = spfld->player[i].dissections.begin();
00160       while ( di != spfld->player[i].dissections.end() ) {
00161          stream->writeInt ( 1 ); // dummy
00162          stream->writeInt ( 1 ); // dummy
00163          stream->writeInt ( di->orgpoints );
00164          stream->writeInt ( di->points );
00165          stream->writeInt ( di->num );
00166 
00167          di++;
00168          if ( di != spfld->player[i].dissections.end() )
00169             stream->writeInt ( 1 );
00170          else
00171             stream->writeInt ( 0 );
00172 
00173          stream->writeInt ( di->fzt->id );
00174          stream->writeInt ( di->tech->id );
00175       }
00176    }
00177 }
00178 
00179 
00180 
00181 /**************************************************************/
00182 /*        Messages  schreiben / lesen                         */
00183 /**************************************************************/
00184 
00185 const int messageVersion = 0xabcdf1;
00186 const int messageMinVersion = 0xabcdef;
00187 
00188 void      tspfldloaders:: writemessages ( void )
00189 {
00190    stream->writeInt ( messageVersion );
00191 
00192    int id = 0;
00193    for ( MessageContainer::iterator mi = spfld->messages.begin(); mi != spfld->messages.end();  ) {
00194       id++;
00195       (*mi)->id = id;
00196 
00197       stream->writeInt ( (*mi)->from );
00198       stream->writeInt ( (*mi)->to );
00199       stream->writeInt ( (*mi)->cc );
00200       stream->writeInt ( (unsigned int) (*mi)->time );
00201       stream->writeInt ( 1 );
00202       stream->writeInt ( (*mi)->id );
00203       stream->writeInt ( (*mi)->gametime.turn() );
00204       stream->writeInt ( (*mi)->gametime.move() );
00205       stream->writeInt( (*mi)->reminder );
00206 
00207 
00208       ASCString& t = (*mi)->text;
00209       
00210       mi++;
00211       stream->writeInt ( mi != spfld->messages.end() ? 1 : 0 );
00212 
00213       stream->writeString ( t );
00214    }
00215 
00216    for ( int i = 0; i < 8; i++ )
00217       writemessagelist ( spfld->player[ i ].oldmessage );
00218 
00219    for ( int i = 0; i < 8; i++ )
00220       writemessagelist ( spfld->player[ i ].unreadmessage );
00221 
00222    for ( int i = 0; i < 8; i++ )
00223       writemessagelist ( spfld->player[ i ].sentmessage );
00224 
00225    writemessagelist ( spfld->unsentmessage );
00226 
00227    stream->writeInt ( messageVersion );
00228 
00229    stream->writeString ( spfld->gameJournal );
00230    stream->writeString ( spfld->newJournal );
00231 }
00232 
00233 
00234 void      tspfldloaders:: writemessagelist( MessagePntrContainer& lst )
00235 {
00236    for ( MessagePntrContainer::iterator i = lst.begin(); i != lst.end(); i++ )
00237       stream->writeInt ( (*i)->id );
00238    stream->writeInt ( 0 );
00239 }
00240 
00241 
00242 /*
00243 class MessageIDequals : public unary_function<Message*,bool>{
00244       int id;
00245    public:
00246       MessageIDequals ( int _id ) { id == _id; };
00247       bool operator() ( const Message* m ) { return m->id == id; };
00248 };
00249 */
00250 
00251 void      tspfldloaders:: readmessagelist( MessagePntrContainer& lst )
00252 {
00253    int i = stream->readInt();
00254    
00255    while ( i ) {
00256       // MessageContainer::iterator mi = find ( spfld->messages.begin(), spfld->messages.end(), MessageIDequals ( i ));
00257       MessageContainer::iterator mi = spfld->messages.end();
00258       for ( MessageContainer::iterator mi2 = spfld->messages.begin(); mi2 != spfld->messages.end(); mi2++ )
00259          if ( (*mi2)->id == i )
00260             mi = mi2;
00261 
00262       if ( mi == spfld->messages.end())
00263          warning( "message list corrupted !\nplease report this bug!\nthe game will continue, but some messages will probably be missing\nand other instabilities may occur.");
00264       lst.push_back ( *mi );
00265       i = stream->readInt();
00266    }
00267 }
00268 
00269 
00270 void      tspfldloaders:: readmessages ( void )
00271 {
00272    int magic = stream->readInt(); 
00273    assertOrThrow( magic >= messageMinVersion  && magic <= messageVersion );
00274 
00275    while ( spfld->__loadmessages ) {
00276       Message* msg = new Message ( spfld );
00277 
00278       msg->from    = stream->readInt();
00279       msg->to      = stream->readInt();
00280       if ( magic >= 0xabcdf0 )
00281          msg->cc      = stream->readInt();
00282       else
00283          msg->cc = 0;
00284 
00285       msg->time    = stream->readInt();
00286       bool msgtext = stream->readInt();
00287       msg->id      = stream->readInt();
00288       int t = stream->readInt();
00289       int m = stream->readInt();
00290       msg->gametime.set ( t, m );
00291       
00292       if ( magic >= 0xabcdf1 )
00293          msg->reminder = stream->readInt();
00294       else
00295          msg->reminder = false;
00296 
00297       spfld->__loadmessages = stream->readInt();
00298 
00299       if ( msgtext )
00300          msg->text = stream->readString( true );
00301       
00302    }
00303 
00304    for ( int i = 0; i < 8; i++ )
00305       if ( spfld->player[ i ].__loadoldmessage )
00306          readmessagelist ( spfld->player[ i ].oldmessage );
00307 
00308    for ( int i = 0; i < 8; i++ )
00309       if ( spfld->player[ i ].__loadunreadmessage )
00310          readmessagelist ( spfld->player[ i ].unreadmessage );
00311 
00312    for ( int i = 0; i < 8; i++ )
00313       if ( spfld->player[ i ].__loadsentmessage )
00314          readmessagelist ( spfld->player[ i ].sentmessage );
00315 
00316    if ( spfld->__loadunsentmessage )
00317       readmessagelist ( spfld->unsentmessage );
00318 
00319    stream->readInt(); // magic
00320 
00321    if ( spfld->___loadJournal )
00322       spfld->gameJournal = stream->readString();
00323 
00324    if (  spfld->___loadNewJournal )
00325       spfld->newJournal = stream->readString();
00326 }
00327 
00328 
00329 
00330 
00331 
00332 
00333 void   tspfldloaders::readoldevents ( void )
00334 {
00335    if ( spfld->loadOldEvents ) {
00336       int  num = stream->readInt();
00337       while ( num ) {
00338          for ( int i = 0;i < num; i++ )
00339             stream->readInt();
00340          for ( int i = 0;i < num; i++ )
00341             stream->readInt();
00342 
00343          num  = stream->readInt();
00344       }
00345    }
00346 }
00347 
00348 void checkForUniqueUnitIDs( GameMap* gamemap )
00349 {
00350    map<int,int> units;
00351    for ( int p = 0; p < gamemap->getPlayerCount(); ++p )
00352       for ( Player::VehicleList::iterator i = gamemap->getPlayer(p).vehicleList.begin(); i != gamemap->getPlayer(p).vehicleList.end(); ++i )
00353          if ( units[(*i)->networkid]++ > 0 ) {
00354             warning("unit with duplicate network ids: " + ASCString::toString( (*i)->networkid ) + "\nThis will lead to replay errors during the next turn." );
00355             (*i)->networkid = gamemap->getNewNetworkID();;
00356          }
00357 }
00358 
00359 /**************************************************************/
00360 /*     map schreiben / lesen / initialisieren          */
00361 /**************************************************************/
00362 
00363 void    tspfldloaders::writemap ( void )
00364 {
00365       checkForUniqueUnitIDs( spfld );
00366        if ( !spfld )
00367           displaymessage ( "tspfldloaders::writemap  ; no map to write ! ",2);
00368 
00369        spfld->write ( *stream );
00370 }
00371 
00372 
00373 void     tmaploaders::initmap ( void )
00374 {
00375     spfld->game_parameter = NULL;
00376 }
00377 
00378 
00379 void     tgameloaders::initmap ( void )
00380 {
00381     spfld->game_parameter = NULL;
00382 }
00383 
00384 
00385 void     tspfldloaders::readmap ( void )
00386 {
00387     spfld = new GameMap;
00388 
00389     spfld->read ( *stream );
00390 }
00391 
00392 
00393 
00394 void tgameloaders :: writeAI ( )
00395 {
00396  #ifdef sgmain
00397    int a = 0;
00398    for ( int i = 0; i< 8; i++ )
00399       if ( spfld->player[i].ai )
00400          a += 1 << i;
00401 
00402    stream->writeInt ( a );
00403 
00404    for ( int i = 0; i < 8; i++ )
00405       if ( spfld->player[i].ai )
00406          spfld->player[i].ai->write( *stream );
00407   #else
00408    stream->writeInt(0);
00409   #endif
00410 }
00411 
00412 void tgameloaders :: readAI ( )
00413 {
00414 #ifdef sgmain
00415    int a = stream->readInt();
00416    for ( int i = 0; i< 8; i++ )
00417       if ( a & ( 1 << i ) ) {
00418          AI* ai = new AI ( spfld, i );
00419          ai->read ( *stream );
00420          spfld->player[i].ai = ai;
00421       } else {
00422          spfld->player[i].ai = NULL;
00423       }
00424  #else
00425    for ( int i = 0; i< 9; i++ )
00426       spfld->player[i].ai = NULL;
00427  #endif
00428 }
00429 
00430 
00431 /**************************************************************/
00432 /*     Network schreiben / lesen                             */
00433 /**************************************************************/
00434 
00435 extern void readLegacyNetworkData ( tnstream& stream );
00436 
00437 
00438 void        tspfldloaders::readLegacyNetwork ( void )
00439 {
00440    if ( spfld->___loadLegacyNetwork )
00441       readLegacyNetworkData( *stream );
00442 }
00443 
00444 
00445 
00446 
00447 /**************************************************************/
00448 /*     fielder schreiben / lesen                              */
00449 /**************************************************************/
00450 
00451 const int objectstreamversion = 3;
00452 
00453 void   tspfldloaders::writefields ( void )
00454 {
00455    int l = 0;
00456    int cnt1 = spfld->xsize * spfld->ysize;
00457    int cnt2;
00458 
00459    do {
00460       cnt2 = 0; 
00461       tfield* fld = &spfld->field[l];
00462       /*
00463 
00464       RLE encoding not supported any more, since tfield is becomming too complex
00465 
00466       if (l + 2 < cnt1) { 
00467          l2 = l + 1; 
00468          fld2 = &spfld->field[l2];
00469        asfasfdasfd
00470          while ((l2 + 2 < cnt1) && ( memcmp(fld2, fld, sizeof(*fld2)) == 0) ) {
00471             cnt2++;
00472             l2++;
00473             fld2 = &spfld->field[l2];
00474          } 
00475       }
00476       */
00477 
00478 
00479       char b1 = 0;
00480       char b3 = 0;
00481       char b4 = 0;
00482 
00483       if (fld->typ->terraintype->id > 255) 
00484          b1 |= csm_typid32; 
00485       if (fld->vehicle != NULL) 
00486          b1 |= csm_vehicle; 
00487       if ( (fld->bdt & getTerrainBitType( cbbuildingentry )).any() )
00488          b1 |= csm_building; 
00489 
00490 
00491       if (cnt2 > 0) 
00492          b1 |= csm_cnt2; 
00493 
00494       if (fld->material > 0) 
00495          b3 |= csm_material; 
00496       if (fld->fuel > 0) 
00497          b3 |= csm_fuel; 
00498 
00499       if (fld->typ != fld->typ->terraintype->weather[0])
00500          b3 |= csm_weather;
00501       if (fld->visible)
00502          b3 |= csm_visible;
00503       if ( !fld->objects.empty() || !fld->mines.empty() )
00504          b4 |= csm_newobject;
00505 
00506       if ( fld->resourceview )
00507          b4 |= csm_resources;
00508 
00509       if ( fld->connection )
00510          b4 |= csm_connection;
00511 
00512       if ( b4 )
00513          b3 |= csm_b4;
00514 
00515       if ( b3 ) 
00516          b1 |= csm_b3; 
00517 
00518       stream->writeChar( b1 );
00519 
00520       if (b1 & csm_b3 ) 
00521          stream->writeChar ( b3 );
00522 
00523       if (b3 & csm_b4 )
00524          stream->writeChar ( b4 );
00525 
00526       if (b1 & csm_cnt2 ) 
00527          stream->writeInt ( cnt2 );
00528 
00529       if (b3 & csm_weather ) {
00530          int k = 1;
00531          while ( fld->typ != fld->typ->terraintype->weather[k]    &&   k < cwettertypennum ) {
00532             k++;
00533          } /* endwhile */
00534          
00535          if ( k == cwettertypennum ) {
00536             k = 0;
00537             displaymessage ( "invalid terrain ( weather not found ) at position %d \n",1,l );
00538           }
00539          stream->writeInt ( k );
00540       }
00541 
00542       if (b1 & csm_typid32 )                  
00543          stream->writeInt ( fld->typ->terraintype->id );
00544       else
00545          stream->writeChar ( fld->typ->terraintype->id );
00546 
00547       if (b1 & csm_vehicle ) 
00548          fld->vehicle->write ( *stream );
00549 
00550 
00551       if (b1 & csm_building ) 
00552          fld->building->write ( *stream );
00553 
00554       if (b3 & csm_material ) 
00555          stream->writeChar ( fld->material );
00556 
00557       if (b3 & csm_fuel ) 
00558          stream->writeChar ( fld->fuel );
00559 
00560       if (b3 & csm_visible )
00561          stream->writeWord ( fld->visible );
00562 
00563       if ( b4 & csm_newobject ) {
00564          stream->writeInt ( objectstreamversion );
00565 
00566          stream->writeInt ( fld->mines.size() );
00567          for ( tfield::MineContainer::iterator m = fld->mines.begin(); m != fld->mines.end(); m++  ) {
00568             stream->writeInt ( m->type );
00569             stream->writeInt ( m->strength );
00570             stream->writeInt ( m->lifetimer );
00571             stream->writeInt ( m->player );
00572          }
00573 
00574          stream->writeInt ( fld->objects.size() );
00575 
00576          for ( tfield::ObjectContainer::iterator o = fld->objects.begin(); o != fld->objects.end(); o++  ) {
00577             stream->writeInt ( 1 ); // was: pointer to type
00578             stream->writeInt ( o->damage );
00579             stream->writeInt ( o->dir );
00580             stream->writeInt ( o->lifetimer );
00581             for ( int i = 0; i < 4; i++ )
00582                stream->writeInt ( 0 );  // dummy
00583             stream->writeInt ( o->typ->id );
00584             stream->writeInt( o->remainingGrowthTime );
00585          }
00586       }
00587 
00588       if (b4 & csm_resources ) {
00589          stream->writeChar ( fld->resourceview->visible );
00590          for ( int i = 0; i < 8; i++ )
00591             stream->writeChar ( fld->resourceview->fuelvisible[i] );
00592          for ( int i = 0; i < 8; i++ )
00593             stream->writeChar ( fld->resourceview->materialvisible[i] );
00594       }
00595 
00596       if ( b4 & csm_connection )
00597          stream->writeInt ( fld->connection );
00598 
00599       l += 1 + cnt2;
00600    }  while (l < cnt1);
00601 }
00602 
00603 
00604 
00605 
00606 
00607 void tspfldloaders::readfields ( void )
00608 {
00609    int cnt2 = 0;
00610    int cnt1 = spfld->xsize * spfld->ysize;
00611 
00612    assertOrThrow( cnt1 > 0 );
00613    assertOrThrow( spfld->xsize > 0 );
00614    assertOrThrow( spfld->ysize > 0 );
00615 
00616    spfld->allocateFields ( spfld->xsize , spfld->ysize );
00617    
00618    if (spfld->field == NULL)
00619       displaymessage ( "Could not allocate memory for map ",2);
00620 
00621    int l = 0;
00622    tfield* lfld = NULL;
00623 
00624    do {
00625       tfield* fld2;
00626 
00627       if (cnt2 == 0) { 
00628 
00629          fld2 = & spfld->field[l];
00630 
00631          fld2->bdt.setInt ( 0 , 0 );
00632 
00633          char b1, b3, b4;
00634          b1 = stream->readChar();
00635 
00636          if (b1 & csm_b3 ) 
00637             b3 = stream->readChar();
00638          else 
00639             b3 = 0; 
00640 
00641          if (b3 & csm_b4 )
00642             b4 = stream->readChar();
00643          else
00644             b4 = 0;
00645 
00646          if (b1 & csm_cnt2 ) 
00647             cnt2 = stream->readInt();
00648          else
00649             cnt2 = 0; 
00650 
00651          int weather;
00652          if (b3 & csm_weather )
00653             weather = stream->readInt();
00654          else 
00655             weather = 0;
00656 
00657 
00658          int k;
00659 
00660          if (b1 & csm_typid32 ) 
00661             k = stream->readInt();
00662          else
00663             k = stream->readChar();
00664 
00665          pterraintype trn = terrainTypeRepository.getObject_byID ( k );
00666          if ( !trn ) 
00667             throw InvalidID ( "terrain", k );
00668 
00669          fld2->typ = trn->weather[weather];
00670          if ( !fld2->typ ) {
00671             fld2->typ = trn->weather[0];
00672             if ( !fld2->typ ) 
00673                throw InvalidID ( "terrain", k );
00674          }
00675 
00676          if (b1 & csm_direction )
00677             stream->readChar();  // fld2->direction = 0; 
00678             
00679 
00680          if (b1 & csm_vehicle ) {
00681              fld2->vehicle = Vehicle::newFromStream ( spfld, *stream );
00682              fld2->vehicle->setnewposition ( l%spfld->xsize, l/spfld->xsize );
00683          }
00684 
00685          if (b1 & csm_building ) {
00686             fld2->building = Building::newFromStream ( spfld, *stream );
00687             fld2->bdt |= getTerrainBitType(cbbuildingentry);
00688          }
00689 
00690          if (b3 & csm_material) 
00691             fld2->material = stream->readChar();
00692          else 
00693             fld2->material = 0; 
00694 
00695          if (b3 & csm_fuel) 
00696             fld2->fuel = stream->readChar();
00697          else 
00698             fld2->fuel = 0;
00699 
00700          if (b3 & csm_visible)
00701             fld2->visible = stream->readWord();
00702          else
00703             fld2->visible = 0;
00704 
00705          bool tempobjects[16];
00706          int  tempobjectNum = 0;
00707 
00708          if (b3 & csm_object ) {
00709 
00710             char minetype = stream->readChar();
00711             char minestrength = stream->readChar();
00712             if ( minetype >> 4 ) {
00713                Mine m( MineTypes((minetype >> 1) & 7), minestrength, minetype >> 4, spfld );
00714                fld2->mines.push_back ( m );
00715             }
00716 
00717             tempobjectNum = stream->readInt();
00718 
00719             for ( int i = 0; i < 16; i++ )
00720                tempobjects[i] = stream->readInt();
00721          }
00722 
00723          int objectversion = 1;
00724          if ( b4 & csm_newobject ) {
00725             objectversion = stream->readInt();
00726 
00727             if ( objectversion < 1 || objectversion > objectstreamversion )
00728                throw tinvalidversion ( "object", objectstreamversion, objectversion );
00729 
00730             int minenum = stream->readInt();
00731 
00732             for ( int i = 0; i < minenum; i++ ) {
00733                MineTypes type = MineTypes(stream->readInt());
00734                int strength = stream->readInt();
00735                int minetime = stream->readInt();
00736                int player = stream->readInt();
00737                if ( player < 0 || player > 7 )
00738                   player = 0;
00739 
00740                assertOrThrow( strength >= 0 );
00741                assertOrThrow( type > 0 && type <= 4 );
00742 
00743                Mine m ( type, strength, player, spfld );
00744                if ( objectversion == 1 ) {
00745                   int endtime = minetime;
00746                   int lifetime = spfld->getgameparameter( GameParameter(cgp_antipersonnelmine_lifetime + m.type - 1));
00747                   if ( lifetime > 0  &&  endtime > 0 )
00748                      m.lifetimer = endtime - spfld->time.turn() + spfld->getgameparameter( GameParameter(cgp_antipersonnelmine_lifetime + m.type - 1));
00749                   else
00750                      if ( lifetime > 0 )
00751                         m.lifetimer = lifetime;
00752                      else
00753                         m.lifetimer = -1;
00754                } else
00755                   m.lifetimer = minetime;
00756                fld2->mines.push_back ( m );
00757             }
00758 
00759             tempobjectNum = stream->readInt();
00760          }
00761 
00762          if ( (b3 & csm_object) || (b4 & csm_newobject )) {
00763             for ( int n = 0; n < tempobjectNum; n++ ) {
00764                Object o;
00765                stream->readInt(); // was: type
00766                o.damage = stream->readInt();
00767                assertOrThrow( o.damage >= 0 );
00768                o.dir = stream->readInt();
00769                if ( objectversion >= 2 )
00770                   o.lifetimer = stream->readInt();
00771                else
00772                   stream->readInt();
00773 
00774                for ( int i = 0; i < 4; i++ )
00775                   stream->readInt(); // dummy
00776 
00777                int id = stream->readInt();
00778                o.typ = objectTypeRepository.getObject_byID ( id );
00779 
00780                if ( !o.typ )
00781                   throw InvalidID ( "object", id );
00782 
00783                if ( objectversion >= 3 )
00784                   o.remainingGrowthTime = stream->readInt();
00785 
00786                if ( objectversion == 1 )
00787                   o.lifetimer = o.typ->lifetime;
00788 
00789 
00790                fld2->objects.push_back ( o );
00791             }
00792             fld2->sortobjects();
00793          }
00794 
00795          if (b4 & csm_resources ) {
00796             fld2->resourceview = new tfield::Resourceview;
00797             fld2->resourceview->visible = stream->readChar();
00798             for ( int i = 0; i < 8; i++ )
00799                fld2->resourceview->fuelvisible[i] = stream->readChar();
00800             for ( int i = 0; i < 8; i++ )
00801                fld2->resourceview->materialvisible[i] = stream->readChar();
00802          }
00803 
00804          if ( b4 & csm_connection ) 
00805             fld2->connection = stream->readInt();
00806          
00807          if (b1 & csm_cnt2 )
00808             lfld = fld2;
00809 
00810       } 
00811       else {
00812          spfld->field[l].typ = lfld->typ;
00813          spfld->field[l].fuel = lfld->material;
00814          spfld->field[l].visible = lfld->visible;
00815          spfld->field[l].tempw = 0;
00816          spfld->field[l].connection = lfld->connection;
00817          for ( int i = 0; i < 8; i++ )
00818             spfld->field[l].view[i] = lfld->view[i];
00819          cnt2--;
00820       } 
00821       l++ ;
00822    }  while (l < cnt1);
00823 
00824    spfld->overviewMapHolder.connect();
00825 
00826 }
00827 
00828 
00829 
00830 /**************************************************************/
00831 /*     Chain Items                                           */
00832 /**************************************************************/
00833 
00834 void   tspfldloaders::chainitems ( GameMap* actmap )
00835 {
00836    int i = 0;
00837    for (int y = 0; y < actmap->ysize; y++)
00838       for (int x = 0; x < actmap->xsize; x++) {
00839           tfield* fld = &actmap->field[i];
00840           fld->setparams();
00841           i++;
00842       }
00843 }
00844 
00845 
00846 
00847 /**************************************************************/
00848 /*     Set Player Existencies                                */
00849 /**************************************************************/
00850 
00851 SigC::Signal1<void,GameMap*> tspfldloaders::mapLoaded;
00852 
00853 
00854 tspfldloaders::tspfldloaders ( void )
00855 {
00856    spfld = NULL;
00857 }
00858 
00859 
00860 tspfldloaders::~tspfldloaders ( void )
00861 {
00862   delete spfld;
00863   spfld = NULL;
00864 }
00865 
00866 
00867 
00868 
00869 
00870 
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878 
00879 
00880 
00881 
00882 
00883 int          tmaploaders::savemap( const ASCString& name, GameMap* gamemap )
00884 { 
00885    #ifdef logging
00886    logtofile ( "loaders / tmaploaders::savemap / started " );
00887    #endif
00888 
00889    tnfilestream filestream ( name, tnstream::writing );
00890 
00891    stream = &filestream;
00892 
00893    spfld = gamemap;
00894 
00895 
00896    /********************************************************************************/
00897    /*   Stream initialisieren, Dateiinfo schreiben , map schreiben          */
00898    /********************************************************************************/
00899    {
00900        stream->writepchar ( getFullVersionString() );  // description is not used any more
00901        stream->writeWord ( fileterminator );
00902        stream->writeInt ( actmapversion  );
00903 
00904        writemap ( );
00905    }
00906 
00907    writefields ();
00908 #ifdef WEATHERGENERATOR
00909    spfld->weatherSystem->write(filestream);
00910 #endif
00911    stream->writeInt ( actmapversion );
00912 
00913    spfld = NULL;
00914 
00915    return 0;
00916 } 
00917 
00918 
00919 
00920 void weatherSystemRequired()
00921 {
00922    throw ASCmsgException( "This file can not be loaded, since it contains data of the discontinued weather generator");
00923 }
00924 
00925 
00926 GameMap* tmaploaders::_loadmap( const ASCString& name )
00927 { 
00928     displayLogMessage ( 4, "loading map %s ... ", name.c_str() );
00929 
00930     tnfilestream filestream ( name, tnstream::reading);
00931 
00932     stream = &filestream;
00933 
00934     char* description = NULL;
00935  
00936     stream->readpchar ( &description );
00937     delete[] description;
00938  
00939     int w = stream->readWord();
00940  
00941     if ( w != fileterminator ) 
00942        throw tinvalidversion ( name, fileterminator, w );
00943 
00944 
00945     int version = stream->readInt();
00946  
00947     if ( version > actmapversion || version < minmapversion )
00948        throw tinvalidversion ( name, actmapversion, version );
00949    
00950 
00951    displayLogMessage ( 8, "map, ");
00952    readmap ();
00953 
00954    if ( version <= 0xfe27 ) {
00955       displayLogMessage ( 8, "eventsToCome, ");
00956       readOldEventLists ( stream, false, spfld );
00957    }
00958 
00959    displayLogMessage ( 8, "fields, ");
00960    readfields ();
00961 
00962    
00963    if(version == 0xfe50)
00964       weatherSystemRequired();
00965 
00966    version = stream->readInt();
00967    if (version > actmapversion || version < minmapversion ) 
00968       throw tinvalidversion ( name, actmapversion, version );
00969    
00970 
00971    displayLogMessage ( 8, "chainItems, ");
00972    chainitems ( spfld );
00973 
00974    for ( int sp = spfld->getPlayerCount()-1; sp >= 0; sp--)
00975       if ( spfld->player[sp].exist() )
00976          spfld->actplayer = sp;
00977 
00978    displayLogMessage ( 8, "setEventTriggers, ");
00979    seteventtriggers( spfld );
00980 
00981    displayLogMessage ( 8, "calculateallobjects ");
00982    calculateallobjects( spfld );
00983 
00984 
00985    displayLogMessage ( 8, "init for playing, ");
00986    
00987    spfld->time.set ( 1, 0 );
00988    spfld->levelfinished = false;
00989    spfld->preferredFileNames.mapname[0] = name ;
00990    checkForUniqueUnitIDs( spfld );
00991    spfld->startGame();
00992 
00993    displayLogMessage ( 4, "done\n");
00994 
00995    GameMap* m  = spfld;
00996    spfld = NULL;
00997    
00998    mapLoaded( m );
00999    
01000    return m;
01001 } 
01002 
01003 
01004 GameMap* tmaploaders::loadmap ( const ASCString& name )
01005 {
01006      tmaploaders gl;
01007      return gl._loadmap ( name );
01008 }     
01009    
01010 
01011 
01012 
01013 
01014 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
01015   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
01016   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  */ 
01017 
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 void   tsavegameloaders::savegame( pnstream strm, GameMap* gamemap, bool writeReplays )
01026 {
01027    stream = strm;
01028    spfld = gamemap;
01029 
01030    stream->writepchar( getFullVersionString() );
01031    stream->writeWord( fileterminator );
01032 
01033    stream->writeInt( actsavegameversion );
01034    writemap ();
01035 
01036    writemessages();
01037 
01038    writefields ( );
01039    
01040    writedissections();
01041 
01042    if ( writeReplays && spfld->replayinfo ) {
01043       stream->writeInt( 1 );
01044       spfld->replayinfo->write(*stream);
01045    } else
01046       stream->writeInt( 0 );
01047 
01048    writeAI();
01049 
01050    stream->writeInt( actsavegameversion );
01051 
01052    spfld = NULL;
01053 }
01054 
01055 
01056 void         tsavegameloaders::savegame( const ASCString& name)
01057 { 
01058    tnfilestream filestream ( name, tnstream::writing );
01059    savegame ( &filestream, actmap, true );
01060 }
01061 
01062 
01063 
01064 GameMap* tsavegameloaders::loadGameFromFile( const ASCString& filename )
01065 {
01066    tnfilestream filestream ( filename, tnstream::reading );
01067    tsavegameloaders gl;
01068    return gl.loadgame( &filestream );
01069 }
01070 
01071 GameMap*          tsavegameloaders::loadgame( pnstream strm )
01072 {
01073    stream = strm;
01074 
01075    stream->readString(); // was: description
01076 
01077    int w = stream->readWord();
01078 
01079    if ( w != fileterminator ) 
01080       throw tinvalidversion ( strm->getDeviceName(), fileterminator, w );
01081    
01082    int version = stream->readInt();
01083 
01084    if (version > actsavegameversion || version < minsavegameversion ) 
01085       throw tinvalidversion ( strm->getDeviceName(), actsavegameversion, version );
01086    
01087 
01088    readmap ();
01089 
01090    readLegacyNetwork ();
01091 
01092    if  ( version <= 0xff39 )
01093       for ( int i = 0; i < 8; i++ )
01094          spfld->player[i].research.read_techs ( *stream );
01095 
01096    readmessages();
01097 
01098    if ( version <= 0xff37 ) {
01099       readOldEventLists ( stream, true, spfld );
01100       readoldevents ();
01101    }
01102 
01103    readfields ( );
01104    
01105    if(version == 0xff60)
01106       weatherSystemRequired();
01107    
01108    readdissections();
01109 
01110    bool loadReplay = true;
01111    if ( version >= 0xff35 ) 
01112       if ( !stream->readInt() )
01113          loadReplay = false;
01114 
01115    if ( loadReplay ) {
01116       spfld->replayinfo = new GameMap::ReplayInfo;
01117       spfld->replayinfo->read ( *stream );
01118    } else
01119       spfld->replayinfo = NULL;
01120 
01121 
01122    if ( version >= 0xff34 )
01123       readAI ();
01124 
01125    version = stream->readInt();
01126    if (version > actsavegameversion || version < minsavegameversion )
01127       throw tinvalidversion ( strm->getDeviceName(), actsavegameversion, version );
01128 
01129    chainitems ( spfld );
01130 
01131    seteventtriggers( spfld );
01132 
01133    calculateallobjects( spfld );
01134    checkForUniqueUnitIDs( spfld );
01135 
01136    mapLoaded( spfld );
01137 
01138    GameMap* s = spfld;
01139    spfld = NULL;  // to avoid that is is deleted by the destructor of tsavegameloaders
01140    return s;
01141 }
01142 
01143 
01144 
01145    /*****************************************************************************************************/
01146    /*   Netzwerk                                                                                       */
01147    /*****************************************************************************************************/
01148 
01149 
01150 
01151 
01152 int          tnetworkloaders::savenwgame( pnstream strm, const GameMap* gamemap )
01153 { 
01154    spfld = const_cast<GameMap*>(gamemap); // yes, this is bad, but spfld can't be made constant because it is also used for loading
01155    
01156    stream = strm;
01157 
01158    stream->writepchar ( getFullVersionString() );  // description is not used any more
01159    stream->writeWord ( fileterminator );
01160  
01161    stream->writeInt ( actnetworkversion );
01162 
01163    writemap ();
01164 
01165    writemessages();
01166 
01167    stream->writeInt ( actnetworkversion );
01168 
01169    writefields ( );
01170 
01171    writedissections();
01172 
01173    if ( spfld->replayinfo )
01174       spfld->replayinfo->write ( *stream );
01175 
01176    // the AI must be the last data of the file
01177    writeAI();
01178 
01179    stream->writeInt ( actnetworkversion );
01180 
01181    spfld = NULL;
01182 
01183    return 0;
01184 } 
01185 
01186 
01187 
01188 
01189 
01190 GameMap*  tnetworkloaders::loadnwgame( pnstream strm )
01191 { 
01192    const char* name = "network game";
01193 
01194    stream = strm;
01195 
01196 
01197    char* description = NULL;
01198    stream->readpchar ( &description );
01199    delete[] description;
01200 
01201    int w = stream->readWord();
01202 
01203    if ( w != fileterminator )
01204       throw tinvalidversion ( name, fileterminator, (int) w );
01205 
01206 
01207    int version = stream->readInt();
01208 
01209    if (version > actnetworkversion || version < minnetworkversion )
01210       throw tinvalidversion ( name, actnetworkversion, version );
01211 
01212    readmap ();
01213 
01214    if ( version <= 0x11 )
01215       for ( int i = 0; i < 8; i++ )
01216          spfld->player[i].research.read_techs ( *stream );
01217 
01218    
01219    //NEW SaveData Weather  
01220    if(version == 0x0030)
01221       weatherSystemRequired();
01222    
01223    /*if(version > 0xfe28){  //Vielleicht minus 1     
01224      actmap->weatherSystem->read(*stream);
01225    }*/
01226    readmessages();
01227    readLegacyNetwork ();
01228 
01229    version = stream->readInt();
01230 
01231    if (version > actnetworkversion || version < minnetworkversion )
01232       throw tinvalidversion ( name, actnetworkversion, version );
01233 
01234 
01235 
01236    if ( version < 10 ) {
01237       readOldEventLists ( stream, true, spfld );
01238       readoldevents    ();
01239    }
01240 
01241    readfields ( );
01242 
01243    readdissections();
01244 
01245    if ( spfld->__loadreplayinfo ) {
01246       spfld->replayinfo = new GameMap::ReplayInfo;
01247       spfld->replayinfo->read ( *stream );
01248    }
01249 
01250    if ( version > 8 )
01251       readAI();
01252 
01253    #ifdef sgmain
01254    version = stream->readInt();   
01255    if (version > actnetworkversion || version < minnetworkversion )
01256       throw tinvalidversion ( name, actnetworkversion, version );
01257    #endif
01258 
01259    chainitems ( spfld );
01260 
01261    seteventtriggers( spfld );
01262 
01263    calculateallobjects( spfld );
01264 
01265    checkForUniqueUnitIDs( spfld );
01266 
01267    spfld->levelfinished = false;
01268    
01269    // there was a bug that made the ammo amount underflow
01270    for ( int i = 0; i < 8; ++i)
01271       for ( Player::BuildingList::iterator b = spfld->player[i].buildingList.begin(); b != spfld->player[i].buildingList.end(); ++b )
01272          for ( int a = 0; a < waffenanzahl; ++a )
01273             if ( (*b)->ammo[a] > 32000 ) {
01274                ASCString s;
01275                s.format( "Player %s had %d ammo of type %s in the building at %d/%d", spfld->player[i].getName().c_str(), (*b)->ammo[a], cwaffentypen[a], (*b)->getEntry().x, (*b)->getEntry().y );
01276                new Message( s, spfld, 1 );
01277                (*b)->ammo[a] = 0;
01278             }
01279 
01280    
01281    GameMap* spfldcopy = spfld;
01282    spfld = NULL;
01283 
01284    mapLoaded( spfldcopy );
01285    
01286    
01287    return spfldcopy;
01288 
01289 }
01290 
01291 
01292 
01293 
01294 
01295 
01296 
01297 
01298 
01299 
01300 
01301 
01302 
01303 
01304 void  savemap( const char * name, GameMap* gamemap )
01305 {
01306 
01307    #ifdef logging
01308    logtofile ( "loaders / savemap / started " );
01309    #endif
01310 
01311    try {
01312      tmaploaders gl;
01313      gl.savemap ( name, gamemap );
01314    } /* endtry */
01315 
01316    catch ( tfileerror err ) {
01317       displaymessage( "file error writing map to filename %s ", 1, err.getFileName().c_str() );
01318    } /* endcatch */
01319    catch ( ASCexception err) {
01320       displaymessage( "error writing map ", 1 );
01321    } /* endcatch */
01322 
01323 }
01324 
01325 
01326 void  savegame( const ASCString& name )
01327 {
01328    try {
01329       tsavegameloaders gl;
01330       gl.savegame ( name );
01331    }
01332    catch ( tfileerror err) {
01333       displaymessage( "error writing map to filename %s ", 1, err.getFileName().c_str() );
01334    } /* endcatch */
01335    catch ( ASCexception err) {
01336       displaymessage( "error writing map ", 1 );
01337    } /* endcatch */
01338 }
01339 
01340 
01341 void  savereplay( GameMap* gamemap, int num )
01342 {
01343    try {
01344       if ( !gamemap->replayinfo )
01345          fatalError ( "treplayloaders :: savereplay   ;   No replay activated !");
01346 
01347       if ( gamemap->replayinfo->map[num] ) {
01348          delete gamemap->replayinfo->map[num];
01349          gamemap->replayinfo->map[num] = NULL;
01350       }
01351 
01352       gamemap->replayinfo->map[num] = new tmemorystreambuf;
01353       tmemorystream memstream ( gamemap->replayinfo->map[num], tnstream::writing );
01354 
01355       memstream.writeInt( actreplayversion );
01356 
01357       tsavegameloaders sgl;
01358       sgl.savegame ( &memstream, gamemap, false );
01359 
01360       memstream.writeInt ( actreplayversion );
01361    }
01362    catch ( ASCexception err ) {
01363       displaymessage( "error saving replay information", 1 );
01364    } /* endcatch */
01365 }
01366 
01367 GameMap*  loadreplay( tmemorystreambuf* streambuf )
01368 {
01369    GameMap* replaymap = NULL;
01370 
01371    try {
01372       const char* name = "memorystream actmap->replayinfo";
01373       tmemorystream memstream ( streambuf, tnstream::reading );
01374 
01375       int version = memstream.readInt();
01376       if (version > actreplayversion || version < minreplayversion )
01377          throw tinvalidversion ( name, actreplayversion, version );
01378 
01379       tsavegameloaders sgl;
01380       replaymap = sgl.loadgame ( &memstream );
01381 
01382       version = memstream.readInt();
01383       if (version > actreplayversion || version < minreplayversion ) {
01384          delete replaymap;
01385          throw tinvalidversion ( name, actreplayversion, version );
01386       }
01387 
01388    }
01389    catch ( InvalidID err ) {
01390       displaymessage( err.getMessage().c_str(), 1 );
01391       replaymap = NULL;
01392    } /* endcatch */
01393    catch ( tinvalidversion err ) {
01394       displaymessage( err.getMessage().c_str(), 1 );
01395       replaymap = NULL;
01396    } /* endcatch */
01397    catch ( tfileerror err) {
01398       displaymessage( "error reading map filename %s ", 1, err.getFileName().c_str() );
01399       replaymap = NULL;
01400    } /* endcatch */
01401    catch ( ASCexception ) {
01402       displaymessage( "error loading replay", 1 );
01403       replaymap = NULL;
01404    } /* endcatch */
01405 
01406    return replaymap;
01407 }
01408 
01409 
01410 
01411 
01412 GameMap* mapLoadingExceptionChecker( const ASCString& filename, MapLoadingFunction loader )
01413 {
01414    GameMap* m = NULL;
01415    try {
01416       m = loader( filename );
01417    }
01418    catch ( InvalidID err ) {
01419       displaymessage( err.getMessage().c_str(), 1 );
01420       return NULL;
01421    } /* endcatch */
01422    catch ( tinvalidversion err ) {
01423       displaymessage( err.getMessage().c_str(), 1 );
01424       return NULL;
01425    } /* endcatch */
01426    catch ( tfileerror err) {
01427       displaymessage( "error reading map filename %s ", 1, err.getFileName().c_str() );
01428       return NULL;
01429    } /* endcatch */
01430    catch ( ASCmsgException msg ) {
01431       displaymessage( "error loading file\n" + msg.getMessage() , 1 );
01432       return NULL;
01433    } /* endcatch */
01434    catch ( ASCexception ) {
01435       displaymessage( "error loading file", 1 );
01436       return NULL;
01437    } /* endcatch */
01438    
01439    return m;
01440 }
01441 
01442 
01443 
01444 
01445 
01446 
01447 
01448 
01449 
01450 bool validatemapfile ( const ASCString& filename )
01451 {
01452 
01453    char* description = NULL;
01454 
01455    try {
01456 
01457       tnfilestream stream ( filename, tnstream::reading );
01458       stream.readpchar ( &description, 200 );
01459       if ( description ) {
01460          delete[]  description ;
01461          description = NULL;
01462       }
01463 
01464       int w = stream.readWord();
01465       if ( w != fileterminator )
01466          throw tinvalidversion ( filename, fileterminator, (int) w );
01467 
01468       int version = stream.re