00001
00002
00003
00004
00005
00006
00007
00008
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "typen.h"
00023 #include "vehicletype.h"
00024 #include "buildingtype.h"
00025 #include "spfst.h"
00026 #include "resourcenet.h"
00027 #include "mapalgorithms.h"
00028 #include "dlg_box.h"
00029 #include "dialog.h"
00030 #include "cannedmessages.h"
00031
00032 SigC::Signal0<void> tributeTransferred;
00033
00034 void MapNetwork :: searchfield ( int x, int y, int dir )
00035 {
00036 int s;
00037
00038 tfield* fld = actmap->getField ( x, y );
00039 if ( !fld )
00040 return;
00041
00042 int arr[sidenum];
00043
00044 do {
00045
00046 if ( fld->a.temp )
00047 return;
00048
00049 #ifdef netdebug
00050 cursor.gotoxy ( a, b );
00051 displaymap();
00052 #endif
00053
00054 if ( fld->building ) {
00055 searchbuilding ( x, y );
00056 return;
00057 }
00058
00059 fld->a.temp = 1;
00060
00061 int d = fieldavail( x, y );
00062 if ( d <= 0 )
00063 return;
00064
00065 searchvehicle ( x, y );
00066
00067 int olddir = dir + sidenum/2;
00068 while (olddir >= sidenum )
00069 olddir -= sidenum;
00070
00071 int r = 0;
00072 for (s = 0; s < sidenum; s++) {
00073 if ( (d & (1 << s)) && ( s != olddir )) {
00074 arr[ r ] = s;
00075 r++;
00076 }
00077 }
00078
00079
00080 if (r > 1) {
00081 for ( s = 0; s < r; s++) {
00082 int nx = x;
00083 int ny = y;
00084 getnextfield ( nx, ny, arr[s] );
00085 searchfield( nx, ny, arr[s] );
00086 if ( searchfinished() )
00087 return ;
00088 }
00089 return;
00090 } else
00091 if ( r == 1 ) {
00092 dir = arr[0];
00093 getnextfield ( x, y, dir );
00094 fld = actmap->getField( x, y );
00095 if ( !fld )
00096 return;
00097 } else
00098 return;
00099 } while ( 1 );
00100
00101 }
00102
00103 void MapNetwork :: searchvehicle ( int x, int y )
00104 {
00105 if ( pass == 2 ) {
00106 tfield* newfield = actmap->getField ( x, y );
00107 if ( newfield )
00108 if ( !newfield->a.temp2 )
00109 if ( newfield->vehicle ) {
00110 checkvehicle ( newfield->vehicle );
00111 newfield->a.temp2 = 1;
00112 }
00113 }
00114 }
00115
00116
00117 void MapNetwork :: searchbuilding ( int x, int y )
00118 {
00119 Building* bld = actmap->getField( x, y )->building;
00120 if ( !bld )
00121 return;
00122
00123 tfield* entry = bld->getEntryField();
00124 if ( entry->a.temp )
00125 return;
00126
00127 if ( pass == 1 )
00128 checkbuilding( bld );
00129
00130 entry->a.temp = 1;
00131
00132 if ( !searchfinished() )
00133 for( int i = 0; i < 4; i++ )
00134 for ( int j = 0; j < 6; j++ ) {
00135 MapCoordinate mc = bld->getFieldCoordinates ( BuildingType::LocalCoordinate(i, j) );
00136 tfield* fld2 = actmap->getField ( mc );
00137 if ( fld2 && fld2->building == bld )
00138 for ( int d = 0; d < sidenum; d++ ) {
00139 int xp2 = mc.x;
00140 int yp2 = mc.y;
00141 getnextfield ( xp2, yp2, d );
00142 tfield* newfield = actmap->getField ( xp2, yp2 );
00143 if ( newfield && newfield->building != bld && !newfield->a.temp )
00144 searchfield ( xp2, yp2, d );
00145
00146 searchvehicle ( xp2, yp2 );
00147
00148 }
00149 }
00150 }
00151
00152
00153 int MapNetwork :: instancesrunning = 0;
00154
00155 MapNetwork :: MapNetwork ( GameMap* gamemap, int checkInstances ) : actmap ( gamemap )
00156 {
00157 if ( checkInstances ) {
00158 if ( instancesrunning )
00159 displaymessage(" fatal error at MapNetwork; there are other running instances ", 2 );
00160 }
00161
00162
00163
00164 instancesrunning++;
00165 pass = 1;
00166 }
00167
00168
00169 MapNetwork :: ~MapNetwork ()
00170 {
00171 instancesrunning--;
00172 }
00173
00174
00175
00176 void MapNetwork :: searchAllVehiclesNextToBuildings ( int player )
00177 {
00178 pass++;
00179 for ( Player::VehicleList::iterator j = actmap->player[player].vehicleList.begin(); j != actmap->player[player].vehicleList.end(); j++ ) {
00180 MapCoordinate3D mc = (*j)->getPosition();
00181 for ( int s = 0; s < sidenum; s++ ) {
00182 tfield* fld = actmap->getField ( getNeighbouringFieldCoordinate ( mc, s ));
00183 if ( fld ) {
00184 Building* bld = fld->building;
00185 if ( bld && bld->color == (*j)->color ) {
00186 tfield* fld2 = actmap->getField( (*j)->getPosition());
00187 if ( !fld2->a.temp2 ) {
00188 fld2->a.temp2 = 1;
00189 checkvehicle ( *j );
00190 }
00191 }
00192 }
00193 }
00194 }
00195 }
00196
00197 void MapNetwork :: start ( int x, int y )
00198 {
00199 if ( globalsearch() == 2 ) {
00200 for ( int i = 0; i < 8; i++ )
00201 if ( actmap->player[i].exist() ) {
00202
00203 for ( Player::BuildingList::iterator j = actmap->player[i].buildingList.begin(); j != actmap->player[i].buildingList.end(); j++ )
00204 checkbuilding(*j);
00205
00206
00207 actmap->cleartemps(7);
00208 searchAllVehiclesNextToBuildings ( i );
00209 actmap->cleartemps(7);
00210
00211 }
00212 } else
00213 if ( globalsearch() == 1 ) {
00214 actmap->cleartemps(7);
00215 startposition.x = x;
00216 startposition.y = y;
00217 searchfield ( x, y, -1 );
00218 actmap->cleartemps(7);
00219 if ( !searchfinished() ) {
00220 pass++;
00221 startposition.x = x;
00222 startposition.y = y;
00223 searchfield ( x, y, -1 );
00224 actmap->cleartemps(7);
00225 }
00226 } else
00227 if ( globalsearch() == 0 ) {
00228 tfield* fld = actmap->getField ( x, y );
00229 if ( fld ) {
00230 if ( fld->building ) {
00231 if ( pass == 1 )
00232 checkbuilding( fld->building );
00233 } else
00234 if ( fld->vehicle )
00235
00236 if ( pass == 2 )
00237 checkvehicle ( fld->vehicle );
00238 }
00239 }
00240 }
00241
00242
00243
00244 int ResourceNet :: fieldavail ( int x, int y )
00245 {
00246 tfield* fld = actmap->getField ( x, y );
00247
00248
00249
00250
00251
00252 if ( fld ) {
00253 TerrainBits tb = getTerrainBitType(cbpipeline);
00254 assert( resourcetype >= 0 );
00255
00256 if ( resourcetype == 0)
00257 tb |= getTerrainBitType(cbpowerline);
00258
00259 if ( (fld->bdt & tb).any() ) {
00260 int d = 0;
00261 for ( int i = 0; i < sidenum; i++ ) {
00262 int xp = x;
00263 int yp = y;
00264 getnextfield ( xp, yp , i );
00265 tfield* fld2 = actmap->getField ( xp, yp );
00266 if ( fld2 )
00267 if ( (fld2->bdt & tb).any() || fld2->building )
00268 d |= ( 1 << i );
00269 }
00270 return d;
00271
00272 } else
00273 return 0;
00274 }
00275 return 0;
00276
00277 }
00278
00279
00280 int StaticResourceNet :: getresource ( int x, int y, int resource, int _need, int _queryonly, int _player, int _scope )
00281 {
00282 if ( actmap->isResourceGlobal ( resource ))
00283 scope = 3;
00284 else
00285 scope = _scope;
00286
00287 player = _player;
00288 resourcetype = resource;
00289 got = 0;
00290 need = _need;
00291 queryonly = _queryonly;
00292
00293 if (scope == 3 && player == 8 )
00294 scope = 0;
00295
00296 start ( x , y );
00297 return got;
00298 }
00299
00300
00301 int StaticResourceNet :: searchfinished ( void )
00302 {
00303 return got >= need;
00304 }
00305
00306
00307
00308
00309
00310 GetResource :: GetResource ( GameMap* gamemap, int scope )
00311 : StaticResourceNet ( gamemap, scope )
00312 {
00313 memset ( tributegot, 0, sizeof ( tributegot ));
00314 }
00315
00316
00317 void GetResource :: checkvehicle ( Vehicle* v )
00318 {
00319 if ( v->color/8 == player && resourcetype == 0 )
00320 got += v->getResource( need-got, Resources::Energy, queryonly, 1, player );
00321 }
00322
00323
00324 void GetResource :: checkbuilding ( Building* b )
00325 {
00326 if ( b->color/8 == player ) {
00327 if ((b->netcontrol & (cnet_stopenergyoutput << resourcetype)) == 0) {
00328 int toget = need-got;
00329 if ( b->actstorage.resource( resourcetype ) < 0 ) {
00330 displaymessage("map corruption detected; building %s storage for %d/%d is negative!",1,resourceNames[resourcetype],b->getEntry().x, b->getEntry().y );
00331 b->actstorage.resource( resourcetype ) = 0;
00332 }
00333
00334
00335 if ( b->actstorage.resource( resourcetype ) < toget )
00336 toget = b->actstorage.resource( resourcetype );
00337
00338 if ( !queryonly )
00339 b->actstorage.resource( resourcetype ) -= toget;
00340 got += toget;
00341 }
00342 } else
00343 if ( b->color/8 < 8 ) {
00344
00345
00346
00347 int gettable = actmap->tribute.avail[ b->color / 8 ][ player ].resource(resourcetype) - tributegot[ resourcetype ][ b->color / 8];
00348 if ( gettable > 0 ) {
00349 int toget = need-got;
00350 if ( toget > gettable )
00351 toget = gettable;
00352
00353
00354 int found = b->actstorage.resource(resourcetype);
00355 if ( toget < found )
00356 found = toget;
00357
00358 if ( !queryonly )
00359 b->actstorage.resource(resourcetype) -= found;
00360
00361 tributegot[ resourcetype ][ b->color / 8] += found;
00362
00363 if ( !queryonly ) {
00364 actmap->tribute.avail[ b->color / 8 ][ player ].resource( resourcetype ) -= found;
00365 actmap->tribute.paid [ player ][ b->color / 8 ].resource( resourcetype ) += found;
00366 if ( found )
00367 tributeTransferred();
00368 }
00369
00370 got += found;
00371 }
00372 }
00373 }
00374
00375 void GetResource :: start ( int x, int y )
00376 {
00377 if ( scope == 3 ) {
00378 got = need;
00379 if ( got > actmap->bi_resource[player].resource( resourcetype ) )
00380 got = actmap->bi_resource[player].resource( resourcetype );
00381
00382 if ( !queryonly )
00383 actmap->bi_resource[player].resource( resourcetype ) -= got;
00384
00385 if ( resourcetype == 0 )
00386 searchAllVehiclesNextToBuildings ( player );
00387
00388 } else
00389 MapNetwork :: start ( x, y );
00390 }
00391
00392
00393
00394
00395
00396
00397
00398
00399 void PutResource :: checkbuilding ( Building* b )
00400 {
00401 if ( b->color/8 == player ) {
00402 if ((b->netcontrol & (cnet_stopenergyinput << resourcetype)) == 0) {
00403 int tostore = need-got;
00404
00405 if ( b->actstorage.resource( resourcetype ) < 0 ) {
00406 displaymessage("map corruption detected; building %s storage for %d/%d is negative!",1,resourceNames[resourcetype],b->getEntry().x, b->getEntry().y );
00407 b->actstorage.resource( resourcetype ) = 0;
00408 }
00409
00410 if ( b->getStorageCapacity().resource( resourcetype ) - b->actstorage.resource( resourcetype ) < tostore )
00411 tostore = b->getStorageCapacity().resource( resourcetype ) - b->actstorage.resource( resourcetype );
00412
00413 if ( !queryonly )
00414 b->actstorage.resource( resourcetype ) += tostore;
00415 got += tostore;
00416 }
00417 }
00418 }
00419
00420
00421 void PutResource :: start ( int x, int y )
00422 {
00423 if ( scope == 3 ) {
00424
00425 got = need;
00426 if ( got > maxint - actmap->bi_resource[player].resource( resourcetype ) )
00427 got = maxint - actmap->bi_resource[player].resource( resourcetype );
00428
00429 if ( !queryonly )
00430 actmap->bi_resource[player].resource( resourcetype ) += got;
00431
00432 } else
00433 MapNetwork :: start ( x, y );
00434 }
00435
00436
00437
00438
00439
00440 void PutTribute :: checkbuilding ( Building* b )
00441 {
00442 if ( b->color/8 == targplayer ) {
00443 if ((b->netcontrol & (cnet_stopenergyinput << resourcetype)) == 0) {
00444 int tostore = need-got;
00445 if ( b->getStorageCapacity().resource( resourcetype ) - b->actstorage.resource( resourcetype ) < tostore )
00446 tostore = b->getStorageCapacity().resource( resourcetype ) - b->actstorage.resource( resourcetype );
00447
00448 if ( !queryonly ) {
00449 b->actstorage.resource( resourcetype ) += tostore;
00450 actmap->tribute.avail[ player ][ targplayer ].resource( resourcetype ) -= tostore;
00451 actmap->tribute.paid [ targplayer ][ player ].resource( resourcetype ) += tostore;
00452 }
00453 got += tostore;
00454 }
00455 }
00456 }
00457
00458
00459 void PutTribute :: start ( int x, int y )
00460 {
00461 int pl = targplayer;
00462 if ( pl == -1 )
00463 targplayer = 0;
00464
00465 do {
00466 if ( targplayer != player )
00467 if ( actmap->player[targplayer].exist() ) {
00468 need = actmap->tribute.avail[ player ][ targplayer ].resource( resourcetype );
00469 if ( need > 0 ) {
00470 if ( scope == 3 ) {
00471
00472 got = need;
00473 if ( got > maxint - actmap->bi_resource[targplayer].resource( resourcetype ) )
00474 got = maxint - actmap->bi_resource[targplayer].resource( resourcetype );
00475
00476 if ( got > actmap->bi_resource[player].resource( resourcetype ) )
00477 got = actmap->bi_resource[player].resource( resourcetype );
00478
00479 if ( !queryonly ) {
00480 actmap->bi_resource[targplayer].resource( resourcetype ) += got;
00481 actmap->bi_resource[player].resource( resourcetype ) -= got;
00482
00483 actmap->tribute.avail[ player ][ targplayer ].resource( resourcetype ) -= got;
00484 actmap->tribute.paid [ targplayer ][ player ].resource( resourcetype ) += got;
00485 }
00486
00487 } else {
00488 int avail = startbuilding->getResource ( need, resourcetype, 1, 0 );
00489 if ( need > avail )
00490 need = avail;
00491 MapNetwork :: start ( x, y );
00492 if ( !queryonly ) {
00493 startbuilding->getResource ( got, resourcetype, queryonly, 0, startbuilding->getOwner() );
00494
00495 }
00496
00497 }
00498 }
00499 }
00500 targplayer++;
00501 } while ( targplayer < 8 && pl == -1 );
00502 }
00503
00504 int PutTribute :: puttribute ( Building* start, int resource, int _queryonly, int _forplayer, int _fromplayer, int _scope )
00505 {
00506 startbuilding = start;
00507 targplayer = _forplayer;
00508 return getresource ( startbuilding->getEntry().x, startbuilding->getEntry().y, resource, 0, _queryonly, _fromplayer, _scope );
00509 }
00510
00511
00512 void transfer_all_outstanding_tribute ( Player& player )
00513 {
00514
00515 int targplayer = player.getPosition();
00516 GameMap* actmap = player.getParentMap();
00517
00518 if ( actmap->player[targplayer].exist() ) {
00519 ASCString text;
00520
00521 for ( int player = 0; player < 8; player++ ) {
00522 if ( targplayer != player )
00523 if ( actmap->player[player].exist() ) {
00524 int topay[3];
00525 int got[3];
00526 for ( int resourcetype = 0; resourcetype < 3; resourcetype++ ) {
00527 got[ resourcetype ] = actmap->tribute.paid[ targplayer ][ player ].resource( resourcetype ) - actmap->tribute.payStatusLastTurn[ targplayer ][ player ].resource( resourcetype );
00528 topay[ resourcetype ] = actmap->tribute.avail[ player ][ targplayer ].resource( resourcetype ) + got[ resourcetype ];
00529
00530 if ( !actmap->isResourceGlobal (resourcetype) ) {
00531 for ( Player::BuildingList::iterator j = actmap->player[player].buildingList.begin(); j != actmap->player[player].buildingList.end() && topay[resourcetype] > got[resourcetype] ; j++ ) {
00532 PutTribute pt ( actmap );
00533 got[resourcetype] += pt.puttribute ( *j, resourcetype, 0, targplayer, player, 1 );
00534 }
00535 } else {
00536 int i;
00537 if ( actmap->bi_resource[ player ].resource(resourcetype) < topay[resourcetype] )
00538 i = actmap->bi_resource[ player ].resource(resourcetype);
00539 else
00540 i = topay[resourcetype];
00541 got [resourcetype ] += i;
00542 actmap->bi_resource[ player ].resource(resourcetype) -= i;
00543 actmap->bi_resource[ targplayer ].resource(resourcetype) += i;
00544
00545 actmap->tribute.avail[ player ][ targplayer ].resource( resourcetype ) -= got[resourcetype];
00546 actmap->tribute.paid[ targplayer ][ player ].resource( resourcetype ) += got[resourcetype];
00547 }
00548 }
00549 actmap->tribute.payStatusLastTurn[ targplayer ][ player ] = actmap->tribute.paid[ targplayer ][ player ];
00550 if ( topay[0] || topay[1] || topay[2] || got[0] || got[1] || got[2]) {
00551 Resources tp ( topay[0], topay[1], topay[2] );
00552 Resources gt ( got[0], got[1], got[2] );
00553
00554 ASCString topayStr = tp.toString();
00555
00556 ASCString gotStr;
00557 if ( gt == tp )
00558 gotStr = "all";
00559 else {
00560 gotStr = gt.toString();
00561 if ( gotStr.empty() )
00562 gotStr = "nothing";
00563 }
00564
00565 ASCString msg;
00566 msg.format ( getmessage( 10020 ) , actmap->player[player].getName().c_str(), topayStr.c_str(), gotStr.c_str() );
00567
00568 text += msg;
00569
00570
00571
00572
00573 if ( got[0] || got[1] || got[2] ) {
00574 msg = "";
00575 gotStr = gt.toString();
00576 msg.format ( getmessage( 10021 ) , gotStr.c_str(), actmap->player[targplayer].getName().c_str());
00577 new Message ( msg, actmap, 1 << player );
00578 }
00579
00580
00581 }
00582
00583 if ( got[0] || got[1] || got[2] )
00584 tributeTransferred();
00585
00586 }
00587 }
00588 if ( !text.empty() )
00589 new Message ( text, actmap, 1 << targplayer );
00590
00591 }
00592 }
00593
00594
00595 void GetResourceCapacity :: checkbuilding ( Building* b )
00596 {
00597 if ( b->color/8 == player ) {
00598 if ((b->netcontrol & (cnet_stopenergyinput << resourcetype)) == 0) {
00599 int t = b->getStorageCapacity().resource( resourcetype );
00600 if ( t > maxint - got )
00601 got = maxint;
00602 else
00603 got += t;
00604 }
00605 }
00606 }
00607
00608
00609 void GetResourceCapacity :: start ( int x, int y )
00610 {
00611 if ( scope == 3 ) {
00612 got = maxint;
00613 } else
00614 MapNetwork :: start ( x, y );
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626 int ResourceChangeNet :: getresource ( int x, int y, int resource, int _player, int _scope )
00627 {
00628 if ( (_scope > 0) && (actmap->isResourceGlobal ( resource )) )
00629 scope = 2;
00630 else
00631 scope = _scope;
00632
00633 player = _player;
00634 resourcetype = resource;
00635 got = 0;
00636 start ( x , y );
00637 return got;
00638 }
00639
00640
00641
00642
00643 void GetResourcePlus :: checkvehicle ( Vehicle* v )
00644 {
00645
00646
00647
00648
00649 }
00650
00651
00652 void GetResourcePlus :: checkbuilding ( Building* bld )
00653 {
00654 if ( bld->color/8 == player )
00655 got += bld->getResourcePlus().resource( resourcetype );
00656 }
00657
00658
00659
00660
00661
00662 void GetResourceUsage :: checkbuilding ( Building* b )
00663 {
00664 if ( b->color/8 == player )
00665 got += b->getResourceUsage().resource( resourcetype );
00666 }
00667
00668
00669
00670 bool compareMapResources( GameMap* currentMap, GameMap* replaymap, int player, ASCString* log )
00671 {
00672 ASCString s;
00673 bool diff = false;
00674 for ( int r = 0; r < 3; ++r ) {
00675 if ( currentMap->isResourceGlobal( r )) {
00676 if ( currentMap->bi_resource[player].resource(r) != replaymap->bi_resource[player].resource(r) ) {
00677 diff = true;
00678 if ( log ) {
00679 s.format ( "Global resource mismatch: %d %s available after replay, but %d available in actual map\n", replaymap-> bi_resource[player].resource(r), resourceNames[r], currentMap->bi_resource[player].resource(r) );
00680 *log += s;
00681 }
00682 }
00683 } else {
00684 GetConnectedBuildings::BuildingContainer cb;
00685 for ( Player::BuildingList::iterator b = currentMap->player[player].buildingList.begin(); b != currentMap->player[player].buildingList.end(); ++b ) {
00686 Building* b1 = *b;
00687 ContainerBase* b2 = replaymap->getContainer( b1->getIdentification() );
00688 if ( !b1 || !b2 ) {
00689 if ( log ) {
00690 s.format ( "Building missing! \n");
00691 *log += s;
00692 }
00693 } else {
00694 if ( find ( cb.begin(), cb.end(), b1 ) == cb.end()) {
00695 int ab1 = b1->getResource( maxint, r, true, 1, player );
00696 int ab2 = b2->getResource( maxint, r, true, 1, player);
00697 if ( ab1 != ab2 ) {
00698 diff = true;
00699 if ( log ) {
00700 s.format ( "Building (%d,%d) resource mismatch: %d %s available after replay, but %d available in actual map\n", b1->getPosition().x, b1->getPosition().y, ab1, resourceNames[r], ab2 );
00701 *log += s;
00702 }
00703 }
00704 cb.push_back ( b1 );
00705 GetConnectedBuildings::BuildingContainer cbl;
00706 GetConnectedBuildings gcb ( cbl, b1->getMap(), r );
00707 gcb.start ( b1->getPosition().x, b1->getPosition().y );
00708 cb.insert ( cb.end(), cbl.begin(), cbl.end() );
00709 }
00710 }
00711 }
00712 }
00713 for ( Player::VehicleList::iterator v = currentMap->player[player].vehicleList.begin(); v != currentMap->player[player].vehicleList.end(); ++v ) {
00714 Vehicle* v1 = *v;
00715 Vehicle* v2 = replaymap->getUnit( v1->networkid );
00716 if ( !v1 || !v2 ) {
00717 if ( log ) {
00718 s.format ( "Vehicle missing! \n");
00719 *log += s;
00720 }
00721 } else {
00722 if ( v1->typ != v2->typ ) {
00723 diff = true;
00724 if ( log ) {
00725 s.format ( "Vehicles with NWID %d don't have matching type, probably production inconsistency. (%s <-> %s)\n", v1->networkid, v1->typ->getName().c_str(), v2->typ->getName().c_str() );
00726 *log += s;
00727 }
00728 } else {
00729 int av1 = v1->getResource( maxint, r, true, 1, player );
00730 int av2 = v2->getResource( maxint, r, true, 1, player );
00731 if ( av1 != av2 ) {
00732 diff = true;
00733 if ( log ) {
00734 s.format ( "Vehicle %s (%d,%d) resource mismatch: %d %s available after replay, but %d available in actual map\n", v1->typ->getName().c_str(), v1->getPosition().x, v1->getPosition().y, av2, resourceNames[r], av1 );
00735 *log += s;
00736 }
00737 }
00738
00739 if ( v1->damage != v2->damage ) {
00740 diff = true;
00741 if ( log ) {
00742 s.format ( "Vehicle (%d,%d) damage mismatch: %d after replay, but %d in actual map\n", v1->getPosition().x, v1->getPosition().y, v2->damage, v1->damage );
00743 *log += s;
00744 }
00745 }
00746 }
00747 }
00748 }
00749
00750 }
00751 if ( currentMap->player[player].vehicleList.size() != replaymap->player[player].vehicleList.size() ) {
00752 diff = true;
00753 if ( log ) {
00754 s.format ( "The number of units differ. Replay: %d ; actual map: %d", replaymap->player[player].vehicleList.size(), currentMap->player[player].vehicleList.size());
00755 *log += s;
00756
00757 GameMap* more;
00758 GameMap* less;
00759 if ( currentMap->player[player].vehicleList.size() > replaymap->player[player].vehicleList.size() ) {
00760 more = currentMap;
00761 less = replaymap;
00762 } else {
00763 more = replaymap;
00764 less = currentMap;
00765 }
00766
00767 for ( Player::VehicleList::iterator i = more->player[player].vehicleList.begin(); i != more->player[player].vehicleList.end(); ++i )
00768 if ( !less->getUnit( (*i)->networkid )) {
00769 s.format( "Type: %s at %d/%d\n", (*i)->getName().c_str(), (*i)->getPosition().x, (*i)->getPosition().y );
00770 *log += s;
00771 }
00772 }
00773 }
00774
00775 if ( currentMap->player[player].buildingList.size() != replaymap->player[player].buildingList.size() ) {
00776 diff = true;
00777 if ( log ) {
00778 s.format ( "The number of buildings differ. Replay: %d ; actual map: %d", replaymap->player[player].buildingList.size(), currentMap->player[player].buildingList.size());
00779 *log += s;
00780 }
00781 }
00782
00783 if ( currentMap->player[player].research.progress != replaymap->player[player].research.progress ) {
00784 diff = true;
00785 if ( log ) {
00786 s.format ( "Research points mismatch! Replay: %d ; actual map: %d", replaymap->player[player].research.progress, currentMap->player[player].research.progress);
00787 *log += s;
00788 }
00789 }
00790
00791 sort ( currentMap->player[player].research.developedTechnologies.begin(), currentMap->player[player].research.developedTechnologies.end() );
00792 sort ( replaymap->player[player].research.developedTechnologies.begin(), replaymap->player[player].research.developedTechnologies.end() );
00793 if ( replaymap->player[player].research.developedTechnologies.size() != currentMap->player[player].research.developedTechnologies.size() ) {
00794 diff = true;
00795 if ( log ) {
00796 s.format ( "Number of developed technologies differ !\n" );
00797 *log += s;
00798 }
00799 } else {
00800 for ( int i = 0; i < replaymap->player[player].research.developedTechnologies.size(); ++i )
00801 if ( replaymap->player[player].research.developedTechnologies[i] != currentMap->player[player].research.developedTechnologies[i] ) {
00802 diff = true;
00803 if ( log ) {
00804 s.format ( "Different technologies developed !\n" );
00805 *log += s;
00806 }
00807 }
00808 }
00809
00810 for ( Player::BuildingList::iterator b = currentMap->player[player].buildingList.begin(); b != currentMap->player[player].buildingList.end(); ++b ) {
00811 Building* b1 = *b;
00812 Building* b2 = dynamic_cast<Building*>(replaymap->getContainer( b1->getIdentification() ));
00813 if ( !b1 || !b2 ) {
00814 if ( log ) {
00815 s.format ( "Building missing! \n");
00816 *log += s;
00817 }
00818 } else {
00819 bool mismatch = false;
00820 for ( int i = 0; i < b1->getProduction().size(); ++i )
00821 if ( b1->getProduction()[i] ) {
00822 bool found = false;
00823 for ( int j = 0; j < b2->getProduction().size(); ++j)
00824 if ( b2->getProduction()[j] == b1->getProduction()[i] )
00825 found = true;
00826 if ( !found)
00827 mismatch = true;
00828 }
00829
00830 for ( int j = 0; j < b2->getProduction().size(); ++j )
00831 if ( b2->getProduction()[j] ) {
00832 bool found = false;
00833 for ( int i = 0; i < b1->getProduction().size(); ++i)
00834 if ( b1->getProduction()[i] == b2->getProduction()[j] )
00835 found = true;
00836 if ( !found)
00837 mismatch = true;
00838 }
00839
00840 if ( mismatch ) {
00841 diff = true;
00842 if ( log ) {
00843 s.format ( "Building (%d,%d) production line mismatch !\n", b1->getPosition().x, b1->getPosition().y );
00844 *log += s;
00845 }
00846 }
00847 }
00848 }
00849
00850 return diff;
00851 }
00852