Advanced Strategic Command
buildingcapture.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  buildingcapture.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 "ai_common.h"
19 
20 #include "../actions/moveunitcommand.h"
21 
22 float AI :: getCaptureValue ( const Building* bld, Vehicle* veh )
23 {
24  HiddenAStar3D ast ( this, veh );
26  ast.findPath ( path, bld->getEntry() );
27  //if ( ast.getTravelTime() >= 0 )
28  if ( ast.visited.back().gval >= 0 )
29  // everything else being equal, prefer cheapest unit
30  // TODO: factor 0.0001 should be made configurable
31  return getCaptureValue ( bld, (int)(ast.visited.back().gval / veh->getMovement() ))-0.0001*veh->aiparam[getPlayerNum()]->getValue() ;
32  else
33  return -1;
34  // return minfloat; // this makes no sense as minfloat>0!
35 }
36 
37 
38 void AI :: BuildingCapture :: write ( tnstream& stream ) const
39 {
40  stream.writeInt( 20 );
41  stream.writeInt ( state );
42  stream.writeInt ( unit );
43  for ( vector<int>::const_iterator i = guards.begin(); i != guards.end(); i++ ) {
44  stream.writeInt ( 1 );
45  stream.writeInt ( *i );
46  }
47  stream.writeInt ( 0 );
48  stream.writeFloat ( captureValue );
49  stream.writeInt ( nearestUnit );
50 }
51 
52 void AI :: BuildingCapture :: read ( tnstream& stream )
53 {
54  stream.readInt(); // version
55  state = BuildingCaptureState( stream.readInt ( ));
56  unit = stream.readInt ( );
57  int i = stream.readInt ();
58  while ( i ) {
59  guards.push_back ( stream.readInt() );
60  i = stream.readInt();
61  }
62  captureValue = stream.readFloat ();
63  nearestUnit = stream.readInt ();
64 }
65 
66 
67 
69  protected:
70  AI& ai;
72  int mode; // (1): nur fusstruppen; (2): 1 und transporter; (3): 2 und geb´┐Żude
73  vector<Vehicle*> enemyUnits; // that can conquer the building
74  float getThreatValueOfUnit ( Vehicle* veh );
75  public:
76  void testfield ( const MapCoordinate& mc );
77  bool returnresult ( );
78  void unitfound ( Vehicle* eht );
79  bool canUnitCapture ( Vehicle* veh );
80  SearchReconquerBuilding ( AI& _ai, Building* bld ) : SearchFields ( _ai.getMap() ), ai ( _ai ), buildingToCapture ( bld ), mode(3) {};
81  };
82 
84 {
85  return !enemyUnits.empty();
86 }
87 
88 
90 {
91  enemyUnits.push_back ( eht );
93 }
94 
96 {
99 
100 }
101 
103 {
104  Vehicle* eht = gamemap->getField(mc)->vehicle;
105  if ( eht )
106  if ( ai.getPlayer().diplomacy.isHostile( eht->getOwner() ) ) {
107  if ( canUnitCapture ( eht )) {
108  if ( MoveUnitCommand::avail( eht )) {
109  MoveUnitCommand muc ( eht );
110  muc.searchFields();
111  if( muc.isFieldReachable( startPos, false ))
112  unitfound(eht);
113  }
114 
115  }
116  else
117  if (mode >= 2)
118  if (eht->typ->maxLoadableUnits > 0)
119  for ( ContainerBase::Cargo::const_iterator i = eht->getCargo().begin(); i != eht->getCargo().end(); ++i )
120  if ( *i )
121  if ( canUnitCapture ( *i ))
122  if (eht->maxMovement() + (*i)->maxMovement() >= beeline(mc, startPos))
123  unitfound(eht);
124 
125  }
126 /*
127  if ( bld )
128  if ( mode >= 3 )
129  if (getdiplomaticstatus(bld->color) != capeace)
130  for ( int w = 0; w <= 31; w++)
131  if ( bld->loading[w] )
132  if ( canUnitCapture ( bld->loading[w] ))
133  if ( bld->loading[w]->typ->movement[getFirstBit(bld->loading[w]->height)] <= beeline(xp,yp,startx,starty))
134  unitfound ( bld->loading[w] );
135 
136 */
137 }
138 
139 
140 float AI :: getCaptureValue ( const Building* bld, int traveltime )
141 {
142  if ( traveltime < 0 )
143  traveltime = 0;
144  return float(bld->aiparam[getPlayerNum()]->getValue()) / float(traveltime+1);
145 }
146 
147 
148 bool AI :: checkReConquer ( Building* bld, Vehicle* veh )
149 {
150  SearchReconquerBuilding srb ( *this, bld );
151  srb.initsearch ( bld->getEntry(), (maxTransportMove + maxUnitMove/2) / maxmalq + 1, 1 );
152  srb.startsearch();
153  bool enemyNear = srb.returnresult();
154 
155  if ( enemyNear && veh ) {
156  float f = 0;
157  for ( ContainerBase::Cargo::const_iterator i = bld->getCargo().begin(); i != bld->getCargo().end(); ++i )
158  if ( *i )
159  if ( (*i)->getMovement() )
160  f += (*i)->aiparam[ getPlayerNum()]->getValue();
161 
163  if ( f > veh->aiparam[getPlayerNum()]->getValue())
164  return false;
165  else
166  return true;
167  }
168 
169  return false;
170 }
171 
172 
176  float val;
177 };
178 
180 
181 typedef vector<pCaptureTriple> CaptureList;
182 
183 class CaptureTripleComp : public binary_function<pCaptureTriple,pCaptureTriple,bool> {
184 public:
185  explicit CaptureTripleComp() {};
186  bool operator() (const pCaptureTriple t1, const pCaptureTriple t2) const {
187  return t1->val > t2->val;
188  }
189 };
190 
191 void AI :: checkConquer( )
192 {
193  // remove all capture orders for buildings which are no longer controlled by the enemy
194 
195  for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); ) {
196  BuildingCaptureContainer::iterator nxt = bi;
197  ++nxt;
198  Vehicle* veh= getMap()->getUnit ( bi->second.unit );
199  Building* bld = getMap()->getField( bi->first )->building;
200  if ( !bld ) {
201  buildingCapture.erase ( bi );
202  bi = nxt;
203  continue;
204  }
205 
206  if ( !getPlayer(bld->getOwner()).diplomacy.isHostile( getPlayerNum() )
207  || !( veh && fieldAccessible ( getMap()->getField( bi->first ), veh ) == 2 )) {
208 
209  if ( veh ) {
210  veh->aiparam[getPlayerNum()]->resetTask ();
211  veh->aiparam[getPlayerNum()]->setNextJob();
212  }
213  buildingCapture.erase ( bi );
214  } else
215  if ( veh && veh->color != getPlayerNum()*8 )
216  buildingCapture.erase ( bi );
217 
218  bi = nxt;
219  }
220 
221  displaymessage2("check for capturing buildings ... ");
222 
223  // check for stagnation
224  int num_reachable_buildings=0;
225  for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); bi++ )
226  if ( bi->second.state!=BuildingCapture::conq_unreachable ) num_reachable_buildings++;
227  // if all blds are marked as unreachable, reevaluate in hope for a map-change
228  if ( buildingCapture.size()>0 && num_reachable_buildings==0 ) {
229  for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); bi++ )
230  bi->second.state=BuildingCapture::conq_noUnit;
231  }
232 
233  CaptureList captureList;
234 
235  int buildingCounter = 0;
236 
237  for ( int c = 0; c <= 8; c++ ) {
238  if ( c<8 ) {
239  if ( !getPlayer(c).exist() ) continue;
240  if ( !getPlayer().diplomacy.isHostile( c) ) continue;
241  }
242  for ( Player::BuildingList::iterator bi = getPlayer(c).buildingList.begin(); bi != getPlayer(c).buildingList.end(); bi++ ) {
243  Building* bld = *bi;
244  int reachable = 0;
245  if ( buildingCapture[ bld->getEntry() ].state != BuildingCapture::conq_noUnit ) continue;
246  bool enemyNear = checkReConquer ( bld, 0 );
247 
248  ++buildingCounter;
249  displaymessage2("check for capturing building %d ", buildingCounter);
250 
251  for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); vi++ ) {
252  Vehicle* veh = *vi;
253  if ( !veh->canMove() ) continue;
254  if ( fieldAccessible ( bld->getEntryField(), veh ) != 2 ) continue;
255  if ( c!=8 && !(veh->typ->hasFunction( ContainerBaseType::ConquerBuildings )) ) continue;
257  veh->aiparam[getPlayerNum()]->getTask() != AiParameter::tsk_nothing ) continue;
258 
259  // here, units can be excluded from capturing
260  if ( c!=8 ) {
261  if( !veh->aiparam[getPlayerNum()]->hasJob(AiParameter::job_conquer) ) continue;
262  if( veh->aiparam[getPlayerNum()]->getTask() != AiParameter::tsk_nothing ) continue;
263  }
264 
265  // any further factors should be incorporated into getCaptureValue
266  float val=getCaptureValue( bld, veh );
267 
268  // malus if enemy is near (relevant if we are short of capture-units
269  // or building is practically worthless)
270  // TODO: should be made an optional parameter to getCaptureValue
271  if ( val>0 && enemyNear ) val -= 0.1*veh->aiparam[getPlayerNum()]->getValue();
272 
273 
274  if ( val > 0 ) {
275  pCaptureTriple triple = new CaptureTriple;
276  triple->bld=bld;
277  triple->veh=veh;
278  triple->val=val;
279  captureList.push_back( triple );
280  reachable = true;
281  }
282  }
283  if ( reachable==0 )
284  buildingCapture[ bld->getEntry() ].state = BuildingCapture::conq_unreachable;
285  }
286  }
287 
288  sort ( captureList.begin(), captureList.end(), CaptureTripleComp() );
289 
290  for ( CaptureList::iterator i = captureList.begin(); i != captureList.end(); i++ ) {
291  Building* bld = (*i)->bld;
292  Vehicle* veh = (*i)->veh;
293  // float val = (*i)->val;
294  delete (*i);
295 
296  // check whether bld and veh are still available
297  if ( buildingCapture[ bld->getEntry() ].state != BuildingCapture::conq_noUnit ) continue;
299  veh->aiparam[getPlayerNum()]->getTask() != AiParameter::tsk_nothing ) continue;
300 
301  // dispatch capture order
302  BuildingCapture& bc = buildingCapture[ bld->getEntry() ];
304  bc.state = BuildingCapture::conq_conqUnit;
305  else
306  bc.state = BuildingCapture::conq_unitNotConq;
307  bc.unit = veh->networkid;
308 
311  veh->aiparam[getPlayerNum()]->dest.setnum( bld->getEntry().x, bld->getEntry().y, -1 );
312  }
313 
314  // execute capture orders
315  for ( BuildingCaptureContainer::iterator bi = buildingCapture.begin(); bi != buildingCapture.end(); ) {
316  BuildingCaptureContainer::iterator nxt = bi;
317  ++nxt;
318  Vehicle* veh = getMap()->getUnit ( bi->second.unit );
319  if ( veh ) {
320  MapCoordinate3D dest = veh->aiparam[getPlayerNum()]->dest;
321  int nwid = veh->networkid;
322  moveUnit ( veh, dest, true );
323  if ( getMap()->getUnit ( nwid ) && veh->getPosition() == dest ) {
324  veh->aiparam[getPlayerNum()]->resetTask ();
325  buildingCapture.erase ( bi );
326  }
327  } else
328  buildingCapture.erase ( bi );
329  checkKeys();
330  bi = nxt;
331  }
332 
333  // do something useful with units that are not used for capturing buildings
334  for ( Player::VehicleList::iterator vi = getPlayer().vehicleList.begin(); vi != getPlayer().vehicleList.end(); vi++ )
335  if ( (*vi)->aiparam[getPlayerNum()] )
336  if ( (*vi)->aiparam[getPlayerNum()]->getJob() == AiParameter::job_conquer &&
337  (*vi)->aiparam[getPlayerNum()]->getTask() == AiParameter::tsk_nothing )
338  (*vi)->aiparam[getPlayerNum()]->setNextJob();
339 
340 }
341 
342 
bool canUnitCapture(Vehicle *veh)
int fieldAccessible(const MapField *field, const Vehicle *vehicle, int uheight, const bool *attacked, bool ignoreVisibility)
Definition: spfst.cpp:124
int maxLoadableUnits
the maximum number of units that can be loaded
virtual void writeInt(int i)
Writes a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is p...
Definition: basestrm.cpp:363
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
GameMap * getMap(void)
returns the map this AI runson
Definition: ai.h:486
Vehicle * vehicle
Definition: mapfield.h:89
bool isHostile(PlayerID towardsPlayer) const
Definition: player.h:80
void testfield(const MapCoordinate &mc)
A 3D path finding algorithm which tries to keep the units hidden from view.
Definition: ai_common.h:96
AiParameter * aiparam[8]
Definition: vehicle.h:182
virtual int readInt(void)
Reads a 32 bit signed Integer. In the stream little-endian byte order is used and a translation is pe...
Definition: basestrm.cpp:284
bool operator()(const pCaptureTriple t1, const pCaptureTriple t2) const
SearchReconquerBuilding(AI &_ai, Building *bld)
DiplomaticStateVector diplomacy
Definition: player.h:209
bool hasFunction(ContainerFunctions function) const
int getOwner() const
returns the number of the player this vehicle/building belongs to
MapCoordinate3D getEntry() const
returns the position of the buildings entry
Definition: buildings.cpp:410
bool hasJob(Job j)
Definition: gamemap.cpp:2130
MapCoordinate3D getPosition() const
returns the units position
Definition: vehicle.cpp:1552
The interface for all kinds of IO stream.
Definition: ai.h:44
MapField * getEntryField() const
returns the field the buildings entry is standing on
Definition: buildings.cpp:405
vector< Vehicle * > enemyUnits
void setJob(const JobList &jobs)
Definition: gamemap.cpp:2112
float getThreatValueOfUnit(Vehicle *veh)
void setNextJob()
Definition: gamemap.cpp:2153
int beeline(const Vehicle *a, const Vehicle *b)
returns the distance between the units a and b
virtual float readFloat(void)
Reads a flaot variable.
Definition: basestrm.cpp:328
int getPlayerNum(void)
returns the number of the player which is controlled by this ai
Definition: ai.h:490
#define maxmalq
Constants that specify the layout of ASC.
Definition: typen.h:429
VehicleList vehicleList
a list of all units
Definition: player.h:135
void setTask(Task t)
void unitfound(Vehicle *eht)
Coordinate on the twodimensional map.
Definition: typen.h:202
Player & getPlayer(void)
Definition: ai.h:492
searches fields in hexagonal "circles" around a field and calls testfield for each field ...
Definition: mapalgorithms.h:28
void setnum(int _x, int _y, int numericalz)
Definition: typen.h:250
void resetTask()
Definition: gamemap.cpp:2097
int getValue()
static bool avail(Vehicle *eht)
Vehicle * getUnit(int x, int y, int nwid)
Definition: gamemap.cpp:1215
MapCoordinate startPos
Definition: mapalgorithms.h:31
void setAdditionalValue(int _addedValue)
vector< pCaptureTriple > CaptureList
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
void displaymessage2(const char *formatstring,...)
displays a message in the status line of ASC
int color
The owner of the container.
ActionResult searchFields(int height=-1, int capabilities=0)
deque< PathPoint > Path
Definition: astar2.h:48
const VehicleType * typ
Definition: vehicle.h:83
Coordinate on the map including height.
Definition: typen.h:238
Building * building
Definition: mapfield.h:102
virtual void writeFloat(float f)
Write a floating point variable.
Definition: basestrm.cpp:385
struct CaptureTriple * pCaptureTriple
An actual building on the map, which references a BuildingType Buildings have an owner,.
Definition: buildings.h:38
MapCoordinate3D dest
const Cargo & getCargo() const
bool isFieldReachable(const MapCoordinate &pos, bool direct)
checks if the field can be reached by the unit this turn Precondition: searchFields(int,int) was called
GameMap * gamemap
Definition: mapalgorithms.h:30
int networkid
a unique identification of the unit that is used everywhere in ASC (and not only the network protocol...
Definition: vehicle.h:140
int getMovement(bool checkFuel=true, bool checkRF=true) const
returns the movement points the unit has left for this turn. CheckFuel should almost always be true...
Definition: vehicle.cpp:558
bool exist() const
does the player exist at all
Definition: player.cpp:313
MapField * getField(int x, int y)
Definition: gamemap.h:465
AiValue * aiparam[8]
Definition: buildings.h:65