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

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

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