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

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