00001
00002
00003
00004
00005
00006
00007
00008
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cmath>
00023 #include <iostream>
00024 #include "research.h"
00025 #include "errors.h"
00026 #include "typen.h"
00027 #include "vehicletype.h"
00028 #include "gamemap.h"
00029 #include "itemrepository.h"
00030
00031 const int techDependencyVersion = 2;
00032
00033 void TechDependency::read ( tnstream& stream )
00034 {
00035 int version = stream.readInt();
00036 if ( version > techDependencyVersion || version < 1 )
00037 throw tinvalidversion( stream.getDeviceName(), techDependencyVersion, version );
00038
00039 requireAllListedTechnologies = stream.readInt();
00040 readClassContainer(requiredTechnologies, stream );
00041 if ( version >= 2 )
00042 readClassContainer(blockingTechnologies, stream );
00043 }
00044
00045 void TechDependency::write ( tnstream& stream ) const
00046 {
00047 stream.writeInt(techDependencyVersion);
00048 stream.writeInt(requireAllListedTechnologies);
00049 writeClassContainer(requiredTechnologies, stream );
00050 writeClassContainer(blockingTechnologies, stream );
00051 }
00052
00053 void TechDependency::runTextIO ( PropertyContainer& pc )
00054 {
00055 pc.addIntRangeArray ( "TechnologiesRequired", requiredTechnologies );
00056 pc.addBool( "RequireAllListedTechnologies", requireAllListedTechnologies, true );
00057 if ( pc.find( "BlockingTechnologies" ) || !pc.isReading() )
00058 pc.addIntRangeArray ( "BlockingTechnologies", blockingTechnologies );
00059 }
00060
00061 bool TechDependency::available( const Research& research ) const
00062 {
00063 return available( CheckTechAvailabilityFunctor( &research, &Research::techResearched )) == Available;
00064 }
00065
00066 ResearchAvailabilityStatus TechDependency::available( CheckTechAvailabilityFunctor checkTechAvailability ) const
00067 {
00068 for ( RequiredTechnologies::const_iterator j = blockingTechnologies.begin(); j != blockingTechnologies.end(); ++j )
00069 for ( int k = j->from; k <= j->to; ++k )
00070 if ( checkTechAvailability ( k ))
00071 return NeverAvailable;
00072
00073
00074 if ( requiredTechnologies.size() ) {
00075 if ( requireAllListedTechnologies ) {
00076 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00077 for ( int k = j->from; k <= j->to; ++k )
00078 if ( !checkTechAvailability( k ))
00079 return UnavailableNow;
00080 return Available;
00081 } else {
00082 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00083 for ( int k = j->from; k <= j->to; ++k )
00084 if ( checkTechAvailability ( k ))
00085 return Available;
00086 return UnavailableNow;
00087 }
00088 } else
00089 return Available;
00090 }
00091
00092
00093 bool TechDependency::eventually_available_single( const Research& res, list<const Technology*>* dependencies, list<int>& stack, int id )
00094 {
00095 Technology* tech = technologyRepository.getObject_byID( id );
00096 if ( !tech )
00097 return false;
00098
00099
00100
00101 return tech->eventually_available( res, dependencies, stack );
00102 }
00103
00104 bool TechDependency::eventually_available( const Research& res, list<const Technology*>* dependencies, list<int>& stack ) const
00105 {
00106 if ( requireAllListedTechnologies ) {
00107 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00108 for ( int k = j->from; k <= j->to; ++k )
00109 if ( !eventually_available_single( res, dependencies, stack, k ))
00110 return false;
00111
00112 return true;
00113 } else {
00114 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00115 for ( int k = j->from; k <= j->to; ++k )
00116 if ( eventually_available_single( res, dependencies, stack, k ))
00117 return true;
00118
00119 return false;
00120 }
00121 return false;
00122 }
00123
00124 bool TechDependency::eventually_available( const Research& res, list<const Technology*>* dependencies ) const
00125 {
00126 list<int> stack;
00127 return eventually_available( res, dependencies, stack );
00128 }
00129
00130
00131
00132 int TechDependency::findInheritanceLevel( int id, vector<int>& stack, const ASCString& sourceTechName ) const
00133 {
00134 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00135 for ( int k = j->from; k <= j->to; ++k )
00136 if ( k > 0 ) {
00137 if ( find( stack.begin(), stack.end(), k ) != stack.end() ) {
00138 ASCString s = "Cyclic reference for technology \n" + sourceTechName + "\n";
00139 for ( vector<int>::iterator i = stack.begin(); i != stack.end(); ++i ) {
00140 Technology* t = technologyRepository.getObject_byID( *i );
00141 if ( t )
00142 s += t->name + "\n";
00143 }
00144 Technology* t = technologyRepository.getObject_byID( k );
00145 if ( t )
00146 s += t->name + "\n";
00147 warning ( s );
00148 return -1;
00149 }
00150
00151 Technology* t = technologyRepository.getObject_byID( k );
00152
00153 if ( t ) {
00154
00155 stack.push_back ( k );
00156
00157 int i = t->techDependency.findInheritanceLevel ( id, stack, sourceTechName );
00158
00159
00160 stack.pop_back();
00161 if ( i > 0 )
00162 return i+1;
00163 }
00164 }
00165
00166 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00167 for ( int k = j->from; k <= j->to; ++k )
00168 if ( id == k && k > 0 )
00169 return 1;
00170
00171 return -1;
00172 }
00173
00174
00175 void TechDependency::writeTreeOutput ( const ASCString& sourceTechName, tnstream& stream, bool reduce ) const
00176 {
00177 map<int,int> ihl;
00178 vector<int> stack;
00179 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00180 for ( int k = j->from; k <= j->to; ++k ) {
00181 ihl[k] = findInheritanceLevel( k , stack, sourceTechName);
00182 }
00183
00184 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00185 for ( int k = j->from; k <= j->to; ++k ) {
00186 const Technology* t = technologyRepository.getObject_byID( k );
00187 if ( t && (ihl[k] == 1 || !reduce) ) {
00188 ASCString s = "\"";
00189 ASCString stn = sourceTechName;
00190
00191 while ( stn.find ( "\"" ) != ASCString::npos )
00192 stn.erase ( stn.find ( "\"" ),1 );
00193
00194 s += stn;
00195 s += "\" -> \"";
00196
00197 ASCString stn2 = t->name;
00198 while ( stn2.find ( "\"" ) != ASCString::npos )
00199 stn2.erase ( stn2.find ( "\"" ),1 );
00200
00201 s += stn2 + "\"";
00202
00203 if ( !requireAllListedTechnologies )
00204 s += "[style=dashed]";
00205
00206 s += "\n";
00207
00208 stream.writeString ( s, false );
00209
00210 stream.writeString ( "\"" + stn + "\" [color=black] \n", false );
00211 }
00212 }
00213 }
00214
00215 ASCString generateTechName( const Technology* tech )
00216 {
00217 ASCString s = ASCString(strrr(tech->id)) + "-";
00218 ASCString stn = tech->name;
00219
00220 while ( stn.find ( "\"" ) != ASCString::npos )
00221 stn.erase ( stn.find ( "\"" ),1 );
00222
00223 return s + stn;
00224 }
00225
00226 ASCString generateTechLabel ( const Technology* tech )
00227 {
00228 ASCString s2 = tech->name;
00229 while ( s2.find ( "\"" ) != ASCString::npos )
00230 s2.erase ( s2.find ( "\"" ),1 );
00231
00232
00233 ASCString s = "\"" + generateTechName(tech) + "\" [color=black label=\"" + s2 + "\\n";
00234
00235 s += ASCString(strrr(tech->researchpoints)) + " RP\"] \n";
00236 return s;
00237 }
00238
00239 void TechDependency::writeInvertTreeOutput ( const Technology* tech, tnstream& stream, vector<int>& history, vector<pair<int,int> >& blockedPrintList, const vector<IntRange>* onlyWithBaseTechs ) const
00240 {
00241 if ( onlyWithBaseTechs && !onlyWithBaseTechs->empty() ) {
00242 vector<int> inheritanceStack;
00243 bool found = false;
00244 for ( vector<IntRange>::const_iterator i = onlyWithBaseTechs->begin(); i != onlyWithBaseTechs->end(); ++i )
00245 for ( int j = i->from; j <= i->to; ++j )
00246 if ( findInheritanceLevel ( j, inheritanceStack, "" ) >= 0 )
00247 found = true;
00248
00249 if ( !found )
00250 return;
00251 }
00252
00253 for ( RequiredTechnologies::const_iterator i = blockingTechnologies.begin(); i != blockingTechnologies.end(); ++i ) {
00254 for ( int l = i->from; l <= i->to; ++l ) {
00255 const Technology* block = technologyRepository.getObject_byID( l );
00256 if ( block && find ( blockedPrintList.begin(), blockedPrintList.end(), make_pair(tech->id,l)) == blockedPrintList.end() ) {
00257 ASCString b = "\"" + generateTechName( block )+ "\" -> \"" + generateTechName( tech ) + "\" [color=red label=\"blocks\" fontcolor=red fontsize=10]\n";
00258 stream.writeString ( b, false );
00259 blockedPrintList.push_back ( make_pair(tech->id,l) );
00260 }
00261 }
00262 }
00263
00264 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00265 for ( int k = j->from; k <= j->to; ++k ) {
00266 const Technology* t = technologyRepository.getObject_byID( k );
00267 if ( t ) {
00268 ASCString s = "\"" + generateTechName( tech )+ "\" -> \"" + generateTechName( t ) + "\"";
00269
00270 if ( !requireAllListedTechnologies )
00271 s += "[style=dotted]";
00272
00273 s += "\n";
00274
00275 stream.writeString ( s, false );
00276
00277
00278 stream.writeString ( generateTechLabel(tech), false );
00279 stream.writeString ( generateTechLabel(t), false );
00280
00281 if ( find ( history.begin(), history.end(), t->id) == history.end()) {
00282 history.push_back ( t->id );
00283 t->techDependency.writeInvertTreeOutput ( t, stream, history, blockedPrintList );
00284 }
00285 }
00286 }
00287 }
00288
00289 void TechDependency::writeInvertTreeOutput ( const ASCString techName, tnstream& stream, vector<int>& history, vector<pair<int,int> >& blockedPrintList, const vector<IntRange>* onlyWithBaseTechs ) const
00290 {
00291 if ( onlyWithBaseTechs && !onlyWithBaseTechs->empty() ) {
00292 vector<int> inheritanceStack;
00293 bool found = false;
00294 for ( vector<IntRange>::const_iterator i = onlyWithBaseTechs->begin(); i != onlyWithBaseTechs->end(); ++i )
00295 for ( int j = i->from; j <= i->to; ++j )
00296 if ( findInheritanceLevel ( j, inheritanceStack, "" ) >= 0 )
00297 found = true;
00298
00299 if ( !found )
00300 return;
00301 }
00302
00303 for ( RequiredTechnologies::const_iterator j = requiredTechnologies.begin(); j != requiredTechnologies.end(); ++j )
00304 for ( int k = j->from; k <= j->to; ++k ) {
00305 const Technology* t = technologyRepository.getObject_byID( k );
00306 if ( t ) {
00307 ASCString s = "\"";
00308 ASCString stn = techName;
00309
00310 s += stn;
00311 s += "\" -> \"";
00312
00313 ASCString stn2 = generateTechName( t );
00314
00315 s += stn2 + "\"";
00316
00317 if ( !requireAllListedTechnologies )
00318 s += "[style=dotted]";
00319
00320 s += "\n";
00321
00322 stream.writeString ( s, false );
00323
00324 stream.writeString ( "\"" + stn + "\" [color=black] \n", false );
00325 if ( find ( history.begin(), history.end(), t->id) == history.end()) {
00326 history.push_back ( t->id );
00327 t->techDependency.writeInvertTreeOutput ( t, stream, history, blockedPrintList );
00328 }
00329 }
00330 }
00331 }
00332
00333 ASCString TechDependency::showDebug( const Research& research ) const
00334 {
00335 ASCString s;
00336 if ( requireAllListedTechnologies )
00337 s += "All of the following Technologies required:\n";
00338 else
00339 s += "One of the following Technologies required:\n";
00340
00341 s += "#indent=20,20#";
00342 for ( RequiredTechnologies::const_iterator r = requiredTechnologies.begin(); r != requiredTechnologies.end(); ++r ) {
00343 for ( int i = r->from; i <= r->to; ++i ) {
00344 Technology* t = technologyRepository.getObject_byID(i);
00345 if ( t ) {
00346 s += " " + t->name + " ";
00347 if ( research.techResearched( t->id ))
00348 s += "#fontcolor=0x00FF00#available";
00349 else
00350 s += "#fontcolor=0xFF0000#missing";
00351 s += "#fontcolor=default#\n";
00352 }
00353 }
00354 }
00355 s += "#indent=0,0#";
00356
00357 if ( !blockingTechnologies.empty() ) {
00358 s += "The following Technologies must NOT be researched:\n";
00359 s += "#indent=20,20#";
00360 for ( RequiredTechnologies::const_iterator r = blockingTechnologies.begin(); r != blockingTechnologies.end(); ++r ) {
00361 for ( int i = r->from; i <= r->to; ++i ) {
00362 Technology* t = technologyRepository.getObject_byID(i);
00363 if ( t ) {
00364 s += " " + t->name;
00365 if ( !research.techResearched( t->id ))
00366 s += "#fontcolor=0x00FF00#not available";
00367 else
00368 s += "#fontcolor=0xFF0000#available";
00369 s += "#fontcolor=default#\n";
00370 }
00371 }
00372 }
00373 }
00374
00375 return s;
00376 }
00377
00378
00379
00380
00381 void TechAdapter::read ( tnstream& stream )
00382 {
00383 int version = stream.readInt();
00384 if ( version > 1 || version < 1 )
00385 throw tinvalidversion( stream.getDeviceName(), 1, version );
00386 name = stream.readString();
00387 techDependency.read( stream );
00388 }
00389
00390 void TechAdapter::write ( tnstream& stream ) const
00391 {
00392 stream.writeInt(1);
00393 stream.writeString( name );
00394 techDependency.write ( stream );
00395 }
00396
00397 void TechAdapter::runTextIO ( PropertyContainer& pc )
00398 {
00399 pc.addString ( "Name", name );
00400 name.toLower();
00401 techDependency.runTextIO ( pc );
00402 }
00403
00404 bool TechAdapter::available( const Research& research ) const
00405 {
00406 return techDependency.available ( research );
00407 }
00408
00409
00410
00411
00412 TechAdapterDependency::TechAdapterDependency() : requireAllListedTechAdapter ( false ) {};
00413
00414 bool TechAdapterDependency::available( const Research& research ) const
00415 {
00416 if ( requiredTechAdapter.size() ) {
00417 if ( requireAllListedTechAdapter ) {
00418 for ( RequiredTechAdapter::const_iterator j = requiredTechAdapter.begin(); j != requiredTechAdapter.end(); ++j )
00419 if ( !research.techAdapterAvail( *j ))
00420 return false;
00421 return true;
00422 } else {
00423 for ( RequiredTechAdapter::const_iterator j = requiredTechAdapter.begin(); j != requiredTechAdapter.end(); ++j )
00424 if ( research.techAdapterAvail ( *j ))
00425 return true;
00426 return false;
00427 }
00428 }
00429
00430 return true;
00431 }
00432
00433
00434 TechAdapter :: TechAdapter() {}
00435
00436 void TechAdapterDependency::read ( tnstream& stream )
00437 {
00438 int version = stream.readInt();
00439 if ( version > 1 || version < 1 )
00440 throw tinvalidversion( stream.getDeviceName(), 1, version );
00441 requireAllListedTechAdapter = stream.readInt();
00442 requiredTechAdapter.clear();
00443 for ( int i = stream.readInt(); i >0 ; --i )
00444 requiredTechAdapter.push_back ( stream.readString() );
00445 }
00446
00447 void TechAdapterDependency::write ( tnstream& stream ) const
00448 {
00449 stream.writeInt(1);
00450 stream.writeInt(requireAllListedTechAdapter);
00451 stream.writeInt( requiredTechAdapter.size() );
00452 for ( RequiredTechAdapter::const_iterator i = requiredTechAdapter.begin(); i != requiredTechAdapter.end(); ++i )
00453 stream.writeString(*i);
00454 }
00455
00456 void TechAdapterDependency::runTextIO ( PropertyContainer& pc, const ASCString& defaultTechAdapter )
00457 {
00458 if ( pc.find( "TechAdapterRequired") || !pc.isReading() ) {
00459 pc.addStringArray ( "TechAdapterRequired", requiredTechAdapter );
00460 if ( pc.isReading())
00461 for ( RequiredTechAdapter::iterator j = requiredTechAdapter.begin(); j != requiredTechAdapter.end(); ++j )
00462 j->toLower();
00463
00464 } else
00465 if ( defaultTechAdapter.length() > 0 )
00466 requiredTechAdapter.push_back ( defaultTechAdapter );
00467
00468 pc.addBool( "RequireAllListedTechAdapter", requireAllListedTechAdapter, true );
00469 }
00470
00471 void TechAdapterDependency::writeInvertTreeOutput ( const ASCString& tech, tnstream& stream, const vector<IntRange>* onlyWithBaseTechs ) const
00472 {
00473 vector<int> history;
00474 vector<pair<int,int> > blockedPrintList;
00475 for ( RequiredTechAdapter::const_iterator r = requiredTechAdapter.begin(); r != requiredTechAdapter.end(); ++r )
00476 for ( TechAdapterContainer::iterator i = techAdapterContainer.begin(); i != techAdapterContainer.end(); ++i )
00477 if ( *r == (*i)->getName() )
00478 (*i)->techDependency.writeInvertTreeOutput ( tech, stream, history, blockedPrintList, onlyWithBaseTechs );
00479 }
00480
00481 ASCString TechAdapterDependency::showDebug( const Research& research ) const
00482 {
00483 ASCString s;
00484 if ( requireAllListedTechAdapter )
00485 s += "All of the following TechAdapter required:\n";
00486 else
00487 s += "One of the following TechAdapter required:\n";
00488
00489 for ( RequiredTechAdapter::const_iterator r = requiredTechAdapter.begin(); r != requiredTechAdapter.end(); ++r ) {
00490 s += " " + *r;
00491 if ( research.techAdapterAvail( *r ))
00492 s += "#image=pad_symbol_ok.png#";
00493 else
00494 s += "#image=pad_symbol_no.png#";
00495 s += "\n";
00496 }
00497
00498 return s;
00499 }
00500
00501
00502 Technology::Technology()
00503 {
00504 icon = NULL;
00505 id = 0;
00506 researchpoints = 0;
00507 requireEvent = false;
00508 techlevel = 0;
00509 }
00510
00511 const int technologyVersion = 4;
00512
00513 void Technology::read( tnstream& stream )
00514 {
00515 int version = stream.readInt();
00516 if ( version > technologyVersion || version < 1 )
00517 throw tinvalidversion( stream.getDeviceName(), technologyVersion, version );
00518 id = stream.readInt();
00519 researchpoints = stream.readInt();
00520 requireEvent = stream.readInt();
00521 techlevel = stream.readInt();
00522 name = stream.readString();
00523 infotext = stream.readString();
00524 techDependency.read( stream );
00525 if ( version >= 2 )
00526 relatedUnitID = stream.readInt();
00527 else
00528 relatedUnitID = -1;
00529
00530 if ( version >= 3 )
00531 readClassContainer( blockingOtherTechnologies, stream );
00532
00533 if ( version >= 4 )
00534 readClassContainer( secondaryIDs, stream );
00535
00536 }
00537
00538 void Technology::write( tnstream& stream ) const
00539 {
00540 stream.writeInt( technologyVersion );
00541 stream.writeInt ( id );
00542 stream.writeInt( researchpoints );
00543 stream.writeInt( requireEvent );
00544 stream.writeInt( techlevel );
00545 stream.writeString( name );
00546 stream.writeString( infotext );
00547 techDependency.write( stream );
00548 stream.writeInt ( relatedUnitID );
00549 writeClassContainer( blockingOtherTechnologies, stream );
00550 writeClassContainer( secondaryIDs, stream );
00551 }
00552
00553 void Technology::runTextIO ( PropertyContainer& pc )
00554 {
00555 pc.addString( "Name", name );
00556 pc.addString( "Infotext", infotext);
00557
00558 pc.addInteger( "Id", id );
00559 if ( pc.find( "SecondaryIDs") || !pc.isReading())
00560 pc.addIntegerArray("SecondaryIDs", secondaryIDs );
00561
00562 pc.addInteger( "Researchpoints", researchpoints );
00563
00564 pc.addInteger( "Techlevel", techlevel );
00565 pc.addBool( "RequireEvent", requireEvent, false );
00566
00567 techDependency.runTextIO( pc );
00568
00569 if ( pc.find ( "BlockingOtherTechnologies" ) || !pc.isReading() )
00570 pc.addIntRangeArray ( "BlockingOtherTechnologies", blockingOtherTechnologies );
00571
00572
00573 pc.addInteger( "RelatedUnitID", relatedUnitID, 0 );
00574 }
00575
00576 bool Technology::eventually_available( const Research& res, list<const Technology*>* dependencies ) const
00577 {
00578 if ( res.techResearched( id ))
00579 return false;
00580
00581 list<int> stack;
00582 return eventually_available( res, dependencies, stack );
00583 }
00584
00585 bool Technology::eventually_available( const Research& res, list<const Technology*>* dependencies, list<int>& stack ) const
00586 {
00587 if ( res.techResearched( id ))
00588 return true;
00589
00590 if ( res.isBlocked( this ))
00591 return false;
00592
00593 if ( find( stack.begin(), stack.end(), id ) != stack.end() )
00594 return false;
00595
00596 stack.push_back( id );
00597 bool result = techDependency.eventually_available( res, dependencies, stack );
00598 stack.pop_back();
00599
00600 if ( result ) {
00601 if ( dependencies )
00602 if ( find( dependencies->begin(), dependencies->end(), this) == dependencies->end() )
00603 dependencies->push_back( this );
00604 return true;
00605 } else
00606 return false;
00607
00608 }
00609
00610
00611
00612 Research :: Research ( ) : goal(NULL)
00613 {
00614 progress = 0;
00615 activetechnology = 0;
00616 ___loadActiveTech = 0;
00617 ___oldVersionLoader = false;
00618 techsAvail = true;
00619 multiplier = 1;
00620 }
00621
00622
00623 void Research :: read ( tnstream& stream )
00624 {
00625 read_struct ( stream );
00626 read_techs ( stream );
00627 evalTechAdapter();
00628 }
00629
00630
00631 const int researchableWeaponImprovements = 8;
00632
00633
00634 const int researchVersion = -5;
00635
00636 void Research :: read_struct ( tnstream& stream, bool merge )
00637 {
00638 int version = stream.readInt();
00639
00640 if ( version < researchVersion )
00641 throw tinvalidversion( stream.getLocation(), -researchVersion, -version );
00642
00643 if ( version >= 0 ) {
00644 progress = version;
00645 ___loadActiveTech = stream.readInt();
00646
00647 for ( int i = 0; i < researchableWeaponImprovements; i++ )
00648 stream.readWord();
00649 stream.readWord();
00650
00651 for ( int j = 0; j < 44-researchableWeaponImprovements*2; j++ )
00652 stream.readChar();
00653
00654 stream.readInt();
00655 stream.readInt();
00656 ___oldVersionLoader = true;
00657 techsAvail = true;
00658 } else {
00659 progress = stream.readInt();
00660 activetechnology = technologyRepository.getObject_byID( stream.readInt());
00661 int size = stream.readInt();
00662
00663 if ( !merge )
00664 developedTechnologies.clear();
00665
00666 for ( int i = 0; i < size; ++i )
00667 developedTechnologies.push_back ( stream.readInt());
00668
00669 ___oldVersionLoader = false;
00670
00671 if ( version <= -2 )
00672 techsAvail = stream.readInt();
00673 else
00674 techsAvail = true;
00675
00676 if ( version <= -3 ) {
00677 if ( merge ) {
00678 vector<ASCString> predefinedTechAdapter_t;
00679 readClassContainer( predefinedTechAdapter_t, stream );
00680 predefinedTechAdapter.insert( predefinedTechAdapter.begin(), predefinedTechAdapter_t.begin(), predefinedTechAdapter_t.end() );
00681 } else {
00682 readClassContainer( predefinedTechAdapter, stream );
00683 }
00684 }
00685 if ( version <= -4 ) {
00686 multiplier = stream.readInt();
00687 }
00688
00689 if ( version <= -5 ) {
00690 int g = stream.readInt();
00691 if ( g > 0 )
00692 goal = technologyRepository.getObject_byID( g );
00693 else
00694 goal = NULL;
00695 } else
00696 goal = NULL;
00697 }
00698 }
00699
00700 void Research :: write ( tnstream& stream ) {
00701 stream.writeInt ( researchVersion );
00702 stream.writeInt( progress );
00703 stream.writeInt ( activetechnology ? activetechnology->id : 0);
00704 stream.writeInt( developedTechnologies.size());
00705 for ( int i = 0; i < developedTechnologies.size(); ++i )
00706 stream.writeInt( developedTechnologies[i] );
00707
00708 stream.writeInt ( techsAvail );
00709 writeClassContainer( predefinedTechAdapter, stream );
00710 stream.writeInt( multiplier );
00711 if ( goal )
00712 stream.writeInt( goal->id );
00713 else
00714 stream.writeInt( 0 );
00715
00716 }
00717
00718
00719 void Research :: read_techs ( tnstream& stream, bool merge )
00720 {
00721 if ( !___oldVersionLoader )
00722 return;
00723
00724 if ( !merge )
00725 developedTechnologies.clear();
00726
00727 int w = stream.readInt ();
00728
00729 while ( w ) {
00730 const Technology* tec = technologyRepository.getObject_byID( w );
00731 if ( !tec )
00732 throw InvalidID ( "technology", w );
00733
00734 developedTechnologies.push_back(tec->id);
00735
00736 w = stream.readInt();
00737 }
00738
00739 if ( ___loadActiveTech ) {
00740 w = stream.readInt ();
00741
00742 activetechnology = technologyRepository.getObject_byID( w );
00743
00744 if ( !activetechnology )
00745 throw InvalidID ( "technology", w );
00746 }
00747 }
00748
00749 void Research::clear()
00750 {
00751 progress = 0;
00752 activetechnology = NULL;
00753 goal = NULL;
00754 developedTechnologies.clear();
00755 predefinedTechAdapter.clear();
00756 triggeredTechAdapter.clear();
00757 }
00758
00759 bool Research::techResearched ( int id ) const
00760 {
00761 for ( vector<int>::const_iterator i = developedTechnologies.begin(); i != developedTechnologies.end(); ++i )
00762 if ( *i == id )
00763 return true;
00764 return false;
00765 }
00766
00767
00768 bool Research::techAdapterAvail( const ASCString& ta ) const
00769 {
00770 if( find ( predefinedTechAdapter.begin(), predefinedTechAdapter.end(), ta ) != predefinedTechAdapter.end() )
00771 return true;
00772
00773 return triggeredTechAdapter.find ( ta ) != triggeredTechAdapter.end();
00774 }
00775
00776 void Research::evalTechAdapter()
00777 {
00778 for ( TechAdapterContainer::iterator i = techAdapterContainer.begin(); i != techAdapterContainer.end(); ++i )
00779 if ( (*i)->available ( *this ))
00780 triggeredTechAdapter[(*i)->getName()] = true;
00781 }
00782
00783
00784 ASCString Research::listTriggeredTechAdapter() const
00785 {
00786 ASCString s;
00787 for ( TriggeredTechAdapter::const_iterator i = triggeredTechAdapter.begin(); i != triggeredTechAdapter.end(); ++i ) {
00788 s += "#fontsize=14# ";
00789 s += i->first + "\n";
00790 s += "#fontsize=10#";
00791 int counter = 0;
00792 for ( TechAdapterContainer::iterator j = techAdapterContainer.begin(); j != techAdapterContainer.end(); ++j ) {
00793 if ( (*j)->getName() == i->first ) {
00794 if ( counter )
00795 s += " ----\n";
00796 ++counter;
00797
00798 s += (*j)->techDependency.showDebug( *this );
00799 }
00800 }
00801 s += "#fontsize=14#\n";
00802
00803
00804 }
00805
00806 return s;
00807 }
00808
00809
00810
00811
00812 bool Research::isBlocked( const Technology* tech ) const
00813 {
00814 for ( int i = 0; i < developedTechnologies.size(); ++i ) {
00815 Technology* t = technologyRepository.getObject_byID( developedTechnologies[i] );
00816 if ( t && !t->techDependency.available ( *this ) ) {
00817
00818 for ( Technology::BlockingOtherTechnologies::iterator j = t->blockingOtherTechnologies.begin(); j != t->blockingOtherTechnologies.end(); ++j)
00819 if ( j->from <= tech->id && tech->id <= j->to )
00820 return true;
00821 }
00822 }
00823 return false;
00824
00825 }
00826
00827
00828 ResearchAvailabilityStatus Research::techAvailable ( const Technology* tech ) const
00829 {
00830 if ( techResearched( tech->id ))
00831 return Researched;
00832
00833 if ( isBlocked( tech ))
00834 return NeverAvailable;
00835
00836 if ( tech->techDependency.available( *this ) ) {
00837 return Available;
00838 } else
00839 return UnavailableNow;
00840 }
00841
00842
00843 void Research :: addanytechnology ( const Technology* tech )
00844 {
00845 if ( tech ) {
00846 developedTechnologies.push_back ( tech->id );
00847
00848 map->player[player].queuedEvents++;
00849 evalTechAdapter();
00850 }
00851 }
00852
00853 void Research :: addtechnology ( void )
00854 {
00855 if ( activetechnology )
00856 addanytechnology ( activetechnology );
00857
00858 activetechnology = 0;
00859 }
00860
00861 void Research :: settechlevel ( int techlevel )
00862 {
00863 if ( techlevel > 0 ) {
00864 for ( int j = 0; j < technologyRepository.getNum(); j++ ) {
00865 const Technology* tech = technologyRepository.getObject_byPos ( j );
00866 if ( tech )
00867 if ( tech->techlevel <= techlevel )
00868 if ( !techResearched ( tech->id ))
00869 addanytechnology ( tech );
00870 }
00871 }
00872 evalTechAdapter();
00873 }
00874
00875
00876 void Research :: cancel ()
00877 {
00878 progress = 0;
00879 activetechnology = NULL;
00880 goal = NULL;
00881 }
00882
00883
00884
00885
00886
00887 bool Research :: vehicletypeavailable ( const Vehicletype* fztyp ) const
00888 {
00889 if ( !fztyp )
00890 return false;
00891 else
00892 return fztyp->techDependency.available( *this );
00893
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 int Research :: getResearchPerTurn() const
00914 {
00915 int rppt = 0;
00916 for ( Player::BuildingList::const_iterator i = map->player[player].buildingList.begin(); i != map->player[player].buildingList.end(); i++ )
00917 rppt += (*i)->researchpoints;
00918
00919 for ( Player::VehicleList::const_iterator i = map->player[player].vehicleList.begin(); i != map->player[player].vehicleList.end(); i++ )
00920 rppt += (*i)->researchpoints;
00921
00922 return rppt * multiplier;
00923 }
00924
00925 int Research :: currentTechAvailableIn() const
00926 {
00927 if ( activetechnology ) {
00928 int rpt = getResearchPerTurn();
00929 if ( !rpt )
00930 return 0;
00931 else
00932 return ( activetechnology->researchpoints - progress + rpt - 1) / rpt;
00933 } else
00934 return -1;
00935 }
00936
00937
00938 Research::~Research () {};
00939
00940
00941
00942 Resources returnResourcenUseForResearch ( const ContainerBase* bld, int research )
00943 {
00944 Resources res;
00945 if ( bld->baseType->nominalresearchpoints == 0 )
00946 return res;
00947
00948 int num = 0;
00949
00950
00951
00952
00953
00954
00955 num = 1;
00956
00957
00958
00959 for ( int r = 0; r < 3; ++r )
00960 if ( bld->baseType->maxplus.resource(r) < 0 ) {
00961 if( research > bld->baseType->nominalresearchpoints ) {
00962 float a = -bld->baseType->maxplus.resource(r) / pow(double(bld->baseType->nominalresearchpoints),2);
00963 res.resource(r) = int( pow(pow(double(research),2) * a, 0.98 + double(num)/50) );
00964 } else
00965 res.resource(r) = -bld->baseType->maxplus.resource(r) * research / bld->baseType->nominalresearchpoints;
00966 }
00967
00968 return res;
00969 }
00970
00971 Resources returnResourcenUseForResearch ( const ContainerBase* bld )
00972 {
00973 return returnResourcenUseForResearch ( bld, bld->researchpoints );
00974 }
00975
00976
00977 #if 0
00978 void returnresourcenuseforresearch ( const Building* bld, int research, int* energy, int* material )
00979 {
00980
00981
00982
00983
00984
00985 double res = research;
00986 double deg = res / bld->typ->maxresearchpoints;
00987
00988 double m = 1 / log ( minresearchcost + maxresearchcost );
00989
00990 *energy = (int)(researchenergycost * research * ( exp ( deg / m ) - ( 1 - minresearchcost ) ) / 1000 * (researchcostdouble+res)/researchcostdouble);
00991 *material = (int)(researchmaterialcost * research * ( exp ( deg / m ) - ( 1 - minresearchcost ) ) / 1000 * (researchcostdouble+res)/researchcostdouble);
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 }
01003 #endif
01004
01005