/*! \file gamemap.h \brief Definition of THE central asc class: tmap */ /*************************************************************************** gamemap.h - description ------------------- begin : Tue Feb 17 2001 copyright : (C) 2001 by Martin Bickel email : bickel@asc-hq.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef gamemapH #define gamemapH #include #include "typen.h" #include "baseaiinterface.h" #include "vehicle.h" #include "buildings.h" #include "basestrm.h" #include "time.h" #include "messages.h" #include "gameeventsystem.h" #include "research.h" #include "password.h" //! The number of game paramters that can be specified for each map. const int gameparameternum = 32; //! The names of the game paramter. \sa gameparameterdefault extern const char* gameparametername[ gameparameternum ]; extern const int gameparameterdefault [ gameparameternum ]; extern const int gameParameterLowerLimit [ gameparameternum ]; extern const int gameParameterUpperLimit [ gameparameternum ]; extern const bool gameParameterChangeableByEvent [ gameparameternum ]; enum GameParameter { cgp_fahrspur, cgp_eis, cgp_movefrominvalidfields, cgp_building_material_factor, cgp_building_fuel_factor, cgp_forbid_building_construction, cgp_forbid_unitunit_construction, cgp_bi3_training, cgp_maxminesonfield, cgp_antipersonnelmine_lifetime, cgp_antitankmine_lifetime, cgp_mooredmine_lifetime, cgp_floatingmine_lifetime, cgp_buildingarmor, cgp_maxbuildingrepair, cgp_buildingrepairfactor, cgp_globalfuel, cgp_maxtrainingexperience, cgp_initialMapVisibility, cgp_attackPower, cgp_jammingAmplifier, cgp_jammingSlope, cgp_superVisorCanSaveMap, cgp_objectsDestroyedByTerrain, cgp_trainingIncrement, cgp_experienceDivisorAttack, cgp_disableDirectView, cgp_disableUnitTransfer, cgp_experienceDivisorDefense, cgp_debugEvents, cgp_objectGrowthMultiplier, cgp_objectGrowOnOtherObjects }; class AgeableItem { protected: AgeableItem() : lifetimer(-1) {}; public: int lifetimer; //! ages the object by one turn. Returns true if the object shall be removed static bool age( AgeableItem& obj ); }; //! an instance of an object type (#tobjecttype) on the map class Object : public AgeableItem { public: pobjecttype typ; int damage; int dir; // int dummy[4]; Object ( void ); Object ( pobjecttype t ); void display ( int x, int y, int weather = 0 ); void setdir ( int dir ); int getdir ( void ); }; #define cminenum 4 extern const char* MineNames[cminenum] ; extern const int MineBasePunch[cminenum] ; enum MineTypes { cmantipersonnelmine = 1 , cmantitankmine, cmmooredmine, cmfloatmine }; class Mine : public AgeableItem { public: Mine( MineTypes type, int strength, int player, tmap* gamemap ); MineTypes type; //! the effective punch of the mine int strength; //! the player who placed the mine; range 0 .. 7 int player; //! can the mine attack this unit bool attacksunit ( const pvehicle veh ); }; class LoadNextMap { public: int id; LoadNextMap( int ID ) : id(ID) {}; }; //! a single field of the map class tfield { pmap gamemap; void init(); protected: tfield ( ); friend class tmap; public: tfield ( pmap gamemap_ ); void operator= ( const tfield& f ); void setMap ( pmap gamemap_ ) { gamemap = gamemap_; }; //! the terraintype (#pwterraintype) of the field TerrainType::Weather* typ; //! mineral resources on this field (should be changed to #ResourcesType sometime...) char fuel, material; //! can this field be seen be the player. Variable is bitmapped; two bits for each player. These two bits can have the states defined in ::VisibilityStates Uint16 visible; //! in the old octagonal version of ASC it was possible to rotate the terraintype; this is not used in the hexagonal version any more char direction; //! units standing on this object will get a bonus to their view int viewbonus; void* picture; //@{ //! Various algorithms need to store some information in the fields they process. These variables are used for this. union { struct { char temp; char temp2; }a; Uint16 tempw; }; int temp3; int temp4; //@} pvehicle vehicle; pbuilding building; struct Resourceview { Resourceview ( void ); char visible; // BM char fuelvisible[8]; char materialvisible[8]; }; //! the mineral resources that were seen by a player on this field; since the actual amount may have decreased since the player looked, this value is not identical to the fuel and material fields. Resourceview* resourceview; typedef list MineContainer; MineContainer mines; //! returns the nth mine. This function should only be used by legacy code; new code should store an iterator instead of an index Mine& getMine ( int n ); typedef vector ObjectContainer; ObjectContainer objects; /** add an object to the field \param obj The object type \param dir The direction of the object type; -1 to use default direction \param force Put the object there even if it cannot normally be placed on this terrain **/ void addobject ( pobjecttype obj, int dir = -1, bool force = false ); //! removes all objects of the given type from the field void removeobject ( pobjecttype obj, bool force = false ); //! sorts the objects. Since objects can be on different levels of height, the lower one must be displayed first void sortobjects ( void ); //! checks if there are objects from the given type on the field and returns them pobject checkforobject ( pobjecttype o ); //! the terraintype properties. They determine which units can move over the field. This variable is recalculated from the terraintype and objects each time something on the field changes (#setparams) TerrainBits bdt; //! are any events connected to this field int connection; //! deletes everything placed on the field void deleteeverything ( void ); //! recalculates the terrain properties, movemalus etc from the terraintype and the objects, void setparams ( void ); //! the defense bonus that unit get when they are attacked int getdefensebonus ( void ); //! the attack bonus that unit get when they are attacking int getattackbonus ( void ); //! the weather that is on this field int getweather ( void ); void setweather( int weather ); //! the radar jamming that is on this field int getjamming ( void ); int getmovemalus ( const pvehicle veh ); int getmovemalus ( int type ); //! can any of the mines on this field attack this unit int mineattacks ( const pvehicle veh ); //! the player who placed the mines on this field. int mineowner ( void ); //! checks if the unit is standing on this field. Since units are being cloned for some checks, this method should be used instead of comparing the pointers to the unit bool unitHere ( const Vehicle* veh ); //! returns a pointer to the #ContainerBase of the field or NULL if there is none ContainerBase* getContainer() { if ( vehicle ) return vehicle; else return building; }; //! put a mine of type typ for player col (0..7) and a punch of strength on the field. Strength is an absolute value (unlike the basestrength of a mine or the punch of the mine-weapon, which are just factors) bool putmine ( int col, int typ, int strength ); /** removes a mine \param num The position of the mine; if num is -1, the last mine is removed) **/ void removemine ( int num ); void endRound( int turn ); //! some variables for the viewcalculation algorithm. see #viewcalculation.cpp for details struct View { int view; int jamming; char mine, satellite, sonar, direct; } view[8]; /** The visibility status for all players is stored in a bitmapped variable. This functions changes the status in this variable for a single player \param valtoset the value that is going to be written into the visibility variable \param actplayer the player for which the view is changed */ void setVisibility ( VisibilityStates valtoset, int actplayer ) { int newval = (valtoset ^ 3) << ( 2 * actplayer ); int oneval = 3 << ( 2 * actplayer ); visible |= oneval; visible ^= newval; }; ~tfield(); private: int getx( void ); int gety( void ); TerrainType::MoveMalus __movemalus; }; //! The map. THE central structure of ASC, which holds everything not globally available together class tmap { void operator= ( const tmap& map ); public: //! the size of the map int xsize, ysize; //! the coordinate of the map that is displayed on upper left corner of the screen int xpos, ypos; //! the array of fields pfield field; //! the codeword for accessing a map in a campaign char codeword[11]; //! the title of the map ASCString maptitle; struct Campaign { //! an identification for identifying a map in the chain of maps that make up a campaign int id; //! the id of the previous map in the campaign. This is only used as a fallback mechanism if the event based chaining fails. It will probably be discared sooner or later int prevmap; //! a campaign is usually designed to be played by a specific player unsigned char player; //! can the map be loaded just by knowing its filenmae? If 0, the codeword is required char directaccess; }; //! the campaign properties of map Campaign* campaign; //! the player who is currently making his moves (may be human or AI) signed char actplayer; //! the time in the game, mesured in a turns and moves GameTime time; struct Weather { Weather():fog(0),windSpeed(0),windDirection(0){}; //! the idea of fog is to reduce the visibility, but this is currently not used int fog; int windSpeed; int windDirection; } weather; /** how are Resources handled on this map 0= "ASC mode": complex system with mineral resources etc 1= "BI mode": simpler system like in Battle Isle **/ int _resourcemode; //! the diplomatic status between the players char alliances[8][8]; //! the different players in ASC. There may be 8 players (0..7) and neutral units (8) class Player { public: //! does the player exist at all bool exist(); //! did the player exist when the turn started? Required for checking if a player has been terminated bool existanceAtBeginOfTurn; typedef list VehicleList; //! a list of all units VehicleList vehicleList; typedef list BuildingList; //! a list of all units BuildingList buildingList; //! the status of the scientific research Research research; //! if the player is run by an AI, this is the pointer to it BaseAI* ai; //! the status of the player: 0=human ; 1=AI ; 2=off enum tplayerstat { human, computer, off } stat; //! the name of the player that is used if the player is human ASCString humanname; //! the name of the player that is used if the player is the AI ASCString computername; //! returns the name of the player depending on the status const ASCString& getName( ); //! the Password required for playing this player Password passwordcrc; class Dissection { public: pvehicletype fzt; const Technology* tech; int orgpoints; int points; int num; }; //! the list of dissected units typedef list DissectionContainer; DissectionContainer dissections; bool __dissectionsToLoad; //! the list of messages that haven't been read by the player yet MessagePntrContainer unreadmessage; bool __loadunreadmessage; //! the list of messages that already have been read by the player yet MessagePntrContainer oldmessage; bool __loadoldmessage; //! the list of messages that have been sent yet MessagePntrContainer sentmessage; bool __loadsentmessage; //! if ASC should check all events for fullfilled triggers, this variable will be set to true. This does not mean that there really ARE events that are ready to be executed int queuedEvents; //! the version of ASC that this player has used to make his last turn int ASCversion; struct PlayTime { int turn; time_t date; }; typedef list PlayTimeContainer; //! The time this player ended his turns. This is very informative in email games with > 2 players to find out who is delaying the game. PlayTimeContainer playTime; } player[9]; typedef map VehicleLookupCache; VehicleLookupCache vehicleLookupCache; int eventID; typedef PointerList Events; Events events; vector eventTimes; /* //! a container for events that were executed during previous maps of the campaign peventstore oldevents; //! the list of events that haven't been triggered yet. pevent firsteventtocome; //! the list of events that already have been triggered. pevent firsteventpassed; */ // required for loading the old map file format; no usage outside the loading routine // bool loadeventstore,loadeventstocome,loadeventpassed; int eventpassed ( int saveas, int action, int mapid ); int eventpassed ( int id, int mapid ); int unitnetworkid; char levelfinished; pnetwork network; // int alliance_names_not_used_any_more[8]; //! only to be used by units and buildings. To speed up map destruction, the view won't be recalculated. No signals will be send when units & buildings are destroyed, either bool __mapDestruction; struct tcursorpos { struct { integer cx; integer sx; integer cy; integer sy; } position[8]; } cursorpos; /** The tribute can not only be used to demand resources from enemies but also to transfer resources to allies. tribute.avail[a][b].energy is the ammount of energy that player b may (still) extract from the net of player a tribute.paid[b][a].energy is the amount of energy that player b has already extracted from player a's net a is source player, b is destination player **/ class ResourceTribute { public: Resources avail[8][8]; Resources paid[8][8]; //! for the messages that are send each turn it is necessary to record how much of the transfer happend during the last turn Resources payStatusLastTurn[8][8]; bool empty ( ); void read ( tnstream& stream ); void write ( tnstream& stream ); } tribute; //! the list of messages that were written this turn and are waiting to be processed at the end of the turn MessagePntrContainer unsentmessage; bool __loadunsentmessage; //! these are the messages themselfs. A #pmessagelist only stores pointers to message body which are archived here MessageContainer messages; bool __loadmessages; //! each message has an identification number (which is incremented with each message) for referencing it in files. The id of the last message is stored here int messageid; //! temporary variables for loading the map bool ___loadJournal, ___loadNewJournal, ___loadtitle; void allocateFields ( int x, int y ); ASCString gameJournal; ASCString newJournal; Password supervisorpasswordcrc; char alliances_at_beginofturn[8]; class Shareview { public: Shareview ( void ); Shareview ( const Shareview* org ); bool mode[8][8]; int recalculateview; void read ( tnstream& stream ); void write( tnstream& stream ); }; // mode[1][6] = visible_all => Spieler 1 gibt Spieler 6 die view frei Shareview* shareview; //! if a player has won a singleplayer map, but wants to continue playing without any enemies, this will be set to 1 int continueplaying; class ReplayInfo { public: ReplayInfo ( void ); pmemorystreambuf guidata[8]; pmemorystreambuf map[8]; pmemorystream actmemstream; //! if stopRecordingActions > 0 then no actions will be recorded. \see LockReplayRecording int stopRecordingActions; void read ( tnstream& stream ); void write ( tnstream& stream ); ~ReplayInfo ( ); }; ReplayInfo* replayinfo; //! a helper variable to store some information during the loading process. No usage outside. bool __loadreplayinfo; //! the player which is currently viewing the map. During replays, for example, this will be different from the player that moves units int playerView; GameTime lastjournalchange; //! in BI resource mode ( see #_resourcemode , #isResourceGlobal ) , this is where the globally available resources are stored. Note that not all resources are globally available. Resources bi_resource[8]; struct PreferredFilenames { ASCString mapname[8]; ASCString savegame[8]; } preferredFileNames; //! for tutorial missions it is possible to highlight elements of the interface with an ellipse using the event system. EllipseOnScreen* ellipse; //! the ID of the graphic set int graphicset; int gameparameter_num; int* game_parameter; int mineralResourcesDisplayed; class ArchivalInformation { public: ArchivalInformation() : modifytime ( 0 ) {}; ASCString author; ASCString description; ASCString tags; ASCString requirements; time_t modifytime; } archivalInformation; //! specifies which vehicle types can be constructed by construction units class UnitProduction { public: typedef vector IDsAllowed; bool check ( int id ); IDsAllowed idsAllowed; } unitProduction; tmap ( void ); pvehicle getUnit ( int x, int y, int nwid ); pvehicle getUnit ( int nwid ); ContainerBase* getContainer ( int nwid ); int getgameparameter ( GameParameter num ); void setgameparameter ( GameParameter num, int value ); void cleartemps( int b = -1, int value = 0 ); bool isResourceGlobal ( int resource ); void setupResources ( void ); const ASCString& getPlayerName ( int playernum ); pfield getField ( int x, int y ); pfield getField ( const MapCoordinate& pos ); void startGame ( ); //! called after a player ends his turn void endTurn(); //! called between endTurn() of player 7 and the next turn of player 0 void endRound(); //! changes to the next player and calls endRound() if necessary. \Returns false if there are no players left bool nextPlayer(); VisibilityStates getInitialMapVisibility( int player ); //! resizes the map. Positive numbers enlarge the map in that direction int resize( int top, int bottom, int left, int right ); bool compareResources( tmap* replaymap, int player, ASCString* log = NULL ); void calculateAllObjects ( void ); void read ( tnstream& stream ); void write ( tnstream& stream ); pterraintype getterraintype_byid ( int id ); pobjecttype getobjecttype_byid ( int id ); pvehicletype getvehicletype_byid ( int id ); pbuildingtype getbuildingtype_byid ( int id ); const Technology* gettechnology_byid ( int id ); pterraintype getterraintype_bypos ( int pos ); pobjecttype getobjecttype_bypos ( int pos ); pvehicletype getvehicletype_bypos ( int pos ); pbuildingtype getbuildingtype_bypos ( int pos ); const Technology* gettechnology_bypos ( int pos ); int getTerrainTypeNum ( ); int getObjectTypeNum ( ); int getVehicleTypeNum ( ); int getBuildingTypeNum ( ); int getTechnologyNum ( ); ~tmap(); //! just a helper variable for loading the map; no function outside; bool loadOldEvents; //! generated a pseudo-random number with the map-internal seed int random( int max ); private: pvehicle getUnit ( pvehicle eht, int nwid ); void objectGrowth(); unsigned int randomSeed; }; typedef tmap::Player Player; #endif