Advanced Strategic Command
valuation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  valuation.cpp - description
3  -------------------
4  begin : Fri Mar 30 2001
5  copyright : (C) 2001 by Martin Bickel
6  email : bickel@asc-hq.org
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include <iostream>
19 #include "ai_common.h"
20 #include "../actions/attackcommand.h"
21 #include "../actions/moveunitcommand.h"
22 
23 const int value_armorfactor = 100;
24 const int value_weaponfactor = 3000;
25 
26 const int ccbt_repairfacility = 200; // basic threatvalues for buildings
27 const int ccbt_hq = 10000;
28 const int ccbt_recycling = 50;
29 const int ccbt_training = 150;
30 
31 
32 
33 
34 
36  protected:
37  AI* ai;
38 
39  const VehicleType* fzt;
40  int weapthreat[8];
41  int value;
42 
43  virtual int getdamage ( void ) { return 0; };
44  virtual int getexpirience ( void ) { return 0; };
45  virtual int getammunition( int i ) { return 1; };
46  virtual int getheight ( void ) { return 255; };
47  public:
48  void calc_threat_vehicletype ( const VehicleType* _fzt );
49  CalculateThreat_VehicleType ( AI* _ai ) { ai = _ai; };
51  };
52 
54  protected:
56  virtual int getdamage ( void );
57  virtual int getexpirience ( void );
58  virtual int getammunition( int i );
59  virtual int getheight ( void );
60  public:
61  void calc_threat_vehicle ( Vehicle* _eht );
63  };
64 
65 
67 {
68  fzt = _fzt;
69 
70  for ( int j = 0; j < 8; j++ )
71  weapthreat[j] = 0;
72 
73  for ( int i = 0; i < fzt->weapons.count; i++)
74  if ( fzt->weapons.weapon[i].shootable() )
75  if ( fzt->weapons.weapon[i].offensive() )
76  for ( int j = 0; j < 8; j++)
77  if ( fzt->weapons.weapon[i].targ & (1 << j) ) {
78  int d = 0;
79  int m = 0;
80  AttackFormula af( ai->getMap() );
81  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
82  d++;
83  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())) );
84  m += int( n / log10(double(10*d)));
85  }
86  if (getammunition(i) == 0)
87  m /= 2;
88 
89  if ( (fzt->weapons.weapon[i].sourceheight & getheight()) == 0)
90  m /= 2;
91 
92  /*
93  if ( !(getheight() & ( 1 << j )))
94  m /= 2;
95  */
96 
97  if (m > weapthreat[j])
98  weapthreat[j] = m;
99  }
100 
101 
102  if ( !fzt->aiparam[ai->getPlayerNum()] )
103  fzt->aiparam[ ai->getPlayerNum() ] = new AiValue ( getFirstBit ( fzt->height ));
104 
105  for ( int l = 0; l < 8; l++ )
107 
108  value = fzt->armor * value_armorfactor * (100 - getdamage()) / 100;
109 
110  for ( int s = 0; s < 7; )
111  if ( weapthreat[s] < weapthreat[s+1] ) {
112  int temp = weapthreat[s];
113  weapthreat[s] = weapthreat[s+1];
114  weapthreat[s+1] = temp;
115  if ( s > 0 )
116  s--;
117  } else
118  s++;
119 
120  for ( int k = 0; k < 8; k++ )
121  value += weapthreat[k] * value_weaponfactor / (k+1);
122 
123  fzt->aiparam[ ai->getPlayerNum() ]->setValue ( value );
124  fzt->aiparam[ ai->getPlayerNum() ]->valueType = 0;
125 }
126 
127 
129 {
130  return eht->ammo[i];
131 }
132 
134 {
135  return eht->height;
136 }
137 
139 {
140  return eht->damage;
141 }
142 
144 {
146 }
147 
148 
150 {
151 
152  eht = _eht;
153  calc_threat_vehicletype ( vehicleTypeRepository.getObject_byID ( eht->typ->id ) );
154 
155  if ( !eht->aiparam[ai->getPlayerNum()] )
156  eht->aiparam[ai->getPlayerNum()] = new AiParameter ( eht );
157 
158  AiParameter* aip = eht->aiparam[ai->getPlayerNum()];
159  for ( int l = 0; l < 8; l++ )
160  aip->threat.threat[l] = eht->typ->aiparam[ ai->getPlayerNum() ]->threat.threat[l];
161 
162  int value = eht->typ->aiparam[ ai->getPlayerNum() ]->getValue();
163  for ( ContainerBase::Cargo::const_iterator i = eht->getCargo().begin(); i != eht->getCargo().end(); ++i )
164  if ( *i ) {
165  if ( !(*i)->aiparam[ai->getPlayerNum()] ) {
166  CalculateThreat_Vehicle ctv ( ai );
167  ctv.calc_threat_vehicle( *i );
168  }
169  value += (*i)->aiparam[ai->getPlayerNum()]->getValue();
170  }
171 
172 
173  aip->setValue ( value );
174 
175 
176  if ( aip->getJob() == AiParameter::job_undefined )
177  if ( eht->canMove() )
178  aip->setJob( AI::chooseJob ( eht->typ ));
179 /*
180  generatethreatvalue();
181  int l = 0;
182  for ( int b = 0; b <= 7; b++) {
183  eht->threatvalue[b] = weapthreatvalue[b];
184  if (weapthreatvalue[b] > l)
185  l = weapthreatvalue[b];
186  } <Zwischenablage leer>
187  eht->completethreatvalue = threatvalue2 + l;
188  eht->completethreatvaluesurr = threatvalue2 + l;
189  eht->threats = 0;
190 */
191 }
192 
193 AiParameter::JobList AI::chooseJob ( const VehicleType* typ )
194 {
195  AiParameter::JobList jobList;
196 
198  jobList.push_back ( typ->recommendedAIJob );
199  return jobList;
200  }
201 
202  int maxmove = minint;
203  for ( int i = 0; i< 8; i++ )
204  if ( typ->height & ( 1 << i ))
205  maxmove = max ( typ->movement[i] , maxmove );
206 
207  int maxstrength = minint;
208  for ( int w = 0; w < typ->weapons.count; w++ )
209  if ( typ->weapons.weapon[w].offensive() )
210  maxstrength= max ( typ->weapons.weapon[w].maxstrength, maxstrength );
211 
212  bool service = false;
213  for ( int w = 0; w < typ->weapons.count; w++ )
214  if ( typ->weapons.weapon[w].service() )
215  service = true;
216 
217  if ( ( typ->hasFunction( ContainerBaseType::ExternalRepair ) || service) && maxmove >= minmalq && maxstrength < 45)
218  jobList.push_back ( AiParameter::job_supply );
219 
220 
222  /* if ( functions & cf_trooper ) {
223  if ( typ->height & chfahrend )
224  jobList.push_back ( AiParameter::job_conquer );
225  } else { */
226  if ( maxstrength < maxmove )
227  jobList.push_back ( AiParameter::job_conquer );
228  // }
229  }
230 
231  if ( ( maxstrength*1.5 < typ->view
232  || (maxstrength*1.5 < typ->jamming && !typ->hasFunction( ContainerBaseType::JamsOnlyOwnField )))
233  && maxmove > minmalq )
234  jobList.push_back ( AiParameter::job_recon );
235 
236  if ( maxstrength > 0 )
237  jobList.push_back ( AiParameter::job_fight );
238 
239  jobList.push_back ( AiParameter::job_undefined );
240  return jobList;
241 }
242 
243 
244 
245 void AI :: calculateThreat ( const VehicleType* vt)
246 {
247  CalculateThreat_VehicleType ctvt ( this );
248  ctvt.calc_threat_vehicletype( vt );
249 }
250 
251 
252 void AI :: calculateThreat ( Vehicle* eht )
253 {
254  CalculateThreat_Vehicle ctv ( this );
255  ctv.calc_threat_vehicle( eht );
256 }
257 
258 
259 void AI :: calculateThreat ( Building* bld )
260 {
261  calculateThreat ( bld, getPlayerNum());
262 // calculateThreat ( bld, 8 );
263 }
264 
265 void AI :: calculateThreat ( Building* bld, int player )
266 {
267  if ( !bld->aiparam[ player ] )
268  bld->aiparam[ player ] = new AiValue ( getFirstBit ( bld->typ->height ) );
269 
270  int b;
271 
272 
273  // Since we have two different resource modes now, this calculation should be rewritten....
274  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);
275 
276  for ( ContainerBase::Cargo::const_iterator i = bld->getCargo().begin(); i != bld->getCargo().end(); ++i )
277  if ( *i ) {
278  if ( !(*i)->aiparam[ player ] )
279  calculateThreat ( *i );
280  value += (*i)->aiparam[ player ]->getValue();
281  }
282 
283  for (b = 0; b < bld->getProduction().size(); b++)
284  if ( bld->getProduction()[b] ) {
285  if ( !bld->getProduction()[b]->aiparam[ player ] )
286  calculateThreat ( bld->getProduction()[b] );
287  value += bld->getProduction()[b]->aiparam[ player ]->getValue() / 10;
288  }
289 
291  value += ccbt_repairfacility;
292 
294  value += ccbt_training;
296  value += ccbt_recycling;
297 
298  bld->aiparam[ player ]->setValue ( value );
299 }
300 
301 
302 
303 void AI :: WeaponThreatRange :: run ( Vehicle* _veh, int x, int y, AiThreat* _threat )
304 {
305  threat = _threat;
306  veh = _veh;
307  for ( height = 0; height < 8; height++ )
308  for ( weap = 0; weap < veh->typ->weapons.count; weap++ )
309  if ( veh->height & veh->typ->weapons.weapon[weap].sourceheight )
310  if ( (1 << height) & veh->typ->weapons.weapon[weap].targ )
311  if ( veh->typ->weapons.weapon[weap].shootable() && veh->typ->weapons.weapon[weap].offensive() ) {
312  initsearch ( MapCoordinate(x, y), veh->typ->weapons.weapon[weap].maxdistance/maxmalq, veh->typ->weapons.weapon[weap].mindistance/maxmalq );
313  startsearch();
314  }
315 }
316 
317 void AI :: WeaponThreatRange :: testfield ( const MapCoordinate& mc )
318 {
319  if ( dist*maxmalq <= veh->typ->weapons.weapon[weap].maxdistance )
320  if ( dist*maxmalq >= veh->typ->weapons.weapon[weap].mindistance ) {
321  AttackFormula af ( ai->getMap() );
322  int strength = int ( WeapDist::getWeaponStrength( &veh->typ->weapons.weapon[weap], ai->getMap()->getField(mc)->getWeather(), dist*maxmalq, veh->height, 1 << height )
323  * veh->typ->weapons.weapon[weap].maxstrength
324  * (1 + af.strength_experience ( veh->getExperience_offensive() ) + af.strength_attackbonus ( gamemap->getField(startPos)->getattackbonus() ))
325  * af.strength_damage ( veh->damage )
326  );
327 
328  if ( strength ) {
329  int pos = mc.x + mc.y * ai->getMap()->xsize;
330  if ( strength > threat[pos].threat[height] )
331  threat[pos].threat[height] = strength;
332  }
333  }
334 }
335 
336 void AI :: calculateFieldInformation ( void )
337 {
338  if ( fieldNum && fieldNum != activemap->xsize * activemap->ysize ) {
339  delete[] fieldInformation;
340  fieldInformation = NULL;
341  fieldNum = 0;
342  }
343  if ( !fieldInformation ) {
344  fieldNum = activemap->xsize * activemap->ysize;
345  fieldInformation = new FieldInformation[ fieldNum ];
346  } else
347  for ( int a = 0; a < fieldNum; a++ )
348  fieldInformation[ a ].reset();
349 
350  AiThreat* singleUnitThreat = new AiThreat[fieldNum];
351 
352  // we now check the whole map
353  for ( int y = 0; y < activemap->ysize; y++ ) {
354  checkKeys();
355  for ( int x = 0; x < activemap->xsize; x++ ) {
356  MapField* fld = activemap->getField ( x, y );
357  if ( config.wholeMapVisible || fieldvisiblenow ( fld, getPlayerNum() ) )
358  if ( fld->vehicle && getPlayer().diplomacy.isHostile( fld->vehicle->getOwner() )) {
359  WeaponThreatRange wr ( this );
360  if ( !fld->vehicle->typ->wait ) {
361 
362  // The unit may have already moved this turn.
363  // So we give it the maximum movementrange
364 
365  TemporaryContainerStorage tus ( fld->vehicle );
366 
367  fld->vehicle->setMovement ( fld->vehicle->maxMovement(), 0);
368 
369  if ( MoveUnitCommand::avail ( fld->vehicle )) {
370  MoveUnitCommand muc ( fld->vehicle );
371  muc.searchFields();
372 
373  const set<MapCoordinate3D>& fields = muc.getReachableFields();
374  for ( set<MapCoordinate3D>::const_iterator i = fields.begin(); i != fields.end(); ++i )
375  wr.run ( fld->vehicle, i->x, i->y, singleUnitThreat );
376 
377  const set<MapCoordinate3D>& ifields = muc.getReachableFieldsIndirect();
378  for ( set<MapCoordinate3D>::const_iterator i = ifields.begin(); i != ifields.end(); ++i )
379  wr.run ( fld->vehicle, i->x, i->y, singleUnitThreat );
380 
381  }
382  tus.restore();
383  } else
384  wr.run ( fld->vehicle, x, y, singleUnitThreat );
385 
386 
387  for ( int a = 0; a < fieldNum; a++ ) {
388  for ( int b = 0; b < 8; b++ )
389  fieldInformation[a].threat.threat[b] += singleUnitThreat[a].threat[b];
390 
391  singleUnitThreat[ a ].reset();
392  }
393  }
394 
395  FieldInformation& fi = fieldInformation[y*getMap()->xsize+x];
396  for ( int i = 0; i< sidenum; i++ ) {
398  if ( f && f->vehicle && f->vehicle->weapexist() && f->vehicle->color < 8*8 )
399  fi.units[f->vehicle->color/8] += 1;
400  }
401  int n = 0;
402  int c = -1;
403  for ( int i = 0; i < 8; i++ ) {
404  if ( fi.units[i] > n ) {
405  n = fi.units[i];
406  c = i;
407  }
408  }
409  fi.control = c;
410  }
411  }
412  delete[] singleUnitThreat;
413 }
414 
415 
416 void AI :: calculateAllThreats( void )
417 {
418  // Calculates the basethreats for all vehicle types
419  if ( !baseThreatsCalculated ) {
420  for ( int w = 0; w < vehicleTypeRepository.getNum(); w++) {
421  VehicleType* fzt = vehicleTypeRepository.getObject_byPos(w);
422  if ( fzt )
423  calculateThreat( fzt );
424 
425  }
426  baseThreatsCalculated = 1;
427  }
428 
429  // Some further calculations that only need to be done once.
430  if ( maxTrooperMove == 0) {
431  for ( int v = 0; v < vehicleTypeRepository.getNum(); v++) {
432  VehicleType* fzt = vehicleTypeRepository.getObject_byPos( v );
433  if ( fzt )
435  if ( fzt->movement[getFirstBit(chfahrend)] > maxTrooperMove ) // buildings can only be conquered on ground level, or by moving to adjecent field which is less
436  maxTrooperMove = fzt->movement[getFirstBit(chfahrend)];
437  }
438  }
439  if ( maxTransportMove == 0 ) {
440  for (int v = 0; v < vehicleTypeRepository.getNum(); v++) {
441  VehicleType* fzt = vehicleTypeRepository.getObject_byPos( v );
442  if ( fzt )
443  for ( int w = 0; w <= 7; w++) // cycle through all levels of height
444  if (fzt->movement[w] > maxTransportMove)
445  maxTransportMove = fzt->movement[w];
446  }
447  maxUnitMove = maxTransportMove;
448  }
449  for ( int height = 0; height < 8; height++ )
450  if ( maxWeapDist[height] < 0 ) {
451 
452  maxWeapDist[height] = 0; // It may be possible that there is no weapon to shoot to a specific height
453 
454  for ( int v = 0; v < vehicleTypeRepository.getNum(); v++) {
455  VehicleType* fzt = vehicleTypeRepository.getObject_byPos( v );
456  if ( fzt )
457  for ( int w = 0; w < fzt->weapons.count ; w++)
458  if ( fzt->weapons.weapon[w].maxdistance > maxWeapDist[height] )
459  if ( fzt->weapons.weapon[w].targ & ( 1 << height )) // targ is a bitmap, each bit standing for a level of height
460  maxWeapDist[height] = fzt->weapons.weapon[w].maxdistance;
461  }
462  }
463 
464 
465 
466 
467  // There are only 8 players in ASC, but there may be neutral units (player == 8)
468  for ( int v = 0; v < 9; v++)
469  if (activemap->player[v].exist() || v == 8) {
470 
471  // Now we cycle through all units of this player
472  for ( Player::VehicleList::iterator vi = getPlayer(v).vehicleList.begin(); vi != getPlayer(v).vehicleList.end(); vi++ ) {
473  Vehicle* veh = *vi;
474  // if ( !veh->aiparam[ getPlayerNum() ] )
475  calculateThreat ( veh );
476  }
477 
478  // Now we cycle through all buildings
479  for ( Player::BuildingList::iterator bi = getPlayer(v).buildingList.begin(); bi != getPlayer(v).buildingList.end(); bi++ )
480  calculateThreat ( *bi );
481  }
482 
483 }
484 
485 void AI :: FieldInformation :: reset ( )
486 {
487  threat.reset();
488  for ( int i = 0; i< 8; i++ )
489  units[i] = 0;
490  control = -1;
491 }
492 
493 
494 AiThreat& AI :: getFieldThreat ( int x, int y )
495 {
496  if ( !fieldInformation )
497  calculateFieldInformation ();
498  return fieldInformation[y * activemap->xsize + x ].threat;
499 }
500 
501 AI::FieldInformation& AI :: getFieldInformation ( int x, int y )
502 {
503  if ( !fieldInformation )
504  calculateFieldInformation ();
505  return fieldInformation[y * activemap->xsize + x ];
506 }
507 
508 
509 void AI :: Section :: init ( AI* _ai, int _x, int _y, int xsize, int ysize, int _xp, int _yp )
510 {
511  ai = _ai;
512  init ( _x, _y, xsize, ysize, _xp, _yp );
513 }
514 
515 void AI :: Section :: init ( int _x, int _y, int xsize, int ysize, int _xp, int _yp )
516 {
517  x1 = _x;
518  y1 = _y;
519  x2 = _x + xsize;
520  y2 = _y + ysize;
521 
522  xp = _xp;
523  yp = _yp;
524 
525  if ( x1 < 0 ) x1 = 0;
526  if ( y1 < 0 ) y1 = 0;
527  if ( x2 >= ai->activemap->xsize ) x2 = ai->activemap->xsize-1;
528  if ( y2 >= ai->activemap->ysize ) y2 = ai->activemap->ysize-1;
529 
530 
531  centerx = (x1 + x2) / 2;
532  centery = (y1 + y2) / 2;
533  numberOfFields = (x2-x1+1) * ( y2-y1+1);
534 
535  absUnitThreat.reset();
536  absFieldThreat.reset();
537 
538  for ( int j = 0; j < aiValueTypeNum; j++ )
539  value[j] = 0;
540 
541  for ( int y = y1; y <= y2; y++ )
542  for ( int x = x1; x <= x2; x++ ) {
543  absFieldThreat += ai->getFieldThreat ( x, y );
544  MapField* fld = ai->activemap->getField ( x, y );
545  if ( fld->vehicle && ai->getPlayer().diplomacy.isHostile( fld->vehicle->getOwner() ) ) {
546  if ( !fld->vehicle->aiparam[ ai->getPlayerNum() ] )
547  ai->calculateThreat ( fld->vehicle );
548  AiParameter& aip = * fld->vehicle->aiparam[ ai->getPlayerNum() ];
549  absUnitThreat += aip.threat;
550  value[ aip.valueType ] += aip.getValue();
551  }
552  }
553 
554  for ( int i = 0; i < absUnitThreat.threatTypes; i++ ) {
555  avgUnitThreat.threat[i] = absUnitThreat.threat[i] / numberOfFields;
556  avgFieldThreat.threat[i] = absFieldThreat.threat[i] / numberOfFields;
557  }
558 
559 }
560 
561 int AI :: Section :: numberOfAccessibleFields ( const Vehicle* veh )
562 {
563  int num = 0;
564  for ( int y = y1; y <= y2; y++ )
565  for ( int x = x1; x <= x2; x++ )
566  if ( fieldAccessible ( ai->activemap->getField ( x, y ), veh ) == 2)
567  num++;
568 
569  return num;
570 }
571 
572 AI :: Sections :: Sections ( AI* _ai ) : ai ( _ai ) , section ( NULL )
573 {
574  sizeX = 8;
575  sizeY = 16;
576  numX = ai->activemap->xsize * 2 / sizeX + 1;
577  numY = ai->activemap->ysize * 2 / sizeY + 1;
578 }
579 
580 void AI :: Sections :: reset ()
581 {
582  if ( section ) {
583  delete[] section;
584  section = NULL;
585  }
586 }
587 
588 AI :: Sections :: ~Sections()
589 {
590  reset();
591 }
592 
593 
594 void AI :: Sections :: calculate ( void )
595 {
596  if ( !section ) {
597  section = new Section[ numX*numY ]; // ( ai );
598  for ( int x = 0; x < numX; x++ )
599  for ( int y = 0; y < numY; y++ )
600  section[ x + numX * y ].init ( ai, x * ai->activemap->xsize / numX, y * ai->activemap->ysize / numY, sizeX, sizeY, x, y );
601 
602  }
603 }
604 
605 AI::Section& AI :: Sections :: getForCoordinate ( int xc, int yc )
606 {
607  if ( !section )
608  calculate();
609 
610  int dist = maxint;
611  Section* sec = NULL;
612  for ( int x = 0; x < numX; x++ )
613  for ( int y = 0; y < numY; y++ ) {
614  Section& s2 = getForPos ( x, y );
615  int d = beeline ( xc, yc, s2.centerx, s2.centery);
616  if ( d < dist ) {
617  dist = d;
618  sec = &getForPos ( x, y );
619  }
620  }
621 
622  return *sec;
623 }
624 
625 AI::Section& AI :: Sections :: getForPos ( int xn, int yn )
626 {
627  if ( xn >= numX || yn >= numY || xn < 0 || yn < 0 )
628  displaymessage( "AI :: Sections :: getForPos - invalid parameters: %d %d", 2, xn, yn );
629 
630  return section[xn+yn*numX];
631 }
632 
633 /*
634  This is like some ball rolling down from some high potential spike
635 */
636 MapCoordinate AI :: Sections :: getAlternativeField( const MapCoordinate& pos, map<MapCoordinate,int>* destinationCounter, int height, AStar3D* ast )
637 {
638  MapCoordinate result = pos;
639  int potential = destinationCounter->operator[](pos);
640  for ( int d = 0; d< 6; ++d ) {
642  if ( ast->getFieldAccess(m) & height) {
643  if ( destinationCounter->find( m ) == destinationCounter->end() )
644  return m;
645  else {
646  if ( (destinationCounter->find(m)->second * 11 / 10) < potential ) {
647  result = m;
648  potential = destinationCounter->find(m)->second;
649  }
650  }
651  }
652  }
653  if ( result == pos )
654  return result;
655  else
656  return getAlternativeField( result , destinationCounter, height, ast );
657 }
658 
659 
660 AI::Section* AI :: Sections :: getBest ( int pass, Vehicle* veh, MapCoordinate3D* dest, bool allowRefuellOrder, bool secondRun, map<MapCoordinate,int>* destinationCounter )
661 {
662  /*
663  In the first pass wwe check were all the units would go if there wouldn't be
664  a threat anywhere.
665  In the second pass the threat of a section is devided by the number of units that
666  are going there
667  */
668  AiParameter& aip = *veh->aiparam[ ai->getPlayerNum() ];
669 
670  float d = minfloat;
671  // float nd = minfloat;
672  AI::Section* frst = NULL;
673 
674  float maxSectionThread = 0;
675  for ( int y = 0; y < numY; y++ )
676  for ( int x = 0; x < numX; x++ ) {
677  AI::Section& sec = getForPos( x, y );
678  int threat = sec.avgUnitThreat.threat[aip.valueType];
679  if ( threat > maxSectionThread )
680  maxSectionThread = threat;
681  }
682 
683  AStar3D* ast = 0;
684  bool deleteAst = false;
685  RefuelConstraint* rfc = NULL;
686 
687  TemporaryContainerStorage tus ( veh );
688  veh->resetMovement(); // to make sure the wait-for-attack flag doesn't hinder the attack
689  veh->attacked = 0;
690 
691  int sectionsPossibleWithMaxFuell = 0;
692 
693  /*
694  int actfields = 0;
695 
696  for ( int h = 1; h < 0xff; h<<= 1 ) {
697  if ( veh->typ->height & h ) {
698  for ( int y = 0; y < numY; y++ ) {
699  for ( int x = 0; x < numX; x++ ) {
700  AI::Section& sec = getForPos( x, y );
701  float t = 0;
702  for ( int i = 0; i < aiValueTypeNum; i++ )
703  t += aip.threat.threat[i] * sec.value[i];
704 
705  float f = t;
706 
707  if ( sec.avgUnitThreat.threat[ veh->getValueType(h) ] ) {
708  int relThreat = int( 4*maxSectionThread / sec.avgUnitThreat.threat[veh->getValueType(h)] + 1);
709  f /= relThreat;
710  }
711 
712  int dist = beeline ( veh->xpos, veh->ypos, sec.centerx, sec.centery ) + 3 * veh->maxMovement();
713  if ( dist )
714  f /= log(double(dist));
715 
716  if ( f > d ) {
717  actfields += abs(sec.y1 - sec.y2) * abs(sec.x1 - sec.x2);
718  }
719  }
720  }
721  }
722  }
723 
724  if (actfields == 0) {
725  return NULL;
726  }
727  */
728 
729  for ( int h = 1; h < 0xff; h<<= 1 )
730  if ( veh->typ->height & h )
731  for ( int y = 0; y < numY; y++ )
732  for ( int x = 0; x < numX; x++ ) {
733  int xtogoSec = -1;
734  int ytogoSec = -1;
735 
736  AI::Section& sec = getForPos( x, y );
737  float t = 0;
738  for ( int i = 0; i < aiValueTypeNum; i++ )
739  t += aip.threat.threat[i] * sec.value[i];
740 
741  float f = t;
742 
743  if ( sec.avgUnitThreat.threat[ veh->getValueType(h) ] ) {
744  int relThreat = int( 4*maxSectionThread / sec.avgUnitThreat.threat[veh->getValueType(h)] + 1);
745  f /= relThreat;
746  }
747 
748  /*
749  if ( sec.avgUnitThreat.threat[aip.valueType] >= 0 )
750  f = t / log( sec.avgUnitThreat.threat[aip.valueType] );
751  else
752  f = t;
753  */
754 
755  int dist = beeline ( veh->xpos, veh->ypos, sec.centerx, sec.centery ) + 3 * veh->maxMovement();
756  if ( dist )
757  f /= log(double(dist));
758 
759  if ( f > d ) {
760  int ac = 0;
761  int nac = 0;
762  int mindist = maxint;
763  int targets = 0;
764 
765  // create an AStar3D object only when needed
766  if ( !ast ) {
767  if ( RefuelConstraint::necessary ( veh, *ai )) {
768  if ( secondRun )
769  rfc = new RefuelConstraint ( *ai, veh, veh->maxMovement()*5 );
770  else
771  rfc = new RefuelConstraint ( *ai, veh );
772 
773  rfc->findPath( false );
774  ast = rfc->getAst();
775  } else {
776  ast = new AStar3D ( ai->getMap(), veh, false );
777  ast->findAllAccessibleFields ( );
778  deleteAst = true;
779  }
780  }
781 
782 
783  for ( int yp = sec.y1; yp <= sec.y2; yp++ )
784  for ( int xp = sec.x1; xp <= sec.x2; xp++ ) {
785  if ( ast->getFieldAccess(xp, yp) & h ) {
786  int mandist = abs( sec.centerx - xp ) + 2*abs ( sec.centery - yp );
787  if ( mandist < mindist ) {
788  mindist = mandist;
789 
790  if ( destinationCounter && destinationCounter->find( MapCoordinate(xp,yp)) != destinationCounter->end() ) {
791  /* we are checking if there are too many units heading for this field already
792  check how many are for neighbouringfields */
793 
794 
795  MapCoordinate alt = getAlternativeField( MapCoordinate(xp,yp), destinationCounter, h, ast );
796  xtogoSec = alt.x;
797  ytogoSec = alt.y;
798  } else {
799  xtogoSec = xp;
800  ytogoSec = yp;
801  }
802  }
803 
804  ai->setVision(visible_all);
805 
806  ac++;
807 
808  veh->xpos = xp;
809  veh->ypos = yp;
810  veh->height = h;
811 
812  if ( AttackCommand::avail( veh )) {
813  AttackCommand attack ( veh );
814  attack.searchTargets();
815  targets += attack.getAttackableUnits().size();
816  }
817  ai->setVision(visible_ago);
818  } else
819  nac++;
820  }
821 
822  if ( xtogoSec >= 0 && ytogoSec >= 0 ) {
823  if ( !rfc || rfc->returnFromPositionPossible ( MapCoordinate3D( xtogoSec, ytogoSec, h ))) {
824  int notAccessible = 100 * nac / (nac+ac);
825  if ( notAccessible < 85 && targets ) { // less than 85% of fields not accessible
826  float nf = f * ( 100-notAccessible) / 100; // * ( 100 - notAccessible );
827  if ( nf > d ) {
828  d = nf;
829  // nd = nf;
830  frst = &getForPos ( x, y );
831  if ( dest )
832  *dest = MapCoordinate3D ( xtogoSec, ytogoSec, h );
833  }
834  }
835  } else
836  if ( allowRefuellOrder ) {
837  if ( rfc && rfc->returnFromPositionPossible ( MapCoordinate3D( xtogoSec, ytogoSec, h ), veh->getStorageCapacity().fuel ))
838  sectionsPossibleWithMaxFuell++;
839  }
840  }
841  }
842  }
843 
844  tus.restore();
845  if ( deleteAst ) {
846  delete ast;
847  } else {
848  ast = NULL;
849  delete rfc;
850  }
851 
852  if ( !frst ) {
853  if ( sectionsPossibleWithMaxFuell && allowRefuellOrder )
854  ai->issueRefuelOrder ( veh, false );
855  else
856  if ( RefuelConstraint::necessary ( veh, *ai ) && !secondRun )
857  return getBest ( pass, veh, dest, allowRefuellOrder, true );
858 
859  }
860  return frst;
861 
862 }
863 
void findAllAccessibleFields()
searches for all fields that are within the range of maxDist and marks them.
Definition: astar2.cpp:562
virtual int getdamage(void)
Definition: valuation.cpp:138
int fuel
Definition: typen.h:101
bool weapexist() const
Is the unit able to shoot ?
Definition: vehicle.cpp:796
bool wait
If the unit cannot attack in the same turn after it has moved, it has to wait.
Definition: vehicletype.h:197
int fieldAccessible(const MapField *field, const Vehicle *vehicle, int uheight, const bool *attacked, bool ignoreVisibility)
Definition: spfst.cpp:124
int xsize
the size of the map
Definition: gamemap.h:201
int getExperience_defensive() const
Definition: vehicle.cpp:258
bool service(void) const
void setValue(int _value)
int getValueType(int uheight) const
For the AI: calculating the ValueType if the unit was on the height uheight.
Definition: vehicle.h:389
const BuildingType * typ
Definition: buildings.h:48
int maxMovement() const
the maximum distance that the unit can drive in a single turn on the current level of height ...
Definition: vehicle.cpp:1069
int damage
Damage. 0 is no damage, when damage reaches 100 the container is destroyed.
the core formula, which weighs the different factory that go into the calculation ...
Definition: attack.h:42
GameMap * getMap(void)
returns the map this AI runson
Definition: ai.h:486
Vehicle * vehicle
Definition: mapfield.h:89
int energy
Definition: typen.h:99
#define minfloat
Definition: typen.h:466
AiParameter * aiparam[8]
Definition: vehicle.h:182
int ammo[16]
Definition: vehicle.h:87
int getFirstBit(int zahl)
Count the number of zero bits on the LSB side of "zahl".
Definition: misc.cpp:45
UnitWeapon weapons
The weapons.
Definition: vehicletype.h:248
Resources getStorageCapacity() const
returns the local storage capacity for the given resource, which depends on the resource mode of the ...
int sourceheight
the weapon can be shot from these levels of height (bitmapped)
Definition: vehicletype.h:108
bool shootable(void) const
int targ
the weapon can attack targets at these levels of height (bitmapped)
Definition: vehicletype.h:105
virtual int getexpirience(void)
Definition: valuation.cpp:44
bool hasFunction(ContainerFunctions function) const
void setMovement(int newmove, double cargoDivisor=-1)
sets a new distance that the unit can move
Definition: vehicle.cpp:527
int getOwner() const
returns the number of the player this vehicle/building belongs to
virtual ~CalculateThreat_VehicleType()
Definition: valuation.cpp:50
vector< AiParameter::Job > JobList
const int value_armorfactor
Definition: valuation.cpp:23
SingleWeapon weapon[16]
Definition: vehicletype.h:170
a single field of the map
Definition: mapfield.h:26
Definition: ai.h:44
if(!yyg->yy_init)
Definition: scanner.cpp:695
int threat[aiValueTypeNum]
const VehicleType * fzt
Definition: valuation.cpp:39
void calc_threat_vehicle(Vehicle *_eht)
Definition: valuation.cpp:149
void calc_threat_vehicletype(const VehicleType *_fzt)
Definition: valuation.cpp:66
virtual int getdamage(void)
Definition: valuation.cpp:43
void setJob(const JobList &jobs)
Definition: gamemap.cpp:2112
virtual int getheight(void)
Definition: valuation.cpp:133
const Production & getProduction() const
vector< int > movement
the distance a unit can travel each round. One value for each of the 8 levels of height ...
Definition: vehicletype.h:203
int view
the visibility range
int height
the current level of height ( BITMAPPED ! )
Definition: vehicle.h:118
const int aiValueTypeNum
how many different target types are there?
int beeline(const Vehicle *a, const Vehicle *b)
returns the distance between the units a and b
const int sidenum
the number of sides that a field has; is now fixed at 6;
Definition: typen.h:438
int getPlayerNum(void)
returns the number of the player which is controlled by this ai
Definition: ai.h:490
bool fieldvisiblenow(const MapField *pe, Vehicle *veh, int player)
{@
Definition: spfst.cpp:399
The class describing properties that are common to all vehicles of a certain kind.
Definition: vehicletype.h:177
#define maxmalq
Constants that specify the layout of ASC.
Definition: typen.h:429
The value of a unit for the AI.
VehicleList vehicleList
a list of all units
Definition: player.h:135
int mindistance
the minimal distance the weapon can shoot
Definition: vehicletype.h:114
ItemRepositoryLoader< VehicleType > vehicleTypeRepository("vehicletype")
const int value_weaponfactor
Definition: valuation.cpp:24
void reset(void)
Definition: gamemap.cpp:2085
void log(const Vehicle *attacker, const Vehicle *attackee)
Definition: attack.cpp:417
friend class Section
Definition: ai.h:448
Coordinate on the twodimensional map.
Definition: typen.h:202
the threat that a unit poses against other units.
Player & getPlayer(void)
Definition: ai.h:492
int jamming
the radar jamming power
void displaymessage(const char *formatstring, int num,...)
displays a dialog box with a message
Definition: dlg_box.cpp:1849
static float getWeaponStrength(const SingleWeapon *weap, int targetFieldWeather=0, int dist=-1, int attacker_height=-1, int defender_height=-1, int reldiff=-1)
Definition: attack.cpp:1092
CalculateThreat_Vehicle(AI *_ai)
Definition: valuation.cpp:62
static bool avail(Vehicle *eht)
int maxdistance
the maximum distance the weapon can shoot
Definition: vehicletype.h:111
virtual int getammunition(int i)
Definition: valuation.cpp:45
int material
Definition: typen.h:100
int getValue()
static bool avail(Vehicle *eht)
AiParameter::Job recommendedAIJob
the recommended task for the unit, set by the unit creater
Definition: vehicletype.h:268
virtual int getexpirience(void)
Definition: valuation.cpp:143
#define chfahrend
Definition: typen.h:413
AiThreat threat
Player player[9]
Definition: gamemap.h:253
Resources plus
the Resources that are produced each turn
virtual int getheight(void)
Definition: valuation.cpp:46
All parameters the AI stores persistently about a unit.
int ysize
Definition: gamemap.h:201
void attack(Vehicle *veh, const MapCoordinate &target)
int height
the levels of height which this unit can enter
BuildingList buildingList
a list of all units
Definition: player.h:139
bool canMove(void) const
can the unit move from its current position (does not check neighbouring fields)
Definition: vehicle.cpp:599
Resources actstorage
the current storage of Resources
Definition: buildings.h:91
AiValue * aiparam[8]
some information the AI stores about this unit
Definition: vehicletype.h:265
int color
The owner of the container.
const int ccbt_training
Definition: valuation.cpp:29
int xpos
the position on the map
Definition: vehicle.h:124
const VehicleType * typ
Definition: vehicle.h:83
int getFieldAccess(int x, int y)
Definition: astar2.cpp:582
bool attacked
did the unit already attack this turn
Definition: vehicle.h:109
Coordinate on the map including height.
Definition: typen.h:238
bool offensive(void) const
A 3D path finding algorithm, based on the 2D algorithm by Amit J. Patel.
Definition: astar2.h:19
#define maxint
Definition: typen.h:462
const int ccbt_repairfacility
Definition: valuation.cpp:26
#define minint
Definition: typen.h:463
An actual building on the map, which references a BuildingType Buildings have an owner,.
Definition: buildings.h:38
const T & max(const T &a, const T &b, const T &c)
Definition: misc.h:97
int maxstrength
strength of the weapon when fired over the minimal distance
Definition: vehicletype.h:120
const Cargo & getCargo() const
void resetMovement(void)
resets a units movement. This is called at the beginning of each turn.
Definition: vehicle.cpp:518
virtual int getammunition(int i)
Definition: valuation.cpp:128
int ypos
Definition: vehicle.h:124
bool exist() const
does the player exist at all
Definition: player.cpp:313
const int ccbt_recycling
Definition: valuation.cpp:28
#define minmalq
Definition: typen.h:430
MapCoordinate3D getNeighbouringFieldCoordinate(const MapCoordinate3D &pos, int direc)
returns the coordinate of the field that is adjecent to the given field in the direction of direc ...
const int ccbt_hq
Definition: valuation.cpp:27
CalculateThreat_VehicleType(AI *_ai)
Definition: valuation.cpp:49
MapField * getField(int x, int y)
Definition: gamemap.h:465
AiValue * aiparam[8]
Definition: buildings.h:65
int getExperience_offensive() const
Definition: vehicle.cpp:253