00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00028
00029 return getCaptureValue ( bld, ast.getTravelTime() )-0.0001*veh->aiparam[getPlayerNum()]->getValue() ;
00030 else
00031 return -1;
00032
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();
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;
00071 vector<Vehicle*> enemyUnits;
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
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
00126
00127
00128
00129
00130
00131
00132
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
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
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
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
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
00264 float val=getCaptureValue( bld, veh );
00265
00266
00267
00268
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
00292 delete (*i);
00293
00294
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
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
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
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