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

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