buildings.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           buildings.cpp  -  description
00003                              -------------------
00004     begin                : Sat Feb 17 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 <algorithm>
00023 #include <cmath>
00024 
00025 #include "vehicletype.h"
00026 #include "buildingtype.h"
00027 #include "buildings.h"
00028 #include "viewcalculation.h"
00029 #include "errors.h"
00030 #include "spfst.h"
00031 #include "resourcenet.h"
00032 #include "itemrepository.h"
00033 #include "containercontrols.h"
00034 #include "misc.h"
00035 
00036 
00037 #ifndef BUILDINGVERSIONLIMIT
00038 # define BUILDINGVERSIONLIMIT -1000000000
00039 #endif
00040 
00041 
00042 const float repairEfficiencyBuilding[resourceTypeNum*resourceTypeNum] = { 1./3., 0,     1. / 3. ,
00043                                                                           0,     1./3., 0,
00044                                                                           0,     0,     0 };
00045 
00046 Building :: Building ( GameMap* actmap, const MapCoordinate& _entryPosition, const BuildingType* type, int player, bool setupImages, bool chainToField )
00047            : ContainerBase ( type, actmap, player ), typ ( type ), repairEfficiency ( repairEfficiencyBuilding )
00048 {
00049    
00050    viewOnMap = false;
00051          
00052    int i;
00053    for ( i = 0; i < 8; i++ )
00054       aiparam[i] = NULL;
00055 
00056    _completion = 0;
00057    connection = 0;
00058 
00059    lastmineddist= 0;
00060 
00061    for ( i = 0; i < waffenanzahl; i++ )
00062       ammo[i] = 0;
00063 
00064    netcontrol = 0;
00065 
00066    visible = 1;
00067    damage = 0;
00068 
00069    entryPosition = _entryPosition;
00070 
00071    gamemap->player[player].buildingList.push_back ( this );
00072 
00073    if ( chainToField )
00074       chainbuildingtofield ( entryPosition, setupImages );
00075 }
00076 
00077 
00078 int Building::repairableDamage() const
00079 {
00080    int d = getMap()->getgameparameter ( cgp_maxbuildingrepair ) - repairedThisTurn;
00081    if ( d < 0 )
00082       d = 0;
00083    if ( d > damage )
00084       d = damage;
00085    return d;
00086 }
00087 
00088 void Building::postRepair ( int oldDamage )
00089 {
00090    repairedThisTurn += oldDamage - damage;
00091 }
00092 
00093 bool Building::canRepair ( const ContainerBase* item ) const
00094 {
00095    return typ->hasFunction( ContainerBaseType::InternalUnitRepair  ) ||
00096          typ->hasFunction( ContainerBaseType::ExternalRepair  ) ||
00097          (item == this  ) ;
00098 }
00099 
00100 int Building::getIdentification() const
00101 {
00102    return -(getPosition().x + (getPosition().y << 16));
00103 }
00104 
00105 void Building :: convert ( int player, bool recursive )
00106 {
00107    if (player > 8)
00108       fatalError("convertbuilding: \n player must be in range 0..8 sein ");
00109 
00110    #ifdef sgmain
00111    if ( typ->hasFunction( ContainerBaseType::SelfDestructOnConquer  ) ) {
00112       delete this;
00113       return;
00114    }
00115 
00116 
00117    int oldnetcontrol = netcontrol;
00118    netcontrol = cnet_stopenergyinput + (cnet_stopenergyinput << 1) + (cnet_stopenergyinput << 2);
00119    Resources put = putResource( actstorage, false );
00120    actstorage -= put;
00121 
00122    netcontrol = oldnetcontrol;
00123 
00124    #endif
00125 
00126    int oldcol = getOwner();
00127 
00128    #ifdef sgmain
00129    if ( oldcol == 8 )
00130       for ( int r = 0; r < 3; r++ )
00131          if ( gamemap->isResourceGlobal( r )) {
00132             gamemap->bi_resource[player].resource(r) += actstorage.resource(r);
00133             actstorage.resource(r) = 0;
00134          }
00135 
00136    #endif
00137    bool hadViewOnMap = viewOnMap;
00138    if ( color < 8*8  && hadViewOnMap)
00139       removeview();
00140 
00141    Player::BuildingList::iterator i = find ( gamemap->player[oldcol].buildingList.begin(), gamemap->player[oldcol].buildingList.end(), this );
00142    if ( i != gamemap->player[oldcol].buildingList.end())
00143       gamemap->player[oldcol].buildingList.erase ( i );
00144 
00145    gamemap->player[player].buildingList.push_back( this );
00146 
00147    color = player * 8;
00148 
00149    if ( hadViewOnMap && player < 8 )
00150       addview();
00151 
00152    if ( recursive )
00153       for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
00154          if ( *i ) 
00155             (*i)->convert( player );
00156 
00157    conquered();
00158    anyContainerConquered(this);
00159 }
00160 
00161 
00162 void Building :: registerForNewOwner( int player )
00163 {
00164    int oldcol = getOwner();
00165    
00166    if ( oldcol < 8 )
00167       removeview();
00168    
00169    Player::BuildingList::iterator i = find ( gamemap->player[oldcol].buildingList.begin(), gamemap->player[oldcol].buildingList.end(), this );
00170    if ( i != gamemap->player[oldcol].buildingList.end())
00171       gamemap->player[oldcol].buildingList.erase ( i );
00172 
00173    gamemap->player[player].buildingList.push_back( this );
00174    
00175    color = player * 8;
00176   
00177    if ( player < 8 )
00178       addview();
00179    
00180    conquered();
00181    anyContainerConquered(this);
00182    
00183 }
00184 
00185   
00186 
00187 
00188 const Surface& Building :: getPicture ( const BuildingType::LocalCoordinate& localCoordinate ) const
00189 {
00190    static Surface emptySurface;
00191    MapField* fld = getField ( localCoordinate );
00192    if ( fld ) {
00193       return typ->getPicture(localCoordinate, fld->getWeather(), _completion);
00194    } else
00195       return emptySurface;
00196 }
00197 
00198 void Building::paintSingleField ( Surface& s, SPoint imgpos, BuildingType::LocalCoordinate pos ) const
00199 {
00200    if ( getHeight() <= chfahrend )
00201       paintField( getPicture( pos ), s, imgpos, 0, false, 0 );
00202    else
00203       paintField( getPicture( pos ), s, imgpos, 0, false );
00204 }
00205 
00206 
00207 
00208 // fucking namespace pollution, we are defining our own...
00209 
00210 template<typename T>
00211 T ASC_min ( T a, T b )
00212 {
00213    if ( a > b )
00214       return b;
00215    else
00216       return a;
00217 }
00218 template<typename T>
00219 T ASC_max ( T a, T b )
00220 {
00221    if ( a > b )
00222       return a;
00223    else
00224       return b;
00225 }
00226 
00227 
00228 
00229 Surface Building::getImage() const
00230 {
00231    int minx = maxint;
00232    int maxx = 0;
00233    int maxy = 0;
00234    int miny = maxint;
00235 
00236    for ( int x = 0; x < 4; x++ )
00237       for ( int y = 0; y < 6; y++ ) 
00238          if ( typ->fieldExists(BuildingType::LocalCoordinate(x,y) )) {
00239             SPoint pos ( x * fielddistx + ( y & 1 ) * fielddisthalfx, y * fielddisty);
00240             minx = ASC_min( minx, int(pos.x) );
00241             maxx = ASC_max( maxx, int(pos.x) + fieldsizex );
00242             miny = ASC_min ( miny, int(pos.y) );
00243             maxy = ASC_max ( maxy, int(pos.y) + fieldsizey );
00244          }
00245 
00246    Surface s = Surface::createSurface(maxx-minx+1,maxy-miny+1, 32,Surface::transparent << 24 );
00247 
00248    typ->paint ( s, SPoint(-minx,-miny), getOwningPlayer().getPlayerColor() ); 
00249    return s;
00250 }
00251 
00252 #ifndef sgmain
00253 void Building :: execnetcontrol ( void ) {}
00254 int Building :: putResource ( int amount, int resourcetype, bool queryonly, int scope, int player ) { return 0; };
00255 int Building :: getResource ( int amount, int resourcetype, bool queryonly, int scope, int player ) { return actstorage.resource(resourcetype); };
00256 int Building :: getAvailableResource ( int amount, int resourcetype, int scope ) const { return actstorage.resource(resourcetype); };
00257 #endif
00258 
00259 void Building :: setCompletion ( int completion, bool setupImages )
00260 {
00261   _completion = completion;
00262 }
00263 
00264 
00265 
00266 
00267 
00268 int  Building :: chainbuildingtofield ( const MapCoordinate& entryPos, bool setupImages )
00269 {
00270    MapCoordinate oldpos = entryPosition;
00271    entryPosition = entryPos;
00272 
00273    for ( int a = 0; a < 4; a++)
00274       for ( int b = 0; b < 6; b++)
00275          if ( typ->fieldExists ( BuildingType::LocalCoordinate( a, b) )) {
00276             MapField* f = getField( BuildingType::LocalCoordinate( a, b) );
00277             if ( !f || f->building ) {
00278                entryPosition = oldpos;
00279                return 1;
00280             }
00281          }
00282 
00283    for ( int a = 0; a < 4; a++)
00284       for ( int b = 0; b < 6; b++)
00285          if ( typ->fieldExists ( BuildingType::LocalCoordinate( a , b ) )) {
00286             MapField* field = getField( BuildingType::LocalCoordinate( a, b) );
00287 
00288             if ( visible ) {
00289                MapField::ObjectContainer::iterator i = field->objects.begin();
00290                while ( i != field->objects.end()) {
00291                   if ( !i->typ->canExistBeneathBuildings )
00292                      i = field->objects.erase ( i );
00293                   else
00294                      i++;
00295                };
00296             }
00297 
00298             if ( field->vehicle && (field->vehicle->height < chtieffliegend )) {
00299                delete field->vehicle;
00300                field->vehicle = NULL;
00301             }
00302 
00303             field->building = this;
00304          }
00305 
00306    for ( Cargo::iterator i = cargo.begin(); i != cargo.end(); ++i )
00307       if ( *i ) 
00308          (*i)->setnewposition ( entryPos.x, entryPos.y );
00309 
00310    MapField* field = getField( typ->entry );
00311    if ( field )
00312       field->bdt |= getTerrainBitType(cbbuildingentry) ;
00313 
00314    if ( setupImages ) 
00315       gamemap->calculateAllObjects();
00316 
00317       
00318    for ( int a = 0; a < 4; a++)
00319       for ( int b = 0; b < 6; b++) 
00320          if ( typ->fieldExists(BuildingType::LocalCoordinate(a,b))) {
00321             MapCoordinate p = getFieldCoordinates( BuildingType::LocalCoordinate(a,b));
00322             BuildingType::LocalCoordinate lc = getLocalCoordinate(p);
00323             if ( lc.x != a || lc.y!= b )
00324                warningMessage( "bug in building coordinate calculation");
00325          }
00326          
00327 
00328    return 0;
00329 }
00330 
00331 
00332 int  Building :: unchainbuildingfromfield ( void )
00333 {
00334    int set = 0;
00335    for (int i = 0; i <= 3; i++)
00336       for (int j = 0; j <= 5; j++)
00337          if ( typ->fieldExists ( BuildingType::LocalCoordinate(i,j) ) ) {
00338             MapField* fld = getField( BuildingType::LocalCoordinate(i,j) );
00339             if ( fld && fld->building == this ) {
00340                set = 1;
00341                fld->building = NULL;
00342 
00343                TerrainBits t = getTerrainBitType(cbbuildingentry);
00344                t.flip();
00345                fld->bdt &= t;
00346             }
00347          }
00348 
00349    return set;
00350 }
00351 
00352 
00353 void Building :: addview ( void )
00354 {
00355    if ( viewOnMap )
00356       fatalError ("void Building :: addview - the building is already viewing the map");
00357 
00358    viewOnMap = true;
00359    
00360    tcomputebuildingview bes ( gamemap );
00361    bes.init( this, +1 );
00362    bes.startsearch();
00363 }
00364 
00365 void Building :: resetview()
00366 {
00367    viewOnMap = false;  
00368 }
00369 
00370 
00371 void Building :: removeview ( void )
00372 {
00373    if ( color != 64 ) {
00374       if ( !viewOnMap )
00375          fatalError ("void Building :: removeview - the building is not viewing the map");
00376       
00377       tcomputebuildingview bes ( gamemap );
00378       bes.init( this, -1 );
00379       bes.startsearch();
00380       
00381       viewOnMap = false;
00382    }
00383 }
00384 
00385 MapCoordinate3D Building::getPosition3D() const 
00386 {
00387    MapCoordinate3D e = getEntry();
00388    MapCoordinate3D p3;
00389    p3.setnum ( e.x, e.y, -1 );
00390    return p3;
00391 }
00392 
00393 int Building :: getArmor ( ) const
00394 {
00395    return typ->_armor * gamemap->getgameparameter( cgp_buildingarmor ) / 100;
00396 }
00397 
00398 
00399 MapField*        Building :: getField( const BuildingType::LocalCoordinate& lc ) const
00400 {
00401   return gamemap->getField ( getFieldCoordinates ( lc ));
00402 }
00403 
00404 
00405 MapField*        Building :: getEntryField( ) const
00406 {
00407   return getField ( typ->entry );
00408 }
00409 
00410 MapCoordinate3D Building :: getEntry( ) const
00411 {
00412   return MapCoordinate3D( entryPosition, typ->height);
00413 }
00414 
00415 
00416 
00417 MapCoordinate Building :: getFieldCoordinates ( const BuildingType::LocalCoordinate& lc ) const
00418 {
00419   return typ->getFieldCoordinate ( entryPosition, lc );
00420 }
00421 
00422 
00423 BuildingType::LocalCoordinate Building::getLocalCoordinate( const MapCoordinate& field ) const
00424 {
00425   return typ->getLocalCoordinate( entryPosition, field );
00426 }
00427 
00428 
00429 Building :: ~Building ()
00430 {
00431    if ( gamemap ) {
00432       int c = color/8;
00433 
00434       Player::BuildingList::iterator i = find ( gamemap->player[c].buildingList.begin(), gamemap->player[c].buildingList.end(), this );
00435       if ( i != gamemap->player[c].buildingList.end() )
00436          gamemap->player[c].buildingList.erase ( i );
00437    }
00438 
00439    for ( int i = 0; i < 8; ++i ) {
00440       delete aiparam[ i ] ;
00441       aiparam[ i ] = NULL;
00442    }
00443 
00444    unchainbuildingfromfield();
00445 }
00446 
00447 
00448 const int buildingstreamversion = -7;
00449 
00450 
00451 void Building :: write ( tnstream& stream, bool includeLoadedUnits ) const
00452 {
00453     stream.writeInt ( max( buildingstreamversion, BUILDINGVERSIONLIMIT ));
00454 
00455     stream.writeInt ( typ->id );
00456     int i;
00457     for ( i = 0; i< resourceTypeNum; i++ )
00458        stream.writeInt ( bi_resourceplus.resource(i) );
00459     stream.writeChar ( color );
00460     stream.writeWord ( getEntry().x );
00461     stream.writeWord ( getEntry().y );
00462     stream.writeChar ( getCompletion() );
00463     for ( i = 0; i < waffenanzahl; i++ )
00464        stream.writeWord ( 0 ); // was: ammoautoproduction
00465 
00466     for ( i = 0; i< resourceTypeNum; i++ )
00467        stream.writeInt ( plus.resource(i) );
00468 
00469     for ( i = 0; i< resourceTypeNum; i++ )
00470        stream.writeInt ( maxplus.resource(i) );
00471 
00472     for ( i = 0; i< resourceTypeNum; i++ )
00473        stream.writeInt ( actstorage.resource(i) );
00474 
00475     for ( i = 0; i< waffenanzahl; i++ )
00476        stream.writeWord ( ammo[i] );
00477 
00478     stream.writeWord ( maxresearchpoints );
00479     stream.writeWord ( researchpoints );
00480     stream.writeChar ( visible );
00481     stream.writeChar ( damage );
00482     stream.writeInt  ( netcontrol );
00483     stream.writeString ( name );
00484 
00485     stream.writeInt ( repairedThisTurn );
00486 
00487     int c = 0;
00488 
00489     if ( includeLoadedUnits )
00490        for ( Cargo::const_iterator i = cargo.begin(); i != cargo.end(); ++i )
00491           if ( *i ) 
00492              ++c;
00493 
00494     if ( BUILDINGVERSIONLIMIT >= -3 )
00495        stream.writeChar( c );
00496     else
00497        stream.writeInt ( c );
00498 
00499     if ( c )
00500        for ( Cargo::const_iterator i = cargo.begin(); i != cargo.end(); ++i )
00501           if ( *i ) 
00502              (*i)->write ( stream );
00503 
00504 
00505     if ( BUILDINGVERSIONLIMIT >= -4 )
00506        stream.writeChar( internalUnitProduction.size() );
00507     else
00508        stream.writeInt( internalUnitProduction.size() );
00509 
00510     for (int k = 0; k < internalUnitProduction.size(); k++ ) {
00511        assert( internalUnitProduction[k] );
00512        stream.writeInt( internalUnitProduction[k]->id );
00513     }   
00514 
00515     if ( BUILDINGVERSIONLIMIT >= -3 )
00516        stream.writeChar(0);
00517 
00518     stream.writeInt( view );
00519     stream.writeString( privateName );
00520 }
00521 
00522 
00523 Building* Building::newFromStream ( GameMap* gamemap, tnstream& stream, bool chainToField )
00524 {
00525     int version = stream.readInt();
00526     int xpos, ypos, color;
00527     Resources res;
00528 
00529     BuildingType* typ;
00530 
00531     if ( version < buildingstreamversion )
00532        throw tinvalidversion( stream.getDeviceName(), buildingstreamversion, version );
00533 
00534     if ( version >= buildingstreamversion && version <= -1 ) {
00535 
00536        int id = stream.readInt ();
00537        typ = gamemap->getbuildingtype_byid ( id );
00538        if ( !typ )
00539           throw InvalidID ( "building", id );
00540 
00541        for ( int i = 0; i < 3; i++ )
00542           res.resource(i) = stream.readInt();
00543 
00544        color = stream.readChar();
00545        xpos = stream.readWord() ;
00546     } else {
00547        int id = version;
00548 
00549        typ = gamemap->getbuildingtype_byid ( id );
00550        if ( !typ )
00551           throw InvalidID ( "building", id );
00552 
00553        color = stream.readChar();
00554        xpos  = stream.readWord();
00555     }
00556 
00557     ypos = stream.readWord();
00558 
00559     Building* bld = new Building ( gamemap, MapCoordinate(xpos,ypos), typ, color/8, false, chainToField );
00560     bld->bi_resourceplus = res;
00561     bld->readData ( stream, version );
00562     return bld;
00563 }
00564 
00565 
00566 
00567 void Building:: read ( tnstream& stream )
00568 {
00569     int version = stream.readInt();
00570 
00571     if ( version >= buildingstreamversion && version <= -1 ) {
00572        stream.readInt (); // id
00573        for ( int i = 0; i < 3; i++ )
00574           bi_resourceplus.resource(i) = stream.readInt();
00575 
00576        stream.readChar(); // color
00577        stream.readWord(); // xpos
00578        stream.readWord(); // ypos
00579     } else {
00580        // int id = version;
00581        stream.readChar(); // color
00582        stream.readWord(); // xpos
00583        stream.readWord(); // ypos
00584        bi_resourceplus = Resources ( 0, 0, 0);
00585     }
00586 
00587     readData ( stream, version );
00588 }
00589 
00590 
00591 void Building :: readData ( tnstream& stream, int version )
00592 {
00593     setCompletion ( stream.readChar(), false );
00594 
00595     int i;
00596     for ( i = 0; i < waffenanzahl; i++)
00597        stream.readWord(); // was : ammoautoproduction
00598 
00599     for ( i = 0; i< 3; i++ )
00600        plus.resource(i) = stream.readInt();
00601 
00602     for ( i = 0; i< 3; i++ )
00603        maxplus.resource(i) = stream.readInt();
00604 
00605 
00606     for ( i = 0; i< 3; i++ )
00607        actstorage.resource(i) = min(stream.readInt(), getStorageCapacity().resource(i) );
00608 
00609     for ( i = 0; i < waffenanzahl; i++)
00610        ammo[i] = stream.readWord();
00611 
00612     maxresearchpoints = stream.readWord();
00613     researchpoints = stream.readWord();
00614 
00615     if ( (researchpoints < typ->maxresearchpoints  &&  !typ->hasFunction(ContainerBaseType::Research)) || (researchpoints > typ->maxresearchpoints))
00616        researchpoints = typ->maxresearchpoints;
00617 
00618 
00619     visible = stream.readChar();
00620     damage = stream.readChar();
00621     
00622     netcontrol = stream.readInt();
00623     netcontrol = 0;
00624     
00625     name = stream.readString ();
00626 
00627     if ( version <= -2 )
00628        repairedThisTurn = stream.readInt ( );
00629     else
00630        repairedThisTurn = 0;
00631 
00632     int c;
00633     if ( version <= -4 )
00634        c = stream.readInt();
00635     else
00636        c = stream.readChar();
00637        
00638     if ( c ) {
00639        for ( int k = 0; k < c; k++) {
00640           Vehicle* v = Vehicle::newFromStream ( gamemap, stream );
00641           v->setnewposition ( getEntry().x, getEntry().y );
00642           addToCargo(v);
00643 
00644           if ( v && v->reactionfire.getStatus() != Vehicle::ReactionFire::off && !v->baseType->hasFunction( ContainerBaseType::MoveWithReactionFire ))
00645              v->reactionfire.disable();
00646 
00647        }
00648     }
00649 
00650     
00651     internalUnitProduction.clear();
00652     if ( version <= -5 )
00653        c = stream.readInt();
00654     else
00655        c = stream.readChar();
00656     
00657     if ( c ) {
00658        for ( int k = 0; k < c ; k++) {
00659 
00660            int id;
00661            if ( version <= -3 )
00662               id = stream.readInt();
00663            else
00664               id = stream.readWord();
00665 
00666            internalUnitProduction.push_back ( gamemap->getvehicletype_byid ( id ) );
00667            if ( !internalUnitProduction[k] )
00668               throw InvalidID ( "unit", id );
00669        }
00670     }
00671 
00672     if ( version >= -3 ) {
00673          c = stream.readChar();
00674          if ( c ) {
00675             for ( int k = 0; k < c ; k++) {
00676                if ( version <= -3 )
00677                   stream.readInt();
00678                else
00679                   stream.readWord();
00680             }
00681          }
00682     }    
00683 
00684     for ( i = 0; i< 3; i++ ) {
00685        if ( typ->maxplus.resource(i) > 0 ) {
00686           if ( plus.resource(i) > typ->maxplus.resource(i) )
00687             plus.resource(i) = typ->maxplus.resource(i);
00688 
00689           if ( maxplus.resource(i) > typ->maxplus.resource(i) )
00690             maxplus.resource(i) = typ->maxplus.resource(i);
00691        } else {
00692           if ( plus.resource(i) < typ->maxplus.resource(i) )
00693             plus.resource(i) = typ->maxplus.resource(i);
00694 
00695           if ( maxplus.resource(i) < typ->maxplus.resource(i) )
00696             maxplus.resource(i) = typ->maxplus.resource(i);
00697        }
00698     }
00699     
00700     if ( version <= -6 )
00701        view = stream.readInt();
00702     else
00703        view = typ->view;
00704     
00705     if ( version <= -7 )
00706        privateName = stream.readString();
00707     else
00708        privateName = "";
00709 }
00710 
00711 ASCString Building::getName ( ) const
00712 {
00713    if ( name.empty())
00714       return typ->name;
00715    else
00716       return name;
00717 }
00718 
00719 int Building::getAmmo( int type, int num, bool queryOnly ) 
00720 {
00721    assert( type >= 0 && type < waffenanzahl );
00722    int got = min( ammo[type], num );
00723    if ( !queryOnly ) {
00724       ammo[type] -= got;
00725       // ammoChanged();
00726    }
00727    return got;
00728 }
00729 
00730 int Building::getAmmo( int type, int num ) const
00731 {
00732    assert( type >= 0 && type < waffenanzahl );
00733    return min( ammo[type], num );
00734 }
00735 
00736 
00737 int Building::putAmmo( int type, int num, bool queryOnly ) 
00738 {
00739    assert( type >= 0 && type < waffenanzahl );
00740    if ( !queryOnly ) {
00741       ammo[type] += num;
00742       // ammoChanged();
00743    }
00744    return num;
00745 }
00746 
00747 
00748 
00749 
00750 void Building::endRound(  )
00751 {
00752    ContainerBase::endRound();
00753    repairedThisTurn = 0;
00754 }
00755 
00756 
00757 vector<MapCoordinate> Building::getCoveredFields()
00758 {
00759    vector<MapCoordinate> fields;
00760    for ( int x = 0; x < 4; x++ )
00761       for ( int y = 0; y < 6; y++)
00762          if ( typ->fieldExists ( BuildingType::LocalCoordinate(x, y) ) )
00763             fields.push_back ( getFieldCoordinates( BuildingType::LocalCoordinate(x, y)));
00764    return fields;
00765 }
00766 
00767 
00768 int Building::getMemoryFootprint() const
00769 {
00770    return sizeof(*this);
00771 }
00772 
00773 
00774 
00775 /*
00776 void Building :: getresourceusage ( Resources* usage )
00777 {
00778    returnresourcenuseforpowerplant ( this, 100, usage, 0 );
00779    if ( typ->special & cgresearchb ) {
00780       int material;
00781       int energy;
00782       returnresourcenuseforresearch ( this, researchpoints, &energy, &material );
00783       usage->material += material;
00784       usage->energy   += energy;
00785       usage->fuel  = 0;
00786    }
00787 }
00788 */
00789 
00790 
00791 
00792    struct  ResearchEfficiency {
00793                float eff;
00794                Building*  bld;
00795                bool operator<( const ResearchEfficiency& re) const { return eff > re.eff; };
00796            };
00797 
00798 
00799 void doresearch ( GameMap* actmap, int player )
00800 {
00801    Research& research = actmap->getPlayer(player).research;
00802    
00803    if ( research.activetechnology == NULL && research.progress ) {
00804       // we don't accumulate research if there is not technology to research
00805       // this is to prevent player from accumulating lots of unused research points and then
00806       // developing several technologies at once  
00807       return;
00808    }
00809    
00810    
00811    typedef vector<ResearchEfficiency> VRE;
00812    VRE vre;
00813 
00814    for ( Player::BuildingList::iterator bi = actmap->player[player].buildingList.begin(); bi != actmap->player[player].buildingList.end(); bi++ ) {
00815       Building* bld = *bi;
00816       if ( bld->typ->hasFunction( ContainerBaseType::Research  ) ) {
00817          Resources res = returnResourcenUseForResearch ( bld, bld->researchpoints );
00818 
00819          int m = max ( res.energy, max ( res.material, res.fuel));
00820 
00821          ResearchEfficiency re;
00822          if ( m )
00823             re.eff = float(bld->researchpoints) / float(m);
00824          else
00825             re.eff = maxint;
00826 
00827          re.bld = bld;
00828 
00829          vre.push_back(re);
00830       } else
00831          if ( bld->researchpoints > 0 )
00832             research.progress += bld->researchpoints *  research.getMultiplier();
00833    }
00834    sort( vre.begin(), vre.end());
00835 
00836    for ( VRE::iterator i = vre.begin(); i != vre.end(); ++i ) {
00837       Building* bld = i->bld;
00838       Resources r = returnResourcenUseForResearch ( bld, bld->researchpoints );
00839       Resources got = bld->getResource ( r, true, 1, player );
00840 
00841       int res = bld->researchpoints;
00842       if ( got < r ) {
00843          int diff = bld->researchpoints / 2;
00844          while ( got < r || diff > 1) {
00845             if ( got < r  )
00846                res -= diff;
00847             else
00848                res += diff;
00849 
00850             if ( res < 0 )
00851                res = 0;
00852 
00853             if ( diff > 1 )
00854                diff /=2;
00855             else
00856                diff = 1;
00857 
00858             r = returnResourcenUseForResearch ( bld, res );
00859          }
00860 
00861          /*
00862          res = returnResourcenUseForResearch ( bld, res+1 );
00863 
00864          if ( ena >= energy  &&  maa >= material )
00865             res++;
00866          else
00867             returnresourcenuseforresearch ( bld, res, &energy, &material );
00868          */
00869 
00870       }
00871 
00872       got = bld->getResource ( r, false, 1, player );
00873 
00874       if ( got < r )
00875          fatalError( "controls : doresearch : inconsistency in getting energy or material for building" );
00876 
00877       research.progress += res * research.getMultiplier();
00878    }
00879 }
00880 
00881 ASCString getBuildingReference ( Building* bld )
00882 {
00883    ASCString s = "The building " + bld->getName();
00884    s += " (position: "+ bld->getPosition().toString() + ") ";
00885    return s;
00886 }
00887 

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