00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00032
00033
00034 tfield :: tfield ( GameMap* gamemap_ )
00035 {
00036 init();
00037 setMap( gamemap_ );
00038 }
00039
00040 tfield :: tfield ( )
00041 {
00042 init();
00043 }
00044
00045
00046 void tfield::init ()
00047 {
00048 bdt.set ( 0 );
00049 typ = NULL;
00050 vehicle = NULL;
00051 building = NULL;
00052 a.temp = 0;
00053 a.temp2 = 0;
00054 temp3 = 0;
00055 temp4 = 0;
00056 visible = 0;
00057 fuel = 0;
00058 material = 0;
00059 resourceview = NULL;
00060 connection = 0;
00061 gamemap = NULL;
00062 viewbonus = 0;
00063 }
00064
00065
00066 void tfield::Resourceview::setview( int player, int material, int fuel )
00067 {
00068 visible |= 1 << player;
00069 materialvisible[player] = material;
00070 fuelvisible[player] = fuel;
00071 }
00072
00073 void tfield::Resourceview::resetview( int player )
00074 {
00075 visible &= ~(1<<player);
00076 }
00077
00078
00079 void tfield::endRound( int turn )
00080 {
00081 bool recalc = false;
00082 for ( ObjectContainer::iterator i = objects.begin(); i != objects.end(); ) {
00083 if ( AgeableItem::age( *i )) {
00084 i = objects.erase(i);
00085 recalc = true;
00086 } else
00087 ++i;
00088 }
00089
00090
00091 for ( MineContainer::iterator i = mines.begin(); i != mines.end(); ) {
00092 if ( AgeableItem::age( *i )) {
00093 i = mines.erase(i);
00094 recalc = true;
00095 } else
00096 ++i;
00097 }
00098
00099
00100 if ( recalc )
00101 setparams();
00102 }
00103
00104
00105 void tfield::operator= ( const tfield& f )
00106 {
00107 typ = f.typ;
00108 fuel = f.fuel;
00109 material = f.material;
00110 visible = f.visible;
00111 tempw = f.tempw;
00112 temp3 = f.temp3;
00113 temp4 = f.temp4;
00114 vehicle = f.vehicle;
00115 building = f.building;
00116 if ( f.resourceview ) {
00117 resourceview = new Resourceview;
00118 *resourceview = *f.resourceview;
00119 } else
00120 resourceview = NULL;
00121 mines = f.mines;
00122 objects = f.objects;
00123 connection = f.connection;
00124 bdt = f.bdt;
00125 for ( int i = 0; i < 8; i++ )
00126 view[i] = f.view[i];
00127 }
00128
00129
00130
00131 int tfield :: mineattacks ( const Vehicle* veh )
00132 {
00133 int i = 1;
00134 for ( MineContainer::iterator m = mines.begin(); m != mines.end(); m++, i++ )
00135 if ( m->attacksunit ( veh ))
00136 return i;
00137
00138 return 0;
00139 }
00140
00141 Mine& tfield::getMine ( int n )
00142 {
00143 int c = 0;
00144 MineContainer::iterator i;
00145 for ( i = mines.begin(); c < n; i++,c++ );
00146 return *i;
00147 }
00148
00149 bool tfield :: addobject( const ObjectType* obj, int dir, bool force )
00150 {
00151 if ( !obj )
00152 return false;
00153
00154 Object* i = checkforobject ( obj );
00155 if ( !i ) {
00156 int buildable = obj->buildable ( this );
00157 if ( !buildable )
00158 if ( force )
00159 buildable = 1;
00160
00161 if ( buildable ) {
00162 Object o ( obj );
00163 if ( dir != -1 )
00164 o.dir = dir;
00165 else
00166 o.dir = 0;
00167
00168 objects.push_back ( o );
00169
00170 if ( dir == -1 )
00171 calculateobject( getx(), gety(), true, obj, gamemap );
00172
00173 sortobjects();
00174 setparams();
00175 return true;
00176 } else
00177 return false;
00178
00179 } else {
00180 if ( dir != -1 )
00181 i->dir |= dir;
00182
00183 i->lifetimer = obj->lifetime;
00184 sortobjects();
00185 return true;
00186 }
00187 }
00188
00189
00190 void tfield :: removeobject( const ObjectType* obj, bool force)
00191 {
00192 if ( !force && building )
00193 return;
00194
00195 #ifndef karteneditor
00196 if ( !force )
00197 if ( vehicle )
00198 if ( vehicle->color != gamemap->actplayer << 3)
00199 return;
00200 #endif
00201
00202 if ( !obj ) {
00203 if ( objects.size() ) {
00204 obj = objects.rbegin()->typ;
00205 objects.pop_back();
00206 }
00207 } else
00208 for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); )
00209 if ( o->typ == obj )
00210 o = objects.erase( o );
00211 else
00212 o++;
00213
00214 setparams();
00215 if ( obj )
00216 calculateobject( getx(), gety(), true, obj );
00217 }
00218
00219 void tfield :: deleteeverything ( void )
00220 {
00221 if ( vehicle ) {
00222 delete vehicle;
00223 vehicle = NULL;
00224 }
00225
00226 if ( building ) {
00227 delete building;
00228 building = NULL;
00229 }
00230
00231 setparams();
00232 }
00233
00234
00235 bool tfield :: unitHere ( const Vehicle* veh )
00236 {
00237 if ( vehicle == veh )
00238 return true;
00239
00240 if ( vehicle && veh && vehicle->networkid == veh->networkid )
00241 return true;
00242 return false;
00243 }
00244
00245 ContainerBase* tfield :: getContainer()
00246 {
00247 if ( vehicle )
00248 return vehicle;
00249 else
00250 return building;
00251 }
00252
00253
00254 int tfield :: getweather ( void )
00255 {
00256 if ( !typ )
00257 return 0;
00258 for ( int w = 0; w < cwettertypennum; w++ )
00259 if ( typ == typ->terraintype->weather[w] )
00260 return w;
00261 return -1;
00262 }
00263
00264 void tfield :: setweather ( int weather )
00265 {
00266 if (typ->terraintype->weather[ weather ] ) {
00267 typ = typ->terraintype->weather[ weather ];
00268 setparams();
00269 } else {
00270 if ( weather == 2 )
00271 setweather(1);
00272 else
00273 if ( weather == 5 )
00274 setweather(4);
00275 else
00276 if (weather==4)
00277 setweather(3);
00278 else {
00279 typ = typ->terraintype->weather[ 0 ];
00280 setparams();
00281 }
00282 }
00283 }
00284
00285 void tfield::setVisibility ( VisibilityStates valtoset, int actplayer )
00286 {
00287 int newval = (valtoset ^ 3) << ( 2 * actplayer );
00288 int oneval = 3 << ( 2 * actplayer );
00289
00290 visible |= oneval;
00291 visible ^= newval;
00292 };
00293
00294 void tfield::resetView( GameMap* gamemap, int playersToReset )
00295 {
00296 int mask = 0;
00297 for ( int i = 0; i < gamemap->getPlayerCount(); ++i )
00298 if ( !(playersToReset & (1 << i)))
00299 mask |= 3 << (2*i);
00300
00301 int l = 0;
00302 for ( int y = 0; y < gamemap->ysize; ++y )
00303 for ( int x = 0; x < gamemap->xsize; ++x ) {
00304 tfield& fld = gamemap->field[l++];
00305 fld.visible &= mask;
00306 }
00307
00308 }
00309
00310
00311
00312 bool compareObjectHeight ( const Object& o1, const Object& o2 )
00313 {
00314 return o1.typ->imageHeight < o2.typ->imageHeight;
00315 }
00316
00317 void tfield :: sortobjects ( void )
00318 {
00319 sort ( objects.begin(), objects.end(), compareObjectHeight );
00320 }
00321
00322 bool tfield :: putmine( int col, int typ, int strength )
00323 {
00324 if ( mineowner() >= 0 && mineowner() != col )
00325 return false;
00326
00327 if ( mines.size() >= gamemap->getgameparameter ( cgp_maxminesonfield ))
00328 return false;
00329
00330 MineTypes mt = MineTypes(typ);
00331 Mine mymine ( mt, strength, col, gamemap );
00332 mines.push_back ( mymine );
00333 return true;
00334 }
00335
00336 int tfield :: mineowner( void )
00337 {
00338 if ( mines.empty() )
00339 return -1;
00340 else
00341 return mines.begin()->player;
00342 }
00343
00344
00345 void tfield :: removemine( int num )
00346 {
00347 if ( num == -1 )
00348 num = mines.size() - 1;
00349
00350 int i = 0;
00351 for ( MineContainer::iterator m = mines.begin(); m != mines.end(); i++)
00352 if ( i == num )
00353 m = mines.erase ( m );
00354 else
00355 m++;
00356 }
00357
00358
00359 int tfield :: getx( void )
00360 {
00361 int n = this - gamemap->field;
00362 return n % gamemap->xsize;
00363 }
00364
00365 int tfield :: gety( void )
00366 {
00367 int n = this - gamemap->field;
00368 return n / gamemap->xsize;
00369 }
00370
00371
00372 int tfield :: getattackbonus ( void )
00373 {
00374 int a = typ->attackbonus;
00375 for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00376 if ( o->typ->attackbonus_abs != -1 )
00377 a = o->typ->attackbonus_abs;
00378 else
00379 a += o->typ->attackbonus_plus;
00380 }
00381
00382 if ( a > -8 )
00383 return a;
00384 else
00385 return -7;
00386 }
00387
00388 int tfield :: getdefensebonus ( void )
00389 {
00390 int a = typ->defensebonus;
00391 for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00392 if ( o->typ->defensebonus_abs != -1 )
00393 a = o->typ->defensebonus_abs;
00394 else
00395 a += o->typ->defensebonus_plus;
00396 }
00397
00398 if ( a > -8 )
00399 return a;
00400 else
00401 return -7;
00402 }
00403
00404 ASCString tfield :: getName()
00405 {
00406 ASCString a = typ->terraintype->name;
00407 for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00408 if ( o->typ->namingMethod == ObjectType::ReplaceTerrain )
00409 a = o->typ->getName();
00410 else
00411 if ( o->typ->namingMethod == ObjectType::AddToTerrain )
00412 a += ", " + o->typ->getName();
00413 }
00414
00415 return a;
00416 }
00417
00418
00419 int tfield :: getjamming ( void )
00420 {
00421 int a = typ->basicjamming;
00422 for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00423 if ( o->typ->basicjamming_abs >= 0 )
00424 a = o->typ->basicjamming_abs;
00425 else
00426 a += o->typ->basicjamming_plus;
00427 }
00428 if ( a > 0 )
00429 return a;
00430 else
00431 return 0;
00432 }
00433
00434 int tfield :: getmovemalus ( const Vehicle* veh )
00435 {
00436 int mnum = mines.size();
00437 if ( mnum ) {
00438 int movemalus = __movemalus.at(veh->typ->movemalustyp);
00439 int col = mineowner();
00440 if ( veh->color == col*8 )
00441 movemalus += movemalus * mine_movemalus_increase * mnum / 100;
00442
00443 if ( movemalus < minmalq )
00444 fatalError ( "invalid movemalus for terraintype ID %d used on field %d / %d" , typ->terraintype->id, getx(), gety() );
00445
00446 return movemalus;
00447 } else {
00448 int mm = __movemalus.at(veh->typ->movemalustyp);
00449 if ( mm < minmalq )
00450 fatalError ( "invalid movemalus for terraintype ID %d used on field %d / %d" , typ->terraintype->id, getx(), gety() );
00451 return mm;
00452 }
00453 }
00454
00455 int tfield :: getmovemalus ( int type )
00456 {
00457 return __movemalus.at(type);
00458 }
00459
00460 void tfield :: setparams ( void )
00461 {
00462 int i;
00463 bdt = typ->art;
00464
00465 for ( i = 0; i < cmovemalitypenum; i++ ) {
00466 __movemalus.at(i) = typ->move_malus[i];
00467 if ( __movemalus[i] < minmalq )
00468 fatalError ( "invalid movemalus for terraintype ID %d used on field %d / %d" , typ->terraintype->id, getx(), gety() );
00469 }
00470
00471 viewbonus = 0;
00472
00473 for ( ObjectContainer::iterator o = objects.begin(); o != objects.end(); o++ ) {
00474 if ( gamemap->getgameparameter ( cgp_objectsDestroyedByTerrain ))
00475 if ( o->typ->getFieldModification(getweather()).terrainaccess.accessible( bdt ) == -1 ) {
00476 objects.erase(o);
00477 setparams();
00478 return;
00479 }
00480
00481 bdt &= o->typ->getFieldModification(getweather()).terrain_and;
00482 bdt |= o->typ->getFieldModification(getweather()).terrain_or;
00483
00484 for ( i = 0; i < cmovemalitypenum; i++ ) {
00485 __movemalus[i] += o->typ->getFieldModification(getweather()).movemalus_plus[i];
00486 if ( (o->typ->getFieldModification(getweather()).movemalus_abs[i] != 0) && (o->typ->getFieldModification(getweather()).movemalus_abs[i] != -1) )
00487 __movemalus[i] = o->typ->getFieldModification(getweather()).movemalus_abs[i];
00488 if ( __movemalus[i] < minmalq )
00489 __movemalus[i] = minmalq;
00490 }
00491
00492 viewbonus += o->typ->viewbonus_plus;
00493 if ( o->typ->viewbonus_abs != -1 )
00494 viewbonus = o->typ->viewbonus_plus;
00495 }
00496
00497 if ( building )
00498 if ( this == building->getField( building->typ->entry ))
00499 bdt |= getTerrainBitType(cbbuildingentry);
00500
00501 }
00502
00503 Object* tfield :: checkforobject ( const ObjectType* o )
00504 {
00505 for ( ObjectContainer::iterator i = objects.begin(); i != objects.end(); i++ )
00506 if ( i->typ == o )
00507 return &(*i);
00508
00509 return NULL;
00510 }
00511
00512
00513 tfield::Resourceview :: Resourceview ( void )
00514 {
00515 visible = 0;
00516 memset ( &fuelvisible, 0, sizeof ( fuelvisible ));
00517 memset ( &materialvisible, 0, sizeof ( materialvisible ));
00518 }
00519
00520
00521 int tfield :: getMemoryFootprint() const
00522 {
00523 int size = sizeof(*this);
00524 return size;
00525 }
00526
00527
00528 tfield :: ~tfield()
00529 {
00530 if ( resourceview ) {
00531 delete resourceview;
00532 resourceview = NULL;
00533 }
00534 }
00535
00536