research.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           research.cpp  -  description
00003                              -------------------
00004     begin                : Tue Jan 23 2001
00005     copyright            : (C) 2001 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00013 /***************************************************************************
00014  *                                                                         *
00015  *   This program is free software; you can redistribute it and/or modify  *
00016  *   it under the terms of the GNU General Public License as published by  *
00017  *   the Free Software Foundation; either version 2 of the License, or     *
00018  *   (at your option) any later version.                                   *
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                // if ( requireAllListedTechnologies  )
00153                   stack.push_back ( k );
00154 
00155                int i = t->techDependency.findInheritanceLevel ( id, stack, sourceTechName );
00156 
00157                // if ( requireAllListedTechnologies )
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 //  s += "ID " + ASCString(strrr( tech->id)) + "; ";
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"; // arrowhead=inv
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(); // unitimprovement.weapons[i] =
00647       stream.readWord(); // unitimprovement.armor =
00648 
00649       for ( int j = 0; j < 44-researchableWeaponImprovements*2; j++ )
00650           stream.readChar(); // dummy
00651 
00652       stream.readInt(); // techlevel =
00653       stream.readInt(); // __loader_techsAvail =
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    } /* endwhile */
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             // this is a root technology
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 void Research::initchoosentechnology()
00881 {
00882    Player& player = map->player[map->actplayer];
00883    player.research.progress = 0;
00884 
00885    Player::DissectionContainer::iterator di = player.dissections.begin();
00886    while ( di != player.dissections.end() ) {
00887       if ( di->tech->id == player.research.activetechnology->id ) {
00888          player.research.progress += di->points;
00889          di = player.dissections.erase ( di );
00890       } else
00891          di++;
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    for ( Player::BuildingList::iterator i = bld->getMap()->player[bld->getOwner()].buildingList.begin(); i != bld->getMap()->player[bld->getOwner()].buildingList.end(); ++i )
00946       if ( (*i)->typ->special & cgresearchb)
00947          if ( (*i)->researchpoints > 0 )
00948             ++num;
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    double esteigung = 55;
00977    double msteigung = 40;
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    if ( bld->typ->maxresearchpoints > 0 ) {
00989       *material = researchmaterialcost * research *
00990       ( exp ( res / msteigung ) - 1 ) / ( exp ( (double)bld->typ->maxresearchpoints / (msteigung*2) ) - 1 ) * (10000+res)/10000 / 1000;
00991       *energy   = researchenergycost   * ( exp ( res / esteigung ) - 1 ) / ( exp ( (double)bld->typ->maxresearchpoints / (esteigung*2) ) - 1 ) * (10000+res)/10000 / 1000;
00992    } else {
00993       *material = 0;
00994       *energy = 0;
00995    }
00996   */
00997 }
00998 #endif
00999 
01000 

Generated on Mon May 21 01:26:36 2012 for Advanced Strategic Command by  doxygen 1.5.1