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