spfst.cpp

Go to the documentation of this file.
00001 
00005 /*
00006     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00007     Copyright (C) 1994-2010  Martin Bickel  and  Marc Schellenberger
00008 
00009     This program is free software; you can redistribute it and/or modify
00010     it under the terms of the GNU General Public License as published by
00011     the Free Software Foundation; either version 2 of the License, or
00012     (at your option) any later version.
00013 
00014     This program is distributed in the hope that it will be useful,
00015     but WITHOUT ANY WARRANTY; without even the implied warranty of
00016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017     GNU General Public License for more details.
00018 
00019     You should have received a copy of the GNU General Public License
00020     along with this program; see the file COPYING. If not, write to the 
00021     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00022     Boston, MA  02111-1307  USA
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    if ( c == visible_all)
00148       if ( field->mines.size() )
00149          for ( int i = 0; i < field->mines.size(); i++ )
00150             if ( field->getMine(i).attacksunit( vehicle ))
00151                return 0;
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 {   // building
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              /* if the unit was a transport and had other units loaded, these units have been deleted as well.
00306                 We don't know which elements of the container are still valid, so we start from the beginning again. */
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 ) //    || ((eht->height == chfahrend) && ( field->typ->art & cbwater ))) ) 
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 void tdrawline8 :: start ( int x1, int y1, int x2, int y2 )
00350 {
00351    x1 += x1 + (y1 & 1);
00352    x2 += x2 + (y2 & 1);
00353    tdrawline::start ( x1, y1, x2, y2 );
00354 }
00355 
00356 void tdrawline8 :: putpix ( int x, int y )
00357 {
00358        if ( (x & 1) == (y & 1) )
00359           putpix8( x/2, y );
00360 }
00361 */
00362 /*
00363 void EllipseOnScreen :: paint ( void )
00364 {
00365    if ( active )
00366       ellipse ( x1, y1, x2, y2, color, precision );
00367 }
00368 
00369 void EllipseOnScreen :: read( tnstream& stream )
00370 {
00371   x1 = stream.readInt();
00372   y1 = stream.readInt();
00373   x2 = stream.readInt();
00374   y2 = stream.readInt();
00375   color = stream.readInt();
00376   precision = stream.readFloat();
00377   active = stream.readInt();
00378 }
00379 
00380 void EllipseOnScreen :: write ( tnstream& stream )
00381 {
00382    stream.writeInt( x1 );
00383    stream.writeInt( y1 );
00384    stream.writeInt( x2 );
00385    stream.writeInt( y2 );
00386    stream.writeInt( color );
00387    stream.writeFloat( precision );
00388    stream.writeInt( active );
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       // ForestCalculation::calculateforest( actmap, obj );
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             // if the field opposite of the border field is connected to, make a straight line out of the map.
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    // vector<ObjectType*> forestObjects;
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              // if ( !(i->typ->netBehaviour & ObjectType::SpecialForest) )
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 

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