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

unitctrl.h

Go to the documentation of this file.
00001 
00002 /*
00003     This file is part of Advanced Strategic Command; http://www.asc-hq.de
00004     Copyright (C) 1994-1999  Martin Bickel  and  Marc Schellenberger
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; see the file COPYING. If not, write to the 
00018     Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
00019     Boston, MA  02111-1307  USA
00020 */
00021 
00022 #ifndef unitctrlH
00023 #define unitctrlH
00024 
00025 #include <vector>
00026 #include <map>
00027 
00028 #include "typen.h"
00029 #include "mapalgorithms.h"
00030 #include "basestrm.h"
00031 #include "spfst.h"
00032 #include "attack.h"
00033 #include "astar2.h"
00034 #include "actions/servicing.h"
00035 
00036 
00042 #ifdef karteneditor
00043 #error The mapeditor does not need any pathfinding
00044 #endif
00045 
00046 
00047 extern SigC::Signal0<void> fieldCrossed;
00048 
00049 
00050 template<class T>
00051 class FieldList {
00052        GameMap* localmap;
00053        int fieldnum;
00054        std::vector<int> xpos;
00055        std::vector<int> ypos;
00056        std::vector<T>   data;
00057      public:
00058        FieldList ( void );
00059        int getFieldNum ( void ) const;
00060        tfield* getField ( int num ) const;
00061        T& getData ( int num );
00062        T& getData ( int x, int y );
00063        void getFieldCoordinates ( int num, int* x, int* y ) const;
00064        MapCoordinate getFieldCoordinates ( int num ) const;
00065        void addField ( int x, int y, const T& _data );
00066        void addField ( const MapCoordinate& mc, const T& _data );
00067        void addField ( int x, int y );
00068        void addField ( const MapCoordinate& mc );
00069        void setMap ( GameMap* map );
00070        GameMap* getMap ( void );
00071        bool isMember ( int x, int y );
00072        bool isMember ( const MapCoordinate& mc );
00073      };
00074 
00075 
00076 typedef FieldList<int> IntFieldList;
00077 typedef FieldList<AttackWeap> AttackFieldList;
00078 
00079 
00080 typedef class PendingVehicleActions* PPendingVehicleActions;
00081 
00082 
00083 enum VehicleActionType { vat_nothing, vat_move, vat_ascent, vat_descent, vat_attack, vat_service, vat_newservice };
00084 
00085 class VehicleAction {
00086            protected:
00087               PPendingVehicleActions pva; 
00088               VehicleActionType actionType;
00089            public:
00090               virtual int getStatus( void ) = 0;
00091               virtual int available ( Vehicle* veh ) const = 0;
00092               virtual int execute ( Vehicle* veh, int x, int y, int step, int param1, int param2 ) = 0;
00093               virtual void registerPVA ( VehicleActionType _actionType, PPendingVehicleActions _pva );
00094               VehicleAction ( VehicleActionType _actionType, PPendingVehicleActions _pva  );
00095               virtual ~VehicleAction ( );
00096          };
00097 
00098 /* Usage of VehicleActions:
00099  *   The contstructor usually requires passing of MapDisplayInterface* which is a class that controls the visual 
00100  *    output of the vehicle action. "defaultMapDisplay" is a global object that handles the output. When NULL is passed, 
00101  *    any graphical output is disabled. 
00102  *   available ( unit ) checks, whether this functions is available or not. If it is available, it can be exectuted
00103  *    with several calls to:
00104  *   execute ( ... ). Most vehicle actions are divided into several tasks, which have to be executed one after another.
00105  *    getStatus() return the current task number, which has to be passed to execute. I recommend to pass hardcoded constants
00106  *    to execute instead of getStatus() to make sure the caller and the action are in sync.
00107  *    The parameters for execute are explained for each vehicle function; -1 is used for parameters that are not used
00108  *    If an error occurs, the result of execute will be negative and indicate an appropriate error message 
00109  *    (file message1.txt). You can get it with getmessage( -result ) or directly print it to the status line with 
00110  *    dispmessage2 ( -result );
00111  *    A result of 1000 shows that the action is completed.
00112  *   registerPVA is usually not necessary to be called externally
00113  */
00114 
00115 
00116 
00117 typedef int trichtungen[sidenum];
00118 
00119 class MapDisplayInterface;
00120 
00121 class BaseVehicleMovement : public VehicleAction {
00122            protected:
00123               MapDisplayInterface* mapDisplay;
00124               int status;
00125            public:
00126               BaseVehicleMovement ( VehicleActionType _actionType, PPendingVehicleActions _pva, MapDisplayInterface* md ) : VehicleAction ( _actionType, _pva ),mapDisplay(md), status(0), attackedByReactionFire(false)  {};
00127               BaseVehicleMovement ( MapDisplayInterface* md ) : VehicleAction ( vat_move, NULL ),mapDisplay(md), status(0), attackedByReactionFire(false) {};
00128               AStar3D::Path path;
00129               int execute ( Vehicle* veh, int x, int y, int step, int height, int noInterrupt );
00130               bool attackedByReactionFire;
00131               Vehicle* getVehicle ( void ) { return vehicle; };
00132               void registerMapDisplay ( MapDisplayInterface* _mapDisplay ) { mapDisplay = _mapDisplay; };
00133               virtual int getStatus ( void ) { return status; };
00134               int available ( Vehicle* veh ) const;
00135 
00136 
00137             protected:
00138                Vehicle* vehicle;
00139 
00140                int moveunitxy ( AStar3D::Path& pathToMove, int noInterrupt = -1 );
00141 
00142                class PathFinder : public AStar3D {
00143                  public:
00144                    PathFinder ( GameMap* actmap, Vehicle* veh, int maxDistance ) : AStar3D(actmap, veh, false, maxDistance ) {};
00145 
00150                    void getMovementFields ( IntFieldList& reachableFields, IntFieldList& reachableFieldsIndirect, int height );
00151               };
00152           };
00153 
00154 
00155 class VehicleMovement : public BaseVehicleMovement {
00156            public:
00157               IntFieldList reachableFields;
00158               IntFieldList reachableFieldsIndirect;
00159               int available ( Vehicle* veh ) const { return status==0 && avail(veh); };
00160               static bool avail ( Vehicle* veh );
00161 
00162               enum  { NoInterrupt = 1, DisableHeightChange = 2 };
00163               int execute ( Vehicle* veh, int x, int y, int step, int height, int capabilities );
00164 
00165               virtual void registerPVA ( VehicleActionType _actionType, PPendingVehicleActions _pva );
00166               VehicleMovement ( MapDisplayInterface* md, PPendingVehicleActions _pva = NULL );
00167               ~VehicleMovement ( );
00168           };
00169 
00170 /* VehicleMovement:
00171  *
00172  *   Step 0:   execute ( vehicle, -1, -1, step = 0 , height, capabilities );
00173  *                 height is usually -1, which means the aircraft will move on the same level of height it currently has
00174  *                        But there are situations like starting aircraft from carriers where it has to be set to the height
00175  *                        the aircraft should move on after start. Don't use this height for regular height changing!
00176  *                        If it is -2 then return fields on all levels of height
00177  *
00178  *             the fields that are reachable will be stored in "reachableFields". "reachableFieldsIndirect" contains fields
00179  *                 the unit could move to if the field was empty
00180  *
00181  *   Step 2:   execute ( NULL, destination-x, destination-y, step = 2, -1, -1 );
00182  *                The destination must be one of the fields in "reachableFields"
00183  *                the effect of this step is that "path" contains the fields that the unit will move over to reach the 
00184  *                 destination.
00185  *            
00186  *   Step 3:   execute ( NULL, destination-x, destination-y, step = 3, -1, NoInterrupt );
00187  *                The destination must be one of the fields in "path"
00188  *                If NoInterrupt is != -1 the unit will not stop when being attacked by mines and reactionfire.
00189  */
00190 
00191 
00192 
00193 class ChangeVehicleHeight : public BaseVehicleMovement {
00194               int newheight;
00195               int dir;
00196            public:
00197               IntFieldList reachableFields;
00198               int execute ( Vehicle* veh, int x, int y, int step, int noInterrupt, int disableMovement );
00199               ChangeVehicleHeight ( MapDisplayInterface* md, PPendingVehicleActions _pva , VehicleActionType vat, int dir_ );
00200           };
00201 
00202 class IncreaseVehicleHeight : public ChangeVehicleHeight {
00203            public:
00204               IncreaseVehicleHeight ( MapDisplayInterface* md, PPendingVehicleActions _pva = NULL );
00205               static bool avail ( Vehicle* veh );
00206               int available ( Vehicle* veh ) const;
00207               ~IncreaseVehicleHeight();
00208           };
00209 
00210 class DecreaseVehicleHeight : public ChangeVehicleHeight {
00211            public:
00212               DecreaseVehicleHeight ( MapDisplayInterface* md, PPendingVehicleActions _pva = NULL );
00213               static bool avail ( Vehicle* veh );
00214               int available ( Vehicle* veh ) const;
00215               ~DecreaseVehicleHeight();
00216           };
00217 
00218 
00219 /* IncreaseVehicleHeight / DecreaseVehicleHeight:
00220  *
00221  *   Step 0:   execute ( vehicle, -1, -1, step = 0 , newheight, allFields );
00222  *                 newheight should be vehicle->height >> 1 for DecreaseVehicleHeight and
00223  *                                     vehicle->height << 1 for IncreaseVehicleHeight.
00224  *                 allFields: 1 all fields are reported that can be reached with moving the unit first
00225  *                            <= 0 ; only fields are reported that the unit can reach changing its
00226  *                                   height without moving first
00227  *                 Depending of the units ability to change its height vertically (for example helicopter and submarine) or
00228  *                   by moving a distance ( normal airplanes ), execute will either immediatly change the units height and
00229  *                   finish (status == 1000), or follow the same procedure as VehicleMovement.
00230  *   (Step 2)  see VehicleMovement
00231  *               if a movement is executed prior to changing the height (allFields == 1 in step 0),
00232  *               step 2 and step 3 of the movement are executed here !
00233  *   (Step 3)  see VehicleMovement
00234  */
00235 
00236 
00237 
00238 class VehicleAttack : public VehicleAction {
00239               Vehicle* vehicle;
00240               int status;
00241               int kamikaze;
00242               class tsearchattackablevehicles : public SearchFields {
00243                                   VehicleAttack* va;
00244                                public:
00245                                   int       anzahlgegner;
00246                                   const Vehicle*  angreifer;
00247                                   int       kamikaze;
00248                                   void            init ( const Vehicle* eht, int _kamikaze, VehicleAttack* _va );
00249                                   virtual void    testfield ( const MapCoordinate& mc );
00250                                   int             run ( void );
00251                                   tsearchattackablevehicles ( GameMap* _gamemap ) : SearchFields ( _gamemap ) {};
00252                           } search;
00253 
00254            protected:
00255               MapDisplayInterface* mapDisplay;
00256            public:
00257               AttackFieldList attackableVehicles;
00258               AttackFieldList attackableBuildings;
00259               AttackFieldList attackableObjects;
00260 
00261               int getStatus( void ) { return status; };
00262               Vehicle* getAttacker() { return vehicle; };
00263               virtual int available ( Vehicle* veh ) const { return status==0 && avail(veh); };
00264               static bool avail( Vehicle* veh );
00265               virtual int execute ( Vehicle* veh, int x, int y, int step, int _kamikaze, int weapnum );
00266               virtual void registerPVA ( VehicleActionType _actionType, PPendingVehicleActions _pva );
00267               VehicleAttack ( MapDisplayInterface* md, PPendingVehicleActions _pva = NULL );
00268               virtual ~VehicleAttack ( );
00269          };
00270 
00271 
00272 
00273 /* VehicleAttack:
00274  *
00275  *   Step 0:   execute ( vehicle, -1, -1, step = 0 , kamikaze, -1 );
00276  *                 kamikaze attack is not implemented yet. Always pass 0
00277  *                        
00278  *                 "attackableVehicles", "attackableBuildings", "attackableObjects" contains the possible targets of the 
00279  *                   unit, along with information about the weapon(s) which can be used for the attack
00280  *
00281  *   Step 2:   execute ( NULL, target-x, target-y, step = 2, -1, weapnum );
00282  *                The target destination must be part of one of the "attackable*" fields.
00283  *                weapnum may either be a specific weapon or -1 if the most powerful one should be used
00284  */
00285 
00286 
00287 
00288 class VehicleService : public VehicleAction {
00289               Vehicle* vehicle;
00290               Building* building;
00291               int status;
00292 
00293           public:
00294               class FieldSearch : public SearchFields {
00295                      VehicleService& vs;
00296                      Vehicle*        veh;
00297                      Building*       bld;
00298                      Resources       buildingResources;
00299                      Resources       resourcesCapacity;
00300                   public:
00301                      struct {
00302                        bool distance;
00303                        bool height;
00304                      } bypassChecks;
00305                      virtual void     testfield ( const MapCoordinate& mc );
00306                      void             checkVehicle2Vehicle ( Vehicle* veh, int xp, int yp );
00307                      void             checkBuilding2Vehicle ( Vehicle* veh );
00308                      bool             initrefuelling( int xp1, int yp1 );
00309                      void             init ( Vehicle* _veh, Building* _bld );
00310                      void             run (  );
00311                      FieldSearch ( VehicleService& _vs, GameMap* _gamemap ) : SearchFields ( _gamemap ), vs ( _vs ) { bypassChecks.distance = false; bypassChecks.height = false; };
00312                   } fieldSearch;
00313 
00314 
00315            protected:
00316               MapDisplayInterface* mapDisplay;
00317            public:
00318               Vehicle* getVehicle ( void ) { return vehicle; };
00319               Building* getBuilding ( void ) { return building; };
00320 
00321               enum Service { srv_repair, srv_resource, srv_ammo };
00322               class Target {
00323                  public:
00324                     Vehicle* dest;
00325 
00326                     struct Service {
00327                       VehicleService::Service type;
00328                       int sourcePos;  
00329                       int targetPos;
00330                       int curAmount;  
00331                       int maxAmount;  
00332                       int minAmount;  
00333                       int maxPercentage;
00334                       int orgSourceAmount;
00335                     };
00336                     vector<Service> service;
00337               };
00338               typedef map<int,Target> TargetContainer;
00339               TargetContainer dest;
00340 
00341               int getStatus( void ) { return status; };
00342               virtual int available ( Vehicle* veh ) const;
00343               static int avail ( const Vehicle* veh );
00344               static int getServices ( Vehicle* veh );
00345               int execute ( Vehicle* veh, int targetNWID, int dummy, int step, int pos, int amount );
00346               int fillEverything ( int targetNWID, bool repairsToo );
00347               virtual void registerPVA ( VehicleActionType _actionType, PPendingVehicleActions _pva );
00348               VehicleService ( MapDisplayInterface* md, PPendingVehicleActions _pva = NULL );
00349               virtual ~VehicleService ( );
00350 
00352               int guimode;
00353          };
00354 
00355 
00356 
00357 /* VehicleService:
00358  *
00359  *   Step 0:   execute ( vehicle, -1, -1, step = 0 , -1, -1 );
00360  *                 if vehicle is going to service some units
00361  *                  OR
00362  *             execute ( NULL, xpos, ypos, step = 0 , -1, -1 );
00363  *                 if the building at xpos, ypos is going to service some units
00364  *
00365  *                 dest then contains all units that can be services together with the services
00366  *                 Use the units networkID as Index
00367  *
00368  *
00369  *   Step 2:   execute ( NULL, targetNWID, -1, step = 2, pos, amount );
00370  *                 targetNWID is the unit that is going to be serviced
00371  *                 pos is the position of the service: dest[targetNWID].service[pos]
00372  *                 amount is the amount of the service that is going to be transferred
00373  */
00374 
00375 
00376 
00377          
00378 #if 1
00379 
00380          class NewVehicleService : public VehicleAction {
00381             public:
00382                typedef ServiceTargetSearcher::Targets Targets;
00383                ServiceTargetSearcher::Targets targets;
00384             private:
00385                ContainerBase* container;
00386                int status;
00387                
00388                
00389             protected:
00390                MapDisplayInterface* mapDisplay;
00391             public:
00392                ContainerBase* getContainer() { return container; };
00393 
00394                int getStatus( void ) { return status; };
00395                virtual int available ( ContainerBase* veh ) const;
00396                virtual int available ( Vehicle* veh ) const;
00397                static int avail ( ContainerBase* veh );
00398                int executeContainer ( ContainerBase* veh, int x, int y, int step, int pos, int amount );
00399                int execute ( Vehicle* veh, int x, int y, int step, int pos, int amount );
00400                
00401                bool targetAvail( const ContainerBase* target );
00402                
00403                int fillEverything ( ContainerBase* target, bool repairsToo = false );
00404                virtual void registerPVA ( VehicleActionType _actionType, PPendingVehicleActions _pva );
00405                NewVehicleService ( MapDisplayInterface* md, PPendingVehicleActions _pva = NULL );
00406                virtual ~NewVehicleService ( );
00407 
00409                int guimode;
00410          };
00411 
00412 
00413 
00414 /* NewVehicleService:
00415          *
00416          *   Step 0:   execute ( vehicle, -1, -1, step = 0 , -1, -1 );
00417          *                 if vehicle is going to service some units
00418          *                  OR
00419          *             execute ( NULL, xpos, ypos, step = 0 , -1, -1 );
00420          *                 if the building at xpos, ypos is going to service some units
00421          *
00422          *                 dest then contains all units that can be services together with the services
00423          *                 Use the units networkID as Index
00424          *
00425          *
00426          *   Step 2:   execute ( NULL, targetNWID, -1, step = 2, pos, amount );
00427          *                 targetNWID is the unit that is going to be serviced
00428          *                 pos is the position of the service: dest[targetNWID].service[pos]
00429          *                 amount is the amount of the service that is going to be transferred
00430  */
00431 
00432 #endif
00433          
00434 
00435 
00436 class PendingVehicleActions {
00437           public:
00438             int actionType;
00439             PendingVehicleActions ( void );
00440             VehicleAction* action;
00441 
00442             VehicleMovement* move;
00443             IncreaseVehicleHeight* ascent;
00444             DecreaseVehicleHeight* descent;
00445             VehicleAttack* attack;
00446             VehicleService* service;
00447             NewVehicleService* newservice;
00448             ~PendingVehicleActions ( );
00449             void reset();
00450          };
00451 
00453 extern PendingVehicleActions pendingVehicleActions;
00454 
00455 
00456 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
00457  * Template implementations
00458  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00459 
00460 template<class T> FieldList<T> :: FieldList ( void )
00461 {
00462    fieldnum = 0;
00463    localmap = NULL;
00464 }
00465 
00466 template<class T> int FieldList<T> :: getFieldNum ( void ) const
00467 {
00468    return fieldnum;
00469 }
00470 
00471 template<class T> tfield* FieldList<T> :: getField ( int num ) const
00472 {
00473    if ( num < fieldnum && num >= 0 )
00474       return getfield ( xpos[num], ypos[num] );
00475    else
00476       return NULL;
00477 }
00478 
00479 
00480 template<class T> T& FieldList<T> :: getData ( int num )
00481 {
00482    if ( num < fieldnum && num >= 0 )
00483       return data[num] ;
00484 
00485    throw OutOfRange();
00486 }
00487 
00488 template<class T> T& FieldList<T> :: getData ( int x, int y )
00489 {
00490    for ( int i = 0; i < fieldnum; i++ )
00491       if ( xpos[i] == x && ypos[i] == y )
00492          return data[i];
00493 
00494    throw OutOfRange();
00495 }
00496 
00497 
00498 template<class T> void FieldList<T> :: getFieldCoordinates ( int num, int* x, int* y ) const
00499 {
00500    if ( num < fieldnum && num >= 0 ) {
00501       *x = xpos[num];
00502       *y = ypos[num];
00503    } else {
00504       *x = -1;
00505       *y = -1;
00506    }
00507 }
00508 
00509 template<class T> MapCoordinate FieldList<T> :: getFieldCoordinates ( int num ) const
00510 {
00511    if ( num < fieldnum && num >= 0 ) {
00512       return MapCoordinate( xpos[num], ypos[num] );
00513    } else {
00514       return MapCoordinate( -1, -1 );
00515    }
00516 }
00517 
00518 
00519 template<class T> void FieldList<T> :: addField ( const MapCoordinate& mc, const T& _data )
00520 {
00521    addField ( mc.x, mc.y, _data );
00522 }
00523 
00524 template<class T> void FieldList<T> :: addField ( int x, int y, const T& _data )
00525 {
00526    int found = 0;
00527    for( int i = 0; i < fieldnum; i++ )
00528       if ( xpos[i] == x && ypos[i] == y )
00529          found = 1;
00530    if ( !found ) {
00531       xpos.push_back ( x );
00532       ypos.push_back ( y );
00533       data.push_back( _data );
00534 
00535       fieldnum++;
00536    }
00537 }
00538 
00539 
00540 
00541 template<class T> void FieldList<T> :: addField ( const MapCoordinate& mc )
00542 {
00543    addField ( mc.x, mc.y );
00544 }
00545 
00546 template<class T> void FieldList<T> :: addField ( int x, int y )
00547 {
00548    int found = 0;
00549    for( int i = 0; i < fieldnum; i++ )
00550       if ( xpos[i] == x && ypos[i] == y )
00551          found = 1;
00552    if ( !found ) {
00553       xpos.push_back ( x );
00554       ypos.push_back ( y );
00555       T t;
00556       data.push_back ( t );
00557       fieldnum++;
00558    }
00559 }
00560 
00561 
00562 template<class T> void FieldList<T> :: setMap ( GameMap* map )
00563 {
00564    localmap = map;
00565 }
00566 
00567 template<class T> GameMap* FieldList<T> :: getMap ( void )
00568 {
00569    return localmap;
00570 }
00571 
00572 template<class T> bool FieldList<T> :: isMember ( int x, int y )
00573 {
00574    for ( int i = 0; i < fieldnum; i++ )
00575       if ( xpos[i] == x && ypos[i] == y )
00576          return true;
00577    return false;
00578 }
00579 
00580 template<class T> bool FieldList<T> :: isMember ( const MapCoordinate& mc )
00581 {
00582    for ( int i = 0; i < fieldnum; i++ )
00583       if ( xpos[i] == mc.x && ypos[i] == mc.y )
00584          return true;
00585    return false;
00586 }
00587 
00588 
00589 #endif
00590 

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