/* Copyright (C) 2001-2004 Stephane Magnenat & Luc-Olivier de Charrière for any question or comment contact us at nct@ysagoon.com or nuage@ysagoon.com 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __MAP_H #define __MAP_H #include #include #include "Building.h" #include "Ressource.h" #include "Sector.h" #include "Team.h" #include "TerrainType.h" #include "BitArray.h" class Unit; //! No global unit identifier. This value means there is no unit. Used at Case::groundUnit or Case::airUnit. #define NOGUID 0xFFFF //! No global building identifier. This value means there is no building. Used at Case::building. #define NOGBID 0xFFFF class Map; class Game; class MapGenerationDescriptor; class SessionGame; // a 1x1 piece of map struct Case { Uint16 terrain; Uint16 building; Ressource ressource; Uint16 groundUnit; Uint16 airUnit; Uint32 forbidden; // This is a mask, one bit by team, 1=forbidden, 0=allowed Uint32 guardArea; // This is a mask, one bit by team, 1=guard area, 0=normal Uint32 clearArea; // This is a mask, one bit by team, 1=clear area, 0=normal }; /*! Map, handle all physical localisations All size are given in 32x32 pixel cell, which is the basic game measurement unit. All functions are wrap-safe, excepted the one specified otherwise. */ class Map { public: //! Type of terrain (used for undermap) public: //! Map constructor Map(); //! Map destructor virtual ~Map(void); //! Reset map and free arrays void clear(); //! Reset map size to width = 2^wDec and height=2^hDec, and fill background with terrainType void setSize(int wDec, int hDec, TerrainType terrainType=WATER); // !This call is needed to use the Map! void setGame(Game *game); //! Load a map from a stream and relink with associated game bool load(GAGCore::InputStream *stream, SessionGame *sessionGame, Game *game=NULL); //! Save a map void save(GAGCore::OutputStream *stream); // add & remove teams, used by the map editor and the random map generator // Have to be called *after* session.numberOfTeam has been changed. void addTeam(void); void removeTeam(void); //! Grow ressources on map void growRessources(void); //! Do a step associated woth map (grow ressources and process bullets) void syncStep(Uint32 stepCounter); //! Switch the Fog of War bufferRessourceType void switchFogOfWar(void); //! Return map width int getW(void) const { return w; } //! Return map height int getH(void) const { return h; } //! Return map width mask int getMaskW(void) const { return wMask; } //! Return map height maskint int getMaskH(void) const { return hMask; } //! Return map width shift int getShiftW(void) const { return wDec; } //! Return map height shift int getShiftH(void) const { return hDec; } //! Return the number of sectors on x, which corresponds to the sector map width int getSectorW(void) const { return wSector; } //! Return the number of sectors on y, which corresponds to the sector map height int getSectorH(void) const { return hSector; } //! Set map to discovered state at position (x, y) for all teams in sharedVision (mask). void setMapDiscovered(int x, int y, Uint32 sharedVision) { size_t index = ((y&hMask)<building; if (bgid != NOGBID) { int id = Building::GIDtoID(bgid); int team = Building::GIDtoTeam(bgid); assert(id>=0); assert(id<1024); assert(team>=0); assert(team<32); teams[team]->myBuildings[id]->seenByMask|=sharedVision; } } //! Make the building at rect (x, y, w, h) visible for all teams in sharedVision (mask). void setMapBuildingsDiscovered(int x, int y, int w, int h, Uint32 sharedVision, Team *teams[32]) { for (int dx=x; dx=128) && (t<128+16)) return SAND; else if ((t>=256) && (t<256+16)) return WATER; else return -1; } Ressource getRessource(int x, int y) { return cases[((y&hMask)<ressource; } Uint32 getForbidden(int x, int y) { return cases[((y&hMask)<=0) && (t<16)); } bool isWater(unsigned pos) { int t = getTerrain(pos)-256; return ((t>=0) && (t<16)); } bool isGrass(int x, int y) { return (getTerrain(x, y)<16); } bool isSand(int x, int y) { int t=getTerrain(x, y); return ((t>=128)&&(t<128+16)); } bool isRessource(int x, int y) { return cases[((y&hMask)<0); } bool isRessource(int x, int y, bool ressourceTypes[BASIC_COUNT]) { const Ressource &ressource = cases[((y&hMask)< 0 && ressource.type < BASIC_COUNT && ressourceTypes[ressource.type]); } bool isRessource(int x, int y, int *ressourceType) { int rt = getRessource(x, y).type; if (rt == 0xFF) return false; *ressourceType = rt; return true; } //! Decrement ressource at position (x,y). Return true on success, false otherwise. void decRessource(int x, int y); //! Decrement ressource at position (x,y) if ressource type = ressourceType. Return true on success, false otherwise. void decRessource(int x, int y, int ressourceType); bool incRessource(int x, int y, int ressourceType, int variety); //! Return true if unit can go to position (x,y) bool isFreeForGroundUnit(int x, int y, bool canSwim, Uint32 teamMask); bool isFreeForGroundUnitNoForbidden(int x, int y, bool canSwim); bool isFreeForAirUnit(int x, int y) { return (getAirUnit(x+w, y+h)==NOGUID); } bool isFreeForBuilding(int x, int y); bool isFreeForBuilding(int x, int y, int w, int h); bool isFreeForBuilding(int x, int y, int w, int h, Uint16 gid); // The "hardSpace" keywork means "Free" but you don't count Ground-Units as obstacles. bool isHardSpaceForGroundUnit(int x, int y, bool canSwim, Uint32 me); bool isHardSpaceForBuilding(int x, int y); bool isHardSpaceForBuilding(int x, int y, int w, int h); bool isHardSpaceForBuilding(int x, int y, int w, int h, Uint16 gid); //! Return true if unit has contact with building gbid. If true, put contact direction in dx, dy bool doesUnitTouchBuilding(Unit *unit, Uint16 gbid, int *dx, int *dy); //! Return true if (x,y) has contact with building gbid. bool doesPosTouchBuilding(int x, int y, Uint16 gbid); //! Return true if (x,y) has contact with building gbid. If true, put contact direction in dx, dy bool doesPosTouchBuilding(int x, int y, Uint16 gbid, int *dx, int *dy); //! Return true if unit has contact with ressource of any ressourceType. If true, put contact direction in dx, dy bool doesUnitTouchRessource(Unit *unit, int *dx, int *dy); //! Return true if unit has contact with ressource of type ressourceType. If true, put contact direction in dx, dy bool doesUnitTouchRessource(Unit *unit, int ressourceType, int *dx, int *dy); //! Return true if (x,y) has contact with ressource of type ressourceType. If true, put contact direction in dx, dy bool doesPosTouchRessource(int x, int y, int ressourceType, int *dx, int *dy); //! Return true if unit has contact with enemy. If true, put contact direction in dx, dy bool doesUnitTouchEnemy(Unit *unit, int *dx, int *dy); //! Return GID Uint16 getGroundUnit(int x, int y) { return cases[((y&hMask)<>4)+((x&wMask)>>4)]); } //! Return a sector in the sector array. It is not clean because too high level Sector *getSector(int i) { assert(i>=0); assert(i