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

viewcalculation.cpp

Go to the documentation of this file.
00001 
00005 /***************************************************************************
00006                           viewcalculation.cpp  -  description
00007                              -------------------
00008     begin                : Thu Oct 5 2000
00009     copyright            : (C) 2000 by Martin Bickel
00010     email                : bickel@asc-hq.org
00011  ***************************************************************************/
00012 
00013 /***************************************************************************
00014  *                                                                         *
00015  *   This program is free software; you can redistribute it and/or modify  *
00016  *   it under the terms of the GNU General Public License as published by  *
00017  *   the Free Software Foundation; either version 2 of the License, or     *
00018  *   (at your option) any later version.                                   *
00019  *                                                                         *
00020  ***************************************************************************/
00021 
00022 #include "global.h" 
00023 #include "viewcalculation.h"
00024 #include "mapalgorithms.h"
00025 
00026 #include "vehicletype.h"
00027 #include "buildingtype.h"
00028 #include "errors.h"
00029 #include "gameeventsystem.h"
00030 
00031 SigC::Signal0<void> buildingSeen;
00032 
00033 
00034 void         tcomputeview::initviewcalculation(  int view, int jamming, int sx, int sy, int _mode, int _height  )  // mode: +1 = add view  ;  -1 = remove view
00035 {
00036    height = _height;
00037 
00038    if ( view < 0 )
00039       view = 0;
00040 
00041    if ( view > 255 )
00042       viewdist = 255;
00043    else
00044       viewdist = view;
00045    jamdist  = jamming;
00046    mode = _mode;
00047 
00048    int md;
00049    if ( viewdist > jamdist )
00050       md = viewdist / minmalq + 1;
00051    else
00052       md = jamdist / minmalq + 1;
00053 
00054    initsearch( MapCoordinate(sx, sy), md, 0 );
00055 }
00056 
00057 
00058 
00059 void         tcomputeview::testfield( const MapCoordinate& mc )
00060 {
00061    int f = beeline(startPos, mc);
00062    tfield* efield = gamemap->getField(mc);
00063 
00064    if ( viewdist && ( f <= 15 ) && (gamemap->getgameparameter( cgp_disableDirectView) == 0  || f < 10 ) )
00065       efield->view[player].direct += mode;
00066 
00067    int str = viewdist;
00068    if ( f ) {
00069       int freefields = 0;
00070 #if 0
00071       if ( height > chhochfliegend )
00072          freefields = 5;
00073       else
00074       if ( height == chhochfliegend )
00075          freefields = 3;
00076       else
00077       if ( height == chfliegend )
00078          freefields = 2;
00079       else
00080       if ( height == chtieffliegend )
00081          freefields = 1;
00082 #endif
00083       if ( height > chhochfliegend )
00084          baseJammingMultiplier = 33;
00085       else
00086       if ( height == chhochfliegend )
00087          baseJammingMultiplier = 50;
00088       else
00089       if ( height == chfliegend )
00090          baseJammingMultiplier = 66;
00091       else
00092          baseJammingMultiplier = 100;
00093       
00094 
00095      tdrawgettempline lne ( freefields, gamemap );
00096 
00097      if ( startPos.x == -1 || startPos.y == -1 )
00098         fatalError("error in tcomputeview::testfield" );
00099 
00100      lne.start ( startPos.x, startPos.y, mc.x, mc.y );
00101      str -= f;
00102      str -= lne.tempsum * baseJammingMultiplier / 100;
00103    }
00104 
00105    if ( str > 0 ) {
00106       efield->view[player].view += str * mode;
00107 
00108       if ( sonar )
00109          efield->view[player].sonar += mode;
00110 
00111       if ( satellitenview )
00112          efield->view[player].satellite += mode;
00113 
00114       if ( minenview )
00115          efield->view[player].mine += mode;
00116    }
00117 
00118    if ( rangeJamming || !f ) {
00119       int jamloss = f * gamemap->getgameparameter ( cgp_jammingSlope ) / 10;
00120       int jamstrength = jamdist * gamemap->getgameparameter ( cgp_jammingAmplifier ) / 100;
00121       if ( jamstrength >= jamloss )
00122          efield->view[player].jamming += (jamstrength - jamloss) * mode;
00123    }
00124 
00125    #ifdef DEBUGVIEW
00126      if ( efield->view[player].view      < 0 ||
00127           efield->view[player].sonar     < 0 ||
00128           efield->view[player].satellite < 0 ||
00129           efield->view[player].jamming   < 0 ||
00130           efield->view[player].mine      < 0 )
00131         displaymessage ( "Warning: inconsistency in view calculation !!\n Please report this bug !", 1 );
00132    #endif
00133 }
00134 
00135 
00136 
00137 void         tcomputevehicleview::init( const Vehicle* eht, int _mode  )   // mode: +1 = add view  ;  -1 = remove view ); )
00138 {
00139    player = eht->getOwner();
00140 
00141    if ( player >= eht->getMap()->getPlayerCount() )
00142       fatalError ( "ComputeVehicleView::init - invalid player ");
00143 
00144    if ( eht->height == chsatellit )
00145       satellitenview = 1;
00146    else
00147       satellitenview = eht->typ->hasFunction( ContainerBaseType::SatelliteView  );
00148 
00149    sonar =  eht->typ->hasFunction( ContainerBaseType::Sonar );
00150    minenview = eht->typ->hasFunction( ContainerBaseType::MineView  );
00151    if ( eht->typ->hasFunction( ContainerBaseType::JamsOnlyOwnField  ) )
00152       rangeJamming = false;
00153 
00154    if ( eht->typ->hasFunction( ContainerBaseType::DetectsMineralResources  ) && _mode == 1 )
00155       eht->searchForMineralResources();
00156 
00157    int view = eht->typ->view+1;
00158    if ( eht->height <= chfahrend) {
00159       view += gamemap->getField ( eht->getPosition() )->viewbonus;
00160       if ( view < 1 )
00161          view = 1;
00162    }
00163 
00164 
00165    tcomputeview::initviewcalculation( view, eht->typ->jamming, eht->xpos, eht->ypos, _mode, eht->height );
00166  //  testfield( eht->getPosition() );
00167 
00168 }
00169 
00170 
00171 
00172 void         tcomputebuildingview::init( const Building*    bld,  int _mode )
00173 {
00174    player = bld->getOwner();
00175 
00176    if ( player >= bld->getMap()->getPlayerCount() )
00177       fatalError ( "ComputeBuildingView::init - invalid player ");
00178 
00179    int  c, j ;
00180 
00181    if (bld->getCompletion() == bld->typ->construction_steps - 1) {
00182       c = bld->typ->view + 1;
00183       if ( bld->typ->buildingheight <= chfahrend ) {
00184          c += gamemap->getField ( bld->getEntry() )->viewbonus;
00185          if ( c < 1 )
00186             c = 1;
00187       }
00188       j = bld->typ->jamming;
00189    } else {
00190       c = 15;
00191       j = 0;
00192    }
00193 
00194    initviewcalculation( c, j, bld->getEntry().x, bld->getEntry().y, _mode, bld->typ->buildingheight );
00195    
00196    if ( bld->typ->buildingheight == chsatellit )
00197       satellitenview = 1;
00198    else
00199       satellitenview = bld->typ->hasFunction( ContainerBaseType::SatelliteView  );
00200 
00201    sonar =  bld->typ->hasFunction( ContainerBaseType::Sonar );
00202    minenview = bld->typ->hasFunction( ContainerBaseType::MineView  );
00203    if ( bld->typ->hasFunction( ContainerBaseType::JamsOnlyOwnField  ) )
00204       rangeJamming = false;
00205 
00206    building = bld;
00207 
00208    for ( int a = 0; a < 4; a++)
00209       for (int b = 0; b < 6; b++)
00210          if ( building->typ->fieldExists ( BuildingType::LocalCoordinate( a, b ) )) {
00211             tfield* efield = building->getField ( BuildingType::LocalCoordinate( a, b ) );
00212             if ( minenview )
00213                efield->view[player].mine += _mode;
00214             efield->view[player].direct += _mode;
00215          }
00216 }
00217 
00218 
00219 
00220 
00221 
00222 void         clearvisibility( GameMap* gamemap, int  reset )
00223 {
00224    if (!gamemap || (gamemap->xsize <= 0) || (gamemap->ysize <= 0))
00225      return;
00226 
00227    for ( int p = 0; p < gamemap->getPlayerCount() ; p++ )
00228       for ( Player::VehicleList::iterator i = gamemap->player[p].vehicleList.begin(); i != gamemap->player[p].vehicleList.end(); i++ )
00229          if ( (*i)->isViewing())
00230             (*i)->removeview();
00231 
00232    int l = 0;
00233    for ( int x = 0; x < gamemap->xsize ; x++)
00234          for ( int y = 0; y < gamemap->ysize ; y++) {
00235             tfield* fld = &gamemap->field[l];
00236             memset ( fld->view, 0, sizeof ( fld->view ));
00237             l++;
00238          }
00239 
00240 
00241 }
00242 
00243 
00244 VisibilityStates calcvisibilityfield ( GameMap* gamemap, tfield* fld, int player, int add, int initial, int additionalEnemyJamming )
00245 {
00246    if ( player == -1 )
00247       return visible_all;
00248    
00249    if ( player <= -2 )
00250       return visible_not;
00251 
00252    if ( gamemap->player[player].stat == Player::supervisor ) 
00253       return visible_all;
00254    
00255    if ( initial == 2 ) 
00256       return visible_all;
00257    
00258    
00259    VisibilityStates view = visible_not;
00260    
00261    if ( ((fld->visible >> (player * 2)) & 3) >= visible_ago || initial == 1)
00262       view = visible_ago;
00263 
00264    if ( add == -1 ) 
00265       add = getPlayersWithSharedViewMask( player, gamemap );
00266    
00267    add |= 1 << player;
00268 
00269    int sight = 0;
00270    int jamming = 0;
00271    int mine = 0;
00272    int satellite = 0;
00273    int direct = 0;
00274    int sonar = 0;
00275    for ( int i = 0; i < gamemap->getPlayerCount(); i++ ){
00276       if ( add & ( 1 << i )) {
00277          sight += fld->view[i].view;
00278          mine  += fld->view[i].mine;
00279          satellite += fld->view[i].satellite;
00280          direct += fld->view[i].direct;
00281          sonar += fld->view[i].sonar;
00282       } else
00283          jamming += fld->view[i].jamming;
00284    }
00285    if ( sight > (jamming + additionalEnemyJamming )   ||  direct  ) {
00286       if (( fld->vehicle  && ( fld->vehicle->getOwner() == player ) && false ) ||
00287             ( fld->vehicle  && ( fld->vehicle->height  < chschwimmend ) && sonar ) ||
00288             ( fld->building && ( fld->building->typ->buildingheight < chschwimmend ) && sonar ) ||
00289             ( !fld->mines.empty() && ( mine  ||  fld->mineowner() == player)) ||
00290             ( fld->vehicle  && ( fld->vehicle->height  >= chsatellit )  && satellite )) {
00291          return visible_all;
00292       } else {
00293          return visible_now;
00294       }
00295    } else
00296       return view;
00297 }
00298 
00299 int  evaluatevisibilityfield ( GameMap* gamemap, tfield* fld, int player, int add, int initial )
00300 {
00301    if ( player < 0 )
00302       return 0;
00303 
00304    int originalVisibility;
00305    if ( initial == 2 ) {
00306       fld->setVisibility(visible_all, player);
00307       return 0;
00308    } else {
00309       originalVisibility = (fld->visible >> (player * 2)) & 3;
00310       if ( originalVisibility >= visible_ago || initial == 1)
00311          fld->setVisibility(visible_ago, player);
00312    }
00313 
00314    VisibilityStates view = calcvisibilityfield( gamemap, fld, player, add, initial, 0 );
00315    fld->setVisibility( view, player );
00316    if ( view >= visible_now )
00317       if ( fld->building && (fld->building->connection & cconnection_seen))
00318          buildingSeen();
00319    return view != originalVisibility; 
00320 }
00321 
00322 
00323 int  evaluateviewcalculation ( GameMap* gamemap, int player_fieldcount_mask, bool disableShareView )
00324 {
00325    int initial = gamemap->getgameparameter ( cgp_initialMapVisibility );
00326    int fieldsChanged = 0;
00327    for ( int player = 0; player < gamemap->getPlayerCount(); player++ )
00328       if ( gamemap->player[player].exist() ) {
00329          int add = 0;
00330          if ( !disableShareView )
00331             add += getPlayersWithSharedViewMask( player, gamemap );
00332       
00333          int nm = gamemap->xsize * gamemap->ysize;
00334          if ( player_fieldcount_mask & (1 << player ))
00335             for ( int i = 0; i < nm; i++ )
00336                 fieldsChanged += evaluatevisibilityfield ( gamemap, &gamemap->field[i], player, add, initial );
00337          else
00338             for ( int i = 0; i < nm; i++ )
00339                 evaluatevisibilityfield ( gamemap, &gamemap->field[i], player, add, initial );
00340       }
00341    return fieldsChanged;
00342 }
00343 
00344 int  evaluateviewcalculation ( GameMap* gamemap, const MapCoordinate& pos, int distance, int player_fieldcount_mask, bool disableShareView )
00345 {
00346    distance = (distance+maxmalq-1)/maxmalq;
00347    int x1 = pos.x - distance;
00348    if ( x1 < 0 )
00349       x1 = 0;
00350 
00351    int y1 = pos.y - distance*2;
00352    if ( y1 < 0 )
00353       y1 = 0;
00354 
00355    int x2 = pos.x + distance;
00356    if ( x2 >= gamemap->xsize )
00357       x2 = gamemap->xsize-1;
00358 
00359    int y2 = pos.y + distance*2;
00360    if ( y2 >= gamemap->ysize )
00361       y2 = gamemap->ysize-1;
00362 
00363    int initial = gamemap->getgameparameter ( cgp_initialMapVisibility );
00364    int fieldsChanged = 0;
00365    for ( int player = 0; player < gamemap->getPlayerCount(); player++ )
00366       if ( gamemap->player[player].exist() ) {
00367          int add = 0;
00368          if ( !disableShareView )
00369             for ( int i = 0; i < gamemap->getPlayerCount(); i++ )
00370                if ( gamemap->player[i].exist() && i != player )
00371                   if ( gamemap->player[i].diplomacy.sharesView( player) )
00372                      add |= 1 << i;
00373 
00374          for ( int yy = y1; yy <= y2; yy++ )
00375             for ( int xx = x1; xx <= x2; xx++ ) {
00376                tfield* fld = gamemap->getField ( xx, yy );
00377                int result = evaluatevisibilityfield ( gamemap, fld, player, add, initial );
00378                if ( player_fieldcount_mask & (1 << player ))
00379                   fieldsChanged += result;
00380             }
00381       }
00382    return fieldsChanged;
00383 }
00384 
00385 
00386 
00387 int computeview( GameMap* gamemap, int player_fieldcount_mask, bool disableShareView )
00388 {
00389    if ( !gamemap || (gamemap->xsize == 0) || (gamemap->ysize == 0))
00390       return 0;
00391 
00392    clearvisibility( gamemap, 1 );
00393 
00394    for ( int a = 0; a < gamemap->getPlayerCount(); a++)
00395       if (gamemap->player[a].exist() ) {
00396 
00397          for ( Player::VehicleList::iterator i = gamemap->player[a].vehicleList.begin(); i != gamemap->player[a].vehicleList.end(); i++ ) {
00398             Vehicle* actvehicle = *i;
00399             if ( actvehicle == gamemap->getField(actvehicle->getPosition())->vehicle)
00400                actvehicle->addview();
00401          }
00402 
00403          for ( Player::BuildingList::iterator i = gamemap->player[a].buildingList.begin(); i != gamemap->player[a].buildingList.end(); i++ )
00404             (*i)->addview();
00405       }
00406 
00407 
00408    return evaluateviewcalculation ( gamemap, player_fieldcount_mask, disableShareView );
00409 }
00410 
00411 
00412 int getPlayersWithSharedViewMask( int player, GameMap* gamemap )
00413 {
00414    if ( player < 0 )
00415       return 0;
00416 
00417    int add = 0;
00418    for ( int i = 0; i < gamemap->getPlayerCount(); i++ )
00419       if ( gamemap->player[i].exist() && i != player )
00420          if ( gamemap->player[i].diplomacy.sharesView( player) )
00421             add |= 1 << i;
00422    
00423    return add;
00424 }
00425       
00426 #if 0
00427 VisibilityStates fieldVisibility( tfield* pe, int player, GameMap* gamemap, int additionalEnemyJamming )
00428 {
00429    evaluatevisibilityfield( gamemap, pe, player, getPlayersWithSharedViewMask(player,gamemap), gamemap->getgameparameter ( cgp_initialMapVisibility ), additionalEnemyJamming );
00430 #ifdef karteneditor
00431    player = 0;
00432 #endif
00433   if ( pe && player >= 0 ) {
00434    VisibilityStates c = VisibilityStates((pe->visible >> ( player * 2)) & 3);
00435 #ifdef karteneditor
00436          c = visible_all;
00437 #endif
00438 
00439       if ( c < gamemap->getInitialMapVisibility( player ) )
00440          c = gamemap->getInitialMapVisibility( player );
00441 
00442       return c;
00443   } else
00444      return visible_not;
00445 }
00446 #endif
00447 
00448 
00449 RecalculateAreaView :: RecalculateAreaView( GameMap* gamemap, const MapCoordinate& pos, int range ) : active(false)
00450 {
00451    position = pos;
00452    this->range = range;
00453    this->gamemap = gamemap;
00454 }
00455 
00456 void RecalculateAreaView::removeView()
00457 {
00458    circularFieldIterator( gamemap, position, 0, range, FieldIterationFunctor( this, &RecalculateAreaView::removeFieldView ));
00459    active = true;
00460 }
00461 
00462 void RecalculateAreaView::addView()
00463 {
00464    circularFieldIterator( gamemap, position, 0, range, FieldIterationFunctor( this, &RecalculateAreaView::addFieldView ));
00465    evaluateviewcalculation( gamemap, position, range );
00466    active = false;
00467 }
00468 
00469 void RecalculateAreaView::removeFieldView( const MapCoordinate& pos )
00470 {
00471    tfield* fld = gamemap->getField(pos);
00472    if ( fld && fld->getContainer() && fld->getContainer()->getOwner() < fld->getContainer()->getMap()->getPlayerCount() )
00473       fld->getContainer()->removeview();
00474 }
00475 
00476 void RecalculateAreaView::addFieldView( const MapCoordinate& pos )
00477 {
00478    tfield* fld = gamemap->getField(pos);
00479    if ( fld && fld->getContainer() && fld->getContainer()->getOwner() < fld->getContainer()->getMap()->getPlayerCount() )  //excluding neutral buildings here
00480       fld->getContainer()->addview();
00481 }
00482 
00483 RecalculateAreaView::~RecalculateAreaView()
00484 {
00485    if ( active )
00486       addView();
00487 }

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