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

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 
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                // if ( requireAllListedTechnologies  )
00155                   stack.push_back ( k );
00156 
00157                int i = t->techDependency.findInheritanceLevel ( id, stack, sourceTechName );
00158 
00159                // if ( requireAllListedTechnologies )
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 //  s += "ID " + ASCString(strrr( tech->id)) + "; ";
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"; // arrowhead=inv
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(); // unitimprovement.weapons[i] =
00649       stream.readWord(); // unitimprovement.armor =
00650 
00651       for ( int j = 0; j < 44-researchableWeaponImprovements*2; j++ )
00652           stream.readChar(); // dummy
00653 
00654       stream.readInt(); // techlevel =
00655       stream.readInt(); // __loader_techsAvail =
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    } /* endwhile */
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             // this is a root technology
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       // return true; // vehicleclassavailable( fztyp, 0 );
00894 }
00895 
00896 /*
00897 void Research::initchoosentechnology()
00898 {
00899    Player& player = map->player[map->actplayer];
00900    player.research.progress = 0;
00901 
00902    Player::DissectionContainer::iterator di = player.dissections.begin();
00903    while ( di != player.dissections.end() ) {
00904       if ( di->tech->id == player.research.activetechnology->id ) {
00905          player.research.progress += di->points;
00906          di = player.dissections.erase ( di );
00907       } else
00908          di++;
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    for ( Player::BuildingList::iterator i = bld->getMap()->player[bld->getOwner()].buildingList.begin(); i != bld->getMap()->player[bld->getOwner()].buildingList.end(); ++i )
00951       if ( (*i)->typ->special & cgresearchb)
00952          if ( (*i)->researchpoints > 0 )
00953             ++num;
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    double esteigung = 55;
00982    double msteigung = 40;
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    if ( bld->typ->maxresearchpoints > 0 ) {
00994       *material = researchmaterialcost * research *
00995       ( exp ( res / msteigung ) - 1 ) / ( exp ( (double)bld->typ->maxresearchpoints / (msteigung*2) ) - 1 ) * (10000+res)/10000 / 1000;
00996       *energy   = researchenergycost   * ( exp ( res / esteigung ) - 1 ) / ( exp ( (double)bld->typ->maxresearchpoints / (esteigung*2) ) - 1 ) * (10000+res)/10000 / 1000;
00997    } else {
00998       *material = 0;
00999       *energy = 0;
01000    }
01001   */
01002 }
01003 #endif
01004 
01005 

Generated on Tue Jun 24 01:27:51 2008 for Advanced Strategic Command by  doxygen 1.4.2