00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <cstring>
00027 #include <utility>
00028 #include <map>
00029
00030
00031 #include "vehicletype.h"
00032 #include "buildingtype.h"
00033
00034 #include "typen.h"
00035 #include "spfst.h"
00036 #include "attack.h"
00037
00038 #include "mapalgorithms.h"
00039 #include "vehicle.h"
00040 #include "buildings.h"
00041 #include "mapfield.h"
00042
00043 #include "spfst-legacy.h"
00044
00045 SigC::Signal0<void> repaintMap;
00046 SigC::Signal0<void> repaintDisplay;
00047 SigC::Signal0<void> updateFieldInfo;
00048 SigC::Signal0<void> cursorMoved;
00049 SigC::Signal1<void,ContainerBase*> showContainerInfo;
00050 SigC::Signal1<void,VehicleType*> showVehicleTypeInfo;
00051 SigC::Signal0<void> viewChanged;
00052 SigC::Signal1<void,GameMap*> mapChanged;
00053 SigC::Signal0<bool> idleEvent;
00054 SigC::Signal1<void, const Context&> fieldCrossed;
00055
00056
00057
00058 void displaymap()
00059 {
00060 repaintMap();
00061 }
00062
00063
00064 GameMap* actmap = NULL;
00065
00066 Schriften schriften;
00067
00068
00069
00070 int terrainaccessible ( const MapField* field, const Vehicle* vehicle, int uheight )
00071 {
00072 int res = terrainaccessible2 ( field, vehicle, uheight );
00073 if ( res < 0 )
00074 return 0;
00075 else
00076 return res;
00077 }
00078
00079 int terrainaccessible2 ( const MapField* field, const Vehicle* vehicle, int uheight )
00080 {
00081 if ( uheight == -1 )
00082 uheight = vehicle->height;
00083
00084 if ( !(uheight & vehicle->typ->height))
00085 return 0;
00086
00087
00088 return terrainaccessible2( field, vehicle->typ->terrainaccess, uheight );
00089 }
00090
00091 int terrainaccessible2 ( const MapField* field, const TerrainAccess& terrainAccess, int uheight )
00092 {
00093 if ( uheight >= chtieffliegend)
00094 return 2;
00095 else {
00096 if ( uheight == chtiefgetaucht )
00097 if ( (field->bdt & getTerrainBitType(cbwater3) ).any() )
00098 return 2;
00099 else
00100 return -1;
00101 else
00102 if ( uheight == chgetaucht )
00103 if ( (field->bdt & ( getTerrainBitType(cbwater3) | getTerrainBitType(cbwater2 )) ).any() )
00104 return 2;
00105 else
00106 return -2;
00107 else {
00108 if ( terrainAccess.accessible ( field->bdt ) > 0 ) {
00109 if ( uheight == chschwimmend ) {
00110 if ( (field->bdt & getTerrainBitType(cbwater)).any() )
00111 return 2;
00112 else
00113 return -3;
00114 } else
00115 return 2;
00116 } else
00117 return -3;
00118 }
00119 }
00120 }
00121
00122
00123
00124 int fieldAccessible( const MapField* field,
00125 const Vehicle* vehicle,
00126 int uheight,
00127 const bool* attacked,
00128 bool ignoreVisibility )
00129 {
00130 if ( !field || !vehicle )
00131 return 0;
00132
00133 if ( uheight == -2 )
00134 uheight = vehicle->height;
00135
00136 if ( !ignoreVisibility ) {
00137 int c = fieldVisibility ( field, vehicle->getOwner() );
00138
00139 if (field == NULL)
00140 return 0;
00141
00142 if (c == visible_not)
00143 return 0;
00144 }
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 if ( (!field->vehicle || field->vehicle == vehicle) && !field->building ) {
00156 if ( vehicle->typ->height & uheight )
00157 return terrainaccessible ( field, vehicle, uheight );
00158 else
00159 return 0;
00160 } else {
00161 if (field->vehicle) {
00162 if ( vehicle->getMap()->getPlayer(vehicle).diplomacy.isAllied( field->vehicle->getOwner()) ) {
00163 if ( field->vehicle->vehicleLoadable ( vehicle, uheight ) )
00164 return 2;
00165 else
00166 if ( terrainaccessible ( field, vehicle, uheight ))
00167 return 1;
00168 else
00169 return 0;
00170 }
00171 else
00172 if ( terrainaccessible ( field, vehicle, uheight ) ) {
00173 if (vehicleplattfahrbar(vehicle,field))
00174 return 2;
00175 else {
00176 if ( getheightdelta(getFirstBit(field->vehicle->height), getFirstBit(vehicle->height)) || (attackpossible28(field->vehicle,vehicle) == false) || ( vehicle->getMap()->getPlayer(vehicle).diplomacy.getState( field->vehicle->getOwner()) >= PEACE ))
00177 return 1;
00178 }
00179 }
00180 }
00181 else {
00182 if ((field->bdt & getTerrainBitType(cbbuildingentry) ).any() && field->building->vehicleLoadable ( vehicle, uheight, attacked ))
00183 return 2;
00184 else
00185 if (uheight >= chtieffliegend || (field->building->typ->height <= chgetaucht && uheight >= chschwimmend ))
00186 return 1;
00187 else
00188 return 0;
00189 }
00190 }
00191 return 0;
00192 }
00193
00194
00195
00196
00197
00198
00199 MapField* getfield(int x,
00200 int y)
00201 {
00202 if ((x < 0) || (y < 0) || (x >= actmap->xsize) || (y >= actmap->ysize))
00203 return NULL;
00204 else
00205 return ( &actmap->field[y * actmap->xsize + x] );
00206 }
00207
00208
00209
00210 void putbuilding( GameMap* actmap,
00211 const MapCoordinate& entryPosition,
00212 int color,
00213 const BuildingType* buildingtyp,
00214 int completion,
00215 int ignoreunits )
00216 {
00217 if ( color & 7 )
00218 fatalError("putbuilding muss eine farbe aus 0,8,16,24,.. uebergeben werden !",2);
00219
00220 for ( int a = 0; a < 4; a++)
00221 for ( int b = 0; b < 6; b++ )
00222 if ( buildingtyp->fieldExists ( BuildingType::LocalCoordinate( a, b ) ) ) {
00223 MapField* field = actmap->getField( buildingtyp->getFieldCoordinate( entryPosition, BuildingType::LocalCoordinate(a,b) ));
00224 if (field == NULL)
00225 return ;
00226 else {
00227 if ( field->vehicle && (!ignoreunits ) )
00228 return;
00229 if (field->building != NULL)
00230 return;
00231 }
00232 }
00233
00234
00235 Building* gbde = new Building ( actmap , entryPosition, buildingtyp, color/8 );
00236
00237 if (completion >= buildingtyp->construction_steps)
00238 completion = buildingtyp->construction_steps - 1;
00239
00240 gbde->setCompletion ( completion );
00241 }
00242
00243
00244
00245
00246
00247 void checkobjectsforremoval ( GameMap* gamemap )
00248 {
00249 for ( int y = 0; y < gamemap->ysize; y++ )
00250 for ( int x = 0; x < gamemap->xsize; x++ ) {
00251 MapField* fld = getfield ( x, y );
00252 for ( MapField::ObjectContainer::iterator i = fld->objects.begin(); i != fld->objects.end(); )
00253 if ( i->typ->getFieldModification(fld->getWeather()).terrainaccess.accessible ( fld->bdt ) < 0 ) {
00254 fld->removeObject ( i->typ, true );
00255 i = fld->objects.begin();
00256 } else
00257 i++;
00258 }
00259 }
00260
00261 void checkunitsforremoval ( GameMap* gamemap )
00262 {
00263 ASCString messages[playerNum];
00264 for ( int y = 0; y < gamemap->ysize; y++ )
00265 for ( int x = 0; x < gamemap->xsize; x++ ) {
00266 MapField* fld = gamemap->getField ( x, y );
00267 if ( (fld->building && fld->building->typ->terrainaccess.accessible( fld->bdt ) < 0) && (fld->building->typ->height <= chfahrend) ) {
00268 messages[fld->building->getOwner()] += getBuildingReference( fld->building ) + " was destroyed \n\n";
00269 delete fld->building;
00270 }
00271 }
00272
00273
00274 for ( int c=0; c<=8 ;c++ ) {
00275 ASCString msg = messages[c];
00276 for ( Player::VehicleList::iterator i = gamemap->player[c].vehicleList.begin(); i != gamemap->player[c].vehicleList.end(); ) {
00277
00278 Vehicle* eht = *i;
00279 MapField* field = gamemap->getField(eht->xpos,eht->ypos);
00280 bool erase = false;
00281
00282 ASCString reason;
00283 if (field->vehicle == eht) {
00284 if ( eht->height <= chfahrend )
00285 if ( eht->typ->terrainaccess.accessible ( field->bdt ) < 0 ) {
00286 erase = true;
00287 reason = "was swallowed by the ground";
00288 }
00289 if ( eht )
00290 if ( getmaxwindspeedforunit( eht ) < gamemap->weather.windSpeed*maxwindspeed ) {
00291 reason = "was blown away by the wind";
00292 erase = true;
00293 }
00294 }
00295 if ( erase ) {
00296 msg += getUnitReference( eht ) + reason;
00297 msg += "\n\n";
00298
00299 Vehicle* pv = *i;
00300 gamemap->player[c].vehicleList.erase ( i );
00301 delete pv;
00302
00303
00304
00305
00306
00307 i = gamemap->player[c].vehicleList.begin();
00308 } else
00309 i++;
00310 }
00311
00312 if ( !msg.empty() )
00313 new Message ( msg, gamemap, 1<<c);
00314 }
00315 }
00316
00317
00318 int getwindheightforunit ( const Vehicle* eht, int uheight )
00319 {
00320 if ( uheight == -1 )
00321 uheight = eht->height;
00322
00323 if ( uheight == chfliegend )
00324 return 1;
00325 else
00326 if ( uheight == chhochfliegend )
00327 return 2;
00328 else
00329 return 0;
00330 }
00331
00332 int getmaxwindspeedforunit ( const Vehicle* eht )
00333 {
00334 MapField* field = eht->getMap()->getField(eht->xpos,eht->ypos);
00335 if ( field->vehicle == eht) {
00336 if (eht->height >= chtieffliegend && eht->height <= chhochfliegend )
00337 return eht->typ->movement[getFirstBit(eht->height)] * 256 ;
00338
00339 if ( (field->bdt & getTerrainBitType(cbfestland)).none() && eht->height <= chfahrend && eht->height >= chschwimmend && (field->bdt & getTerrainBitType(cbharbour)).none() && (field->bdt & getTerrainBitType(cbwater0)).none())
00340 return eht->typ->maxwindspeedonwater * maxwindspeed;
00341 }
00342 return maxint;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 int getheightdelta ( const ContainerBase* c1, const ContainerBase* c2 )
00394 {
00395 return getheightdelta( getFirstBit(c1->getHeight()), getFirstBit(c2->getHeight() ));
00396 }
00397
00398
00399 bool fieldvisiblenow( const MapField* pe, Vehicle* veh, int player )
00400 {
00401 GameMap* gamemap = pe->getMap();
00402 if ( player == -1 )
00403 return true;
00404
00405 if ( player < -1 )
00406 return false;
00407
00408 if ( !gamemap )
00409 return false;
00410
00411 if ( pe ) {
00412 int c = (pe->visible >> ( player * 2)) & 3;
00413
00414 if ( c < gamemap->getInitialMapVisibility( player ) )
00415 c = gamemap->getInitialMapVisibility( player );
00416
00417 if (c > visible_ago) {
00418 if ( !veh )
00419 veh = pe->vehicle;
00420
00421 if ( veh ) {
00422 if ((c == visible_all) || (veh->color / 8 == player ) || ((veh->height >= chschwimmend) && (veh->height <= chhochfliegend)))
00423 return true;
00424 }
00425 else
00426 if (pe->building != NULL) {
00427 if ((c == visible_all) || (pe->building->typ->height >= chschwimmend) || (pe->building->color == player*8))
00428 return true;
00429 }
00430 else
00431 return true;
00432 }
00433 }
00434 return false;
00435 }
00436
00437
00438
00439
00440 VisibilityStates fieldVisibility( const MapField* pe )
00441 {
00442 return fieldVisibility( pe, pe->getMap()->actplayer );
00443 }
00444
00445 VisibilityStates fieldVisibility( const MapField* pe, int player )
00446 {
00447 GameMap* gamemap = pe->getMap();
00448
00449 if ( player < 0 )
00450 return visible_all;
00451
00452 if ( pe ) {
00453 VisibilityStates c = VisibilityStates((pe->visible >> ( player * 2)) & 3);
00454 if ( c < gamemap->getInitialMapVisibility( player ) )
00455 c = gamemap->getInitialMapVisibility( player );
00456
00457 return c;
00458 } else
00459 return visible_not;
00460 }
00461
00462
00463 void calculateobject( const MapCoordinate& pos,
00464 bool mof,
00465 const ObjectType* obj,
00466 GameMap* gamemap )
00467 {
00468 calculateobject( pos.x, pos.y, mof, obj, gamemap );
00469 }
00470
00471
00472 void calculateobject( int x,
00473 int y,
00474 bool mof,
00475 const ObjectType* obj,
00476 GameMap* actmap )
00477 {
00478 if ( obj->netBehaviour & ObjectType::KeepOrientation )
00479 return;
00480
00481 if ( obj->netBehaviour & ObjectType::SpecialForest ) {
00482
00483 return;
00484 }
00485
00486 MapField* fld = actmap->getField(x,y) ;
00487 Object* oi2 = fld-> checkForObject ( obj );
00488
00489 int c = 0;
00490 for ( int dir = 0; dir < sidenum; dir++) {
00491 int a = x;
00492 int b = y;
00493 getnextfield( a, b, dir );
00494 MapField* fld2 = actmap->getField(a,b);
00495
00496 if ( fld2 ) {
00497 if ( obj->netBehaviour & ObjectType::NetToSelf )
00498 if ( fld2->checkForObject ( obj )) {
00499 c |= 1 << dir ;
00500 if ( mof )
00501 calculateobject ( a, b, false, obj, actmap );
00502 }
00503
00504
00505 for ( int oj = 0; oj < int(obj->linkableObjects.size()); oj++ ) {
00506 for ( int id = obj->linkableObjects[oj].from; id <= obj->linkableObjects[oj].to; ++id ) {
00507 Object* oi = fld2->checkForObject ( actmap->getobjecttype_byid ( id ) );
00508 if ( oi ) {
00509 c |= 1 << dir ;
00510 if ( mof )
00511 calculateobject ( a, b, false, oi->typ, actmap );
00512 }
00513 }
00514 }
00515
00516 for ( unsigned int t = 0; t < obj->linkableTerrain.size(); t++ )
00517 for ( int id = obj->linkableTerrain[t].from; id <= obj->linkableTerrain[t].to; ++id )
00518 if ( fld2->typ->terraintype->id == id )
00519 c |= 1 << dir ;
00520
00521 if ( fld2->building && !fld2->building->typ->hasFunction( ContainerBaseType::NoObjectChaining ) ) {
00522 if ( (obj->netBehaviour & ObjectType::NetToBuildingEntry) && (fld2->bdt & getTerrainBitType(cbbuildingentry) ).any() )
00523 c |= 1 << dir;
00524
00525 if ( obj->netBehaviour & ObjectType::NetToBuildings )
00526 c |= 1 << dir;
00527 }
00528
00529 }
00530 else {
00531 if ( obj->netBehaviour & ObjectType::NetToBorder )
00532 c |= 1 << dir;
00533 }
00534 }
00535
00536 if ( obj->netBehaviour & ObjectType::AutoBorder ) {
00537 int autoborder = 0;
00538 int count = 0;
00539 for ( int dir = 0; dir < sidenum; dir++) {
00540 int a = x;
00541 int b = y;
00542 getnextfield( a, b, dir );
00543 MapField* fld2 = actmap->getField(a,b);
00544 if ( !fld2 ) {
00545
00546 if ( c & (1 << ((dir+sidenum/2) % sidenum ))) {
00547 autoborder |= 1 << dir;
00548 count++;
00549 }
00550 }
00551 }
00552 if ( count == 1 )
00553 c |= autoborder;
00554 }
00555
00556 if ( oi2 ) {
00557 oi2->setDir ( c );
00558 }
00559
00560 }
00561
00562
00563
00564
00565 void calculateallobjects( GameMap* actmap )
00566 {
00567
00568 for ( int y = 0; y < actmap->ysize ; y++)
00569 for ( int x = 0; x < actmap->xsize ; x++) {
00570 MapField* fld = actmap->getField(x,y);
00571
00572 for ( MapField::ObjectContainer::iterator i = fld->objects.begin(); i != fld->objects.end(); i++ )
00573
00574 calculateobject( x, y, false, i->typ, actmap );
00575 #if 0
00576 else
00577 if ( find ( forestObjects.begin(), forestObjects.end(), i->typ ) == forestObjects.end())
00578 forestObjects.push_back ( i->typ );
00579 #endif
00580
00581 fld->setparams();
00582 }
00583 #if 0
00584 for ( vector<ObjectType*>::iterator i = forestObjects.begin(); i != forestObjects.end(); i++ )
00585 ForestCalculation::calculateforest( actmap, *i );
00586 #endif
00587 }
00588
00589
00590