reactionfire.cpp

Go to the documentation of this file.
00001 
00002 
00003 /*
00004     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00005     Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; see the file COPYING. If not, write to the 
00019     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00020     Boston, MA  02111-1307  USA
00021 */
00022 
00023 
00024 #include "buildings.h"
00025 #include "vehicle.h"
00026 #include "typen.h"
00027 #include "gamemap.h"
00028 #include "stack.h"
00029 #include "viewcalculation.h"
00030 #include "replay.h"
00031 #include "attack.h"
00032 #include "util/messaginghub.h"
00033 #include "mapdisplayinterface.h"
00034 #include "reactionfire.h"
00035 #include "spfst.h"
00036 #include "itemrepository.h"
00037 
00038                 typedef struct tunitlist* punitlist;
00039                 struct tunitlist {
00040                         Vehicle* eht;
00041                         punitlist next;
00042                      };
00043 
00044                 punitlist unitlist[8];
00045 
00046 
00047 int tsearchreactionfireingunits :: maxshootdist[8] = { -1, -1, -1, -1, -1, -1, -1, -1 };
00048 
00049 tsearchreactionfireingunits :: tsearchreactionfireingunits ( GameMap* gamemap )
00050 {
00051    this->gamemap = gamemap;
00052    for ( int i = 0; i < 8; i++ )
00053       unitlist[i] = NULL;
00054 }
00055 
00056 void tsearchreactionfireingunits :: init ( Vehicle* eht, const MapCoordinate3D& pos )
00057 {
00058    initLimits();
00059    findOffensiveUnits( eht, pos.getNumericalHeight(), pos.x, pos.y, pos.x, pos.y );
00060 }
00061 
00062 
00063 void tsearchreactionfireingunits :: initLimits()
00064 {
00065    if ( maxshootdist[0] == -1 ) {
00066       for (int i = 0; i < 8; i++ )
00067          maxshootdist[i] = 0;
00068 
00069       for (int i = 0; i < vehicleTypeRepository.getNum(); i++ ) {
00070          VehicleType* fzt = vehicleTypeRepository.getObject_byPos ( i );
00071          if ( fzt )
00072             for (int j = 0; j < fzt->weapons.count; j++ )
00073                if ( fzt->weapons.weapon[j].shootable() )
00074                   for (int h = 0; h < 8; h++ )
00075                      if ( fzt->weapons.weapon[j].targ & ( 1 << h ) )
00076                         if ( fzt->weapons.weapon[j].maxdistance > maxshootdist[h] )
00077                            maxshootdist[h] = fzt->weapons.weapon[j].maxdistance;
00078       }
00079    }
00080 }
00081 
00082 void tsearchreactionfireingunits :: findOffensiveUnits( Vehicle* vehicle, int height, int x1, int y1, int x2, int y2 )
00083 {
00084    x1 -= maxshootdist[height];
00085    y1 -= maxshootdist[height];
00086    x2 += maxshootdist[height];
00087    y2 += maxshootdist[height];
00088 
00089    GameMap* gamemap = vehicle->getMap();
00090    
00091    if ( x1 < 0 )
00092       x1 = 0;
00093    if ( y1 < 0 )
00094       y1 = 0;
00095    if ( x2 >= gamemap->xsize )
00096       x2 = gamemap->xsize -1;
00097    if ( y2 >= gamemap->ysize )
00098       y2 = gamemap->ysize -1;
00099 
00100    for ( int y = y1; y <= y2; y++ )
00101       for ( int x = x1; x <= x2; x++ ) {
00102          Vehicle* eht = gamemap->getField ( x, y )->vehicle;
00103          if ( eht )
00104             if ( eht->color != vehicle->color )
00105                if ( eht->reactionfire.getStatus() >= Vehicle::ReactionFire::ready )
00106                   // if ( eht->reactionfire.enemiesAttackable & ( 1 << ( vehicle->color / 8 )))
00107                      if ( gamemap->player[eht->getOwner()].diplomacy.isHostile( gamemap->actplayer))
00108                         if ( attackpossible2u ( eht, vehicle, NULL, vehicle->typ->height ) )
00109                            addunit ( eht );
00110 
00111       }
00112       if ( gamemap->getField(vehicle->xpos, vehicle->ypos)->vehicle == vehicle )
00113          for ( int i = 0; i < 8; i++ )
00114             if ( fieldvisiblenow ( gamemap->getField ( vehicle->xpos, vehicle->ypos ), i )) {
00115             punitlist ul  = unitlist[i];
00116             while ( ul ) {
00117                punitlist next = ul->next;
00118                
00119                AttackWeap* atw = attackpossible ( ul->eht, vehicle->xpos, vehicle->ypos );
00120                for ( int j = 0; j < atw->count; ++j )
00121                   if ( ul->eht->reactionfire.weaponShots[atw->num[j]] ) {
00122                      removeunit ( ul->eht );
00123                      break;
00124                   }   
00125 
00126                delete atw;
00127                ul = next;
00128             } /* endwhile */
00129          }
00130 
00131    for ( int player = 0; player < gamemap->getPlayerCount(); ++player ) {
00132       if ( gamemap->getPlayer(vehicle).diplomacy.isHostile( player )) {
00133          for ( Player::VehicleList::iterator i = gamemap->getPlayer(vehicle).vehicleList.begin(); i != gamemap->getPlayer(vehicle).vehicleList.end(); ++i) {
00134             if ( fieldvisiblenow( gamemap->getField( (*i)->getPosition() ), player )) {
00135                if ( visibleUnits.find( *i ) == visibleUnits.end() )
00136                   visibleUnits[*i] = 1 << player;
00137                else
00138                   visibleUnits[*i] |= 1 << player;
00139             }
00140          }
00141       }
00142    }
00143      
00144 
00145 }
00146 
00147 
00148 void tsearchreactionfireingunits :: init ( Vehicle* vehicle, const AStar3D::Path& fieldlist )
00149 {
00150    initLimits();
00151 
00152    int x1 = maxint;
00153    int y1 = maxint;
00154    int x2 = 0;
00155    int y2 = 0;
00156 
00157    for ( AStar3D::Path::const_iterator i = fieldlist.begin(); i != fieldlist.end(); i++) {
00158       if ( i->x > x2 )
00159          x2 = i->x ;
00160       if ( i->y > y2 )
00161          y2 = i->y ;
00162 
00163       if ( i->x < x1 )
00164          x1 = i->x ;
00165       if ( i->y < y1 )
00166          y1 = i->y ;
00167    }
00168    findOffensiveUnits ( vehicle, getFirstBit ( vehicle->height ), x1,y1,x2,y2);
00169           
00170 }
00171 
00172 void  tsearchreactionfireingunits :: addunit ( Vehicle* eht )
00173 {
00174    int c = eht->color / 8;
00175    punitlist ul = new tunitlist;
00176    ul->eht = eht;
00177    ul->next= unitlist[c];
00178    unitlist[c] = ul;
00179 }
00180 
00181 
00182 void tsearchreactionfireingunits :: removeunit ( Vehicle* vehicle )
00183 {
00184    int c = vehicle->color / 8;
00185    punitlist ul = unitlist[c];
00186    punitlist last = NULL;
00187    while ( ul  &&  ul->eht != vehicle ) {
00188       last = ul;
00189       ul = ul->next;
00190   }
00191   if ( ul  &&  ul->eht == vehicle ) {
00192      if ( last )
00193         last->next = ul->next;
00194      else
00195         unitlist[c] = ul->next;
00196 
00197      delete ul;
00198   }
00199 }
00200 
00201 
00202 int tsearchreactionfireingunits :: attack( Vehicle* attacker, Vehicle* target, const Context& context )
00203 {
00204    MapField* fld = target->getMap()->getField( target->getPosition() );
00205    
00206    
00207    int result = 0;
00208    if ( attacker->reactionfire.canPerformAttack( target )) { 
00209       AttackWeap* atw = attackpossible ( attacker, target->xpos, target->ypos );
00210       if ( atw->count ) { // && (attacker->reactionfire.enemiesAttackable & (1 << (target->color / 8)))) {
00211 
00212          int ad1, ad2, dd1, dd2;
00213 
00214          int strength = 0;
00215          int num = -1;
00216          for ( int j = 0; j < atw->count; j++ )
00217             if ( attacker->reactionfire.weaponShots[atw->num[j]] > 0 )
00218                if ( atw->strength[j]  > strength ) {
00219                   strength = atw->strength[j];
00220                   num = j;
00221                }
00222 
00223                if ( num >= 0 ) {
00224 
00225                   int visibility = 0;
00226                   if ( context.display ) {
00227                      MessagingHub::Instance().statusInformation( "attacking with weapon " + ASCString::toString( atw->num[num] ));
00228 
00229                      if ( fieldvisiblenow ( gamemap->getField (attacker->xpos, attacker->ypos ), gamemap->getPlayerView())) {
00230                         ++visibility;
00231                         context.display->cursor_goto( attacker->getPosition() );
00232                         int t = ticker;
00233                         while ( t + 15 > ticker )
00234                            releasetimeslice();
00235                      }
00236 
00237                      if ( fieldvisiblenow ( fld, target, gamemap->getPlayerView() )) {
00238                         ++visibility;
00239                         context.display->cursor_goto( target->getPosition() );
00240                         int t = ticker;
00241                         while ( t + 15 > ticker )
00242                            releasetimeslice();
00243                      }
00244                   }
00245 
00246                   tunitattacksunit battle ( attacker, target, 0, atw->num[num], true );
00247                   // int nwid = target->networkid;
00248 
00249                   ad1 = battle.av.damage;
00250                   dd1 = battle.dv.damage;
00251 
00252                   if ( context.display && visibility)
00253                      context.display->showBattle( battle ); 
00254                   else
00255                      battle.calc();
00256 
00257                   ad2 = battle.av.damage;
00258                   dd2 = battle.dv.damage;
00259 
00260                   if ( battle.dv.damage >= 100 )
00261                      result = 2;
00262                   else
00263                      result = 1;
00264 
00265                   battle.setresult( context );
00266 
00267                   updateFieldInfo();
00268                }
00269       }
00270       delete atw;
00271    }
00272 
00273    return result;
00274 }
00275 
00276 
00277 int  tsearchreactionfireingunits :: checkfield ( const MapCoordinate3D& pos, Vehicle* &vehicle, const Context& context )
00278 {
00279 
00280    int attacks = 0;
00281    int result = 0;
00282 
00283    MapField* fld = gamemap->getField( pos.x, pos.y );
00284 
00285    for ( int i = 0; i < 8; i++ ) {
00286       if ( fieldvisiblenow ( fld, i )) {
00287          punitlist ul  = unitlist[i];
00288          while ( ul  &&  !result ) {
00289             punitlist next = ul->next;
00290             
00291             int r = attack( ul->eht, vehicle, context );
00292             if ( r > 0 )
00293                ++attacks;
00294             
00295             if ( r > 1 )
00296                result = 1;
00297             
00298             ul = next;
00299          } /* endwhile */
00300       }
00301    }
00302 
00303    if ( result )
00304       vehicle = NULL;
00305 
00306    return attacks;
00307 }
00308 
00309 
00310 int  tsearchreactionfireingunits :: finalCheck ( int currentPlayer, const Context& context )
00311 {
00312    int destroyedUnits = 0;
00313    for ( int player = 0; player < gamemap->getPlayerCount(); ++player ) {
00314       if ( gamemap->getPlayer(currentPlayer).diplomacy.isHostile( player )) {
00315          list<int> exposedTargets;
00316          for ( Player::VehicleList::iterator exposedTarget = gamemap->getPlayer(currentPlayer).vehicleList.begin(); exposedTarget != gamemap->getPlayer(currentPlayer).vehicleList.end(); ++exposedTarget) {
00317             if ( fieldvisiblenow( gamemap->getField( (*exposedTarget)->getPosition() ), player )) {
00318                if ( visibleUnits.find( *exposedTarget ) == visibleUnits.end() || !(visibleUnits[*exposedTarget] & (1 << player)) ) { 
00319                   if ( (*exposedTarget)->getMap()->getField( (*exposedTarget)->getPosition() )->unitHere( *exposedTarget ))
00320                      exposedTargets.push_back( (*exposedTarget )->networkid );
00321                }
00322             }
00323          }
00324           
00325          for ( list<int>::iterator exposedTargetID = exposedTargets.begin(); exposedTargetID != exposedTargets.end(); ++exposedTargetID ) {
00326             Vehicle* exposedTarget = gamemap->getUnit( *exposedTargetID );
00327             if ( exposedTarget )  {
00328                bool destroyed = false;
00329                
00330                for ( Player::VehicleList::iterator enemyUnit = gamemap->getPlayer(player).vehicleList.begin(); enemyUnit != gamemap->getPlayer(player).vehicleList.end() && !destroyed; ++enemyUnit) {
00331                   if ( (*enemyUnit)->reactionfire.canPerformAttack( exposedTarget )) {
00332                      if ( beeline( *enemyUnit, exposedTarget ) <= maxshootdist[ exposedTarget->getPosition().getNumericalHeight()]) {
00333                         int r = attack( *enemyUnit, exposedTarget, context );
00334                         if ( r > 1 ) { 
00335                            destroyed = true;
00336                            ++destroyedUnits;
00337                         }
00338                      }
00339                   } 
00340                }
00341             }
00342          }
00343       }
00344    }
00345    return destroyedUnits;
00346 }
00347 
00348 
00349 
00350 tsearchreactionfireingunits :: ~tsearchreactionfireingunits()
00351 {
00352    for ( int i = 0; i < 8; i++ ) {
00353       punitlist ul = unitlist[i];
00354       while ( ul ) {
00355          punitlist ul2 = ul->next;
00356          delete ul;
00357          ul = ul2;
00358       }
00359    }
00360 }
00361 
00362 
00363 

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