| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 | /* * RmgMap.cpp, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */#include "StdInc.h"#include "RmgMap.h"#include "TileInfo.h"#include "CMapGenOptions.h"#include "Zone.h"#include "../mapping/CMapEditManager.h"#include "../mapping/CMap.h"#include "../CTownHandler.h"#include "modificators/ObjectManager.h"#include "modificators/RoadPlacer.h"#include "modificators/TreasurePlacer.h"#include "modificators/PrisonHeroPlacer.h"#include "modificators/QuestArtifactPlacer.h"#include "modificators/ConnectionsPlacer.h"#include "modificators/TownPlacer.h"#include "modificators/MinePlacer.h"#include "modificators/ObjectDistributor.h"#include "modificators/WaterAdopter.h"#include "modificators/WaterProxy.h"#include "modificators/WaterRoutes.h"#include "modificators/RockPlacer.h"#include "modificators/RockFiller.h"#include "modificators/ObstaclePlacer.h"#include "modificators/RiverPlacer.h"#include "modificators/TerrainPainter.h"#include "Functions.h"#include "CMapGenerator.h"VCMI_LIB_NAMESPACE_BEGINRmgMap::RmgMap(const CMapGenOptions& mapGenOptions, IGameCallback * cb) :	mapGenOptions(mapGenOptions), zonesTotal(0){	mapInstance = std::make_unique<CMap>(cb);	mapProxy = std::make_shared<MapProxy>(*this);	getEditManager()->getUndoManager().setUndoRedoLimit(0);}int RmgMap::getDecorationsPercentage() const{	return 15; // arbitrary value to generate more readable map}void RmgMap::foreach_neighbour(const int3 & pos, const std::function<void(int3 & pos)> & foo) const{	for(const int3 &dir : int3::getDirs())	{		int3 n = pos + dir;		/*important notice: perform any translation before this function is called,		 so the actual mapInstance->position is checked*/		if(mapInstance->isInTheMap(n))			foo(n);	}}void RmgMap::foreachDirectNeighbour(const int3 & pos, const std::function<void(int3 & pos)> & foo) const{	for(const int3 &dir : rmg::dirs4)	{		int3 n = pos + dir;		if(mapInstance->isInTheMap(n))			foo(n);	}}void RmgMap::foreachDiagonalNeighbour(const int3 & pos, const std::function<void(int3 & pos)> & foo) const{	for (const int3 &dir : rmg::dirsDiagonal)	{		int3 n = pos + dir;		if (mapInstance->isInTheMap(n))			foo(n);	}}void RmgMap::initTiles(CMapGenerator & generator, CRandomGenerator & rand){	mapInstance->initTerrain();		tiles.resize(boost::extents[mapInstance->width][mapInstance->height][mapInstance->levels()]);	zoneColouring.resize(boost::extents[mapInstance->width][mapInstance->height][mapInstance->levels()]);		//init native town count with 0	for (auto faction : VLC->townh->getAllowedFactions())		zonesPerFaction[faction] = 0;		getEditManager()->clearTerrain(&rand);	getEditManager()->getTerrainSelection().selectRange(MapRect(int3(0, 0, 0), mapGenOptions.getWidth(), mapGenOptions.getHeight()));	getEditManager()->drawTerrain(ETerrainId::GRASS, getDecorationsPercentage(), &rand);	const auto * tmpl = mapGenOptions.getMapTemplate();	zones.clear();	for(const auto & option : tmpl->getZones())	{		auto zone = std::make_shared<Zone>(*this, generator, rand);		zone->setOptions(*option.second);		zones[zone->getId()] = zone;	}		switch(mapGenOptions.getWaterContent())	{		case EWaterContent::NORMAL:		case EWaterContent::ISLANDS:			TRmgTemplateZoneId waterId = zones.size() + 1;			rmg::ZoneOptions options;			options.setId(waterId);			options.setType(ETemplateZoneType::WATER);			auto zone = std::make_shared<Zone>(*this, generator, rand);			zone->setOptions(options);			//std::set<FactionID> allowedMonsterFactions({FactionID::CASTLE, FactionID::INFERNO}); // example of filling allowed monster factions			//zone->setMonsterTypes(allowedMonsterFactions); // can be set here, probably from template json, along with the treasure ranges and densities			zone->monsterStrength = EMonsterStrength::ZONE_NONE; // can be set to other value, probably from a new field in the template json			zones[zone->getId()] = zone;			break;	}}void RmgMap::addModificators(){	bool hasObjectDistributor = false;	bool hasHeroPlacer = false;	bool hasRockFiller = false;	for(auto & z : getZones())	{		auto zone = z.second;				zone->addModificator<ObjectManager>();		if (!hasObjectDistributor)		{			zone->addModificator<ObjectDistributor>();			hasObjectDistributor = true;		}		if (!hasHeroPlacer)		{			zone->addModificator<PrisonHeroPlacer>();			hasHeroPlacer = true;		}		zone->addModificator<TreasurePlacer>();		zone->addModificator<ObstaclePlacer>();		zone->addModificator<TerrainPainter>();				if(zone->getType() == ETemplateZoneType::WATER)		{			for(auto & z1 : getZones())			{				z1.second->addModificator<WaterAdopter>();				z1.second->getModificator<WaterAdopter>()->setWaterZone(zone->getId());			}			zone->addModificator<WaterProxy>();			zone->addModificator<WaterRoutes>();		}		else		{			zone->addModificator<TownPlacer>();			zone->addModificator<MinePlacer>();			zone->addModificator<QuestArtifactPlacer>();			zone->addModificator<ConnectionsPlacer>();			zone->addModificator<RoadPlacer>();			zone->addModificator<RiverPlacer>();		}				if(zone->isUnderground())		{			zone->addModificator<RockPlacer>();			if (!hasRockFiller)			{				zone->addModificator<RockFiller>();				hasRockFiller = true;			}		}			}}int RmgMap::levels() const{	return mapInstance->levels();}int RmgMap::width() const{	return mapInstance->width;}int RmgMap::height() const{	return mapInstance->height;}PlayerInfo & RmgMap::getPlayer(int playerId){	return mapInstance->players.at(playerId);}std::shared_ptr<MapProxy> RmgMap::getMapProxy() const{	return mapProxy;}CMap& RmgMap::getMap(const CMapGenerator*) const{	return *mapInstance;}CMapEditManager* RmgMap::getEditManager() const{	return mapInstance->getEditManager();}bool RmgMap::isOnMap(const int3 & tile) const{	return mapInstance->isInTheMap(tile);}const CMapGenOptions& RmgMap::getMapGenOptions() const{	return mapGenOptions;}void RmgMap::assertOnMap(const int3& tile) const{	if (!mapInstance->isInTheMap(tile))		throw rmgException(boost::str(boost::format("Tile %s is outside the map") % tile.toString()));}RmgMap::Zones & RmgMap::getZones(){	return zones;}RmgMap::Zones RmgMap::getZonesOnLevel(int level) const{	Zones zonesOnLevel;	for(const auto& zonePair : zones)	{		if(zonePair.second->isUnderground() == level)		{			zonesOnLevel.insert(zonePair);		}	}	return zonesOnLevel;}bool RmgMap::isBlocked(const int3 &tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].isBlocked();}bool RmgMap::shouldBeBlocked(const int3 &tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].shouldBeBlocked();}bool RmgMap::isPossible(const int3 &tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].isPossible();}bool RmgMap::isFree(const int3 &tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].isFree();}bool RmgMap::isUsed(const int3 &tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].isUsed();}bool RmgMap::isRoad(const int3& tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].isRoad();}void RmgMap::setOccupied(const int3 &tile, ETileType state){	assertOnMap(tile);		tiles[tile.x][tile.y][tile.z].setOccupied(state);}void RmgMap::setRoad(const int3& tile, RoadId roadType){	assertOnMap(tile);		tiles[tile.x][tile.y][tile.z].setRoadType(roadType);}TileInfo RmgMap::getTileInfo(const int3& tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z];}TerrainTile & RmgMap::getTile(const int3& tile) const{	return mapInstance->getTile(tile);}TRmgTemplateZoneId RmgMap::getZoneID(const int3& tile) const{	assertOnMap(tile);		return zoneColouring[tile.x][tile.y][tile.z];}void RmgMap::setZoneID(const int3& tile, TRmgTemplateZoneId zid){	assertOnMap(tile);		zoneColouring[tile.x][tile.y][tile.z] = zid;}void RmgMap::setNearestObjectDistance(const int3 &tile, float value){	assertOnMap(tile);		tiles[tile.x][tile.y][tile.z].setNearestObjectDistance(value);}float RmgMap::getNearestObjectDistance(const int3 &tile) const{	assertOnMap(tile);		return tiles[tile.x][tile.y][tile.z].getNearestObjectDistance();}void RmgMap::registerZone(FactionID faction){	//FIXME: Protect with lock guard?	zonesPerFaction[faction]++;	zonesTotal++;}ui32 RmgMap::getZoneCount(FactionID faction){	return zonesPerFaction[faction];}ui32 RmgMap::getTotalZoneCount() const{	return zonesTotal;}bool RmgMap::isAllowedSpell(const SpellID & sid) const{	assert(sid.getNum() >= 0);	if (sid.getNum() < mapInstance->allowedSpells.size())	{		return mapInstance->allowedSpells.count(sid);	}	else		return false;}void RmgMap::dump(bool zoneId) const{	static int id = 0;	std::ofstream out(boost::str(boost::format("zone_%d.txt") % id++));	int levels = mapInstance->levels();	int width =  mapInstance->width;	int height = mapInstance->height;	for (int k = 0; k < levels; k++)	{		for(int j = 0; j < height; j++)		{			for (int i = 0; i < width; i++)			{				if(zoneId)				{					out << getZoneID(int3(i, j, k));				}				else				{					char t = '?';					switch (getTileInfo(int3(i, j, k)).getTileType())					{						case ETileType::FREE:							t = ' '; break;						case ETileType::BLOCKED:							t = '#'; break;						case ETileType::POSSIBLE:							t = '-'; break;						case ETileType::USED:							t = 'O'; break;					}					out << t;				}			}			out << std::endl;		}		out << std::endl;	}	out << std::endl;}VCMI_LIB_NAMESPACE_END
 |