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

buildingcapture.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           buildingcapture.cpp  -  description
00003                              -------------------
00004     begin                : Fri Mar 30 2001
00005     copyright            : (C) 2001 by Martin Bickel
00006     email                : bickel@asc-hq.org
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #include "ai_common.h"
00019 
00020 
00021 float AI :: getCaptureValue ( const Building* bld, Vehicle* veh  )
00022 {
00023    HiddenAStar ast ( this, veh );
00024    HiddenAStar::Path path;
00025    ast.findPath ( path, bld->getEntry().x, bld->getEntry().y );
00026    if ( ast.getTravelTime() >= 0 )
00027       // everything else being equal, prefer cheapest unit
00028       // TODO: factor 0.0001 should be made configurable
00029       return getCaptureValue ( bld, ast.getTravelTime() )-0.0001*veh->aiparam[getPlayerNum()]->getValue() ;
00030    else
00031       return -1;
00032       // return minfloat; // this makes no sense as minfloat>0!
00033 }
00034 
00035 
00036 void AI :: BuildingCapture :: write ( tnstream& stream ) const
00037 {
00038   stream.writeInt( 20 );
00039   stream.writeInt ( state );
00040   stream.writeInt ( unit );
00041   for ( vector<int>::const_iterator i = guards.begin(); i  != guards.end(); i++ ) {
00042      stream.writeInt ( 1 );
00043      stream.writeInt ( *i );
00044   }
00045   stream.writeInt ( 0 );
00046   stream.writeFloat ( captureValue );
00047   stream.writeInt ( nearestUnit );
00048 }
00049 
00050 void AI :: BuildingCapture :: read ( tnstream& stream )
00051 {
00052   stream.readInt(); // version
00053   state = BuildingCaptureState( stream.readInt ( ));
00054   unit = stream.readInt ( );
00055   int i = stream.readInt ();
00056   while ( i ) {
00057      guards.push_back ( stream.readInt() );
00058      i = stream.readInt();
00059   }
00060   captureValue = stream.readFloat ();
00061   nearestUnit = stream.readInt ();
00062 }
00063 
00064 
00065 
00066 class  SearchReconquerBuilding : public SearchFields {
00067                                 protected:
00068                                    AI& ai;
00069                                    Building* buildingToCapture;
00070                                    int mode;        // (1): nur fusstruppen; (2): 1 und transporter; (3): 2 und geb„ude
00071                                    vector<Vehicle*> enemyUnits; // that can conquer the building
00072                                    float getThreatValueOfUnit ( Vehicle* veh );
00073                                 public:
00074                                    void testfield ( const MapCoordinate& mc );
00075                                    bool returnresult ( );
00076                                    void unitfound ( Vehicle* eht );
00077                                    bool canUnitCapture ( Vehicle* veh );
00078                                    SearchReconquerBuilding ( AI& _ai, Building* bld ) : SearchFields ( _ai.getMap() ), ai ( _ai ), buildingToCapture ( bld ), mode(3) {};
00079                                 };
00080 
00081 bool SearchReconquerBuilding :: returnresult( )
00082 {
00083   return !enemyUnits.empty();
00084 }
00085 
00086 
00087 void         SearchReconquerBuilding :: unitfound(Vehicle*     eht)
00088 {
00089   enemyUnits.push_back ( eht );
00090   buildingToCapture->aiparam[ai.getPlayerNum()]->setAdditionalValue ( buildingToCapture->aiparam[ai.getPlayerNum()]->getValue() );
00091 }
00092 
00093 bool SearchReconquerBuilding :: canUnitCapture( Vehicle* eht )
00094 {
00095    return (eht->typ->hasFunction( ContainerBaseType::ConquerBuildings ) )
00096            && fieldAccessible ( buildingToCapture->getEntryField(), eht) == 2 ;
00097 
00098 }
00099 
00100 void         SearchReconquerBuilding :: testfield(const MapCoordinate& mc)
00101 {
00102       Vehicle* eht = gamemap->getField(mc)->vehicle;
00103       // Building* bld = getfield(xp,yp)->building;
00104       if ( eht )
00105          if ( ai.getPlayer().diplomacy.isHostile( eht->getOwner() ) )
00106             if ( canUnitCapture ( eht )) {
00107                VehicleMovement vm ( NULL );
00108                if ( vm.available ( eht )) {
00109                   vm.execute ( eht, -1, -1, 0 , -1, -1 );
00110                   if ( vm.reachableFields.isMember ( startPos ))
00111                      unitfound(eht);
00112                }
00113             }
00114             else
00115                if (mode >= 2)
00116                   if (eht->typ->maxLoadableUnits > 0)
00117                      for ( ContainerBase::Cargo::const_iterator i = eht->getCargo().begin(); i != eht->getCargo().end(); ++i )
00118                         if ( *i )
00119                            if ( canUnitCapture ( *i ))
00120                               if (eht->maxMovement() + (*i)->maxMovement() >= beeline(mc, startPos))
00121                                  unitfound(eht);
00122 
00123 
00124 /*
00125       if ( bld )
00126          if ( mode >= 3 )
00127             if (getdiplomaticstatus(bld->color) != capeace)
00128                for ( int w = 0; w <= 31; w++)
00129                   if ( bld->loading[w] )
00130                      if ( canUnitCapture ( bld->loading[w] ))
00131                         if ( bld->loading[w]->typ->movement[log2(bld->loading[w]->height)] <= beeline(xp,yp,startx,starty))
00132                            unitfound ( bld->loading[w] );
00133 
00134 */
00135 }
00136 
00137 
00138 float AI :: getCaptureValue ( const Building* bld, int traveltime  )
00139 {
00140    if ( traveltime < 0 )
00141       traveltime = 0;
00142    return float(bld->aiparam[getPlayerNum()]->getValue()) / float(traveltime+1);
00143 }
00144 
00145 
00146 bool AI :: checkReConquer ( Building* bld, Vehicle* veh )
00147 {
00148    SearchReconquerBuilding srb ( *this, bld );
00149    srb.initsearch ( bld->getEntry(), (maxTransportMove + maxUnitMove/2) / maxmalq + 1, 1 );
00150    srb.startsearch();
00151    bool enemyNear = srb.returnresult();
00152 
00153    if ( enemyNear && veh ) {
00154       float f = 0;
00155       for ( ContainerBase::Cargo::const_iterator i = bld->getCargo().begin(); i != bld->getCargo().end(); ++i )
00156          if ( *i )
00157             if ( (*i)->getMovement() )
00158                f += (*i)->aiparam[ getPlayerNum()]->getValue();
00159 
00161       if ( f > veh->aiparam[getPlayerNum()]->getValue())
00162          return false;
00163       else
00164          return true;
00165    }
00166    
00167    return false;
00168 }
00169 
00170 
00171 struct CaptureTriple {
00172   Building* bld;
00173   Vehicle* veh;
00174   float val;
00175 };
00176 
00177 typedef struct CaptureTriple* pCaptureTriple;
00178 
00179 typedef vector<pCaptureTriple> CaptureList;
00180 
00181 class CaptureTripleComp : public binary_function<pCaptureTriple,pCaptureTriple,bool> {
00182 public:
00183   explicit CaptureTripleComp() {};
00184   bool operator() (const pCaptureTriple t1, const pCaptureTriple t2) const {
00185     return t1->val > t2->val;
00186   }
00187 };
00188 
00189 void AI :: checkConquer( )
00190 {
00191    // remove all capture orders for buildings which are no longer controlled by the enemy
00192 
00193    for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); ) {
00194       BuildingCaptureContainer::iterator nxt = bi;
00195       ++nxt;
00196       Vehicle* veh= getMap()->getUnit ( bi->second.unit );
00197       Building* bld = getMap()->getField( bi->first )->building;
00198       if ( !bld ) {
00199          buildingCapture.erase ( bi );
00200          bi = nxt;
00201          continue;
00202       }
00203 
00204       if ( !getPlayer(bld->getOwner()).diplomacy.isHostile( getPlayerNum() ) 
00205            || !( veh && fieldAccessible ( getMap()->getField( bi->first ), veh ) == 2 )) {
00206 
00207          if ( veh ) {
00208             veh->aiparam[getPlayerNum()]->resetTask ();
00209             veh->aiparam[getPlayerNum()]->setNextJob();
00210          }
00211          buildingCapture.erase ( bi );
00212       } else
00213          if ( veh && veh->color != getPlayerNum()*8 )
00214             buildingCapture.erase ( bi );
00215 
00216       bi = nxt;
00217    }
00218 
00219    displaymessage2("check for capturing buildings ... ");
00220 
00221    // check for stagnation
00222    int num_reachable_buildings=0;
00223    for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); bi++ ) 
00224       if ( bi->second.state!=BuildingCapture::conq_unreachable ) num_reachable_buildings++;
00225    // if all blds are marked as unreachable, reevaluate in hope for a map-change
00226    if ( buildingCapture.size()>0 && num_reachable_buildings==0 ) {
00227       for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); bi++ ) 
00228         bi->second.state=BuildingCapture::conq_noUnit;
00229    }
00230    
00231    CaptureList captureList;
00232 
00233    int buildingCounter = 0;
00234 
00235    for ( int c = 0; c <= 8; c++ ) {
00236       if ( c<8 ) {
00237          if ( !getPlayer(c).exist() ) continue;
00238          if ( !getPlayer().diplomacy.isHostile( c)  ) continue;
00239       }
00240       for ( Player::BuildingList::iterator bi = getPlayer(c).buildingList.begin(); bi != getPlayer(c).buildingList.end(); bi++ ) {
00241          Building* bld = *bi;
00242          int reachable = 0;
00243          if ( buildingCapture[ bld->getEntry() ].state != BuildingCapture::conq_noUnit ) continue;
00244          bool enemyNear = checkReConquer ( bld, 0 );
00245 
00246          ++buildingCounter;
00247          displaymessage2("check for capturing building %d ", buildingCounter);
00248 
00249          for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); vi++ ) {
00250             Vehicle* veh = *vi;
00251             if ( !veh->canMove() ) continue;
00252             if ( fieldAccessible ( bld->getEntryField(), veh ) != 2 ) continue;
00253             if ( c!=8 && !(veh->typ->hasFunction( ContainerBaseType::ConquerBuildings  )) ) continue;
00254             if ( veh->aiparam[getPlayerNum()]->hasJob( AiParameter::job_conquer)  &&
00255                  veh->aiparam[getPlayerNum()]->getTask() != AiParameter::tsk_nothing ) continue;
00256 
00257             // here, units can be excluded from capturing
00258             if ( c!=8 ) {
00259                 if( !veh->aiparam[getPlayerNum()]->hasJob(AiParameter::job_conquer)  ) continue;
00260                 if( veh->aiparam[getPlayerNum()]->getTask() != AiParameter::tsk_nothing ) continue;
00261             }
00262 
00263             // any further factors should be incorporated into getCaptureValue
00264             float val=getCaptureValue( bld, veh );
00265 
00266             // malus if enemy is near (relevant if we are short of capture-units
00267             // or building is practically worthless)
00268             // TODO: should be made an optional parameter to getCaptureValue
00269             if ( val>0 && enemyNear ) val -= 0.1*veh->aiparam[getPlayerNum()]->getValue();
00270 
00271 
00272             if ( val > 0 ) {
00273                pCaptureTriple triple = new CaptureTriple;
00274                triple->bld=bld;
00275                triple->veh=veh;
00276                triple->val=val;
00277                captureList.push_back( triple );
00278                reachable = true;
00279             }
00280          }
00281          if ( reachable==0 )
00282             buildingCapture[ bld->getEntry() ].state = BuildingCapture::conq_unreachable;
00283       }
00284    }
00285 
00286    sort ( captureList.begin(), captureList.end(), CaptureTripleComp() );
00287 
00288    for ( CaptureList::iterator i = captureList.begin(); i != captureList.end(); i++ ) {
00289       Building* bld = (*i)->bld;
00290       Vehicle* veh = (*i)->veh;
00291       // float val = (*i)->val;
00292       delete (*i);
00293 
00294       // check whether bld and veh are still available
00295       if ( buildingCapture[ bld->getEntry() ].state != BuildingCapture::conq_noUnit ) continue;
00296       if ( veh->aiparam[getPlayerNum()]->getJob() == AiParameter::job_conquer &&
00297            veh->aiparam[getPlayerNum()]->getTask() != AiParameter::tsk_nothing ) continue;
00298 
00299       // dispatch capture order
00300       BuildingCapture& bc = buildingCapture[ bld->getEntry() ];
00301       if ( veh->typ->hasFunction( ContainerBaseType::ConquerBuildings  ))
00302          bc.state = BuildingCapture::conq_conqUnit;
00303       else
00304          bc.state = BuildingCapture::conq_unitNotConq;
00305       bc.unit = veh->networkid;
00306       
00307       veh->aiparam[getPlayerNum()]->setJob ( AiParameter::job_conquer );
00308       veh->aiparam[getPlayerNum()]->setTask ( AiParameter::tsk_move );
00309       veh->aiparam[getPlayerNum()]->dest.setnum( bld->getEntry().x, bld->getEntry().y, -1 );
00310    }
00311 
00312    // execute capture orders
00313    for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); ) {
00314       BuildingCaptureContainer::iterator nxt = bi;
00315       ++nxt;
00316       Vehicle* veh = getMap()->getUnit ( bi->second.unit );
00317       if ( veh ) {
00318          MapCoordinate3D dest = veh->aiparam[getPlayerNum()]->dest;
00319          int nwid = veh->networkid;
00320          moveUnit ( veh, dest, true );
00321          if ( getMap()->getUnit ( nwid ) && veh->getPosition() == dest ) {
00322             veh->aiparam[getPlayerNum()]->resetTask ();
00323             buildingCapture.erase ( bi );
00324          }
00325       } else
00326          buildingCapture.erase ( bi );
00327       checkKeys();
00328       bi = nxt;
00329    }
00330 
00331    // do something useful with units that are not used for capturing buildings
00332    for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); vi++ )
00333       if ( (*vi)->aiparam[getPlayerNum()]->getJob() == AiParameter::job_conquer &&
00334            (*vi)->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_nothing )
00335            (*vi)->aiparam[getPlayerNum()]->setNextJob();
00336 
00337 }
00338 
00339 

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