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