mapfield.cpp

Go to the documentation of this file.
00001 
00005 /***************************************************************************
00006                           mapfield.cpp  -  description
00007                              -------------------
00008     begin                : Tue May 21 2005
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 <algorithm>
00023 #include <ctime>
00024 #include <cmath>
00025 
00026 #include "global.h"
00027 #include "typen.h"
00028 #include "vehicletype.h"
00029 #include "buildingtype.h"
00030 #include "spfst.h"
00031 #include "actions/context.h"
00032 #include "actions/removeobject.h"
00033 
00034 MapField :: MapField ( GameMap* gamemap_ )
00035 {
00036   init();
00037   setMap( gamemap_ );
00038 }
00039 
00040 MapField :: MapField (  )
00041 {
00042   init();
00043 }
00044 
00045 
00046 void MapField::init ()
00047 {
00048    bdt.set ( 0 );
00049    typ = NULL;
00050    vehicle = NULL;
00051    secondvehicle = NULL;
00052    building = NULL;
00053    a.temp = 0;
00054    a.temp2 = 0;
00055    temp3 = 0;
00056    temp4 = 0;
00057    visible = 0;
00058    fuel = 0;
00059    material = 0;
00060    resourceview = NULL;
00061    connection = 0;
00062    gamemap = NULL;
00063    viewbonus = 0;
00064 }
00065 
00066 int MapField::getMineralMaterial() const
00067 {
00068    return material;
00069 }
00070 
00071 int MapField::getMineralFuel() const
00072 {
00073    return fuel;
00074 }
00075    
00076 void MapField::setMineralMaterial( int material )
00077 {
00078    if ( material < 0 )
00079       this->material = 0;
00080    else
00081       if ( material > 255 )
00082          this->material = 255;
00083       else
00084          this->material = material;
00085 }
00086 void MapField::setMineralFuel( int fuel )
00087 {
00088    if ( fuel < 0 )
00089       this->fuel = 0;
00090    else
00091       if ( fuel > 255 )
00092          this->fuel = 255;
00093    else
00094       this->fuel = fuel;
00095 }
00096 
00097 void MapField::Resourceview::setview( int player, int material, int fuel )
00098 {
00099    visible |= 1 << player;
00100    materialvisible[player] = material;
00101    fuelvisible[player] = fuel;
00102 }
00103 
00104 void MapField::Resourceview::resetview( int player )
00105 {
00106    visible &= ~(1<<player);
00107 }
00108 
00109 
00110 void MapField::endRound( int turn )
00111 {
00112    bool recalc = false;
00113    for ( ObjectContainer::iterator i = objects.begin(); i != objects.end(); ) {
00114       if ( AgeableItem::age( *i )) {
00115          i = objects.erase(i);
00116          recalc = true;
00117       } else
00118          ++i;
00119    }
00120    // remove_if( objects.begin(), objects.end(), Object::age );
00121 
00122    for ( MineContainer::iterator i = mines.begin(); i != mines.end(); ) {
00123       if ( AgeableItem::age( *i )) {
00124          i = mines.erase(i);
00125          recalc = true;
00126       } else
00127          ++i;
00128    }
00129    // remove_if( mines.begin(), mines.end(), Object::age );
00130 
00131    if ( recalc )
00132       setparams();
00133 }
00134 
00135 
00136 void MapField::operator= ( const MapField& f )
00137 {
00138    typ = f.typ;
00139    fuel = f.fuel;
00140    material = f.material;
00141    visible = f.visible;
00142    tempw = f.tempw;
00143    temp3 = f.temp3;
00144    temp4 = f.temp4;
00145    vehicle = f.vehicle;
00146    building = f.building;
00147    if ( f.resourceview ) {
00148       resourceview = new Resourceview;
00149       *resourceview = *f.resourceview;
00150    } else
00151       resourceview = NULL;
00152    mines = f.mines;
00153    objects = f.objects;
00154    connection = f.connection;
00155    bdt = f.bdt;
00156    for ( int i = 0; i < 8; i++ )
00157       view[i] = f.view[i];
00158 }
00159 
00160 
00161 const TerrainType* MapField::getTerrainType() const 
00162 {
00163    return typ->terraintype;
00164 }
00165 
00166 void MapField::changeTerrainType( const TerrainType* terrain )
00167 {
00168    int weather = getWeather();
00169    if ( terrain->weather[weather] )
00170       typ = terrain->weather[weather];
00171    else
00172       typ = terrain->weather[0];
00173    
00174    setparams ();
00175 }
00176 
00177 
00178 int MapField :: mineattacks ( const Vehicle* veh )
00179 {
00180    int i = 1;
00181    for ( MineContainer::iterator m = mines.begin(); m != mines.end(); m++, i++ )
00182       if ( m->attacksunit ( veh ))
00183          return i;
00184 
00185    return 0;
00186 }
00187 
00188 Mine& MapField::getMine ( int n )
00189 {
00190   int c = 0;
00191   MineContainer::iterator i;
00192   for ( i = mines.begin(); c < n; i++,c++ );
00193   return *i;
00194 }
00195 
00196 bool  MapField :: addobject( const ObjectType* obj, int dir, bool force, MapField::ObjectRemovalStrategy* objectRemovalStrategy )
00197 {
00198    if ( !obj )
00199       return false;
00200 
00201    Object* i = checkForObject ( obj );
00202    if ( !i ) {
00203      int buildable = obj->buildable ( this );
00204      if ( !buildable )
00205           if ( force )
00206              buildable = 1;
00207 
00208      if ( buildable ) {
00209          Object o ( obj );
00210          if ( dir != -1 )
00211             o.dir = dir;
00212          else
00213             o.dir = 0;
00214 
00215          objects.push_back ( o );
00216 
00217          sortobjects();
00218          if ( dir == -1 )
00219             calculateobject( getx(), gety(), true, obj, gamemap );
00220 
00221          if ( objectRemovalStrategy )
00222             setparams( objectRemovalStrategy );
00223          else
00224             setparams();
00225          return true;
00226      } else
00227         return false;
00228      
00229    } else {
00230       if ( dir != -1 )
00231          i->dir |= dir;
00232 
00233       i->lifetimer = obj->lifetime;
00234       sortobjects();
00235       return true;
00236    }
00237 }
00238 
00239 
00240 bool MapField :: removeObject( const ObjectType* obj, bool force, ObjectRemovalStrategy* objectRemovalStrategy )
00241 {
00242    if ( !force && building )
00243       return false;
00244 
00245    #ifndef karteneditor
00246    if ( !force )
00247       if ( vehicle )
00248          if ( vehicle->getOwner() != gamemap->actplayer )
00249            return false;
00250    #endif
00251 
00252    bool removed = false;
00253    
00254    if ( !obj ) {
00255       if ( objects.size() ) {
00256          obj = objects.rbegin()->typ;
00257          objects.pop_back();
00258          removed = true;
00259       }
00260    } else
00261       for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); )
00262          if ( o->typ == obj ) {
00263             o = objects.erase( o );
00264             removed = true;
00265          } else
00266             o++;
00267 
00268    if ( objectRemovalStrategy )
00269       setparams( objectRemovalStrategy );
00270    else
00271       setparams();
00272    
00273    if ( obj )
00274       calculateobject( getx(), gety(), true, obj, gamemap );
00275    
00276    return removed;
00277 }
00278 
00279 void MapField :: deleteeverything ( void )
00280 {
00281    if ( vehicle ) {
00282       delete vehicle;
00283       vehicle = NULL;
00284    }
00285 
00286    if ( building ) {
00287       delete building;
00288       building = NULL;
00289    }
00290 
00291    setparams();
00292 }
00293 
00294 
00295 bool MapField :: unitHere ( const Vehicle* veh )
00296 {
00297    if ( vehicle == veh )
00298       return true;
00299 
00300    if ( vehicle && veh && vehicle->networkid == veh->networkid )
00301       return true;
00302    return false;
00303 }
00304 
00305 Building* MapField::getBuildingEntrance()
00306 {
00307    if ( building &&  (bdt & getTerrainBitType(cbbuildingentry)).any() )
00308       return building;
00309    else
00310       return NULL;
00311 }
00312 
00313 
00314 
00315 ContainerBase* MapField :: getContainer()
00316 {
00317    if ( vehicle )
00318       return vehicle;
00319    else
00320       return building;
00321 }
00322 
00323 const ContainerBase* MapField :: getContainer() const
00324 {
00325    if ( vehicle )
00326       return vehicle;
00327    else
00328       return building;
00329 }
00330 
00331 
00332 void MapField :: removeBuilding() 
00333 {
00334    if ( building )
00335       delete building;
00336 }
00337 
00338 void MapField :: removeUnit()
00339 {
00340    if ( vehicle ) {
00341       delete vehicle;
00342       vehicle = NULL;
00343    }
00344 }
00345 
00346 
00347 int MapField :: getWeather ( void )
00348 {
00349    if ( !typ )
00350       return 0;
00351    for ( int w = 0; w < cwettertypennum; w++ )
00352       if ( typ == typ->terraintype->weather[w] )
00353          return w;
00354    return -1;
00355 }
00356 
00357 void MapField :: setWeather ( int weather )
00358 {
00359    if ( weather < 0 || weather >= cwettertypennum )
00360       return;
00361    
00362      if (typ->terraintype->weather[ weather ] ) {
00363         typ = typ->terraintype->weather[ weather ];
00364         setparams();
00365      } else {
00366         if ( weather == 2 )
00367            setWeather(1);
00368         else
00369            if ( weather == 5 )
00370               setWeather(4);
00371            else
00372               if (weather==4)
00373                  setWeather(3);
00374               else {
00375                  typ = typ->terraintype->weather[ 0 ];
00376                  setparams();
00377               }
00378      }
00379 }
00380 
00381 void MapField::setVisibility ( VisibilityStates valtoset, int actplayer ) 
00382 {
00383       int newval = (valtoset ^ 3) << ( 2 * actplayer );
00384       int oneval = 3 << ( 2 * actplayer );
00385 
00386       visible |= oneval;
00387       visible ^= newval;
00388 };
00389 
00390 void MapField::resetView( GameMap* gamemap, int playersToReset )
00391 {
00392    int mask = 0;
00393    for ( int i = 0; i < gamemap->getPlayerCount(); ++i )
00394       if ( !(playersToReset & (1 << i)))
00395          mask |= 3 << (2*i);
00396 
00397    int l = 0;
00398    for ( int y = 0; y < gamemap->ysize; ++y )
00399       for ( int x = 0; x < gamemap->xsize; ++x ) {
00400          MapField& fld = gamemap->field[l++];
00401          fld.visible &= mask;
00402       }
00403         
00404 }
00405 
00406 
00407 
00408 bool compareObjectHeight ( const Object& o1, const Object& o2 )
00409 {
00410    return o1.typ->imageHeight < o2.typ->imageHeight;
00411 }
00412 
00413 void MapField :: sortobjects ( void )
00414 {
00415    sort ( objects.begin(), objects.end(), compareObjectHeight );
00416 }
00417 
00418 bool  MapField :: putmine( int owner, MineTypes typ, int strength )
00419 {
00420    if ( mineowner() >= 0  && mineowner() != owner )
00421       return false;
00422 
00423    if ( mines.size() >= gamemap->getgameparameter ( cgp_maxminesonfield ))
00424       return false;
00425 
00426    Mine mymine ( typ, strength, owner, gamemap );
00427    mines.push_back ( mymine );
00428    return true;
00429 }
00430 
00431 int MapField :: mineowner( void )
00432 {
00433    if ( mines.empty() )
00434       return -1;
00435    else
00436       return mines.begin()->player;
00437 }
00438 
00439 
00440 void MapField :: removemine( int num )
00441 { 
00442    if ( num == -1 )
00443       num = mines.size() - 1;
00444 
00445    int i = 0;
00446    for ( MineContainer::iterator m = mines.begin(); m != mines.end(); i++)
00447       if ( i == num )
00448          m = mines.erase ( m );
00449       else
00450           m++;
00451 }
00452 
00453 
00454 int MapField :: getx( void )
00455 {
00456    int n = this - gamemap->field;
00457    return n % gamemap->xsize;
00458 }
00459 
00460 int MapField :: gety( void )
00461 {
00462    int n = this - gamemap->field;
00463    return n / gamemap->xsize;
00464 }
00465 
00466 
00467 int MapField :: getattackbonus ( void )
00468 {
00469    int a = typ->attackbonus;
00470    for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00471       if ( o->typ->attackbonus_abs != -1 )
00472          a = o->typ->attackbonus_abs;
00473       else
00474          a += o->typ->attackbonus_plus;
00475    }
00476 
00477    if ( a > -8 )
00478       return a;
00479    else
00480       return -7;
00481 }
00482 
00483 int MapField :: getdefensebonus ( void )
00484 {
00485    int a = typ->defensebonus;
00486    for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00487       if ( o->typ->defensebonus_abs != -1 )
00488          a = o->typ->defensebonus_abs;
00489       else
00490          a += o->typ->defensebonus_plus;
00491    }
00492 
00493    if ( a > -8 )
00494       return a;
00495    else
00496       return -7;
00497 }
00498 
00499 ASCString MapField :: getName()
00500 {
00501    ASCString a = typ->terraintype->name;
00502    for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00503       if ( o->typ->namingMethod == ObjectType::ReplaceTerrain )
00504          a = o->typ->getName();
00505       else
00506          if ( o->typ->namingMethod == ObjectType::AddToTerrain )
00507             a += ", " + o->typ->getName();
00508    }
00509    
00510    return a;
00511 }
00512 
00513 
00514 int MapField :: getjamming ( void )
00515 {
00516    int a = typ->basicjamming;
00517    for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00518       if ( o->typ->basicjamming_abs >= 0 )
00519          a = o->typ->basicjamming_abs;
00520       else
00521          a += o->typ->basicjamming_plus;
00522    }
00523    if ( a > 0 )
00524       return a;
00525    else
00526       return 0;
00527 }
00528 
00529 int MapField :: getmovemalus ( const Vehicle* veh )
00530 {
00531    int mnum = mines.size();
00532    if ( mnum ) {
00533       int movemalus = __movemalus.at(veh->typ->movemalustyp);
00534       int col = mineowner();
00535       if ( veh->color == col*8 )
00536          movemalus += movemalus * mine_movemalus_increase * mnum / 100;
00537 
00538       if ( movemalus < minmalq )
00539          fatalError ( "invalid movemalus for terraintype ID %d used on field %d / %d" , typ->terraintype->id, getx(), gety() );
00540 
00541       return movemalus;
00542    } else {
00543       int mm = __movemalus.at(veh->typ->movemalustyp);
00544       if ( mm < minmalq )
00545          fatalError ( "invalid movemalus for terraintype ID %d used on field %d / %d" , typ->terraintype->id, getx(), gety() );
00546       return mm;
00547    }
00548 }
00549 
00550 int MapField :: getmovemalus ( int type )
00551 {
00552   return __movemalus.at(type);
00553 }
00554 
00555 MapCoordinate MapField :: getPosition()
00556 {
00557    return MapCoordinate( getx(), gety() );  
00558 }
00559 
00560 
00561 class SimpleObjectRemoval : public MapField::ObjectRemovalStrategy {
00562    public:
00563       virtual void removeObject( MapField* fld, const ObjectType* obj )
00564       {
00565          for ( MapField::ObjectContainer::iterator o = fld->objects.begin(); o != fld->objects.end();  ) {
00566             if ( o->typ == obj )
00567                o = fld->objects.erase( o );
00568             else
00569                ++o ;
00570          }
00571       }
00572 };
00573 
00574 
00575 
00576 void MapField :: setparams (  )
00577 {
00578    SimpleObjectRemoval sor;
00579    setparams( &sor );     
00580 }
00581 
00582 void MapField :: setparams ( ObjectRemovalStrategy* objectRemovalStrategy )
00583 {
00584    int i;
00585    bdt = typ->art;
00586 
00587    for ( i = 0; i < cmovemalitypenum; i++ )   {
00588       __movemalus.at(i) = typ->move_malus[i];
00589       if ( __movemalus[i] < minmalq )
00590          fatalError ( "invalid movemalus for terraintype ID %d used on field %d / %d" , typ->terraintype->id, getx(), gety() );
00591    }
00592 
00593    viewbonus = 0;
00594 
00595    for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00596       if ( gamemap->getgameparameter ( cgp_objectsDestroyedByTerrain ))
00597          if ( o->typ->getFieldModification(getWeather()).terrainaccess.accessible( bdt ) == -1 ) {
00598             objectRemovalStrategy->removeObject( this, o->typ );
00599             setparams( objectRemovalStrategy );
00600             return;
00601          }
00602 
00603       bdt  &=  o->typ->getFieldModification(getWeather()).terrain_and;
00604       bdt  |=  o->typ->getFieldModification(getWeather()).terrain_or;
00605 
00606       for ( i = 0; i < cmovemalitypenum; i++ ) {
00607          __movemalus[i] += o->typ->getFieldModification(getWeather()).movemalus_plus[i];
00608          if ( (o->typ->getFieldModification(getWeather()).movemalus_abs[i] != 0) && (o->typ->getFieldModification(getWeather()).movemalus_abs[i] != -1) )
00609             __movemalus[i] = o->typ->getFieldModification(getWeather()).movemalus_abs[i];
00610          if ( __movemalus[i] < minmalq )
00611             __movemalus[i] = minmalq;
00612       }
00613 
00614       viewbonus += o->typ->viewbonus_plus;
00615       if ( o->typ->viewbonus_abs != -1 )
00616          viewbonus = o->typ->viewbonus_plus;
00617    }
00618 
00619    if ( building ) 
00620       if ( this == building->getField( building->typ->entry ))
00621          bdt |= getTerrainBitType(cbbuildingentry);
00622    
00623 }
00624 
00625 Object* MapField :: checkForObject ( const ObjectType*  o )
00626 {
00627    for ( ObjectContainer::iterator i = objects.begin(); i != objects.end(); i++ )
00628       if ( i->typ == o )
00629          return &(*i);
00630 
00631    return NULL;
00632 }
00633 
00634 
00635 MapField::Resourceview :: Resourceview ( void )
00636 {
00637    visible = 0;
00638    memset ( &fuelvisible, 0, sizeof ( fuelvisible ));
00639    memset ( &materialvisible, 0, sizeof ( materialvisible ));
00640 }
00641 
00642 
00643 int MapField :: getMemoryFootprint() const
00644 {
00645    int size = sizeof(*this);
00646    return size;
00647 }
00648 
00649 
00650 MapField :: ~MapField()
00651 {
00652    if ( resourceview ) {
00653       delete resourceview;
00654       resourceview = NULL;
00655    }
00656 }
00657 
00658 

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