Advanced Strategic Command
reactionfire.cpp
Go to the documentation of this file.
1 
2 
3 /*
4  This file is part of Advanced Strategic Command; http://www.asc-hq.de
5  Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; see the file COPYING. If not, write to the
19  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  Boston, MA 02111-1307 USA
21 */
22 
23 
24 #include "buildings.h"
25 #include "vehicle.h"
26 #include "typen.h"
27 #include "gamemap.h"
28 #include "stack.h"
29 #include "viewcalculation.h"
30 #include "replay.h"
31 #include "attack.h"
32 #include "util/messaginghub.h"
33 #include "mapdisplayinterface.h"
34 #include "reactionfire.h"
35 #include "spfst.h"
36 #include "itemrepository.h"
37 
38  typedef struct tunitlist* punitlist;
39  struct tunitlist {
41  punitlist next;
42  };
43 
44 const int rfPlayerCount = playerNum-1;
45 
46  punitlist unitlist[rfPlayerCount];
47 
48 
49 int tsearchreactionfireingunits :: maxshootdist[rfPlayerCount] = { -1, -1, -1, -1, -1, -1, -1, -1 };
50 
52 {
53  this->gamemap = gamemap;
54  for ( int i = 0; i < rfPlayerCount; i++ )
55  unitlist[i] = NULL;
56 }
57 
59 {
60  initLimits();
61  findOffensiveUnits( eht, pos.getNumericalHeight(), pos.x, pos.y, pos.x, pos.y );
62 }
63 
64 
65 void tsearchreactionfireingunits :: initLimits()
66 {
67  if ( maxshootdist[0] == -1 ) {
68  for (int i = 0; i < rfPlayerCount; i++ )
69  maxshootdist[i] = 0;
70 
71  for (int i = 0; i < vehicleTypeRepository.getNum(); i++ ) {
72  VehicleType* fzt = vehicleTypeRepository.getObject_byPos ( i );
73  if ( fzt )
74  for (int j = 0; j < fzt->weapons.count; j++ )
75  if ( fzt->weapons.weapon[j].shootable() )
76  for (int h = 0; h < choehenstufennum; h++ )
77  if ( fzt->weapons.weapon[j].targ & ( 1 << h ) )
78  if ( fzt->weapons.weapon[j].maxdistance > maxshootdist[h] )
80  }
81  }
82 }
83 
84 void tsearchreactionfireingunits :: findOffensiveUnits( Vehicle* vehicle, int height, int x1, int y1, int x2, int y2 )
85 {
86  x1 -= maxshootdist[height];
87  y1 -= maxshootdist[height];
88  x2 += maxshootdist[height];
89  y2 += maxshootdist[height];
90 
91  GameMap* gamemap = vehicle->getMap();
92 
93  if ( x1 < 0 )
94  x1 = 0;
95  if ( y1 < 0 )
96  y1 = 0;
97  if ( x2 >= gamemap->xsize )
98  x2 = gamemap->xsize -1;
99  if ( y2 >= gamemap->ysize )
100  y2 = gamemap->ysize -1;
101 
102  for ( int y = y1; y <= y2; y++ )
103  for ( int x = x1; x <= x2; x++ ) {
104  Vehicle* eht = gamemap->getField ( x, y )->vehicle;
105  if ( eht )
106  if ( eht->color != vehicle->color )
108  // if ( eht->reactionfire.enemiesAttackable & ( 1 << ( vehicle->color / 8 )))
109  if ( gamemap->player[eht->getOwner()].diplomacy.isHostile( gamemap->actplayer))
110  if ( attackpossible2u ( eht, vehicle, NULL, vehicle->typ->height ) )
111  addunit ( eht );
112 
113  }
114 
115  if ( gamemap->getField(vehicle->xpos, vehicle->ypos)->vehicle == vehicle )
116  for ( int i = 0; i < rfPlayerCount; i++ )
117  if ( fieldvisiblenow ( gamemap->getField ( vehicle->xpos, vehicle->ypos ), i )) {
118  punitlist ul = unitlist[i];
119  while ( ul ) {
120  punitlist next = ul->next;
121 
122  AttackWeap* atw = attackpossible ( ul->eht, vehicle->xpos, vehicle->ypos );
123  for ( int j = 0; j < atw->count; ++j )
124  if ( ul->eht->reactionfire.weaponShots[atw->num[j]] ) {
125  removeunit ( ul->eht );
126  break;
127  }
128 
129  delete atw;
130  ul = next;
131  } /* endwhile */
132  }
133 
134  for ( int player = 0; player < gamemap->getPlayerCount(); ++player ) {
135  if ( gamemap->getPlayer(vehicle).diplomacy.isHostile( player )) {
136  for ( Player::VehicleList::iterator i = gamemap->getPlayer(vehicle).vehicleList.begin(); i != gamemap->getPlayer(vehicle).vehicleList.end(); ++i) {
137  if ( fieldvisiblenow( gamemap->getField( (*i)->getPosition() ), player )) {
138  if ( visibleUnits.find( *i ) == visibleUnits.end() )
139  visibleUnits[*i] = 1 << player;
140  else
141  visibleUnits[*i] |= 1 << player;
142  }
143  }
144  }
145  }
146 
147 
148 }
149 
150 
151 void tsearchreactionfireingunits :: init ( Vehicle* vehicle, const AStar3D::Path& fieldlist )
152 {
153  initLimits();
154 
155  int x1 = maxint;
156  int y1 = maxint;
157  int x2 = 0;
158  int y2 = 0;
159 
160  for ( AStar3D::Path::const_iterator i = fieldlist.begin(); i != fieldlist.end(); i++) {
161  if ( i->x > x2 )
162  x2 = i->x ;
163  if ( i->y > y2 )
164  y2 = i->y ;
165 
166  if ( i->x < x1 )
167  x1 = i->x ;
168  if ( i->y < y1 )
169  y1 = i->y ;
170  }
171  findOffensiveUnits ( vehicle, getFirstBit ( vehicle->height ), x1,y1,x2,y2);
172 
173 }
174 
176 {
177  int c = eht->getOwner();
178  if ( c < 0 || c >= rfPlayerCount )
179  return;
180 
181  punitlist ul = new tunitlist;
182  ul->eht = eht;
183  ul->next= unitlist[c];
184  unitlist[c] = ul;
185 }
186 
187 
189 {
190  int c = vehicle->getOwner();
191  if ( c < 0 || c >= rfPlayerCount )
192  return;
193 
194  punitlist ul = unitlist[c];
195  punitlist last = NULL;
196  while ( ul && ul->eht != vehicle ) {
197  last = ul;
198  ul = ul->next;
199  }
200  if ( ul && ul->eht == vehicle ) {
201  if ( last )
202  last->next = ul->next;
203  else
204  unitlist[c] = ul->next;
205 
206  delete ul;
207  }
208 }
209 
210 
211 int tsearchreactionfireingunits :: attack( Vehicle* attacker, Vehicle* target, const Context& context )
212 {
213  MapField* fld = target->getMap()->getField( target->getPosition() );
214 
215 
216  int result = 0;
217  if ( attacker->reactionfire.canPerformAttack( target )) {
218  AttackWeap* atw = attackpossible ( attacker, target->xpos, target->ypos );
219  if ( atw->count ) { // && (attacker->reactionfire.enemiesAttackable & (1 << (target->color / 8)))) {
220 
221  int strength = 0;
222  int num = -1;
223  for ( int j = 0; j < atw->count; j++ )
224  if ( attacker->reactionfire.weaponShots[atw->num[j]] > 0 )
225  if ( atw->strength[j] > strength ) {
226  strength = atw->strength[j];
227  num = j;
228  }
229 
230  if ( num >= 0 ) {
231 
232  int visibility = 0;
233  if ( context.display ) {
234  MessagingHub::Instance().statusInformation( "attacking with weapon " + ASCString::toString( atw->num[num] ));
235 
236  if ( fieldvisiblenow ( gamemap->getField (attacker->xpos, attacker->ypos ), gamemap->getPlayerView())) {
237  ++visibility;
238  context.display->cursor_goto( attacker->getPosition() );
239  int t = ticker;
240  while ( t + 15 > ticker )
242  }
243 
244  if ( fieldvisiblenow ( fld, target, gamemap->getPlayerView() )) {
245  ++visibility;
246  context.display->cursor_goto( target->getPosition() );
247  int t = ticker;
248  while ( t + 15 > ticker )
250  }
251  }
252 
253  tunitattacksunit battle ( attacker, target, false, atw->num[num], true );
254  // int nwid = target->networkid;
255 
256  if ( context.display && visibility)
257  context.display->showBattle( battle );
258  else
259  battle.calc();
260 
261  if ( battle.dv.damage >= 100 )
262  result = 2;
263  else
264  result = 1;
265 
266  battle.setresult( context );
267 
268  updateFieldInfo();
269  }
270  }
271  delete atw;
272  }
273 
274  return result;
275 }
276 
277 
278 int tsearchreactionfireingunits :: checkfield ( const MapCoordinate3D& pos, Vehicle* &vehicle, const Context& context )
279 {
280 
281  int attacks = 0;
282  int result = 0;
283 
284  MapField* fld = gamemap->getField( pos.x, pos.y );
285 
286  for ( int i = 0; i < rfPlayerCount; i++ ) {
287  if ( fieldvisiblenow ( fld, i )) {
288  punitlist ul = unitlist[i];
289  while ( ul && !result ) {
290  punitlist next = ul->next;
291 
292  if ( ul->eht ) { // the unit
293  int nwid = ul->eht->networkid;
294  int r = attack( ul->eht, vehicle, context );
295  ul->eht = gamemap->getUnit(nwid); // could have been destroyed and be null now
296  if ( r > 0 )
297  ++attacks;
298 
299  if ( r > 1 )
300  result = 1;
301  }
302 
303  ul = next;
304  } /* endwhile */
305  }
306  }
307 
308  if ( result )
309  vehicle = NULL;
310 
311  return attacks;
312 }
313 
314 
315 int tsearchreactionfireingunits :: finalCheck ( int currentPlayer, const Context& context )
316 {
317  int destroyedUnits = 0;
318  for ( int player = 0; player < gamemap->getPlayerCount(); ++player ) {
319  if ( gamemap->getPlayer(currentPlayer).diplomacy.isHostile( player )) {
320  list<int> exposedTargets;
321  for ( Player::VehicleList::iterator exposedTarget = gamemap->getPlayer(currentPlayer).vehicleList.begin(); exposedTarget != gamemap->getPlayer(currentPlayer).vehicleList.end(); ++exposedTarget) {
322  if ( fieldvisiblenow( gamemap->getField( (*exposedTarget)->getPosition() ), player )) {
323  if ( visibleUnits.find( *exposedTarget ) == visibleUnits.end() || !(visibleUnits[*exposedTarget] & (1 << player)) ) {
324  if ( (*exposedTarget)->getMap()->getField( (*exposedTarget)->getPosition() )->unitHere( *exposedTarget ))
325  exposedTargets.push_back( (*exposedTarget )->networkid );
326  }
327  }
328  }
329 
330  for ( list<int>::iterator exposedTargetID = exposedTargets.begin(); exposedTargetID != exposedTargets.end(); ++exposedTargetID ) {
331  Vehicle* exposedTarget = gamemap->getUnit( *exposedTargetID );
332  if ( exposedTarget ) {
333  bool destroyed = false;
334 
335  for ( Player::VehicleList::iterator enemyUnit = gamemap->getPlayer(player).vehicleList.begin(); enemyUnit != gamemap->getPlayer(player).vehicleList.end() && !destroyed; ++enemyUnit) {
336  if ( (*enemyUnit)->reactionfire.canPerformAttack( exposedTarget )) {
337  if ( beeline( *enemyUnit, exposedTarget ) <= maxshootdist[ exposedTarget->getPosition().getNumericalHeight()]) {
338  int r = attack( *enemyUnit, exposedTarget, context );
339  if ( r > 1 ) {
340  destroyed = true;
341  ++destroyedUnits;
342  }
343  }
344  }
345  }
346  }
347  }
348  }
349  }
350  return destroyedUnits;
351 }
352 
353 
354 
356 {
357  for ( int i = 0; i < rfPlayerCount; i++ ) {
358  punitlist ul = unitlist[i];
359  while ( ul ) {
360  punitlist ul2 = ul->next;
361  delete ul;
362  ul = ul2;
363  }
364  }
365 }
366 
367 
368 
Player & getPlayer(PlayerID p)
Definition: gamemap.h:257
int xsize
the size of the map
Definition: gamemap.h:201
map accessing and usage routines used by ASC and the mapeditor
struct tfight::tavalues dv
punitlist unitlist[rfPlayerCount]
const int choehenstufennum
The number of levels of height.
Definition: typen.h:67
Vehicle * vehicle
Definition: mapfield.h:89
bool isHostile(PlayerID towardsPlayer) const
Definition: player.h:80
Structure to store the weapons which a unit can use to perform an attack.
Definition: attack.h:291
int strength[16]
Definition: attack.h:295
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
bool shootable(void) const
DiplomaticStateVector diplomacy
Definition: player.h:209
int targ
the weapon can attack targets at these levels of height (bitmapped)
Definition: vehicletype.h:105
int getOwner() const
returns the number of the player this vehicle/building belongs to
vector< int > weaponShots
Definition: vehicle.h:165
int getNumericalHeight() const
Definition: typen.h:242
MapCoordinate3D getPosition() const
returns the units position
Definition: vehicle.cpp:1552
SingleWeapon weapon[16]
Definition: vehicletype.h:170
The buildings which a placed on the map.
a single field of the map
Definition: mapfield.h:26
int checkfield(const MapCoordinate3D &pos, Vehicle *&eht, const Context &context)
void calc(void)
Performs the calculation of the attack. The result is only stored in the av and dv structures and is ...
Definition: attack.cpp:178
int height
the current level of height ( BITMAPPED ! )
Definition: vehicle.h:118
int beeline(const Vehicle *a, const Vehicle *b)
returns the distance between the units a and b
int getPlayerView() const
the player which is currently viewing the map.
Definition: gamemap.cpp:1007
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
const int rfPlayerCount
static ASCString toString(int i)
converts the parameter to a String
Definition: ascstring.cpp:193
class Vehicle::ReactionFire reactionfire
VehicleList vehicleList
a list of all units
Definition: player.h:135
ItemRepositoryLoader< VehicleType > vehicleTypeRepository("vehicletype")
Interface for recording and playing replays.
virtual void cursor_goto(const MapCoordinate &pos)=0
Definition of THE central asc class: GameMap.
Interface for all the fighting routines of ASC.
int maxdistance
the maximum distance the weapon can shoot
Definition: vehicletype.h:111
void setresult(const Context &context)
Writes the result of the attack calculation to the actual units.
Definition: attack.cpp:445
bool attackpossible2u(const Vehicle *attacker, const Vehicle *target, AttackWeap *atw, int targetheight)
Is attacker able to attack target ? Distance is not evaluated.
Definition: attack.cpp:939
int num[16]
Definition: attack.h:296
void removeunit(Vehicle *vehicle)
sigc::signal< void > updateFieldInfo
Definition: spfst.cpp:47
signed char actplayer
the player who is currently making his moves (may be human or AI)
Definition: gamemap.h:232
int releasetimeslice(void)
Definition: events.cpp:209
virtual int finalCheck(int currentPlayer, const Context &context)
Vehicle * getUnit(int x, int y, int nwid)
Definition: gamemap.cpp:1215
MapDisplayInterface * display
Definition: context.h:39
Player player[9]
Definition: gamemap.h:253
void addunit(Vehicle *vehicle)
int ysize
Definition: gamemap.h:201
int attack(Vehicle *attacker, Vehicle *target, const Context &context)
int height
the levels of height which this unit can enter
int color
The owner of the container.
int xpos
the position on the map
Definition: vehicle.h:124
int count
Definition: attack.h:294
deque< PathPoint > Path
Definition: astar2.h:48
const VehicleType * typ
Definition: vehicle.h:83
Coordinate on the map including height.
Definition: typen.h:238
AttackWeap * attackpossible(const Vehicle *attacker, int x, int y)
Is attacker able to attack anything in field x/y ?
Definition: attack.cpp:842
tsearchreactionfireingunits(GameMap *gamemap)
#define maxint
Definition: typen.h:462
bool canPerformAttack(Vehicle *target)
Definition: vehicle.cpp:763
GameMap * getMap() const
Status getStatus() const
for each player that can still be attacked one bit is set
Definition: vehicle.h:155
Vehicle * eht
const int playerNum
the maximum number of players that ASC can manage.
Definition: typen.h:54
virtual void showBattle(tfight &battle)=0
int ypos
Definition: vehicle.h:124
int getPlayerCount() const
Definition: gamemap.h:255
void init(Vehicle *eht, const AStar3D::Path &fieldlist)
struct tunitlist * punitlist
punitlist next
Interface for a small general-purpose stack (not type safe)
int networkid
a unique identification of the unit that is used everywhere in ASC (and not only the network protocol...
Definition: vehicle.h:140
The map. THE central structure of ASC, which holds everything not globally available together...
Definition: gamemap.h:182
volatile int ticker
Definition: events.cpp:234
MapField * getField(int x, int y)
Definition: gamemap.h:465