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

service.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           service.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 
00022 AI :: ServiceOrder :: ServiceOrder ( AI* _ai, VehicleService::Service _requiredService, int UnitID, int _pos )
00023 {
00024    active = false;
00025    failure = 0;
00026    ai = _ai;
00027    targetUnitID = UnitID;
00028    requiredService = _requiredService;
00029    serviceUnitID = 0;
00030    position = _pos;
00031    time = ai->getMap()->time;
00032 
00033    nextServiceBuilding = NULL;
00034    if ( ai->getMap()->getUnit ( UnitID )->canMove()) {
00035       MapCoordinate3D sb = ai->findServiceBuilding ( *this, &nextServiceBuildingDistance );
00036       if ( sb.valid() )
00037          nextServiceBuilding = ai->getMap()->getField( sb )->building;
00038    }
00039 }
00040 
00041 AI :: ServiceOrder :: ServiceOrder ( AI* _ai, tnstream& stream )
00042 {
00043   active = false;
00044   failure = 0;
00045   ai = _ai;
00046   read ( stream );
00047 }
00048 
00049 void AI :: ServiceOrder :: activate( ServiceOrder& so )
00050 {
00051    so.active = true;
00052 }
00053 
00054 
00055 const int currentServiceOrderVersion = 10002;
00056 
00057 void AI :: ServiceOrder :: read ( tnstream& stream )
00058 {
00059   int version = stream.readInt( );
00060   if ( version > currentServiceOrderVersion )
00061      throw tinvalidversion ( "AI :: ServiceOrder", currentServiceOrderVersion, version );
00062   targetUnitID = stream.readInt (  );
00063   serviceUnitID = stream.readInt (  );
00064   position = stream.readInt (  );
00065   time.abstime = stream.readInt (  );
00066   if ( version >= 10001 ) {
00067      int i= stream.readInt();
00068      if ( i )  {
00069         MapCoordinate3D mc;
00070         mc.read ( stream );
00071         nextServiceBuilding = ai->getMap()->getField( mc )->building;
00072         nextServiceBuildingDistance = stream.readInt();
00073      } else
00074         nextServiceBuilding = NULL;
00075 
00076      if ( version >= 10002 )
00077         requiredService = VehicleService::Service( stream.readInt() );
00078   }
00079 }
00080 
00081 void AI :: ServiceOrder :: write ( tnstream& stream ) const
00082 {
00083   stream.writeInt( currentServiceOrderVersion );
00084   stream.writeInt ( targetUnitID );
00085   stream.writeInt ( serviceUnitID );
00086   stream.writeInt ( position );
00087   stream.writeInt ( time.abstime );
00088   if ( nextServiceBuilding ) {
00089      stream.writeInt ( 1 );
00090      nextServiceBuilding->getEntry().write ( stream );
00091      stream.writeInt ( nextServiceBuildingDistance );
00092   } else {
00093      stream.writeInt ( 0 );
00094   }
00095   stream.writeInt ( requiredService );
00096 }
00097 
00098 bool AI :: ServiceOrder :: completelyFailed ()
00099 {
00100   return failure > 2 ;
00101 }
00102 
00103 
00104 int AI::ServiceOrder::possible ( Vehicle* supplier )
00105 {
00106    if ( !ai->getMap()->getField( getTargetUnit()->getPosition())->unitHere ( getTargetUnit() ))
00107      return 0;
00108    bool result = false;
00109 
00110    VehicleService vs ( NULL, NULL);
00111    vs.fieldSearch.bypassChecks.distance = true;
00112    vs.fieldSearch.bypassChecks.height   = true;
00113    vs.fieldSearch.init ( supplier, NULL );
00114    vs.fieldSearch.checkVehicle2Vehicle ( getTargetUnit(), getTargetUnit()->xpos, getTargetUnit()->ypos );
00115 
00116    VehicleService::TargetContainer::iterator i = vs.dest.find ( targetUnitID );
00117    if ( i != vs.dest.end() ) {
00118       VehicleService::Target target = i->second;
00119       int serviceAmount = 0;
00120       for ( unsigned int j = 0; j < target.service.size(); j++ ) {
00121          serviceAmount += target.service[j].maxPercentage;
00122          if ( target.service[j].type == requiredService ) {
00123             bool enoughResources = false;
00124             if ( requiredService == VehicleService::srv_repair ) {
00125                 if ( target.service[j].minAmount <  target.service[j].curAmount - 5 )
00126                   enoughResources = true;
00127             } else
00128                if ( target.service[j].targetPos == position ) {  // is this stuff the one we need
00129                   int requiredAmount = target.service[j].maxAmount - target.service[j].curAmount;
00130                   if ( requiredAmount >= 0 ) {
00131                      if ( requiredService == VehicleService::srv_resource ) {
00132                         if ( target.service[j].targetPos == Resources::Fuel ) { // fuel  ; 30 fields requiredForHome
00133                             if ( requiredAmount < target.service[j].orgSourceAmount - supplier->typ->fuelConsumption * 30 )
00134                                enoughResources = true;
00135                         } else {
00136                             if ( getTargetUnit()->aiparam[ai->getPlayerNum()]->getJob() == AiParameter::job_supply ) {
00137                                if ( target.service[j].orgSourceAmount > requiredAmount )
00138                                   enoughResources = true;
00139                             } else
00140                                if ( target.service[j].maxPercentage > 80 )
00141                                   enoughResources = true;
00142                         }
00143                      }
00144                      if ( requiredService == VehicleService::srv_ammo ) {
00145                         if ( getTargetUnit()->aiparam[ai->getPlayerNum()]->getJob() == AiParameter::job_supply ) {
00146                            if ( target.service[j].orgSourceAmount > requiredAmount )
00147                               enoughResources = true;
00148                         } else
00149                            if ( target.service[j].maxPercentage > 80 )
00150                               enoughResources = true;
00151                      }
00152                   }
00153                }
00154 
00155             if ( enoughResources )
00156                result = true;
00157 
00158          }
00159       }
00160 
00161       if( result )
00162          return serviceAmount;
00163    }
00164    return 0;
00165 }
00166 
00167 
00168 bool AI::ServiceOrder::execute1st ( Vehicle* supplier )
00169 {
00170    Vehicle* targ = getTargetUnit();
00171    MapCoordinate3D meet;
00172 
00173    vector<MapCoordinate3D> dest;
00174    for ( int h = 0; h < 8; h++ ) {
00175       if ( supplier->typ->height & ( 1<<h)) {
00176          for ( int i = 0; i < sidenum; i++ ) {
00177              int x = targ->xpos;
00178              int y = targ->ypos;
00179              getnextfield ( x, y, i );
00180              tfield* fld = getfield ( x, y );
00181              if ( fld && fieldAccessible ( fld, supplier, 1<<h ) == 2 && !fld->building && !fld->vehicle ) {
00182                 bool result = false;
00183                 TemporaryContainerStorage tus ( supplier );
00184                 supplier->xpos = x;
00185                 supplier->ypos = y;
00186                 supplier->height = 1 << h;
00187 
00188                 VehicleService vs ( NULL, NULL);
00189                 vs.fieldSearch.init ( supplier, NULL );
00190                 vs.fieldSearch.checkVehicle2Vehicle ( targ, targ->xpos, targ->ypos );
00191 
00192                 VehicleService::TargetContainer::iterator i = vs.dest.find ( targetUnitID );
00193                 if ( i != vs.dest.end() ) {
00194                    VehicleService::Target target = i->second;
00195                    for ( unsigned int j = 0; j < target.service.size(); j++ )
00196                       if ( target.service[j].type == requiredService )
00197                          result = true;
00198                 }
00199 
00200                 tus.restore();
00201 
00202                 if ( result )
00203                    dest.push_back ( MapCoordinate3D(x, y, 1<<h ));
00204              }
00205          }
00206       }
00207    }
00208 
00209    if ( !dest.size() )
00210       return false;
00211 
00212    AStar3D ast ( ai->getMap(), supplier, true, supplier->typ->maxSpeed()*6 );
00213    AStar3D::Path path;
00214    ast.findPath(  path, dest );
00215    if ( path.size() ) {
00216       meet = *path.rbegin();
00217 
00218       int supplySpeed = supplier->maxMovement();
00219       if ( !canWait() )
00220          supplySpeed += targ->maxMovement();
00221       if ( supplySpeed == 0 )
00222          fatalError ( "AI::ServiceOrder::execute1st - supplySpeed is 0 ");
00223 
00224       if ( !targ->maxMovement() || beeline(supplier,targ) / supplySpeed < nextServiceBuildingDistance/targ->maxMovement() || nextServiceBuildingDistance < 0 ) {
00225          supplier->aiparam[ai->getPlayerNum()]->dest = meet;
00226          supplier->aiparam[ai->getPlayerNum()]->setTask( AiParameter::tsk_move );
00227          supplier->aiparam[ai->getPlayerNum()]->dest_nwid = targ->networkid;
00228 
00229          setServiceUnit ( supplier );
00230          return true;
00231       }
00232    }
00233    return false;
00234 }
00235 
00236 void AI::ServiceOrder::setServiceUnit ( Vehicle* veh )
00237 {
00238    if ( veh )
00239       serviceUnitID = veh->networkid;
00240    else
00241       serviceUnitID = 0;
00242 }
00243 
00244 void AI::ServiceOrder::releaseServiceUnit ( ServiceOrder& so )
00245 {
00246    Vehicle* veh = so.getServiceUnit();
00247    if ( veh ) {
00248       so.setServiceUnit ( NULL );
00249       veh->aiparam[so.ai->getPlayerNum()]->resetTask();
00250    }
00251 }
00252 
00253 
00254 bool AI::ServiceOrder::timeOut ( )
00255 {
00256   GameTime t = time;
00257   t.set ( t.turn() + 2, t.move() );
00258   return ( t.abstime <= ai->getMap()->time.abstime );
00259 }
00260 
00261 bool AI::ServiceOrder::canWait( )
00262 {
00263    if ( requiredService == VehicleService::srv_repair )
00264       return false;
00265 
00266    if ( requiredService == VehicleService::srv_ammo ) {
00267       if ( getTargetUnit()->ammo[position] )
00268          return true;
00269 
00270       if ( ai->targetsNear( getTargetUnit() ))
00271          return true;
00272    }
00273 
00274    bool fuelLack = requiredService == VehicleService::srv_resource && position == 2 ;
00275    bool couldWait = fuelLack || !timeOut();
00276    if ( couldWait )
00277       return serviceUnitExists();
00278    else
00279       return false;
00280 }
00281 
00282 bool AI::ServiceOrder::serviceUnitExists()
00283 {
00284    for ( Player::VehicleList::iterator vi = ai->getPlayer().vehicleList.begin(); vi != ai->getPlayer().vehicleList.end(); vi++ )
00285        if ( possible ( *vi ))
00286           return true;
00287    return false;
00288 }
00289 
00290 
00291 bool AI::ServiceOrder::valid (  ) const
00292 {
00293    switch ( requiredService ) {
00294       case VehicleService::srv_repair     : return getTargetUnit()->damage > 0;
00295       case VehicleService::srv_ammo       : return getTargetUnit()->ammo[position] < getTargetUnit()->typ->weapons.weapon[position].count;
00296       case VehicleService::srv_resource   : return getTargetUnit()->getResource(getTargetUnit()->getStorageCapacity().resource(position), position, 1) < getTargetUnit()->getStorageCapacity().resource(position);
00297       default: return false;
00298    }
00299 }
00300 
00301 bool AI::ServiceOrder::invalid ( const ServiceOrder& so )
00302 {
00303    return !so.valid();
00304 }
00305 
00306 bool AI::ServiceOrder::operator==( const ServiceOrder& so ) const
00307 {
00308    return    targetUnitID    == so.targetUnitID
00309           && requiredService == so.requiredService
00310           && ai              == so.ai
00311           && position        == so.position;
00312 }
00313 
00314 bool AI::ServiceOrder::operator!=( const ServiceOrder& so ) const
00315 {
00316   return ! (*this == so);
00317 }
00318 
00319 
00320 AI :: ServiceOrder :: ~ServiceOrder (  )
00321 {
00322    if ( active ) {
00323       Vehicle* serv = getServiceUnit();
00324       if ( serv )
00325          serv->aiparam[ai->getPlayerNum()]->resetTask();
00326    }
00327 }
00328 
00329 AI::ServiceOrder& AI :: issueService ( VehicleService::Service requiredService, int UnitID, int pos )
00330 {
00331    ServiceOrder so ( this, requiredService, UnitID, pos );
00332    ServiceOrderContainer::iterator soi = find ( serviceOrders.begin(), serviceOrders.end(), so );
00333    if ( soi == serviceOrders.end() ) {
00334       serviceOrders.push_back ( so );
00335       ServiceOrder::activate ( *serviceOrders.rbegin() );
00336       return *serviceOrders.rbegin();
00337    } else {
00338       return *soi;
00339    }
00340 }
00341 
00342 
00343 
00344 void AI :: issueServices ( )
00345 {
00346    displaymessage2("issuing services ... ");
00347    serviceOrders.erase ( remove_if ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::targetDestroyed ), serviceOrders.end());
00348 
00349    for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); vi++ ) {
00350       Vehicle* veh = *vi;
00351       if ( getMap()->getField( veh->getPosition() )->unitHere( veh )) {
00352          if ( veh->damage > config.damageLimit )
00353             issueService ( VehicleService::srv_repair, veh->networkid ) ;
00354 
00355          for ( int i = 0; i< resourceTypeNum; i++ )
00356             if ( veh->maxMovement() ) // stationary units are ignored
00357                if ( veh->getResource(maxint, i, 1) < veh->getStorageCapacity().resource(i) * config.resourceLimit.resource(i) / 100 )
00358                   issueService ( VehicleService::srv_resource, veh->networkid, i);
00359 
00360          for ( int w = 0; w< veh->typ->weapons.count; w++ )
00361             if ( veh->typ->weapons.weapon[w].count )
00362                if ( veh->ammo[w] <= veh->typ->weapons.weapon[w].count * config.ammoLimit / 100 )
00363                   issueService ( VehicleService::srv_ammo, veh->networkid, w);
00364       }
00365    }
00366 }
00367 
00368 AI::ServiceOrder& AI :: issueRefuelOrder ( Vehicle* veh, bool returnImmediately )
00369 {
00370    ServiceOrder& so = issueService ( VehicleService::srv_resource, veh->networkid, Resources::Fuel);
00371    if ( returnImmediately ) {
00372       if ( RefuelConstraint::necessary ( veh, *this )) {
00373          RefuelConstraint apl ( *this, veh );
00374          veh->aiparam[getPlayerNum()]->dest = apl.getNearestRefuellingPosition ( true, true, false );
00375          if ( veh->aiparam[getPlayerNum()]->dest.valid() ) {
00376             veh->aiparam[getPlayerNum()]->setTask( AiParameter::tsk_serviceRetreat );
00377             runUnitTask ( veh );
00378          }
00379       } else {
00380 
00381       }
00382    }
00383    return so;
00384 }
00385 
00386 
00387 
00388 MapCoordinate3D AI :: findServiceBuilding ( const ServiceOrder& so, int* distance )
00389 {
00390    Vehicle* veh = so.getTargetUnit();
00391    if ( getMap()->getField( veh->getPosition())->unitHere ( veh ))
00392       if ( !veh->canMove() )
00393          return MapCoordinate3D ( -1, -1, 1 );
00394 
00395    /*
00396    RefuelConstraint* rc = NULL;
00397    if ( RefuelConstraint::necessary  ( veh, this ))
00398       rc = new RefuelConstraint ( veh, this );
00399    */
00400 
00401    int maxMovement = 0;
00402    for ( int i = 0; i < 8; i++ )
00403       maxMovement = max ( maxMovement, veh->typ->movement[i] );
00404 
00405    AStar3D astar ( getMap(), veh, true, maxMovement*10 );
00406    astar.findAllAccessibleFields ( );
00407 
00408    Building* bestBuilding = NULL;
00409    int bestDistance = maxint;
00410    MapCoordinate3D bestPos;
00411 
00412    Building* bestBuilding_p = NULL;
00413    int bestDistance_p = maxint;
00414    MapCoordinate3D bestPos_p;
00415 
00416    for ( Player::BuildingList::iterator bi = getPlayer().buildingList.begin(); bi != getPlayer().buildingList.end(); bi++ ) {
00417       Building* bld = *bi;
00418       if ( astar.getFieldAccess( bld->getEntry())  ) { // ####TRANS
00419          MapCoordinate3D buildingPos = bld->getEntry();
00420          buildingPos.setnum ( buildingPos.x, buildingPos.y, -1 );
00421          /*
00422          if ( !(bld->typ->loadcapability & buildingPos.z))
00423             buildingPos.z = 1 << log2 ( astar.getFieldAccess(bld->getEntry()) & bld->typ->loadcapability );
00424          */
00425 
00426          bool loadable = true;
00427          if ( loadable ) {
00428             int fullfillableServices = 0;
00429             int partlyFullfillabelServices = 0;
00430             switch ( so.requiredService ) {
00431                case VehicleService::srv_repair : if ( bld->canRepair( veh ) ) {
00432                                                     int mr =  bld->getMaxRepair( veh );
00433                                                     if ( mr == 0 )
00434                                                        fullfillableServices++;
00435 
00436                                                     if ( mr < veh->damage )
00437                                                        partlyFullfillabelServices++;
00438 
00439                                                  }
00440                                                  break;
00441                case VehicleService::srv_resource:  {
00442                                                      Resources needed =  veh->getStorageCapacity() - veh->getResource(Resources(maxint,maxint,maxint), true);
00443                                                      Resources avail = bld->getResource ( needed, 1 );
00444                                                      if ( avail < needed )
00445                                                         avail += bld->netResourcePlus( ) * config.waitForResourcePlus;
00446 
00447                                                      int missing = 0;
00448                                                      int pmissing = 0;
00449                                                      for ( int r = 0; r < resourceTypeNum; r++ ) {
00450                                                         if( needed.resource(r) * 75 / 100 > avail.resource(r) )
00451                                                            missing ++;
00452 
00453                                                         if( needed.resource(r) * 10 / 100 > avail.resource(r) )
00454                                                            pmissing ++;
00455                                                      }
00456                                                      if ( missing == 0 )
00457                                                         fullfillableServices++;
00458 
00459                                                      if ( pmissing == 0)
00460                                                        partlyFullfillabelServices++;
00461                                                  }
00462                                                  break;
00463                case VehicleService::srv_ammo :  {
00464                                                    int missing = 0;
00465                                                    int pmissing = 0;
00466                                                    int ammoNeeded[waffenanzahl];
00467                                                    for ( int t = 0; t < waffenanzahl; t++ )
00468                                                       ammoNeeded[t] = 0;
00469 
00470                                                    for ( int i = 0; i < veh->typ->weapons.count; i++ )
00471                                                       if ( veh->typ->weapons.weapon[i].requiresAmmo() )
00472                                                          ammoNeeded[ veh->typ->weapons.weapon[i].getScalarWeaponType() ] += veh->typ->weapons.weapon[i].count - veh->ammo[i];
00473 
00474                                                    Resources needed;
00475                                                    for ( int  j = 0; j < waffenanzahl; j++ ) {
00476                                                        int n = ammoNeeded[j] - bld->ammo[j];
00477                                                        if ( n > 0 )
00478                                                           if ( bld->typ->hasFunction( ContainerBaseType::AmmoProduction  )) {
00479                                                              for ( int r = 0; r < resourceTypeNum; r++ )
00480                                                                 needed.resource(r) += (n+4)/5 * cwaffenproduktionskosten[j][r];
00481                                                           } else
00482                                                              missing++;
00483                                                    }
00484                                                    Resources avail = bld->getResource ( needed, 1 );
00485                                                    if ( avail < needed )
00486                                                       avail += bld->netResourcePlus( ) * config.waitForResourcePlus;
00487 
00488                                                    for ( int r = 0; r < resourceTypeNum; r++ ) {
00489                                                       if ( avail.resource(r) < needed.resource (r) )
00490                                                          missing++;
00491                                                       if ( avail.resource(r) <= needed.resource (r)/3 )
00492                                                          pmissing++;
00493                                                    }
00494 
00495                                                    if ( missing == 0 )
00496                                                        fullfillableServices++;
00497 
00498                                                    if ( pmissing == 0)
00499                                                      partlyFullfillabelServices++;
00500 
00501                                                  }
00502                                                  break;
00503 
00504             };
00505 
00506             if ( fullfillableServices ) {
00507                const AStar3D::Node* nde = astar.fieldVisited(buildingPos);
00508                if ( nde ) {
00509                   int dist = int( nde->gval );
00510                   if ( dist < bestDistance ) {
00511                      bestDistance = dist;
00512                      bestBuilding = bld;
00513                      bestPos = buildingPos;
00514                   }
00515                }
00516             } else
00517                if ( partlyFullfillabelServices ) {
00518                   const AStar3D::Node* nde = astar.fieldVisited(buildingPos);
00519                   if ( nde ) {
00520                      int dist = int( nde->gval );
00521                      if ( dist < bestDistance_p ) {
00522                         bestDistance_p = dist;
00523                         bestBuilding_p = bld;
00524                         bestPos_p = buildingPos;
00525                      }
00526                   }
00527                }
00528          }
00529       }
00530    }
00531 
00532    if ( bestBuilding && (bestDistance < bestDistance_p*3)) {
00533       if ( distance )
00534          *distance = bestDistance;
00535       return bestPos;
00536    } else {
00537       if ( distance )
00538          *distance = bestDistance_p;
00539       return bestPos_p;
00540    }
00541 }
00542 
00543 
00544 
00545 
00546 bool AI :: ServiceTargetEquals :: operator() (const ServiceOrder& so ) const
00547 {
00548    Vehicle* t = so.getTargetUnit();
00549    return target== t;
00550 }
00551 
00552 
00553 
00554 void AI::removeServiceOrdersForUnit ( const Vehicle* veh )
00555 {
00556    serviceOrders.erase ( remove_if ( serviceOrders.begin(), serviceOrders.end(), ServiceTargetEquals( veh ) ), serviceOrders.end());
00557 }
00558 
00559 void AI :: runServiceUnit ( Vehicle* supplyUnit )
00560 {
00561    bool destinationReached = false;
00562    typedef multimap<float,ServiceOrder*> ServiceMap;
00563    ServiceMap serviceMap;
00564 
00565    // building a list of all fullfillable service tasks
00566    for ( ServiceOrderContainer::iterator i = serviceOrders.begin(); i != serviceOrders.end(); i++ ) {
00567        if ( !i->getServiceUnit() && i->getTargetUnit() ) {
00568           int poss = i->possible( supplyUnit );
00569           if ( poss ) {
00570              float f =  i->getTargetUnit()->aiparam[getPlayerNum()]->getValue() * poss/100 / beeline( i->getTargetUnit() ,supplyUnit );
00571              serviceMap.insert(make_pair(f,&(*i)));
00572           }
00573   /*
00574           veh->aiparam[getPlayerNum()]->getTask() = AiParameter::tsk_serviceRetreat;
00575           Building* bld = findServiceBuilding( **i );
00576           if ( bld )
00577              veh->aiparam[ getPlayerNum() ]->dest = bld->getEntry ( );
00578   */
00579        }
00580    }
00581    int target = 0;
00582    int counter = 0;
00583    for ( ServiceMap::reverse_iterator ri = serviceMap.rbegin(); ri != serviceMap.rend(); ri++ ) {
00584       displaymessage2("test service %d", ++counter);
00585       if ( ri->second->execute1st( supplyUnit ) ) {
00586          target = supplyUnit->aiparam[getPlayerNum()]->dest_nwid;
00587          destinationReached = runUnitTask ( supplyUnit );
00588          break;
00589       }
00590    }
00591 
00592    if ( destinationReached ) {
00593       VehicleService vs ( mapDisplay, NULL );
00594       if ( !vs.available ( supplyUnit ))
00595          displaymessage ("AI :: runServiceUnit ; inconsistency in VehicleService.availability",1 );
00596 
00597       vs.execute ( supplyUnit, -1, -1, 0, -1, -1 );
00598       VehicleService::TargetContainer::iterator i = vs.dest.find ( target );
00599       if ( i != vs.dest.end() ) {
00600          vs.fillEverything ( target, true );
00601          Vehicle* targetUnit = getMap()->getUnit(target);
00602          if ( targetUnit->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_serviceRetreat )
00603              targetUnit->aiparam[getPlayerNum()]->resetTask();
00604 
00605 
00606          removeServiceOrdersForUnit ( targetUnit );
00607 
00608          // search for next unit to be serviced
00609          runServiceUnit( supplyUnit );
00610       } else
00611          displaymessage ("AI :: runServiceUnit ; inconsistency in VehicleService.execution level 0 ; unit is %d",1, supplyUnit->networkid  );
00612 
00613    }
00614 }
00615 
00616 
00617 AI::AiResult AI :: executeServices ( )
00618 {
00619   // removing all service orders for units which no longer exist
00620   removeServiceOrdersForUnit ( NULL );
00621   serviceOrders.erase ( remove_if ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::invalid ), serviceOrders.end());
00622 
00623   for_each ( serviceOrders.begin(), serviceOrders.end(), ServiceOrder::releaseServiceUnit );
00624 
00625   AiResult res;
00626 
00627   vector<int> unitIds;
00628   for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); ++vi )
00629      unitIds.push_back ( (*vi)->networkid );
00630 
00631 
00632   for ( vector<int>::iterator vi = unitIds.begin(); vi != unitIds.end(); ++vi ) {
00633       Vehicle* veh = getMap()->getUnit( *vi );
00634       if ( veh ) {
00635         checkKeys();
00636         if ( veh->aiparam[getPlayerNum()]->getJob() == AiParameter::job_supply ) 
00637            runServiceUnit ( veh );
00638       }
00639   }
00640 
00641   removeServiceOrdersForUnit ( NULL );
00642   int counter = 0;
00643   for ( ServiceOrderContainer::iterator i = serviceOrders.begin(); i != serviceOrders.end();  ) {
00644       ServiceOrderContainer::iterator nxt = i;
00645       ++nxt;
00646 
00647       if ( !i->canWait() ) {
00648          displaymessage2("executing priority service order %d", ++counter);
00649          Vehicle* veh = i->getTargetUnit();
00650          if ( i->getServiceUnit() ) {
00651             if ( veh->canMove() ) {
00652                veh->aiparam[ getPlayerNum() ]->dest = i->getServiceUnit()->getPosition();
00653                veh->aiparam[ getPlayerNum() ]->dest_nwid = i->getServiceUnit()->networkid;
00654                veh->aiparam[ getPlayerNum() ]->setTask( AiParameter::tsk_serviceRetreat );
00655             }
00656          } else {
00658             if ( (veh->height & ( chtieffliegend | chfliegend | chhochfliegend )) && veh->typ->fuelConsumption && false ) {
00659                RefuelConstraint apl ( *this, veh );
00660                MapCoordinate3D dst = apl.getNearestRefuellingPosition( true, true, false );
00661                if ( dst.x != -1 ) {
00662                   veh->aiparam[ getPlayerNum() ]->dest = dst;
00663                   veh->aiparam[ getPlayerNum() ]->setTask( AiParameter::tsk_serviceRetreat );
00664                }
00665             } else {
00666                MapCoordinate3D dest = findServiceBuilding( *i );
00667                if ( dest.valid() && veh->canMove() ) {
00668                   veh->aiparam[ getPlayerNum() ]->dest = dest;
00669                   veh->aiparam[ getPlayerNum() ]->setTask( AiParameter::tsk_serviceRetreat );
00670                } else {
00671                   // displaymessage("warning: no service building found found for unit %s - %d!",1, veh->typ->description, veh->typ->id);
00672                }
00673             }
00674          }
00675       }
00676 
00677       i = nxt;
00678   }
00679 
00680 
00681   unitIds.clear();
00682   for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); ++vi ) 
00683      unitIds.push_back ( (*vi)->networkid );
00684   
00685   
00686   counter = 0;
00687   for ( vector<int>::iterator vi = unitIds.begin(); vi != unitIds.end(); ++vi ) {
00688      Vehicle* veh = getMap()->getUnit( *vi );
00689      checkKeys();
00690 
00691      if ( veh && veh->canMove() && veh->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_serviceRetreat ) {
00692         displaymessage2("retreating with unit %d", ++counter);
00693         int nwid = veh->networkid;
00694         moveUnit ( veh, veh->aiparam[ getPlayerNum() ]->dest, true );
00695 
00696         // the unit may have been shot down
00697         if ( getMap()->getUnit ( nwid )) {
00698            if ( veh->getPosition3D() == veh->aiparam[ getPlayerNum() ]->dest ) {
00699               tfield* fld = getfield ( veh->xpos, veh->ypos );
00700               if ( fld->building ) {
00701                  VehicleService vc ( mapDisplay, NULL );
00702                  MapCoordinate mc = fld->building->getEntry();
00703                  vc.execute ( NULL, mc.x, mc.y, 0, -1, -1 );
00704 
00705                  if ( vc.getStatus () == 2 ) {
00706                     if ( vc.dest.find ( veh->networkid ) != vc.dest.end() )
00707                        vc.fillEverything ( veh->networkid, true );
00708                     else
00709                        displaymessage ( "AI :: executeServices / Vehicle cannot be serviced (1) ", 1);
00710                  } else
00711 //                    if ( vc.getStatus() != -210 )
00712                     displaymessage ( "AI :: executeServices / Vehicle cannot be serviced (2) ", 1);
00713 
00714                  removeServiceOrdersForUnit ( veh );
00715 
00716                  if ( veh->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_serviceRetreat )
00717                      veh->aiparam[getPlayerNum()]->resetTask();
00718 
00719               }
00720            }
00721         }
00722      }
00723   }
00724 
00725   /*
00726   for ( ServiceOrderContainer::iterator i = serviceOrders.begin(); i != serviceOrders.end(); i++ ) {
00727       if ( !i->timeOut() && i->requiredService == VehicleService::srv_repair ) {
00728          Vehicle* veh = i->getTargetUnit();
00729          veh->aiparam[getPlayerNum()]->getTask() = AiParameter::tsk_serviceRetreat;
00730          Building* bld = findServiceBuilding( *i );
00731          if ( bld )
00732             veh->aiparam[ getPlayerNum() ]->dest = bld->getEntry ( );
00733          else {
00734             // displaymessage("warning: no service building found found for unit %s - %d!",1, veh->typ->description, veh->typ->id);
00735          }
00736 
00737       }
00738   }
00739 */
00740   return res;
00741 
00742 }

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