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

valuation.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           valuation.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 
00019 #include "ai_common.h"
00020 
00021 const int value_armorfactor = 100;
00022 const int value_weaponfactor = 3000;
00023 
00024 const int ccbt_repairfacility = 200;    //  basic threatvalues for buildings
00025 const int ccbt_hq = 10000;
00026 const int ccbt_recycling = 50;
00027 const int ccbt_training = 150;
00028 
00029 
00030 
00031 
00032 
00033   class CalculateThreat_VehicleType {
00034                          protected:
00035                               AI*               ai;
00036 
00037                               const Vehicletype*      fzt;
00038                               int               weapthreat[8];
00039                               int               value;
00040 
00041                               virtual int       getdamage ( void )      { return 0;   };
00042                               virtual int       getexpirience ( void )  { return 0;   };
00043                               virtual int       getammunition( int i )  { return 1;   };
00044                               virtual int       getheight ( void )      { return 255; };
00045                           public:
00046                               void              calc_threat_vehicletype ( const Vehicletype* _fzt );
00047                               CalculateThreat_VehicleType ( AI* _ai ) { ai = _ai; };
00048                               virtual ~CalculateThreat_VehicleType() {};
00049                        };
00050 
00051   class CalculateThreat_Vehicle : public CalculateThreat_VehicleType {
00052                            protected:
00053                                 Vehicle*          eht;
00054                                 virtual int       getdamage ( void );
00055                                 virtual int       getexpirience ( void );
00056                                 virtual int       getammunition( int i );
00057                                 virtual int       getheight ( void );
00058                            public:
00059                               void              calc_threat_vehicle ( Vehicle* _eht );
00060                               CalculateThreat_Vehicle ( AI* _ai ) : CalculateThreat_VehicleType ( _ai ) {};
00061                        };
00062 
00063 
00064 void         CalculateThreat_VehicleType :: calc_threat_vehicletype ( const Vehicletype* _fzt )
00065 {
00066    fzt = _fzt;
00067 
00068    for ( int j = 0; j < 8; j++ )
00069       weapthreat[j] = 0;
00070 
00071    for ( int i = 0; i < fzt->weapons.count; i++)
00072       if ( fzt->weapons.weapon[i].shootable() )
00073          if ( fzt->weapons.weapon[i].offensive() )
00074             for ( int j = 0; j < 8; j++)
00075                if ( fzt->weapons.weapon[i].targ & (1 << j) ) {
00076                   int d = 0;
00077                   int m = 0;
00078                   AttackFormula af;
00079                   for ( int e = (fzt->weapons.weapon[i].mindistance + maxmalq - 1)/ maxmalq; e <= fzt->weapons.weapon[i].maxdistance / maxmalq; e++ ) {    // the distance between two fields is maxmalq
00080                      d++;
00081                      int n = int( WeapDist::getWeaponStrength( &fzt->weapons.weapon[i], 0, e*maxmalq ) * fzt->weapons.weapon[i].maxstrength * af.strength_damage(getdamage()) * ( 1 + af.strength_experience(getexpirience())) );
00082                      m += int( n / log10(double(10*d)));
00083                   }
00084                   if (getammunition(i) == 0)
00085                      m /= 2;
00086 
00087                   if ( (fzt->weapons.weapon[i].sourceheight & getheight()) == 0)
00088                      m /= 2;
00089 
00090                   /*
00091                   if ( !(getheight() & ( 1 << j )))
00092                      m /= 2;
00093                   */
00094 
00095                   if (m > weapthreat[j])
00096                      weapthreat[j] = m;
00097                }
00098 
00099 
00100    if ( !fzt->aiparam[ai->getPlayerNum()] )
00101       fzt->aiparam[ ai->getPlayerNum() ] = new AiValue ( log2 ( fzt->height ));
00102 
00103    for ( int l = 0; l < 8; l++ )
00104       fzt->aiparam[ ai->getPlayerNum() ]->threat.threat[l] = weapthreat[l];
00105 
00106    value = fzt->armor * value_armorfactor * (100 - getdamage()) / 100;
00107 
00108    for ( int s = 0; s < 7; )
00109       if ( weapthreat[s] < weapthreat[s+1] ) {
00110          int temp = weapthreat[s];
00111          weapthreat[s] = weapthreat[s+1];
00112          weapthreat[s+1] = temp;
00113          if ( s > 0 )
00114             s--;
00115       } else
00116          s++;
00117 
00118    for ( int k = 0; k < 8; k++ )
00119       value += weapthreat[k] * value_weaponfactor / (k+1);
00120 
00121    fzt->aiparam[ ai->getPlayerNum() ]->setValue ( value );
00122    fzt->aiparam[ ai->getPlayerNum() ]->valueType = 0;
00123 }
00124 
00125 
00126 int          CalculateThreat_Vehicle :: getammunition( int i )
00127 {
00128    return eht->ammo[i];
00129 }
00130 
00131 int          CalculateThreat_Vehicle :: getheight(void)
00132 {
00133    return eht->height;
00134 }
00135 
00136 int          CalculateThreat_Vehicle :: getdamage(void)
00137 {
00138    return eht->damage;
00139 }
00140 
00141 int          CalculateThreat_Vehicle :: getexpirience(void)
00142 {
00143    return eht->experience;
00144 }
00145 
00146 
00147 void         CalculateThreat_Vehicle :: calc_threat_vehicle ( Vehicle* _eht )
00148 {
00149 
00150    eht = _eht;
00151    calc_threat_vehicletype ( vehicleTypeRepository.getObject_byID ( eht->typ->id ) );
00152 
00153    if ( !eht->aiparam[ai->getPlayerNum()] )
00154       eht->aiparam[ai->getPlayerNum()] = new AiParameter ( eht );
00155 
00156    AiParameter* aip = eht->aiparam[ai->getPlayerNum()];
00157    for ( int l = 0; l < 8; l++ )
00158       aip->threat.threat[l] = eht->typ->aiparam[ ai->getPlayerNum() ]->threat.threat[l];
00159 
00160    int value = eht->typ->aiparam[ ai->getPlayerNum() ]->getValue();
00161    for ( ContainerBase::Cargo::const_iterator i = eht->getCargo().begin(); i != eht->getCargo().end(); ++i )
00162       if ( *i ) {
00163          if ( !(*i)->aiparam[ai->getPlayerNum()] ) {
00164             CalculateThreat_Vehicle ctv ( ai );
00165             ctv.calc_threat_vehicle( *i );
00166          }
00167          value += (*i)->aiparam[ai->getPlayerNum()]->getValue();
00168       }
00169       
00170 
00171    aip->setValue ( value );
00172 
00173 
00174    if ( aip->getJob() == AiParameter::job_undefined )
00175       if ( eht->canMove() )
00176          aip->setJob( AI::chooseJob ( eht->typ ));
00177 /*
00178    generatethreatvalue();
00179    int l = 0;
00180    for ( int b = 0; b <= 7; b++) {
00181       eht->threatvalue[b] = weapthreatvalue[b];
00182       if (weapthreatvalue[b] > l)
00183          l = weapthreatvalue[b];
00184    }                         <Zwischenablage leer>
00185    eht->completethreatvalue = threatvalue2 + l;
00186    eht->completethreatvaluesurr = threatvalue2 + l;
00187    eht->threats = 0;
00188 */
00189 }
00190 
00191 AiParameter::JobList AI::chooseJob ( const Vehicletype* typ )
00192 {
00193    AiParameter::JobList jobList;
00194 
00195    if ( typ->recommendedAIJob != AiParameter::job_undefined ) {
00196       jobList.push_back ( typ->recommendedAIJob );
00197       return jobList;
00198    }
00199 
00200    int maxmove = minint;
00201    for ( int i = 0; i< 8; i++ )
00202       if ( typ->height & ( 1 << i ))
00203          maxmove = max ( typ->movement[i] , maxmove );
00204 
00205    int maxstrength = minint;
00206    for ( int w = 0; w < typ->weapons.count; w++ )
00207       if ( typ->weapons.weapon[w].offensive() )
00208          maxstrength= max (  typ->weapons.weapon[w].maxstrength, maxstrength );
00209 
00210    bool service = false;
00211    for ( int w = 0; w < typ->weapons.count; w++ )
00212       if ( typ->weapons.weapon[w].service() )
00213          service = true;
00214 
00215    if ( ( typ->hasFunction( ContainerBaseType::ExternalRepair ) || service) && maxmove >= minmalq && maxstrength < 45)
00216       jobList.push_back ( AiParameter::job_supply );
00217 
00218 
00219    if ( typ->hasFunction( ContainerBaseType::ConquerBuildings ) ) {
00220       /* if ( functions & cf_trooper )  {
00221          if ( typ->height & chfahrend )
00222             jobList.push_back ( AiParameter::job_conquer );
00223       } else { */
00224          if ( maxstrength < maxmove )
00225             jobList.push_back ( AiParameter::job_conquer );
00226       // }
00227    }
00228 
00229    if ( ( maxstrength*1.5 < typ->view
00230            || (maxstrength*1.5 < typ->jamming && !typ->hasFunction( ContainerBaseType::JamsOnlyOwnField )))
00231        && maxmove > minmalq  )
00232       jobList.push_back (  AiParameter::job_recon );
00233 
00234    if ( maxstrength > 0 )
00235       jobList.push_back ( AiParameter::job_fight );
00236 
00237    jobList.push_back ( AiParameter::job_undefined );
00238    return jobList;
00239 }
00240 
00241 
00242 
00243 void  AI :: calculateThreat ( const Vehicletype* vt)
00244 {
00245    CalculateThreat_VehicleType ctvt ( this );
00246    ctvt.calc_threat_vehicletype( vt );
00247 }
00248 
00249 
00250 void  AI :: calculateThreat ( Vehicle* eht )
00251 {
00252    CalculateThreat_Vehicle ctv ( this );
00253    ctv.calc_threat_vehicle( eht );
00254 }
00255 
00256 
00257 void  AI :: calculateThreat ( Building* bld )
00258 {
00259    calculateThreat ( bld, getPlayerNum());
00260 //   calculateThreat ( bld, 8 );
00261 }
00262 
00263 void  AI :: calculateThreat ( Building* bld, int player )
00264 {
00265    if ( !bld->aiparam[ player ] )
00266       bld->aiparam[ player ] = new AiValue ( log2 ( bld->typ->buildingheight ) );
00267 
00268    int b;
00269 
00270 
00271    // Since we have two different resource modes now, this calculation should be rewritten....
00272    int value = (bld->plus.energy / 10) + (bld->plus.fuel / 10) + (bld->plus.material / 10) + (bld->actstorage.energy / 20) + (bld->actstorage.fuel / 20) + (bld->actstorage.material / 20);
00273    
00274    for ( ContainerBase::Cargo::const_iterator i = bld->getCargo().begin(); i != bld->getCargo().end(); ++i )
00275       if ( *i ) {
00276          if ( !(*i)->aiparam[ player ] )
00277             calculateThreat ( *i );
00278          value += (*i)->aiparam[ player ]->getValue();
00279       }
00280 
00281    for (b = 0; b < bld->getProduction().size(); b++)
00282       if ( bld->getProduction()[b] )  {
00283          if ( !bld->getProduction()[b]->aiparam[ player ] )
00284             calculateThreat ( bld->getProduction()[b] );
00285          value += bld->getProduction()[b]->aiparam[ player ]->getValue() / 10;
00286       }
00287 
00288    if (bld->typ->hasFunction( ContainerBaseType::InternalUnitRepair  ))
00289       value += ccbt_repairfacility;
00290    
00291    if (bld->typ->hasFunction( ContainerBaseType::TrainingCenter  ) )
00292       value += ccbt_training;
00293    if (bld->typ->hasFunction( ContainerBaseType::RecycleUnits  )  )
00294       value += ccbt_recycling;
00295 
00296    bld->aiparam[ player ]->setValue ( value );
00297 }
00298 
00299 
00300 
00301 void AI :: WeaponThreatRange :: run ( Vehicle* _veh, int x, int y, AiThreat* _threat )
00302 {
00303    threat = _threat;
00304    veh = _veh;
00305    for ( height = 0; height < 8; height++ )
00306       for ( weap = 0; weap < veh->typ->weapons.count; weap++ )
00307          if ( veh->height & veh->typ->weapons.weapon[weap].sourceheight )
00308             if ( (1 << height) & veh->typ->weapons.weapon[weap].targ )
00309                 if ( veh->typ->weapons.weapon[weap].shootable()  && veh->typ->weapons.weapon[weap].offensive() ) {
00310                    initsearch ( MapCoordinate(x, y), veh->typ->weapons.weapon[weap].maxdistance/maxmalq, veh->typ->weapons.weapon[weap].mindistance/maxmalq );
00311                    startsearch();
00312                 }
00313 }
00314 
00315 void AI :: WeaponThreatRange :: testfield ( const MapCoordinate& mc )
00316 {
00317    if ( dist*maxmalq <= veh->typ->weapons.weapon[weap].maxdistance )
00318       if ( dist*maxmalq >= veh->typ->weapons.weapon[weap].mindistance ) {
00319          AttackFormula af;
00320          int strength = int ( WeapDist::getWeaponStrength( &veh->typ->weapons.weapon[weap], ai->getMap()->getField(mc)->getweather(), dist*maxmalq, veh->height, 1 << height )
00321                               * veh->typ->weapons.weapon[weap].maxstrength
00322                               * (1 + af.strength_experience ( veh->experience ) + af.strength_attackbonus ( gamemap->getField(startPos)->getattackbonus() ))
00323                               * af.strength_damage ( veh->damage )
00324                              );
00325 
00326          if ( strength ) {
00327             int pos = mc.x + mc.y * ai->getMap()->xsize;
00328             if ( strength > threat[pos].threat[height] )
00329                threat[pos].threat[height] = strength;
00330          }
00331       }
00332 }
00333 
00334 void AI :: calculateFieldInformation ( void )
00335 {
00336    if ( fieldNum && fieldNum != activemap->xsize * activemap->ysize ) {
00337       delete[] fieldInformation;
00338       fieldInformation = NULL;
00339       fieldNum = 0;
00340    }
00341    if ( !fieldInformation ) {
00342       fieldNum = activemap->xsize * activemap->ysize;
00343       fieldInformation = new FieldInformation[ fieldNum ];
00344    } else
00345       for ( int a = 0; a < fieldNum; a++ )
00346          fieldInformation[ a ].reset();
00347 
00348    AiThreat*  singleUnitThreat = new AiThreat[fieldNum];
00349 
00350    // we now check the whole map
00351    for ( int y = 0; y < activemap->ysize; y++ ) {
00352       checkKeys();
00353       for ( int x = 0; x < activemap->xsize; x++ ) {
00354          tfield* fld = activemap->getField ( x, y );
00355          if ( config.wholeMapVisible || fieldvisiblenow ( fld, getPlayerNum() ) )
00356             if ( fld->vehicle && getPlayer().diplomacy.isHostile( fld->vehicle->getOwner() )) {
00357                WeaponThreatRange wr ( this );
00358                if ( !fld->vehicle->typ->wait ) {
00359 
00360                   // The unit may have already moved this turn.
00361                   // So we give it the maximum movementrange
00362 
00363                   TemporaryContainerStorage tus ( fld->vehicle );
00364 
00365                   fld->vehicle->setMovement ( fld->vehicle->maxMovement(), 0);
00366 
00367                   VehicleMovement vm ( NULL, NULL );
00368                   if ( vm.available ( fld->vehicle )) {
00369                      vm.execute ( fld->vehicle, -1, -1, 0, -1, -1 );
00370 
00371                      // Now we cycle through all fields that are reachable...
00372                      for ( int f = 0; f < vm.reachableFields.getFieldNum(); f++ ) {
00373                         int xp, yp;
00374                         vm.reachableFields.getFieldCoordinates ( f, &xp, &yp );
00375                         // ... and check for each which fields are threatened if the unit was standing there
00376                         wr.run ( fld->vehicle, xp, yp, singleUnitThreat );
00377                      }
00378 
00379                      for ( int g = 0; g < vm.reachableFieldsIndirect.getFieldNum(); g++ ) {
00380                         int xp, yp;
00381                         vm.reachableFieldsIndirect.getFieldCoordinates ( g, &xp, &yp );
00382                         wr.run ( fld->vehicle, xp, yp, singleUnitThreat );
00383                      }
00384                   }
00385                   tus.restore();
00386                } else
00387                   wr.run ( fld->vehicle, x, y, singleUnitThreat );
00388 
00389 
00390                for ( int a = 0; a < fieldNum; a++ ) {
00391                   for ( int b = 0; b < 8; b++ )
00392                      fieldInformation[a].threat.threat[b] += singleUnitThreat[a].threat[b];
00393 
00394                   singleUnitThreat[ a ].reset();
00395                }
00396             }
00397 
00398          FieldInformation& fi = fieldInformation[y*getMap()->xsize+x];
00399          for ( int i = 0; i< sidenum; i++ ) {
00400             tfield* f = getMap()->getField ( getNeighbouringFieldCoordinate ( MapCoordinate(x,y), i ));
00401             if ( f && f->vehicle && f->vehicle->weapexist() && f->vehicle->color < 8*8 )
00402                fi.units[f->vehicle->color/8] += 1;
00403          }
00404          int n = 0;
00405          int c = -1;
00406          for ( int i = 0; i < 8; i++ ) {
00407             if ( fi.units[i] > n ) {
00408                n = fi.units[i];
00409                c = i;
00410             }
00411          }
00412          fi.control = c;
00413       }
00414    }
00415 }
00416 
00417 
00418 void     AI :: calculateAllThreats( void )
00419 {
00420    // Calculates the basethreats for all vehicle types
00421    if ( !baseThreatsCalculated ) {
00422       for ( int w = 0; w < vehicleTypeRepository.getNum(); w++) {
00423          Vehicletype* fzt = vehicleTypeRepository.getObject_byPos(w);
00424          if ( fzt )
00425             calculateThreat( fzt );
00426 
00427       }
00428       baseThreatsCalculated = 1;
00429    }
00430 
00431    // Some further calculations that only need to be done once.
00432    if ( maxTrooperMove == 0) {
00433       for ( int v = 0; v < vehicleTypeRepository.getNum(); v++) {
00434          Vehicletype* fzt = vehicleTypeRepository.getObject_byPos( v );
00435          if ( fzt )
00436             if ( fzt->hasFunction( ContainerBaseType::ConquerBuildings  ) )
00437                if ( fzt->movement[log2(chfahrend)] > maxTrooperMove )   // buildings can only be conquered on ground level, or by moving to adjecent field which is less
00438                   maxTrooperMove = fzt->movement[log2(chfahrend)];
00439       }
00440    }
00441    if ( maxTransportMove == 0 ) {
00442       for (int v = 0; v < vehicleTypeRepository.getNum(); v++) {
00443          Vehicletype* fzt = vehicleTypeRepository.getObject_byPos( v );
00444          if ( fzt )
00445             for ( int w = 0; w <= 7; w++) // cycle through all levels of height
00446                if (fzt->movement[w] > maxTransportMove)
00447                   maxTransportMove = fzt->movement[w];
00448       }
00449       maxUnitMove = maxTransportMove;
00450    }
00451    for ( int height = 0; height < 8; height++ )
00452       if ( maxWeapDist[height] < 0 ) {
00453 
00454          maxWeapDist[height] = 0; // It may be possible that there is no weapon to shoot to a specific height
00455 
00456          for ( int v = 0; v < vehicleTypeRepository.getNum(); v++) {
00457             Vehicletype* fzt = vehicleTypeRepository.getObject_byPos( v );
00458             if ( fzt )
00459                for ( int w = 0; w < fzt->weapons.count ; w++)
00460                   if ( fzt->weapons.weapon[w].maxdistance > maxWeapDist[height] )
00461                      if ( fzt->weapons.weapon[w].targ & ( 1 << height ))   // targ is a bitmap, each bit standing for a level of height
00462                          maxWeapDist[height] = fzt->weapons.weapon[w].maxdistance;
00463          }
00464       }
00465 
00466 
00467 
00468 
00469    // There are only 8 players in ASC, but there may be neutral units (player == 8)
00470    for ( int v = 0; v < 9; v++)
00471       if (activemap->player[v].exist() || v == 8) {
00472 
00473          // Now we cycle through all units of this player
00474          for ( Player::VehicleList::iterator vi = getPlayer(v).vehicleList.begin(); vi != getPlayer(v).vehicleList.end(); vi++ ) {
00475             Vehicle* veh = *vi;
00476             // if ( !veh->aiparam[ getPlayerNum() ] )
00477                calculateThreat ( veh );
00478          }
00479 
00480          // Now we cycle through all buildings
00481          for ( Player::BuildingList::iterator bi = getPlayer(v).buildingList.begin(); bi != getPlayer(v).buildingList.end(); bi++ )
00482             calculateThreat ( *bi );
00483       }
00484 
00485 }
00486 
00487 void AI :: FieldInformation :: reset ( )
00488 {
00489    threat.reset();
00490    for ( int i = 0; i< 8; i++ )
00491       units[i] = 0;
00492    control = -1;
00493 }
00494 
00495 
00496 AiThreat& AI :: getFieldThreat ( int x, int y )
00497 {
00498    if ( !fieldInformation )
00499       calculateFieldInformation ();
00500    return fieldInformation[y * activemap->xsize + x ].threat;
00501 }
00502 
00503 AI::FieldInformation& AI :: getFieldInformation ( int x, int y )
00504 {
00505    if ( !fieldInformation )
00506       calculateFieldInformation ();
00507    return fieldInformation[y * activemap->xsize + x ];
00508 }
00509 
00510 
00511 void AI :: Section :: init ( AI* _ai, int _x, int _y, int xsize, int ysize, int _xp, int _yp )
00512 {
00513    ai = _ai;
00514    init ( _x, _y, xsize, ysize, _xp, _yp );
00515 }
00516 
00517 void AI :: Section :: init ( int _x, int _y, int xsize, int ysize, int _xp, int _yp )
00518 {
00519    x1 = _x;
00520    y1 = _y;
00521    x2 = _x + xsize;
00522    y2 = _y + ysize;
00523 
00524    xp = _xp;
00525    yp = _yp;
00526 
00527    if ( x1 < 0 ) x1 = 0;
00528    if ( y1 < 0 ) y1 = 0;
00529    if ( x2 >= ai->activemap->xsize ) x2 = ai->activemap->xsize-1;
00530    if ( y2 >= ai->activemap->ysize ) y2 = ai->activemap->ysize-1;
00531 
00532 
00533    centerx = (x1 + x2) / 2;
00534    centery = (y1 + y2) / 2;
00535    numberOfFields = (x2-x1+1) * ( y2-y1+1);
00536 
00537    absUnitThreat.reset();
00538    absFieldThreat.reset();
00539 
00540    for ( int j = 0; j < aiValueTypeNum; j++ )
00541      value[j] = 0;
00542 
00543    for ( int y = y1; y <= y2; y++ )
00544       for ( int x = x1; x <= x2; x++ ) {
00545          absFieldThreat += ai->getFieldThreat ( x, y );
00546          tfield* fld = ai->activemap->getField ( x, y );
00547          if ( fld->vehicle && ai->getPlayer().diplomacy.isHostile( fld->vehicle->getOwner() ) ) {
00548             if ( !fld->vehicle->aiparam[ ai->getPlayerNum() ] )
00549                ai->calculateThreat ( fld->vehicle );
00550             AiParameter& aip = * fld->vehicle->aiparam[ ai->getPlayerNum() ];
00551             absUnitThreat += aip.threat;
00552             value[ aip.valueType ] += aip.getValue();
00553          }
00554       }
00555 
00556    for ( int i = 0; i <  absUnitThreat.threatTypes; i++ ) {
00557       avgUnitThreat.threat[i] = absUnitThreat.threat[i] / numberOfFields;
00558       avgFieldThreat.threat[i] = absFieldThreat.threat[i] / numberOfFields;
00559    }
00560 
00561 }
00562 
00563 int AI :: Section :: numberOfAccessibleFields ( const Vehicle* veh )
00564 {
00565    int num = 0;
00566    for ( int y = y1; y <= y2; y++ )
00567       for ( int x = x1; x <= x2; x++ )
00568          if ( fieldAccessible ( ai->activemap->getField ( x, y ), veh ) == 2)
00569             num++;
00570 
00571    return num;
00572 }
00573 
00574 AI :: Sections :: Sections ( AI* _ai ) : ai ( _ai ) , section ( NULL )
00575 {
00576    sizeX = 8;
00577    sizeY = 16;
00578    numX = ai->activemap->xsize * 2 / sizeX + 1;
00579    numY = ai->activemap->ysize * 2 / sizeY + 1;
00580 }
00581 
00582 void AI :: Sections :: reset ( void )
00583 {
00584    if ( section ) {
00585       delete[] section;
00586       section = NULL;
00587    }
00588 }
00589 
00590 
00591 void AI :: Sections :: calculate ( void )
00592 {
00593    if ( !section ) {
00594       section = new Section[ numX*numY ]; //  ( ai );
00595       for ( int x = 0; x < numX; x++ )
00596          for ( int y = 0; y < numY; y++ )
00597             section[ x + numX * y ].init ( ai, x * ai->activemap->xsize / numX, y * ai->activemap->ysize / numY, sizeX, sizeY, x, y );
00598 
00599     }
00600 }
00601 
00602 AI::Section& AI :: Sections :: getForCoordinate ( int xc, int yc )
00603 {
00604    if ( !section )
00605       calculate();
00606 
00607    int dist = maxint;
00608    Section* sec = NULL;
00609    for ( int x = 0; x < numX; x++ )
00610       for ( int y = 0; y < numY; y++ ) {
00611          Section& s2 = getForPos ( x, y );
00612          int d = beeline ( xc, yc, s2.centerx, s2.centery);
00613          if ( d < dist ) {
00614             dist = d;
00615             sec = &getForPos ( x, y );
00616          }
00617       }
00618 
00619    return *sec;
00620 }
00621 
00622 AI::Section& AI :: Sections :: getForPos ( int xn, int yn )
00623 {
00624    if ( xn >= numX || yn >= numY || xn < 0 || yn < 0 )
00625       displaymessage( "AI :: Sections :: getForPos - invalid parameters: %d %d", 2, xn, yn );
00626 
00627    return section[xn+yn*numX];
00628 }
00629 
00630 AI::Section* AI :: Sections :: getBest ( int pass, Vehicle* veh, MapCoordinate3D* dest, bool allowRefuellOrder, bool secondRun )
00631 {
00632    /*
00633       In the first pass wwe check were all the units would go if there wouldn't be
00634       a threat anywhere.
00635       In the second pass the threat of a section is devided by the number of units that
00636       are going there
00637    */
00638 
00639    AStar3D* ast = 0;
00640    RefuelConstraint* rfc = NULL;
00641    if ( RefuelConstraint::necessary ( veh, *ai )) {
00642       if ( secondRun )
00643          rfc = new RefuelConstraint ( *ai, veh, veh->maxMovement()*5 );
00644       else
00645          rfc = new RefuelConstraint ( *ai, veh );
00646 
00647       rfc->findPath();
00648    } else {
00649       ast = new AStar3D ( ai->getMap(), veh );
00650       ast->findAllAccessibleFields (  );
00651    }
00652 
00653 
00654    AiParameter& aip = *veh->aiparam[ ai->getPlayerNum() ];
00655 
00656    float d = minfloat;
00657    // float nd = minfloat;
00658    AI::Section* frst = NULL;
00659 
00660    float maxSectionThread = 0;
00661    for ( int y = 0; y < numY; y++ )
00662       for ( int x = 0; x < numX; x++ ) {
00663           AI::Section& sec = getForPos( x, y );
00664           int threat = sec.avgUnitThreat.threat[aip.valueType];
00665           if ( threat > maxSectionThread )
00666               maxSectionThread = threat;
00667       }
00668 
00669 
00670    TemporaryContainerStorage tus ( veh );
00671    veh->resetMovement(); // to make sure the wait-for-attack flag doesn't hinder the attack
00672    veh->attacked = 0;
00673 
00674    int sectionsPossibleWithMaxFuell = 0;
00675 
00676    for ( int h = 1; h < 0xff; h<<= 1 )
00677       if ( veh->typ->height & h )
00678          for ( int y = 0; y < numY; y++ )
00679             for ( int x = 0; x < numX; x++ ) {
00680                 int xtogoSec = -1;
00681                 int ytogoSec = -1;
00682 
00683                 AI::Section& sec = getForPos( x, y );
00684                 float t = 0;
00685                 for ( int i = 0; i < aiValueTypeNum; i++ )
00686                    t += aip.threat.threat[i] * sec.value[i];
00687 
00688                 float f = t;
00689 
00690                 if ( sec.avgUnitThreat.threat[ veh->getValueType(h) ] ) {
00691                    int relThreat = int( 4*maxSectionThread / sec.avgUnitThreat.threat[veh->getValueType(h)] + 1);
00692                    f /= relThreat;
00693                 }
00694 
00695                 /*
00696                 if ( sec.avgUnitThreat.threat[aip.valueType] >= 0 )
00697                    f = t / log( sec.avgUnitThreat.threat[aip.valueType] );
00698                 else
00699                    f = t;
00700                 */
00701 
00702                 int dist = beeline ( veh->xpos, veh->ypos, sec.centerx, sec.centery ) + 3 * veh->maxMovement();
00703                 if ( dist )
00704                    f /= log(double(dist));
00705 
00706                 if ( f > d ) {
00707                    int ac  = 0;
00708                    int nac = 0;
00709                    int mindist = maxint;
00710                    int targets = 0;
00711 
00712 
00713                    for ( int yp = sec.y1; yp <= sec.y2; yp++ )
00714                       for ( int xp = sec.x1; xp <= sec.x2; xp++ ) {
00715                          tfield* fld = ai->getMap()->getField(xp, yp );
00716                          if ( fld->a.temp & h ) {
00717                             int mandist = abs( sec.centerx - xp ) + 2*abs ( sec.centery - yp );
00718                             if ( mandist < mindist ) {
00719                                mindist = mandist;
00720                                xtogoSec = xp;
00721                                ytogoSec = yp;
00722                             }
00723 
00724                             ai->_vision = visible_all;
00725 
00726                             ac++;
00727 
00728                             veh->xpos = xp;
00729                             veh->ypos = yp;
00730                             veh->height = h;
00731 
00732                             VehicleAttack va ( NULL, NULL );
00733                             if ( va.available ( veh )) {
00734                                va.execute ( veh, -1, -1, 0, 0, -1 );
00735                                targets += va.attackableVehicles.getFieldNum();
00736                             }
00737                             ai->_vision = visible_ago;
00738                          } else
00739                             nac++;
00740                       }
00741 
00742                    if ( xtogoSec >= 0 && ytogoSec >= 0 )
00743                       if ( !rfc || rfc->returnFromPositionPossible ( MapCoordinate3D( xtogoSec, ytogoSec, h ))) {
00744                          int notAccessible = 100 * nac / (nac+ac);
00745                          if ( notAccessible < 85  && targets ) {   // less than 85% of fields not accessible
00746                             float nf = f * ( 100-notAccessible) / 100; // *  ( 100 - notAccessible );
00747                             if ( nf > d ) {
00748                                d = nf;
00749                                // nd = nf;
00750                                frst = &getForPos ( x, y );
00751                                if ( dest )
00752                                   *dest = MapCoordinate3D ( xtogoSec, ytogoSec, h );
00753                             }
00754                          }
00755                       } else
00756                          if ( allowRefuellOrder ) {
00757                             if ( rfc && rfc->returnFromPositionPossible ( MapCoordinate3D( xtogoSec, ytogoSec, h ), veh->getStorageCapacity().fuel ))
00758                                sectionsPossibleWithMaxFuell++;
00759                          }
00760 
00761                 }
00762             }
00763 
00764    tus.restore();
00765    delete ast;
00766    delete rfc;
00767 
00768    if ( !frst ) {
00769       if ( sectionsPossibleWithMaxFuell && allowRefuellOrder )
00770          ai->issueRefuelOrder ( veh, false );
00771       else
00772         if ( RefuelConstraint::necessary ( veh, *ai ) && !secondRun )
00773            return getBest ( pass, veh, dest, allowRefuellOrder, true );
00774 
00775    }
00776    return frst;
00777 
00778 }
00779 

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