Ejemplo n.º 1
0
void _set_temperature (const Planet& planet, const Climate_parameters&, Climate_generation_season& season) {
	auto temperature_at_latitude = [](float latitude) {
		return freezing_point() - 25 + 50*cos(latitude);
	};
	
	for (auto& t : tiles(planet)) {
		float temperature = temperature_at_latitude(season.tropical_equator - latitude(planet, vector(t)));
		if (is_land(nth_tile(terrain(planet), id(t)))) {
			if (elevation(nth_tile(terrain(planet), id(t))) > sea_level(planet))
				temperature -= temperature_lapse(elevation(nth_tile(terrain(planet), id(t))) - sea_level(planet));
		}
		else {
			temperature = 0.3*temperature + 0.7*temperature_at_latitude(latitude(planet, vector(t)));
		}
		season.tiles[id(t)].temperature = temperature;
	}
}
Ejemplo n.º 2
0
void testAreaShader()
{
    Mercator::Area* a1 = new Mercator::Area(1, false);
    
    WFMath::Polygon<2> p;
    p.addCorner(p.numCorners(), Point2(3, 4));
    p.addCorner(p.numCorners(), Point2(10, 10));
    p.addCorner(p.numCorners(), Point2(14, 6));
    p.addCorner(p.numCorners(), Point2(18, 4));
    p.addCorner(p.numCorners(), Point2(17, 19));
    p.addCorner(p.numCorners(), Point2(6, 20));
    p.addCorner(p.numCorners(), Point2(-1, 18));
    p.addCorner(p.numCorners(), Point2(-8, 11));
    
    a1->setShape(p);
    
    Mercator::Area* a2 = new Mercator::Area(1, false);
    
    WFMath::Polygon<2> p2;
    p2.addCorner(p2.numCorners(), Point2(25, 18));
    p2.addCorner(p2.numCorners(), Point2(72, 22));
    p2.addCorner(p2.numCorners(), Point2(60, 30));
    p2.addCorner(p2.numCorners(), Point2(27, 28));
    p2.addCorner(p2.numCorners(), Point2(25, 45));
    p2.addCorner(p2.numCorners(), Point2(3, 41));
    p2.addCorner(p2.numCorners(), Point2(-2, 20));
    a2->setShape(p2);
    
    Mercator::Terrain terrain(Mercator::Terrain::SHADED, 16);
    
    Mercator::Shader * base_shader =
          new Mercator::FillShader(Mercator::Shader::Parameters());
    terrain.addShader(base_shader, 0);

    Mercator::AreaShader* ashade = new Mercator::AreaShader(1);
    terrain.addShader(ashade, 1);
    
    terrain.setBasePoint(0, 0, -1);
    terrain.setBasePoint(0, 1, 8);
    terrain.setBasePoint(1, 0, 2);
    terrain.setBasePoint(1, 1, 11);
    terrain.setBasePoint(2, 0, 2);
    terrain.setBasePoint(2, 1, 11);
    
    terrain.addArea(a1);
   // terrain.addArea(a2);
    
    Mercator::Segment* seg = terrain.getSegment(0,0);
    assert(a1->checkIntersects(*seg));
    
    seg->populateSurfaces();
    writePGMForSurface("test1.pgm", seg->getSize(), seg->getSurfaces()[1]);
    
    
    seg = terrain.getSegment(1,0);    
    seg->populateSurfaces();
    writePGMForSurface("test2.pgm", seg->getSize(), seg->getSurfaces()[1]);
}
Ejemplo n.º 3
0
void _set_humidity (const Planet& planet, const Climate_parameters& par, Climate_generation_season& season) {
	for (auto& t : tiles(planet)) {
		float humidity = 0.0;		
		if (is_water(nth_tile(terrain(planet), id(t)))) {
			humidity = saturation_humidity(season.tiles[id(t)].temperature);
		}
		season.tiles[id(t)].humidity = humidity;
	}
	_iterate_humidity(planet, par, season);
}
Ejemplo n.º 4
0
void _iterate_humidity (const Planet& planet, const Climate_parameters& par, Climate_generation_season& season) {
	std::deque<float> humidity;
	std::deque<float> precipitation;
	humidity.resize(tile_count(planet));
	precipitation.resize(tile_count(planet));
	
	float delta = 1.0;
	while (delta > par.error_tolerance) {
//		std::cout << "delta: " << delta << "\n";
		for (int i=0; i<tile_count(planet); i++) {
			precipitation[i] = 0.0;
			if (is_land(nth_tile(terrain(planet), i))) {
				humidity[i] = 0.0;
				precipitation[i] = 0.0;
				float incoming_wind = _incoming_wind(planet, season, i);
				float outgoing_wind = _outgoing_wind(planet, season, i);
				if (incoming_wind > 0.0) {
					float convection = outgoing_wind - incoming_wind;
					float incoming_humidity = _incoming_humidity(planet, season, i);
					// less humidity when incoming wind is less than outgoing
					float density = convection > 0 ?
						incoming_humidity / (incoming_wind + convection) :
						incoming_humidity / incoming_wind;
					float saturation = saturation_humidity(season.tiles[i].temperature);
					// limit to saturation humidity
					humidity[i] = std::min(saturation, density);
					if (saturation < density)
						precipitation[i] += (density - saturation) * incoming_wind;
					// increase humidity when outgoing wind is less than incoming
					if (convection < 0) {
						float convective = humidity[i] * (-convection / incoming_wind);
						if (humidity[i] + convective > saturation)
							precipitation[i] += (humidity[i] + convective - saturation) * (-convection);
						humidity[i] = std::min(saturation, humidity[i] + convective);
					}
				}
				// scale by constant and area
				precipitation[i] *= 3.0 / area(planet, nth_tile(planet, i));
			}
			else
				humidity[i] = season.tiles[i].humidity;
		}
		float largest_change = 0.0;
		for (int i=0; i<tile_count(planet); i++) {
			largest_change = std::max(largest_change, _humidity_change(season.tiles[i].humidity, humidity[i]));
		}
		delta = largest_change;
		for (int i=0; i<tile_count(planet); i++) {
			season.tiles[i].humidity = humidity[i];
			season.tiles[i].precipitation = precipitation[i];
		}
	}
}
Ejemplo n.º 5
0
void terrain(int *h, int x1, int y1, int x2, int y2)
{
	int midx, midy, x, y;
	double nh, r, factor, oldheight;

	if (y2 < y1)
		swap(&y1, &y2);
	if (x2 < x1)
		swap(&x1, &x2);

	if (x2 - x1 < 2)
		return;
	if (y2 - y1 < 2)
		return;

	midx = x1 + (x2 - x1) / 2; 
	midy = y1 + (y2 - y1) / 2; 

	factor = (x2 - x1) / 2.0;

	oldheight = (double) h[idx(x1, y1)];
	oldheight += (double) h[idx(x1, y2)];
	oldheight += (double) h[idx(x2, y1)];
	oldheight += (double) h[idx(x2, y2)];
	oldheight /= 4.0;


	r = 0.0 + rand() / (0.0 + RAND_MAX) - 0.5;
	nh = (oldheight + factor * r);
	for (x = x1; x < x2; x++) {
		for (y = y1; y < y2; y++) {
			h[idx(x, y)] = nh;
		}
	}
	terrain(h, x1, y1, midx, midy);
	terrain(h, midx, y1, x2, midy);
	terrain(h, x1, midy, midx, y2);
	terrain(h, midx, midy, x2, y2);
}
Ejemplo n.º 6
0
void create_terrain_maps(const config::const_child_itors &cfgs,
                         t_translation::ter_list& terrain_list,
                         std::map<t_translation::terrain_code, terrain_type>& letter_to_terrain)
{
	for (const config &terrain_data : cfgs)
	{
		terrain_type terrain(terrain_data);
		DBG_G << "create_terrain_maps: " << terrain.number() << " "
			<< terrain.id() << " " << terrain.name() << " : " << terrain.editor_group() << "\n";

		std::pair<std::map<t_translation::terrain_code, terrain_type>::iterator, bool> res;
		res = letter_to_terrain.insert(std::make_pair(terrain.number(), terrain));
		if (!res.second) {
			terrain_type& curr = res.first->second;
			if(terrain == curr) {
				LOG_G << "Merging terrain " << terrain.number()
					<< ": " << terrain.id() << " (" << terrain.name() << ")\n";
				std::vector<std::string> eg1 = utils::split(curr.editor_group());
				std::vector<std::string> eg2 = utils::split(terrain.editor_group());
				std::set<std::string> egs;
				bool clean_merge = true;
				for (std::string& t : eg1) {
					clean_merge &= egs.insert(t).second;
				}
				for (std::string& t : eg2) {
					clean_merge &= egs.insert(t).second;
				}

				std::string joined = utils::join(egs);
				curr.set_editor_group(joined);
				if(clean_merge) {
					LOG_G << "Editor groups merged to: " << joined << "\n";
				} else {
					LOG_G << "Merged terrain " << terrain.number()
					<< ": " << terrain.id() << " (" << terrain.name() << ") "
					<< "with duplicate editor groups [" << terrain.editor_group() << "] "
					<< "and [" << curr.editor_group() << "]\n";
				}
			} else {
				ERR_G << "Duplicate terrain code definition found for " << terrain.number() << "\n"
					<< "Failed to add terrain " << terrain.id() << " (" << terrain.name() << ") "
					<< "[" << terrain.editor_group() << "]" << "\n"
					<< "which conflicts with  " << curr.id() << " (" << curr.name() << ") "
					<< "[" << curr.editor_group() << "]" << "\n\n";
			}
		} else {
			terrain_list.push_back(terrain.number());
		}
	}
}
Ejemplo n.º 7
0
int main(int argc, char** argv) {
	char temp[1024]="";
	char ini_file[]="lightfield.ini";

	ini_gets("Main", "TerrainFile", "", temp, 512, ini_file);
	string terrain_file=ToString(temp);
	ini_gets("Main", "Resources", "", temp, 512, ini_file);
	string resources=ToString(temp);
	ini_gets("Main", "Stage", "", temp, 512, ini_file);
	string stage=ToString(temp);
	ini_gets("Main", "GIA", "", temp, 512, ini_file);
	string gia=ToString(temp);

	float sample_unit_distance=ini_getf("Main", "SampleUnitDistance", 0.75f, ini_file);
	float saturation_multiplier=ini_getf("Main", "SaturationMultiplier", 1.0f, ini_file);
	float lookup_grid_size=ini_getf("Main", "LookupGridSize", 5.0f, ini_file);

	LibGens::initialize();
	LibGens::Error::setLogging(true);

	LibGens::Terrain terrain(terrain_file, resources, stage, gia);
	printf("Done loading Terrain\n");

	// Sample Unit Distance, Saturation Multiplier
	LibGens::VRMap *vrmap=terrain.generateVRMap(sample_unit_distance, saturation_multiplier);
	printf("VR Map setup...\n");

	vrmap->generateLookupGrid(lookup_grid_size, sample_unit_distance);
	printf("Done generating VR Map of %d samples covering %f units of area.\n", vrmap->getSampleList().size(), vrmap->getAABB().size());

	LibGens::LightField lightfield;

	float ambient_color_r=ini_getf("Main", "AmbientColorR", 1.0f, ini_file);
	float ambient_color_g=ini_getf("Main", "AmbientColorG", 1.0f, ini_file);
	float ambient_color_b=ini_getf("Main", "AmbientColorB", 1.0f, ini_file);
	float ambient_color_a=ini_getf("Main", "AmbientColorA", 1.0f, ini_file);
	int sample_min_count=ini_getl("Main", "SampleMinCount", 2, ini_file);
	float sample_blend_distance=ini_getf("Main", "SampleBlendDistance", 8.0f, ini_file);
	float min_octree_cube_size=ini_getf("Main", "MinOctreeCubeSize", 3.0f, ini_file);
	int cpu_threads=ini_getl("Main", "Threads", 1, ini_file);

	// Ambient Color, Sample Min Count, Sample Blend Distance, Min Octree Cube Size
	lightfield.generate(vrmap, LibGens::Color(ambient_color_r, ambient_color_g, ambient_color_b, ambient_color_a), sample_min_count, sample_blend_distance, min_octree_cube_size, cpu_threads);
	printf("Done generating lightfield.\n");
	lightfield.save("light-field.lft");
	printf("Saved lightfield. Press Enter to exit.\n");
    getchar();
    return 0;
}
Ejemplo n.º 8
0
int main(int argc, char *argv[])
{
	int x, y;

	opencscad_init();
	memset(height, 0, sizeof(height));
	terrain(height, 0, 0, dim - 1, dim - 1);

	for (y = 0; y < dim; y++) {
		for (x = 0; x < dim; x++) {
			xlate(x, y, 0);
				cube(1.05, 1.05, (double) height[idx(x, y)], 0);
			endxlate();
		}
	}
	finalize();
}
Ejemplo n.º 9
0
		void getModifiedAttackAndDefenseTest()
		{
			// Test values > 0
			qrw::Square square(0, 0);
			qrw::Terrain terrain(qrw::ET_HILL, 1, -1);
			square.setTerrain(&terrain);

			unit1->setSquare(&square);

			CPPUNIT_ASSERT_EQUAL(3, unit1->getModifiedAttack());
			CPPUNIT_ASSERT_EQUAL(0, unit1->getModifiedDefense());

			// Test values < 0
			qrw::Terrain terrain2(qrw::ET_WALL, -3, -12);
			square.setTerrain(&terrain2);

			CPPUNIT_ASSERT_EQUAL(0, unit1->getModifiedAttack());
			CPPUNIT_ASSERT_EQUAL(0, unit1->getModifiedDefense());
		}
Ejemplo n.º 10
0
void EnemyAspect::followTerrain(float _dt)
{
	TerrainContainer &terrain(*c.get<TerrainContainer>(Containers::TERRAIN));
	int index = 0;
	float height;
	glm::vec2 tempPos;
	for(uint j = 0; j < ec->pos.size(); j++)
	{
		for(uint k = 0; k < HORDESIZE; k++)
		{
			index = j*HORDESIZE + k;
			tempPos = glm::vec2(ec->pos[j].x + ec->hordeunits[index].pos.x,
								ec->pos[j].z + ec->hordeunits[index].pos.z);

			height = Utility::mapToTerrain(tempPos, terrain).y;
			height = std::max(50.f, height);
			ec->hordeunits[index].pos.y = height + 10 + std::sin(ec->hordeunitwavevar1[index] * 3) * 2;
		}
	}
}
Ejemplo n.º 11
0
void colour_topography (Planet_colours& c, const Planet& p) {
	static const Colour water_deep = Colour(0.0, 0.0, 0.25);
	static const Colour water = Colour(0.0, 0.12, 0.5);
	static const Colour water_shallow = Colour(0.0, 0.4, 0.6);

	static const Colour land[6] = {
		Colour(0.0, 0.4, 0.0),
		Colour(0.0, 0.7, 0.0),
		Colour(1.0, 1.0, 0.0),
		Colour(1.0, 0.5, 0.0),
		Colour(0.7, 0.0, 0.0),
		Colour(0.1, 0.1, 0.1)};
	double land_limits[7] = {-500, 0, 500, 1000, 1500, 2000, 2500};
	for (const Tile& t : tiles(p)) {
		const Terrain_tile& ter = nth_tile(terrain(p), id(t));
		double elev = elevation(ter) - sea_level(p);
		if (is_water(ter)) {
			if (elev < -1000) {
				c.tiles[id(t)] = water_deep;
			}
			else if (elev < -500) {
				double d = (elev+500)/(-500);
				c.tiles[id(t)] = interpolate(water, water_deep, d);
			}
			else {
				double d = elev/(-500);
				c.tiles[id(t)] = interpolate(water_shallow, water, d);
			}
		}
		else {
			c.tiles[id(t)] = land[5];
			for (int i=0; i<5; i++) {
				if (elev <= land_limits[i+1]) {
					double d = std::max(0.0, std::min(1.0, (elev - land_limits[i]) / (land_limits[i+1] - land_limits[i])));
					c.tiles[id(t)] = interpolate(land[i], land[i+1], d);
					break;
				}
			}
		}
	}
}
Ejemplo n.º 12
0
void testFillShader()
{
  dymaxion::Terrain terrain(dymaxion::Terrain::SHADED, 16);

  dymaxion::Shader::Parameters params;

  dymaxion::FillShader * dshade = new dymaxion::FillShader();
  delete dshade;
  dshade = new dymaxion::FillShader(params);
  terrain.addShader(dshade, 0);

  terrain.setBasePoint(0, 0, -20);
  terrain.setBasePoint(0, 1, 1);
  terrain.setBasePoint(1, 0, 2);
  terrain.setBasePoint(1, 1, 0.5);

  dymaxion::Segment * seg = terrain.getSegment(0, 0);

  seg->populate();
  seg->populateSurfaces();
}
Ejemplo n.º 13
0
bool CTerrainMapaManager::Load( TiXmlElement* pXMLData )
{

  if ( !pXMLData ) return false;

  THROW_GAME_EXCEPTION_IF( !pXMLData->Attribute( "default" ),
                           "Error Mapa: terreno por defecto no definido" );
  std::string sTerrain( pXMLData->Attribute( "default" ) );

  CTerrainType* pTerrain = TerrainManager.GetTerrainType( sTerrain );
  THROW_GAME_EXCEPTION_IF( !( pTerrain ),
                           "Error Mapa: el tipo de terreno " + sTerrain );

  int basex = 0;
  int basey = 0;
  int raiz = 3; //!TODO Realizar bien esto
  basey = 0;
  for ( int y = 0; y < m_pModel->getResolution(); y++ ) {

    basex = 0;
    for ( int x = 0; x < m_pModel->getResolution(); x++ ) {

      CTerrainMapa_ptr terrain( new CTerrainMapa( m_pModel ) );
      terrain->SetTile( pTerrain->GetTile( basex ),
                        gcn::Point( x,
                                    y ) );
      m_TerrainMapa.push_back( terrain );

      basex = ( ( basex + 1 ) % raiz ) + basey * raiz;

    }

    basey = ( basey + 1 ) % raiz;

  }

  return true;

}
Ejemplo n.º 14
0
Qt3DCore::QEntity *QgsDemTerrainTileLoader::createEntity( Qt3DCore::QEntity *parent )
{
  QgsTerrainTileEntity *entity = new QgsTerrainTileEntity;

  // create geometry renderer

  Qt3DRender::QGeometryRenderer *mesh = new Qt3DRender::QGeometryRenderer;
  mesh->setGeometry( new DemTerrainTileGeometry( mResolution, mHeightMap, mesh ) );
  entity->addComponent( mesh ); // takes ownership if the component has no parent

  // create material

  createTextureComponent( entity );

  // create transform

  Qt3DCore::QTransform *transform;
  transform = new Qt3DCore::QTransform();
  entity->addComponent( transform );

  float zMin, zMax;
  _heightMapMinMax( mHeightMap, zMin, zMax );

  const Qgs3DMapSettings &map = terrain()->map3D();
  QgsRectangle extent = map.terrainGenerator()->tilingScheme().tileToExtent( mNode->tileX(), mNode->tileY(), mNode->tileZ() ); //node->extent;
  double x0 = extent.xMinimum() - map.originX();
  double y0 = extent.yMinimum() - map.originY();
  double side = extent.width();
  double half = side / 2;

  transform->setScale3D( QVector3D( side, map.terrainVerticalScale(), side ) );
  transform->setTranslation( QVector3D( x0 + half, 0, - ( y0 + half ) ) );

  mNode->setExactBbox( QgsAABB( x0, zMin * map.terrainVerticalScale(), -y0, x0 + side, zMax * map.terrainVerticalScale(), -( y0 + side ) ) );

  entity->setEnabled( false );
  entity->setParent( parent );
  return entity;
}
Ejemplo n.º 15
0
void colour_humidity (Planet_colours& c, const Planet& p, const Season& s) {
	static const Colour water = Colour(1.0, 1.0, 1.0);
	static const Colour land_dry = Colour(1.0, 1.0, 0.5);
	static const Colour land_mid = Colour(1.0, 1.0, 0.0);
	static const Colour land_humid = Colour(0.0, 0.7, 0.0);
	
	for (const Tile& t : tiles(p)) {
		double h = humidity(nth_tile(s, id(t))) / saturation_humidity(temperature(nth_tile(s, id(t))));
		if (is_water(nth_tile(terrain(p), id(t)))) {
			c.tiles[id(t)] = water;
		}
		else {
			if (h <= 0.5) {
				double d = h / 0.5;
				c.tiles[id(t)] = interpolate(land_dry, land_mid, d);
			}
			else {
				double d = (h-0.5)/0.5;
				c.tiles[id(t)] = interpolate(land_mid, land_humid, d);
			}
		}
	}
}
Ejemplo n.º 16
0
void colour_precipitation (Planet_colours& c, const Planet& p, const Season& s) {
	static const Colour water = Colour(1.0, 1.0, 1.0);
	static const Colour dry = Colour(1.0, 1.0, 0.5);
	static const Colour medium = Colour(0.0, 1.0, 0.0);
	static const Colour wet = Colour(0.0, 0.0, 1.0);

	for (const Tile& t : tiles(p)) {
		double high = 7e-8;
		double low = high/10;
		if (is_water(nth_tile(terrain(p), id(t))))
			c.tiles[id(t)] = water;
		else {
			float prec = precipitation(nth_tile(s, id(t)));
			if (prec < low) {
				double d = prec / low;
				c.tiles[id(t)] = interpolate(dry, medium, d);
			}
			else {
				double d = std::min(1.0, (prec - low) / (high - low));
				c.tiles[id(t)] = interpolate(medium, wet, d);
			}
		}
	}
}
Ejemplo n.º 17
0
int main(int argc,char** args) {

    srand(time(NULL));

    try {

        if (SDL_Init(SDL_INIT_VIDEO)) {
            fprintf(stderr,"Unable to initialize SDL: %s\n",SDL_GetError());
            return EXIT_FAILURE;
        }
        atexit(SDL_Quit);

        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
#if 0
        screen = SDL_SetVideoMode(1440,900,32,SDL_OPENGL|SDL_FULLSCREEN);
#else
        screen = SDL_SetVideoMode(1024,768,32,SDL_OPENGL/*|SDL_FULLSCREEN*/);
#endif
        if(!screen) {
            fprintf(stderr,"Unable to create SDL screen: %s\n",SDL_GetError());
            return EXIT_FAILURE;
        }
        SDL_WM_SetCaption("GlestNG","GlestNG");

        GLenum err = glewInit();
        if(GLEW_OK != err) {
            fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
            return EXIT_FAILURE;
        }
        fprintf(stdout, "Status: Using GLEW %s\n", glewGetString(GLEW_VERSION));

        // we have a GL context so we can go ahead and init all the singletons
        std::auto_ptr<fs_t> fs_settings(fs_t::create("data/"));
        fs_t::settings = fs_settings.get(); // set it globally
        std::auto_ptr<xml_parser_t> xml_settings(new xml_parser_t("UI Settings",fs_settings->get_body("ui_settings.xml")));
        xml_settings->set_as_settings();
        std::auto_ptr<graphics_t::mgr_t> graphics_mgr(graphics_t::create());
        std::auto_ptr<fonts_t> fonts(fonts_t::create());
        std::auto_ptr<fs_t> fs;
        try {
            fs.reset(fs_t::create("data/Glest"));
            if(false) {
                fs_file_t::ptr_t logo_file(fs_settings->get("logo.g3d"));
                istream_t::ptr_t logostream(logo_file->reader());
                logo = std::auto_ptr<model_g3d_t>(new model_g3d_t(*logostream));
            }
            load(*fs);
        } catch(glest_exception_t* e) {
            std::cerr << "cannot load glest data: " << e << std::endl;
            delete e;
        }
        std::auto_ptr<ui_mgr_t> ui_(ui_mgr());
        std::auto_ptr<mod_ui_t> mod_ui(mod_ui_t::create());

        std::auto_ptr<terrain_t> terrain(terrain_t::gen_planet(5,500,3));
        //world()->dump(std::cout);

        v4_t light_amb(0,0,0,1), light_dif(1.,1.,1.,1.), light_spec(1.,1.,1.,1.), light_pos(1.,1.,-1.,0.),
             mat_amb(.7,.7,.7,1.), mat_dif(.8,.8,.8,1.), mat_spec(1.,1.,1.,1.);
        glLightfv(GL_LIGHT0,GL_AMBIENT,light_amb.v);
        glLightfv(GL_LIGHT0,GL_DIFFUSE,light_dif.v);
        glLightfv(GL_LIGHT0,GL_SPECULAR,light_spec.v);
        glLightfv(GL_LIGHT0,GL_POSITION,light_pos.v);
        glLightfv(GL_LIGHT1,GL_AMBIENT,light_amb.v);
        glLightfv(GL_LIGHT1,GL_DIFFUSE,light_dif.v);
        glLightfv(GL_LIGHT1,GL_SPECULAR,light_spec.v);
        glMaterialfv(GL_FRONT,GL_AMBIENT,mat_amb.v);
        glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_dif.v);
        glMaterialfv(GL_FRONT,GL_SPECULAR,mat_spec.v);
        glMaterialf(GL_FRONT,GL_SHININESS,100.0);
        glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        glEnable(GL_LIGHT1);
        glDepthFunc(GL_LEQUAL);
        glEnable(GL_DEPTH_TEST);
        glAlphaFunc(GL_GREATER,0.4);
        glEnable(GL_COLOR_MATERIAL);
        glEnable(GL_RESCALE_NORMAL);
        glEnable(GL_BLEND);
        glEnable(GL_TEXTURE_2D);
        glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
        glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
        glEnable(GL_COLOR_MATERIAL);
        glEnable(GL_NORMALIZE);
        glFrontFace(GL_CW);
        camera();
        bool quit = false;
        SDL_Event event;
        SDL_EnableKeyRepeat(200,20);
        SDL_EnableUNICODE(true);
        const unsigned start = SDL_GetTicks();
        framerate.reset();
        while(!quit) {
            set_now(SDL_GetTicks()-start);
            while(!quit && SDL_PollEvent(&event)) {
                if(ui_mgr()->offer(event))
                    continue;
                switch (event.type) {
                case SDL_MOUSEMOTION:
                    if(selection)
                        std::cout << "drag" << std::endl;
                    /*printf("Mouse moved by %d,%d to (%d,%d)\n",
                    event.motion.xrel, event.motion.yrel,
                    event.motion.x, event.motion.y);*/
                    break;
                case SDL_MOUSEBUTTONDOWN:
                    click(event.button.x,event.button.y);
                    if(selection)
                        std::cout << "selection: "<<selected_point<<std::endl;
                    break;
                case SDL_MOUSEBUTTONUP:
                    if(selection)
                        std::cout << "selection stopped" << std::endl;
                    selection = false;
                    break;
                case SDL_KEYDOWN:
                    switch(event.key.keysym.sym) {
                    case SDLK_PLUS:
                        zoom += 1;
                        camera();
                        break;
                    case SDLK_MINUS:
                        zoom -= 1;
                        camera();
                        break;
                    case SDLK_ESCAPE:
                        quit = true;
                        break;
                    case SDLK_m: // MODDING MODE
                        if(!fs.get()) {
                            std::cerr << "(modding menu triggered but mod not loaded)" << std::endl;
                            break;
                        }
                        if(mod_ui->is_shown())
                            mod_ui->hide();
                        else
                            mod_ui->show(ref_t(*techtree,TECHTREE,techtree->name));
                        break;
                    default:
                        std::cout << "Ignoring key " <<
                                  (int)event.key.keysym.scancode << "," <<
                                  event.key.keysym.sym << "," <<
                                  event.key.keysym.mod << "," <<
                                  event.key.keysym.unicode << std::endl;
                    }
                    break;
                case SDL_QUIT:
                    quit = true;
                    break;
                }
            }
            framerate.tick(now());
            tick();
        }
        for(tests_t::iterator i=objs.begin(); i!=objs.end(); i++)
            delete *i;
        return EXIT_SUCCESS;
    } catch(data_error_t* de) {
        std::cerr << "Oh! " << de << std::endl;
    } catch(graphics_error_t* ge) {
        std::cerr << "Oh! " << ge << std::endl;
    } catch(panic_t* panic) {
        std::cerr << "Oh! " << panic << std::endl;
    }
    return EXIT_FAILURE;
}
Ejemplo n.º 18
0
int main(int argc, char* argv[])
{
	LibVolume::Window::Window window;
	window.setTitle("Nilts");

	LibVolume::Engine::Realm realm;
	realm.linkTo(window);

	realm.background_colour = glm::vec3(4.0, 3.0, 8.0) * 0.2f;

	//Move a kilometre out
	realm.camera.state.position = glm::vec3(1000.0, 1000.0, 64.0);

	LibVolume::Render::Structures::Light sun(LibVolume::Render::Structures::LightType::Directional, glm::vec3(0.8, 0.25, -1.0), glm::vec3(3.0, 3.0, 3.9) * 0.4f, 0.2);
	realm.addLight(sun);

	LibVolume::Engine::VoxelTerrain terrain(glm::ivec3(32, 32, 32), LibVolume::Engine::MeshingAlgorithm::MarchingCubes, false, true);

	realm.addObject(terrain);

	while (window.tick() == false)
	{
		glm::f64vec3 new_camera_position = realm.camera.state.position;

		if (window.event_manager.keyboard_state.key_down)
			new_camera_position += (glm::f64vec3(0.0, 0.0, 3.0) * 0.02) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_right)
			new_camera_position += (glm::f64vec3(3.0, 0.0, 0.0) * 0.02) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_left)
			new_camera_position += (glm::f64vec3(-3.0, 0.0, 0.0) * 0.02) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_up)
			new_camera_position += (glm::f64vec3(0.0, 0.0, -3.0) * 0.02) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_space)
			new_camera_position += (glm::f64vec3(0.0, 3.0, 0.0) * 0.02) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_shift)
			new_camera_position += (glm::f64vec3(0.0, -3.0, 0.0) * 0.02) * realm.camera.state.orientation;

		//Stop the camera moving if it's going to go inside the terrain
		/*if (terrain.existsAt((glm::vec3)(new_camera_position / 32.0)))
		{
			if (terrain.getAt((glm::vec3)new_camera_position / 32.0f)->getDensityAt(glm::mod((glm::vec3)new_camera_position, 32.0f)) < 0.5)
				realm.camera.state.position = new_camera_position;
		}
		else*/
			realm.camera.state.position = new_camera_position;

		if (terrain.existsAt((glm::vec3)(realm.camera.state.position / 32.0)))
		{
			while (terrain.getAt((glm::vec3)realm.camera.state.position / 32.0f)->getDensityAt(glm::mod((glm::vec3)realm.camera.state.position, 32.0f)) > 0.5)
			{
				realm.camera.state.position += terrain.getAt((glm::vec3)new_camera_position / 32.0f)->getNormalAt(glm::mod((glm::vec3)new_camera_position, 32.0f)) * 0.01f;
			}
		}

		if (window.event_manager.keyboard_state.key_a)
			realm.camera.state.orientation = glm::f64quat(glm::vec3(0.0, -0.03, 0.0)) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_d)
			realm.camera.state.orientation = glm::f64quat(glm::vec3(0.0, 0.03, 0.0)) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_w)
			realm.camera.state.orientation = glm::f64quat(glm::vec3(0.03, 0.0, 0.0)) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_s)
			realm.camera.state.orientation = glm::f64quat(glm::vec3(-0.03, 0.0, 0.0)) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_q)
			realm.camera.state.orientation = glm::f64quat(glm::vec3(0.0, 0.0, -0.03)) * realm.camera.state.orientation;
		if (window.event_manager.keyboard_state.key_e)
			realm.camera.state.orientation = glm::f64quat(glm::vec3(0.0, 0.0, 0.03)) * realm.camera.state.orientation;

		for (int x = -2; x < 3; x ++)
		{
			for (int y = -2; y < 3; y ++)
			{
				for (int z = 0; z < 2; z ++)
				{
					loadAt(glm::ivec3(x, y, z) + glm::ivec3(realm.camera.state.position.x, realm.camera.state.position.y, 0) / 32, terrain);
					//terrain.getAt(glm::ivec3(x, y, z))->extract(LibVolume::Engine::MeshingAlgorithm::MarchingCubes);
				}
			}
		}

		realm.tick();
		realm.render();
	}

	return 0;
}
Ejemplo n.º 19
0
void ScenarioMapLoader::Impl::loadMap(std::fstream& f, Scenario& oScenario)
{
  CityPtr oCity = oScenario.getCity();
  Tilemap& oTilemap = oCity->getTilemap();

  /* get number of city */

  f.seekg(kLocation, std::ios::beg);
  unsigned int location=0;
  f.read((char*)&location, 1);
  StringHelper::debug( 0xff, "Location of city is %d", (int)(location+1) );

  std::string cityName = "";
  switch( location+1 ) {
    case 1: case 29: cityName = "Lugdunum"; break;
    case 2: cityName = "Corinthus"; break;
    case 3: case 37: cityName = "Londinium"; break;
    case 4: case 13: case 28: cityName = "Mediolanum"; break;
    case 5: case 40: cityName = "Lindum"; break;
    case 6: cityName = "Toletum"; break;
    case 7: case 33: cityName = "Valentia"; break;
    case 8: case 35: cityName = "Caesarea"; break;
    case 9: case 30: cityName = "Carthago"; break;
    case 10: cityName = "Cyrene"; break;
    case 11: case 15: case 25: cityName = "Tarraco"; break;
    case 12: cityName = "Hierosolyma"; break;
    case 14: case 26: cityName = "Syracusae"; break;
    case 16: case 31: cityName = "Tarsus"; break;
    case 17: case 32: cityName = "Tingis"; break;
    case 18: cityName = "Augusta Trevorum"; break;
    case 19: cityName = "Carthago Nova"; break;
    case 20: cityName = "Leptis Magna"; break;
    case 21: cityName = "Athenae"; break;
    case 22: cityName = "Brundisium"; break;
    case 23: cityName = "Capua"; break;
    case 24: cityName = "Tarentum"; break;
    case 27: cityName = "Miletus"; break;
    case 34: cityName = "Lutetia"; break;
    case 36: cityName = "Sarmizegetusa"; break;
    case 38: cityName = "Damascus"; break;
    case 39: cityName = "Massilia"; break;
  }

  oCity->setName( cityName );

  f.seekg(kSize, std::ios::beg);

  int size;  // 32bits
  int size_2;
  f.read((char*)&size,   4);
  f.read((char*)&size_2, 4);
  StringHelper::debug( 0xff, "Map size is %d", size );

  if (size != size_2)
  {
    THROW("Horisontal and vertical map sizes are different!");
  }

  oTilemap.init(size);

  // need to rewrite better
  short int     *pGraphicGrid = (short int     *)malloc(52488);
  unsigned char *pEdgeGrid    = (unsigned char *)malloc(26244);
  short int     *pTerrainGrid = (short int     *)malloc(52488);
  unsigned char *pRndmTerGrid = (unsigned char *)malloc(26244);
  unsigned char *pRandomGrid  = (unsigned char *)malloc(26244);
  unsigned char *pZeroGrid    = (unsigned char *)malloc(26244);
  
  if( pGraphicGrid == NULL || pEdgeGrid == NULL || pTerrainGrid == NULL ||
      pRndmTerGrid == NULL || pRandomGrid == NULL || pZeroGrid == NULL )
  {
    THROW("NOT ENOUGH MEMORY!!!! FATAL");
  }  
  
  // here also make copy of original arrays in memory

  f.seekg(kGraphicGrid, std::ios::beg);
  f.read((char*)pGraphicGrid, 52488);
  f.seekg(kEdgeGrid, std::ios::beg);
  f.read((char*)pEdgeGrid, 26244);
  f.seekg(kTerrainGrid, std::ios::beg);
  f.read((char*)pTerrainGrid, 52488);
  f.seekg(kRndmTerGrid, std::ios::beg);
  f.read((char*)pRndmTerGrid, 26244);
  f.seekg(kRandomGrid, std::ios::beg);
  f.read((char*)pRandomGrid, 26244);
  f.seekg(kZeroGrid, std::ios::beg);
  f.read((char*)pZeroGrid, 26244);

  // loads the graphics map
  int border_size = (162 - size) / 2;

  for (int itA = 0; itA < size; ++itA)
  {
    for (int itB = 0; itB < size; ++itB)
    {
      int i = itB;
      int j = size - itA - 1;

      int index = 162 * (border_size + itA) + border_size + itB;

      TerrainTile terrain(pGraphicGrid[index],
			  pEdgeGrid[index],
			  pTerrainGrid[index],
			  pRndmTerGrid[index],
			  pRandomGrid[index],
			  pZeroGrid[index]
			  );      
      
      Tile& tile = oTilemap.at(i, j);
      Picture& pic = Picture::load( TerrainTileHelper::convId2PicName( pGraphicGrid[index] ) );
      tile.setPicture( &pic );
      
      tile.getTerrain() = terrain; // what happens here?
    }    
  }

  for (int i = 0; i < size; ++i)
  {
    for (int j = 0; j < size; ++j)
    {
      Tile& tile = oTilemap.at(i, j);
      TerrainTile& terrain = tile.getTerrain();

      if (terrain.getEdgeData()==0x00)
      {
        int size = 1;

	      {
	        int dj;
	        try
	        {	
	          // find size, 5 is maximal size for building
	          for (dj = 0; dj < 5; ++dj)
	          {
	            int edge = oTilemap.at(i, j - dj).getTerrain().getEdgeData();
	            // find bottom left corner
	            if (edge == 8 * dj + 0x40)
	            {
	              size = dj + 1;
	              break;
	            }
	          }
	        }
	        catch(...)
	        {
	          size = dj + 1;
	        }
	      }
	
        StringHelper::debug( 0xff, "Multi-tile x %d at (%d,%d)", size, i, j );
	
	      bool bBad = false;
	
	      //Str << "probing ";
      	
         /* for (int di = 0; di < size && !bBad; ++di)
        {
	        for (int dj = 0; dj < size && !bBad; ++dj)
	        {
	          //std::cout << i - di << "," << j - dj << " ";
	          try
	          {
	            int edge = oTilemap.at(i - di, j - dj).getTerrain().getEdgeData();
	          }
	          catch(...)
	          {
      	      
	          }
      //	    if (edge != 8 * dj + di && edge != 8 * dj + 0x40)
      //	      bBad = true;
	        }
        }*/
	
	//std::cout << std::endl;
	
	      if (bBad)
	        THROW ("ERROR in multi-tiles!!!");
      	
	      Tile& master = oTilemap.at(i, j - size + 1);
      	
        StringHelper::debug( 0xff, "Master will be at (%d,%d)", master.getI(), master.getJ() );
      	
	      for (int di = 0; di < size; ++di)
        {
	        for (int dj = 0; dj < size; ++dj)
	        {
	            oTilemap.at(master.getI() + di, master.getJ() + dj).setMasterTile(&master);
	        }
        }
    	
        StringHelper::debug( 0xff, " decoding " );
      }
      
      TilePos pos( i, j );

      Tile &ttile = oTilemap.at( pos );

      LandOverlayPtr overlay = ttile.getTerrain().getOverlay();

      // Check if it is building and type of building
      //if (ttile.getMasterTile() == NULL)
      decodeTerrain(ttile, oCity );
    }
  }
}
Ejemplo n.º 20
0
DWORD LandScape::execV( LS_OPCODE _opcode, va_list _va )
{
   // reset the return status - individual functions will alter this if need be
   mExecStatus = EXEC_SUCCESS;
   mExecString[0] = '\0';
      
   switch( _opcode )
   {
      case LS_SEED: setSeed( va_arg(_va,DWORD) ); break;
      case LS_LOAD: return load( va_arg(_va,char*) );

      case LS_LOADM:
   		{
   			char * tmpCh = va_arg(_va,char*);
   			double tmpD = va_arg(_va,double);
   			return load(tmpCh, float(tmpD));
   		}
      case LS_SAVE: return save( va_arg(_va,char*) );
      case LS_CLEAR: clear(); break;
      case LS_PUSH: push( va_arg(_va,int)); break;
      case LS_POP:  pop(); break;
      case LS_GET:  return (DWORD)get( va_arg(_va,int) );
      case LS_SWAP: swap(); break;
      case LS_DUP:  dup(); break;
      case LS_ADD:  add( float(va_arg(_va,double)) ); break;
      case LS_SUB:  sub( float(va_arg(_va,double)) ); break;
      case LS_MUL:  mul( float(va_arg(_va,double)) ); break;
      case LS_DIV:  div( float(va_arg(_va,double)) ); break;
      case LS_EXP:  exp( float(va_arg(_va,double)) ); break;
      case LS_NEG:  neg(); break;
      case LS_CLR:  clr( float(va_arg(_va,double)) ); break;
      case LS_DIFF: diff(); break;

      case LS_NORMALIZE:
         {
            double i = va_arg(_va,double);
            double j = va_arg(_va,double);
            normalize( float(i), float(j) ); 
         }
         break;

      case LS_ADDS: addStack(); break;
      case LS_SUBS: subStack(); break;

      case LS_FLOOR:
         {
            double i = va_arg(_va,double);
            double j = va_arg(_va,double);
            double k = va_arg(_va,double);
            floor( float(i), float(j), float(k) );   
         }
         break;

      case LS_CEIL:
         {
            double i = va_arg(_va,double);
            double j = va_arg(_va,double);
            double k = va_arg(_va,double);
            ceil( i, j, k );   
         }
         break;

      case LS_CLIPMIN:  clipMin( float(va_arg(_va,double)) ); break;
      case LS_CLIPMAX:  clipMax( float(va_arg(_va,double)) ); break;
      case LS_ROT:   rot();   break;
      case LS_FLIPX: flipX(); break;
      case LS_FLIPY: flipY(); break;

      case LS_TERRAIN:
         {
         int    i = va_arg(_va,int);
         double j = va_arg(_va,double);
         if (i > 256)
         {
            terrain( 256, float(j) );
            size(i);
         }
         else
            terrain( i, float(j) );
         }
         break;

      case LS_PLASMA:
         {
         int    i = va_arg(_va,int);
         double j = va_arg(_va,double);
         if (i > 256)
         {
            plasma( 256, float(j) );
            size(i);
         }
         else
            plasma( i, float(j) );
         }
         break;

      case LS_SIZE: size( va_arg(_va,int) );  break;

      case LS_SLOPE:
         {
         double i = va_arg(_va,double);
         int    j = va_arg(_va,int);
         slope( i, float(j) );
         }
         break;

      case LS_SHAVE:
         {
         double i = va_arg(_va,double);
         double j = va_arg(_va,double);
         double k = va_arg(_va,double);
         shaveArea( float(i), float(j), float(k) );
         }
         break;
 
      case LS_CURVE:
         {
         double i = va_arg(_va,double);
         int    j = va_arg(_va,int);
         curve( float(i), j );
         }
         break;

      case LS_FFT:
         if (stack.size() > 1)
             fft( va_arg(_va,int) ); break;

      case LS_FILL_N:
        if (stack.size() > 1)
             fillNormal( float(va_arg(_va,double)) ); break;

      case LS_OVERLAY:
         {
         int    i = va_arg(_va,int);
         double j = va_arg(_va,double);
         overlay( i, float(j) );
         }
         break;

      case LS_ALPHABLEND:
         {
            int x = va_arg(_va, int);
            int y = va_arg(_va, int);
            alphablend(x, y);
         }
        break;

      case LS_BLEND:
         {
            int   i = va_arg(_va,int);
            int   j = va_arg(_va,int);
            blend( i, j );
         }

      case LS_SMOOTH:
         {
            double i = va_arg(_va,double);
            double j = va_arg(_va,double);
            smooth( float(i), float(j) ); 
         }
         break;

      case LS_TILE:  tile(); break;
      case LS_WRAP:  wrap(); break;

      case LS_CLAMP:
         {
         int    i = va_arg(_va,int);
         double j = va_arg(_va,double);
         clamp(i, float(j));
         }
         break;

      case LS_MASK:
         {
         int    i = va_arg(_va,int);
         double j = va_arg(_va,double);
         mask(i, float(j));
         }
         break;

      case LS_CRATER:
      case LS_PEAK:
      case LS_RING:
      case LS_FILLBASIN:
      case LS_LPFILTER:
      case LS_HPFILTER:
      case LS_BPFILTER:
      case LS_BRFILTER:
      case LS_FFLP:
      case LS_FFHP:
      case LS_FFBP:
      case LS_FFBR:
      default:
         break;
   }
   return NULL;
}
Ejemplo n.º 21
0
std::string default_generate_map(size_t width, size_t height, size_t island_size, size_t island_off_center,
                                 size_t iterations, size_t hill_size,
						         size_t max_lakes, size_t nvillages, size_t castle_size, size_t nplayers, bool roads_between_castles,
								 std::map<map_location,std::string>* labels, const config& cfg)
{
	log_scope("map generation");

	// Odd widths are nasty
	VALIDATE(is_even(width), _("Random maps with an odd width aren't supported."));

	int ticks = SDL_GetTicks();

	// Find out what the 'flatland' on this map is, i.e. grassland.
	std::string flatland = cfg["default_flatland"];
	if(flatland == "") {
		flatland = t_translation::write_terrain_code(t_translation::GRASS_LAND);
	}

	const t_translation::t_terrain grassland = t_translation::read_terrain_code(flatland);

	// We want to generate a map that is 9 times bigger
	// than the actual size desired.
	// Only the middle part of the map will be used,
	// but the rest is so that the map we end up using
	// can have a context (e.g. rivers flowing from
	// out of the map into the map, same for roads, etc.)
	width *= 3;
	height *= 3;

	LOG_NG << "generating height map...\n";
	// Generate the height of everything.
	const height_map heights = generate_height_map(width,height,iterations,hill_size,island_size,island_off_center);
	LOG_NG << "done generating height map...\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	config naming = cfg.child_or_empty("naming");
	// HACK: dummy names to satisfy unit_race requirements
	naming["id"] = "village_naming";
	naming["plural_name"] = "villages";

	// Make a dummy race for generating names
	const unit_race name_generator(naming);

	std::vector<terrain_height_mapper> height_conversion;

	BOOST_FOREACH(const config &h, cfg.child_range("height")) {
		height_conversion.push_back(terrain_height_mapper(h));
	}

	terrain_map terrain(width, t_translation::t_list(height, grassland));
	size_t x, y;
	for(x = 0; x != heights.size(); ++x) {
		for(y = 0; y != heights[x].size(); ++y) {
			for(std::vector<terrain_height_mapper>::const_iterator i = height_conversion.begin();
			    i != height_conversion.end(); ++i) {
				if(i->convert_terrain(heights[x][y])) {
					terrain[x][y] = i->convert_to();
					break;
				}
			}
		}
	}

	std::map<int, t_translation::coordinate> starting_positions;
	LOG_NG << output_map(terrain, starting_positions);
	LOG_NG << "placed land forms\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	// Now that we have our basic set of flatland/hills/mountains/water,
	// we can place lakes and rivers on the map.
	// All rivers are sourced at a lake.
	// Lakes must be in high land - at least 'min_lake_height'.
	// (Note that terrain below a certain altitude may be made
	// into bodies of water in the code above - i.e. 'sea',
	// but these are not considered 'lakes', because
	// they are not sources of rivers).
	//
	// We attempt to place 'max_lakes' lakes.
	// Each lake will be placed at a random location,
	// if that random location meets the minimum terrain requirements for a lake.
	// We will also attempt to source a river from each lake.
	std::set<location> lake_locs;

	std::map<location, std::string> river_names, lake_names, road_names, bridge_names, mountain_names, forest_names, swamp_names;

	const size_t nlakes = max_lakes > 0 ? (rand()%max_lakes) : 0;
	for(size_t lake = 0; lake != nlakes; ++lake) {
		for(int tries = 0; tries != 100; ++tries) {
			const int x = rand()%width;
			const int y = rand()%height;
			if (heights[x][y] > cfg["min_lake_height"].to_int()) {
				std::vector<location> river = generate_river(heights,
					terrain, x, y, cfg["river_frequency"]);

				if(river.empty() == false && labels != NULL) {
					std::string base_name;
					LOG_NG << "generating name for river...\n";
					const std::string& name = generate_name(name_generator,"river_name",&base_name);
					LOG_NG << "named river '" << name << "'\n";
					size_t name_frequency = 20;
					for(std::vector<location>::const_iterator r = river.begin(); r != river.end(); ++r) {

						const map_location loc(r->x-width/3,r->y-height/3);

						if(((r - river.begin())%name_frequency) == name_frequency/2) {
							labels->insert(std::pair<map_location,std::string>(loc,name));
						}

						river_names.insert(std::pair<location,std::string>(loc,base_name));
					}

					LOG_NG << "put down river name...\n";
				}

				LOG_NG << "generating lake...\n";
				std::set<location> locs;
				bool res = generate_lake(terrain, x, y, cfg["lake_size"], locs);
				if(res && labels != NULL) {
					bool touches_other_lake = false;

					std::string base_name;
					const std::string& name = generate_name(name_generator,"lake_name",&base_name);

					std::set<location>::const_iterator i;

					// Only generate a name if the lake hasn't touched any other lakes,
					// so that we don't end up with one big lake with multiple names.
					for(i = locs.begin(); i != locs.end(); ++i) {
						if(lake_locs.count(*i) != 0) {
							touches_other_lake = true;

							// Reassign the name of this lake to be the same as the other lake
							const location loc(i->x-width/3,i->y-height/3);
							const std::map<location,std::string>::const_iterator other_name = lake_names.find(loc);
							if(other_name != lake_names.end()) {
								base_name = other_name->second;
							}
						}

						lake_locs.insert(*i);
					}

					if(!touches_other_lake) {
						const map_location loc(x-width/3,y-height/3);
						labels->erase(loc);
						labels->insert(std::pair<map_location,std::string>(loc,name));
					}

					for(i = locs.begin(); i != locs.end(); ++i) {
						const location loc(i->x-width/3,i->y-height/3);
						lake_names.insert(std::pair<location, std::string>(loc, base_name));
					}
				}

				break;
			}
		}
	}

	LOG_NG << "done generating rivers...\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	const size_t default_dimensions = 40*40*9;

	/*
	 * Convert grassland terrain to other types of flat terrain.
	 *
	 * We generate a 'temperature map' which uses the height generation
	 * algorithm to generate the temperature levels all over the map.  Then we
	 * can use a combination of height and terrain to divide terrain up into
	 * more interesting types than the default.
	 */
	const height_map temperature_map = generate_height_map(width,height,
		cfg["temperature_iterations"].to_int() * width * height / default_dimensions,
		cfg["temperature_size"], 0, 0);

	LOG_NG << "generated temperature map...\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	std::vector<terrain_converter> converters;
	BOOST_FOREACH(const config &cv, cfg.child_range("convert")) {
		converters.push_back(terrain_converter(cv));
	}

	LOG_NG << "created terrain converters\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();


	// Iterate over every flatland tile, and determine
	// what type of flatland it is, based on our [convert] tags.
	for(x = 0; x != width; ++x) {
		for(y = 0; y != height; ++y) {
			for(std::vector<terrain_converter>::const_iterator i = converters.begin(); i != converters.end(); ++i) {
				if(i->convert_terrain(terrain[x][y],heights[x][y],temperature_map[x][y])) {
					terrain[x][y] = i->convert_to();
					break;
				}
			}
		}
	}

	LOG_NG << "placing villages...\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	/*
	 * Place villages in a 'grid', to make placing fair, but with villages
	 * displaced from their position according to terrain and randomness, to
	 * add some variety.
	 */
	std::set<location> villages;

	LOG_NG << "placing castles...\n";

	/** Try to find configuration for castles. */
	const config &castle_config = cfg.child("castle");
	if (!castle_config) {
		LOG_NG << "Could not find castle configuration\n";
		return std::string();
	}

	/*
	 * Castle configuration tag contains a 'valid_terrain' attribute which is a
	 * list of terrains that the castle may appear on.
	 */
	const t_translation::t_list list =
		t_translation::read_list(castle_config["valid_terrain"]);

	const is_valid_terrain terrain_tester(terrain, list);

	/*
	 * Attempt to place castles at random.
	 *
	 * Once we have placed castles, we run a sanity check to make sure that the
	 * castles are well-placed.  If the castles are not well-placed, we try
	 * again.  Definition of 'well-placed' is if no two castles are closer than
	 * 'min_distance' hexes from each other, and the castles appear on a
	 * terrain listed in 'valid_terrain'.
	 */
	std::vector<location> castles;
	std::set<location> failed_locs;

	for(size_t player = 0; player != nplayers; ++player) {
		LOG_NG << "placing castle for " << player << "\n";
		log_scope("placing castle");
		const int min_x = width/3 + 3;
		const int min_y = height/3 + 3;
		const int max_x = (width/3)*2 - 4;
		const int max_y = (height/3)*2 - 4;
		int min_distance = castle_config["min_distance"];

		location best_loc;
		int best_ranking = 0;
		for(int x = min_x; x != max_x; ++x) {
			for(int y = min_y; y != max_y; ++y) {
				const location loc(x,y);
				if(failed_locs.count(loc)) {
					continue;
				}

				const int ranking = rank_castle_location(x,y,terrain_tester,min_x,max_x,min_y,max_y,min_distance,castles,best_ranking);
				if(ranking <= 0) {
					failed_locs.insert(loc);
				}

				if(ranking > best_ranking) {
					best_ranking = ranking;
					best_loc = loc;
				}
			}
		}
		if(best_ranking == 0) {
			ERR_NG << "No castle location found, aborting.\n";
			std::string error = _("No valid castle location found. Too many or too few mountain hexes? (please check the 'max hill size' parameter)");
			throw mapgen_exception(error);
		}
		assert(std::find(castles.begin(), castles.end(), best_loc) == castles.end());
		castles.push_back(best_loc);
		// Make sure the location can't get a second castle.
		failed_locs.insert(best_loc);
	}

	LOG_NG << "placing roads...\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	// Place roads.
	// We select two tiles at random locations on the borders
	// of the map, and try to build roads between them.
	int nroads = cfg["roads"];
	if(roads_between_castles) {
		nroads += castles.size()*castles.size();
	}

	std::set<location> bridges;

	road_path_calculator calc(terrain,cfg);
	for (int road = 0; road != nroads; ++road) {
		log_scope("creating road");

		/*
		 * We want the locations to be on the portion of the map we're actually
		 * going to use, since roads on other parts of the map won't have any
		 * influence, and doing it like this will be quicker.
		 */
		location src = random_point_at_side(width/3 + 2,height/3 + 2);
		location dst = random_point_at_side(width/3 + 2,height/3 + 2);

		src.x += width/3 - 1;
		src.y += height/3 - 1;
		dst.x += width/3 - 1;
		dst.y += height/3 - 1;

		if (roads_between_castles && road < int(castles.size() * castles.size())) {
			const size_t src_castle = road/castles.size();
			const size_t dst_castle = road%castles.size();
			if(src_castle >= dst_castle) {
				continue;
			}

			src = castles[src_castle];
			dst = castles[dst_castle];
		}

		// If the road isn't very interesting (on the same border), don't draw it.
		else if(src.x == dst.x || src.y == dst.y) {
			continue;
		}

		if (calc.cost(src, 0.0) >= 1000.0 || calc.cost(dst, 0.0) >= 1000.0) {
			continue;
		}

		// Search a path out for the road
		pathfind::plain_route rt = pathfind::a_star_search(src, dst, 10000.0, &calc, width, height);

		std::string road_base_name;
		const std::string& name = generate_name(name_generator, "road_name", &road_base_name);
		const int name_frequency = 20;
		int name_count = 0;

		bool on_bridge = false;

		// Draw the road.
		// If the search failed, rt.steps will simply be empty.
		for(std::vector<location>::const_iterator step = rt.steps.begin();
				step != rt.steps.end(); ++step) {

			const int x = step->x;
			const int y = step->y;

			if(x < 0 || y < 0 || x >= static_cast<long>(width) ||
					y >= static_cast<long>(height)) {

				continue;
			}

			// Find the configuration which tells us
			// what to convert this tile to, to make it into a road.
			if (const config &child = cfg.find_child("road_cost", "terrain",
					t_translation::write_terrain_code(terrain[x][y])))
			{
				// Convert to bridge means that we want to convert
				// depending upon the direction the road is going.
				// Typically it will be in a format like,
				// convert_to_bridge=\,|,/
				// '|' will be used if the road is going north-south
				// '/' will be used if the road is going south west-north east
				// '\' will be used if the road is going south east-north west
				// The terrain will be left unchanged otherwise
				// (if there is no clear direction).
				const std::string &convert_to_bridge = child["convert_to_bridge"];
				if(convert_to_bridge.empty() == false) {
					if(step == rt.steps.begin() || step+1 == rt.steps.end())
						continue;

					const location& last = *(step-1);
					const location& next = *(step+1);

					location adj[6];
					get_adjacent_tiles(*step,adj);

					int direction = -1;

					// If we are going north-south
					if((last == adj[0] && next == adj[3]) || (last == adj[3] && next == adj[0])) {
						direction = 0;
					}

					// If we are going south west-north east
					else if((last == adj[1] && next == adj[4]) || (last == adj[4] && next == adj[1])) {
						direction = 1;
					}

					// If we are going south east-north west
					else if((last == adj[2] && next == adj[5]) || (last == adj[5] && next == adj[2])) {
						direction = 2;
					}

					if(labels != NULL && on_bridge == false) {
						on_bridge = true;
						std::string bridge_base_name;
						const std::string& name = generate_name(name_generator, "bridge_name", &bridge_base_name);
						const location loc(x - width / 3, y-height/3);
						labels->insert(std::pair<map_location,std::string>(loc,name));
						bridge_names.insert(std::pair<location,std::string>(loc, bridge_base_name)); //add to use for village naming
						bridges.insert(loc);
					}

					if(direction != -1) {
						const std::vector<std::string> items = utils::split(convert_to_bridge);
						if(size_t(direction) < items.size() && items[direction].empty() == false) {
							terrain[x][y] = t_translation::read_terrain_code(items[direction]);
						}

						continue;
					}
				} else {
					on_bridge = false;
				}

				// Just a plain terrain substitution for a road
				const std::string &convert_to = child["convert_to"];
				if(convert_to.empty() == false) {
					const t_translation::t_terrain letter =
						t_translation::read_terrain_code(convert_to);
					if(labels != NULL && terrain[x][y] != letter && name_count++ == name_frequency && on_bridge == false) {
						labels->insert(std::pair<map_location,std::string>(map_location(x-width/3,y-height/3),name));
						name_count = 0;
					}

					terrain[x][y] = letter;
					const location loc(x - width / 3, y - height / 3); //add to use for village naming
					road_names.insert(std::pair<location,std::string>(loc, road_base_name));
				}
			}
		}

		LOG_NG << "looked at " << calc.calls << " locations\n";
	}


	// Now that road drawing is done, we can plonk down the castles.
	for(std::vector<location>::const_iterator c = castles.begin(); c != castles.end(); ++c) {
		if(c->valid() == false) {
			continue;
		}

		const int x = c->x;
		const int y = c->y;
		const int player = c - castles.begin() + 1;
		const struct t_translation::coordinate coord(x, y);
		starting_positions.insert(std::pair<int, t_translation::coordinate>(player, coord));
		terrain[x][y] = t_translation::HUMAN_KEEP;

		const int castles[13][2] = {
		  {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1},
		  {-2, 1}, {-2, 0}, {-2, -1}, {-1, -2}, {0, -2}, {1, -2}
		};

		for (size_t i = 0; i < castle_size - 1; i++) {
		  terrain[x+castles[i][0]][y+castles[i][1]] = t_translation::HUMAN_CASTLE;
		}

		// Remove all labels under the castle tiles
		if(labels != NULL) {
		  labels->erase(location(x-width/3,y-height/3));
		  for (size_t i = 0; i < castle_size - 1; i++) {
		    labels->erase(location(x+castles[i][0]-width/3,
					   y+castles[i][1]-height/3));
		  }

		}

	}

	LOG_NG << "placed castles\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	/*Random naming for landforms: mountains, forests, swamps, hills
	 *we name these now that everything else is placed (as e.g., placing
	 * roads could split a forest)
	 */
	for (x = width / 3; x < (width / 3)*2; x++) {
		for (y = height / 3; y < (height / 3) * 2;y++) {
		//check the terrain of the tile
		const location loc(x - width / 3, y - height / 3);
		const t_translation::t_terrain terr = terrain[x][y];
		std::string name, base_name;
		std::set<std::string> used_names;
		if (t_translation::terrain_matches(terr, t_translation::ALL_MOUNTAINS)) {
			//name every 15th mountain
			if ((rand()%15) == 0) {
				for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
					name = generate_name(name_generator, "mountain_name", &base_name);
				}
				labels->insert(std::pair<map_location, std::string>(loc, name));
				mountain_names.insert(std::pair<location, std::string>(loc, base_name));
			}
		}
		else if (t_translation::terrain_matches(terr, t_translation::ALL_FORESTS)) {
			//if the forest tile is not named yet, name it
			const std::map<location, std::string>::const_iterator forest_name = forest_names.find(loc);
			if(forest_name == forest_names.end()) {
				for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
					name = generate_name(name_generator, "forest_name", &base_name);
				}
				forest_names.insert(std::pair<location, std::string>(loc, base_name));
				// name all connected forest tiles accordingly
				flood_name(loc, base_name, forest_names, t_translation::ALL_FORESTS, terrain, width, height, 0, labels, name);
			}
		}
		else if (t_translation::terrain_matches(terr, t_translation::ALL_SWAMPS)) {
			//if the swamp tile is not named yet, name it
			const std::map<location, std::string>::const_iterator swamp_name = swamp_names.find(loc);
			if(swamp_name == swamp_names.end()) {
				for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
					name = generate_name(name_generator, "swamp_name", &base_name);
				}
				swamp_names.insert(std::pair<location, std::string>(loc, base_name));
				// name all connected swamp tiles accordingly
				flood_name(loc, base_name, swamp_names, t_translation::ALL_SWAMPS, terrain, width, height, 0, labels, name);
			}
		}

		}
	}

	if (nvillages > 0)
	{
		config naming_cfg = cfg.child_or_empty("village_naming");
		// HACK: dummy names to satisfy unit_race requirements
		naming_cfg["id"] = "village_naming";
		naming_cfg["plural_name"] = "villages";

		const unit_race village_names_generator(naming_cfg);

		// First we work out the size of the x and y distance between villages
		const size_t tiles_per_village = ((width*height)/9)/nvillages;
		size_t village_x = 1, village_y = 1;

		// Alternate between incrementing the x and y value.
		// When they are high enough to equal or exceed the tiles_per_village,
		// then we have them to the value we want them at.
		while(village_x*village_y < tiles_per_village) {
			if(village_x < village_y) {
				++village_x;
			} else {
				++village_y;
			}
		}

		std::set<std::string> used_names;
		tcode_list_cache adj_liked_cache;

		for(size_t vx = 0; vx < width; vx += village_x) {
			LOG_NG << "village at " << vx << "\n";
			for(size_t vy = rand()%village_y; vy < height; vy += village_y) {

				const size_t add_x = rand()%3;
				const size_t add_y = rand()%3;
				const size_t x = (vx + add_x) - 1;
				const size_t y = (vy + add_y) - 1;

				const map_location res = place_village(terrain,x,y,2,cfg,adj_liked_cache);

				if(res.x >= static_cast<long>(width) / 3 &&
						res.x  < static_cast<long>(width * 2) / 3 &&
						res.y >= static_cast<long>(height) / 3 &&
						res.y  < static_cast<long>(height * 2) / 3) {

					const std::string str =
						t_translation::write_terrain_code(terrain[res.x][res.y]);
					if (const config &child = cfg.find_child("village", "terrain", str))
					{
						const std::string &convert_to = child["convert_to"];
						if(convert_to != "") {
							terrain[res.x][res.y] =
								t_translation::read_terrain_code(convert_to);

							villages.insert(res);

							if(labels != NULL && naming_cfg.empty() == false) {
								const map_location loc(res.x-width/3,res.y-height/3);

								map_location adj[6];
								get_adjacent_tiles(loc,adj);

								std::string name_type = "village_name";
								const t_translation::t_list
									field    = t_translation::t_list(1, t_translation::GRASS_LAND),
									forest   = t_translation::t_list(1, t_translation::FOREST),
									mountain = t_translation::t_list(1, t_translation::MOUNTAIN),
									hill     = t_translation::t_list(1, t_translation::HILL);

								size_t field_count = 0, forest_count = 0, mountain_count = 0, hill_count = 0;

								utils::string_map symbols;

								size_t n;
								for(n = 0; n != 6; ++n) {
									const std::map<location,std::string>::const_iterator road_name = road_names.find(adj[n]);
									if(road_name != road_names.end()) {
										symbols["road"] = road_name->second;
										name_type = "village_name_road";
										break;
									}

									const std::map<location,std::string>::const_iterator river_name = river_names.find(adj[n]);
									if(river_name != river_names.end()) {
										symbols["river"] = river_name->second;
										name_type = "village_name_river";

										const std::map<location,std::string>::const_iterator bridge_name = bridge_names.find(adj[n]);
										if(bridge_name != bridge_names.end()) {
										//we should always end up here, since if there is an adjacent bridge, there has to be an adjacent river too
										symbols["bridge"] = bridge_name->second;
										name_type = "village_name_river_bridge";
										}

										break;
									}

									const std::map<location,std::string>::const_iterator forest_name = forest_names.find(adj[n]);
									if(forest_name != forest_names.end()) {
										symbols["forest"] = forest_name->second;
										name_type = "village_name_forest";
										break;
									}

									const std::map<location,std::string>::const_iterator lake_name = lake_names.find(adj[n]);
									if(lake_name != lake_names.end()) {
										symbols["lake"] = lake_name->second;
										name_type = "village_name_lake";
										break;
									}

									const std::map<location,std::string>::const_iterator mountain_name = mountain_names.find(adj[n]);
									if(mountain_name != mountain_names.end()) {
										symbols["mountain"] = mountain_name->second;
										name_type = "village_name_mountain";
										break;
									}

									const std::map<location,std::string>::const_iterator swamp_name = swamp_names.find(adj[n]);
									if(swamp_name != swamp_names.end()) {
										symbols["swamp"] = swamp_name->second;
										name_type = "village_name_swamp";
										break;
									}

									const t_translation::t_terrain terr =
										terrain[adj[n].x+width/3][adj[n].y+height/3];

									if(std::count(field.begin(),field.end(),terr) > 0) {
										++field_count;
									} else if(std::count(forest.begin(),forest.end(),terr) > 0) {
										++forest_count;
									} else if(std::count(hill.begin(),hill.end(),terr) > 0) {
										++hill_count;
									} else if(std::count(mountain.begin(),mountain.end(),terr) > 0) {
										++mountain_count;
									}
								}

								if(n == 6) {
									if(field_count == 6) {
										name_type = "village_name_grassland";
									} else if(forest_count >= 2) {
										name_type = "village_name_forest";
									} else if(mountain_count >= 1) {
										name_type = "village_name_mountain_anonymous";
									} else if(hill_count >= 2) {
										name_type = "village_name_hill";
									}
								}

								std::string name;
								for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
									name = generate_name(village_names_generator,name_type,NULL,&symbols);
								}

								used_names.insert(name);
								labels->insert(std::pair<map_location,std::string>(loc,name));
							}
						}
					}
				}
			}
		}
	}

	LOG_NG << "placed villages\n";
	LOG_NG << (SDL_GetTicks() - ticks) << "\n"; ticks = SDL_GetTicks();

	return output_map(terrain, starting_positions);
}
Ejemplo n.º 22
0
int delegate_server(
      void *query, size_t query_length,
      void **response, size_t *response_length,
      int source, void *arg) {
  if(query_length <= 0) {
    error("Empty message - something went wrong.");
    return -1;
  }
  delegate_t *data = (delegate_t*)arg;
  char cmd = ((char*)query)[0];
  if(cmd == ACT_DELEGATE_GIVE_WORK) {
    int wrkno;
    if(match(query, query_length, "@c %i", ACT_DELEGATE_GIVE_WORK, &wrkno) == 0) {
      if(Wydobyte[wrkno + data->l] == Rezerwacje[wrkno + data->l]) {
        combine(response, response_length, "%c", ACT_REJECT);
        Uswiadomione[wrkno+data->l] = 1;
        return 0;
      } else {
        combine(response, response_length, "%c %i", ACT_OK, terrain(wrkno+data->l, Wydobyte[wrkno+data->l]));
        return 0;
      }
    } else {
      combine(response, response_length, "%c", ACT_ERROR);
      return 0;
    }
  } else if(cmd == ACT_DELEGATE_CHECK_WORK) {
    int wrkno;
    int sym;
    int results[32];
    if(match(query, query_length, "@c %i %i %b", ACT_DELEGATE_CHECK_WORK, &wrkno, &sym, results, 32 * sizeof(int)) == 0) {
      long long int mul = results[0], ter = terrain(wrkno+data->l, Wydobyte[wrkno+data->l]);
      for(int i = 1; i < 32; i++) mul *= results[i];
      if(mul > ter || sym != ter || ter % mul != 0) {
        combine(response, response_length, "%c", ACT_ERROR);
        return 0;
      } else {
        pthread_mutex_lock(&ochrona);
        Wydobyte[wrkno+data->l]++;
        if(Wydobyte[wrkno+data->l] == data->g) {
          int flag = 1;
          for(int i = 0; i < data->k; i++) {
            if(Wydobyte[data->l + i] < data->g || Uswiadomione[data->l + i] == 0) {
              flag = 0; break;
            }
          }
          if(flag) {
            data->do_exit = 1;
            for(int i = 0; i < data->k; i++) {
              Rezerwacje[data->l + i] = 0;
            }
          }
        }
        pthread_mutex_unlock(&ochrona);
        combine(response, response_length, "%c", ACT_OK);
        return 0;
      }
    } else {
      combine(response, response_length, "%c", ACT_ERROR);
      return 0;
    }
  } else if(cmd == ACT_DELEGATE_FIRE) {
    pthread_mutex_lock(&ochrona);
    data->do_exit = 1;
    for(int i = 0; i < data->k; i++) {
      Rezerwacje[data->l + i] = 0;
    }
    pthread_mutex_unlock(&ochrona);
  } else {
    warning("Unsupported command 0x%x.", cmd);
    combine(response, response_length, "%c", ACT_ERROR);
    return 0;
  }
  return -1;
}
Ejemplo n.º 23
0
Wind _default_wind (const Planet& p, int i, double tropical_equator) {
	Vector2 pressure_force = _default_pressure_gradient_force(tropical_equator, latitude(p, vector(nth_tile(p,i))));
	double coriolis_coeff = coriolis_coefficient(p, latitude(p, vector(nth_tile(p,i))));
	double friction = is_land(nth_tile(terrain(p), i)) ? 0.000045 : 0.000045;
	return _prevailing_wind(pressure_force, coriolis_coeff, friction);
}
Ejemplo n.º 24
0
int main(int argc, char* argv[])
{
    Mercator::Area* a1 = new Mercator::Area(1, false);
    
    WFMath::Polygon<2> p;
    p.addCorner(p.numCorners(), Point2(3, 4));
    p.addCorner(p.numCorners(), Point2(10, 10));
    p.addCorner(p.numCorners(), Point2(-1, 18));
    p.addCorner(p.numCorners(), Point2(-8, 11));
    
    a1->setShape(p);
    
    Mercator::Terrain terrain(Mercator::Terrain::SHADED, seg_size);

    Mercator::AreaShader* ashade = new Mercator::AreaShader(1);
    terrain.addShader(ashade, 0);
    
    terrain.setBasePoint(-2, -1, 5);
    terrain.setBasePoint(-2, 0, 2);
    terrain.setBasePoint(-2, 1, 19);
    
    terrain.setBasePoint(-1, -1, 4);
    terrain.setBasePoint(-1, 0, 6);
    terrain.setBasePoint(-1, 1, 10);
    
    terrain.setBasePoint(0, -1, 2);
    terrain.setBasePoint(0, 0, -1);
    terrain.setBasePoint(0, 1, 8);
    terrain.setBasePoint(0, 2, 11);
    
    terrain.setBasePoint(1, -1, 7);
    terrain.setBasePoint(1, 0, 2);
    terrain.setBasePoint(1, 1, 11);
    terrain.setBasePoint(1, 2, 9);
    
    terrain.setBasePoint(2, -1, 3);
    terrain.setBasePoint(2, 0, 8);
    terrain.setBasePoint(2, 1, 2);

    terrain.setBasePoint(3, -1, 6);
    terrain.setBasePoint(3, 0, 7);
    terrain.setBasePoint(3, 1, 9);
    
    terrain.addArea(a1);
    
    Mercator::Segment* seg = terrain.getSegment(0,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    seg = terrain.getSegment(1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);

    WFMath::Polygon<2> clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());
    
    seg = terrain.getSegment(-1,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());
    
    seg = terrain.getSegment(0,1);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());

    seg = terrain.getSegment(2,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);

    p.clear();
    p.addCorner(p.numCorners(), Point2(3 + seg_size, 4));
    p.addCorner(p.numCorners(), Point2(10 + seg_size, 10));
    p.addCorner(p.numCorners(), Point2(-1 + seg_size, 18));
    p.addCorner(p.numCorners(), Point2(-8 + seg_size, 11));
    
    a1->setShape(p);

    terrain.updateArea(a1);

    seg = terrain.getSegment(0,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    seg = terrain.getSegment(1,0);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));

    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());
    
    seg = terrain.getSegment(-1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);
    
    seg = terrain.getSegment(0,1);
    assert(seg->getAreas().size() == 1);
    assert(seg->getAreas().count(1) == 1);
    assert(a1->checkIntersects(*seg));
    
    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());

    seg = terrain.getSegment(2,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);
    assert(a1->checkIntersects(*seg) == false);

    clipped = a1->clipToSegment(*seg);
    assert(clipped.isValid());

    terrain.removeArea(a1);

    seg = terrain.getSegment(0,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    seg = terrain.getSegment(1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    seg = terrain.getSegment(-1,0);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    seg = terrain.getSegment(0,1);
    assert(seg->getAreas().size() == 0);
    assert(seg->getAreas().count(1) == 0);

    testAreaShader();

    testAddToSegment();
    
    return EXIT_SUCCESS;
}
Ejemplo n.º 25
0
void DownGroup::updateVisuals()
{
    ParticleGroup::updateVisuals();

    PxParticleReadData * readData = m_particleSystem->lockParticleReadData();
    assert(readData);

    m_particleDrawable->updateParticles(readData);

    // Get drained Particles
    std::vector<uint32_t> particlesToDelete;
    PxStrideIterator<const PxParticleFlags> flagsIt(readData->flagsBuffer);
    PxStrideIterator<const PxVec3> positionIt = readData->positionBuffer;


    TerrainInteraction terrain("water");
    std::vector<unsigned int> lavaToSteam;
    glowutils::AxisAlignedBoundingBox steamBbox;
    std::vector<glm::vec3> steamPositions;

    const TerrainSettings & terrainSettings = terrain.terrain().settings;

    for (unsigned i = 0; i < readData->validParticleRange; ++i, ++flagsIt, ++positionIt) {
        // check range
        if (!(*flagsIt & PxParticleFlag::eVALID)) {
            continue;
        }

        if (positionIt->y > terrainSettings.maxHeight * 0.75f) {
            particlesToDelete.push_back(i);
            continue;
        }

        if (*flagsIt & PxParticleFlag::eCOLLISION_WITH_STATIC) {
            if (positionIt->y < m_particleSize + 0.1)   // collision with water plane
            {
                if (m_elementName == "lava")
                {
                    lavaToSteam.push_back(i);
                    steamBbox.extend(reinterpret_cast<const glm::vec3&>(*positionIt));
                    steamPositions.push_back(reinterpret_cast<const glm::vec3&>(*positionIt));
                    continue;
                } else {
                    particlesToDelete.push_back(i);
                    continue;
                }
            }
            if (terrain.topmostElementAt(positionIt->x, positionIt->z) == m_elementName)
            {
                particlesToDelete.push_back(i);
            }
        }
    }

    assert(m_numParticles == readData->nbValidParticles);
    readData->unlock();

    if (!particlesToDelete.empty())
        releaseParticles(particlesToDelete);

    if (!lavaToSteam.empty())
    {
        DownGroup * steamGroup = ParticleGroupTycoon::instance().getNearestGroup("steam", steamBbox.center());
        steamGroup->createParticles(steamPositions);
        releaseParticles(lavaToSteam);
    }
}
Ejemplo n.º 26
0
Terrain *TerrainGenerator::generateRandomLandform()
{
    std::unique_ptr<Terrain> terrain(new Terrain(size_));

    // Make sure size is power of two
    Q_ASSERT((size_.width() & (size_.width() - 1)) == 0);
    Q_ASSERT((size_.height() & (size_.height() - 1)) == 0);

    // Make sure size is square
    Q_ASSERT(size_.width() == size_.height());

    const int sz = size_.width();
    std::mt19937 rnd(static_cast<std::uint_fast32_t>(std::random_device()()));
    std::normal_distribution<float> dist;

    auto landform = [&](int x, int y) -> float& {
        return terrain->landform(x & sz - 1, y & sz - 1);
    };

    landform(0, 0) = 50.f;

    float noiseScale = 30.f;
    for(int detail = sz >> 1; detail >= 1; detail >>= 1) {
        int step = detail << 1;
        for (int y = 0; y < sz; y += step) {
            for (int x = 0; x < sz; x += step) {
                auto p1 = landform(x, y);
                auto p2 = landform(x + step, y);
                auto p3 = landform(x, y + step);
                auto p4 = landform(x + step, y + step);
                landform(x + detail, y) = (p1 + p2) * 0.5f + dist(rnd) * noiseScale;
                landform(x, y + detail) = (p1 + p3) * 0.5f + dist(rnd) * noiseScale;
                landform(x + detail, y + detail) = (p1 + p4 + p2 + p3) * 0.25f + dist(rnd) * noiseScale;
            }
        }
        noiseScale *= 0.5f;
    }

    for (int y = 0; y < sz; ++y) {
        for (int x = 0; x < sz; ++x) {
            float altitude = 62.5f - terrain->landform(x, y);
            float red, green, blue;

            float landAltitude = std::max(altitude, 0.f);

            red = landAltitude * 1.5f + 140.f;
            green = 160.f + std::max(landAltitude - 40.f, 0.f);
            blue =  80.f + std::max(landAltitude - 40.f, 0.f) * 2.f;

            if (altitude < 0.f) {
                float mix = 1.f - std::exp2(altitude * .3f);
                mix = .2f + mix * 0.8f;
                red += (10.f - red) * mix;
                green += (100.f - green) * mix;
                blue += (160.f - blue) * mix;
            }

            red = std::min(red, 255.f);
            green = std::min(green, 255.f);
            blue = std::min(blue, 255.f);
            red = std::max(red, 0.f);
            green = std::max(green, 0.f);
            blue = std::max(blue, 0.f);

            //red = green = blue = latitude * 4.f + 128.f;

            terrain->color(x, y) =
               static_cast<int>(blue) | (static_cast<int>(green) << 8) |
               (static_cast<int>(red) << 16);
        }
    }

    return terrain.release();
}
Ejemplo n.º 27
0
void display(void)
{
#if 1
	glViewport(0, 0, gw, gh / 5 * 4);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(80, 1, 1, 400);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	x = current_origin_x + _distance * cos(angle * vl_pi / 180);
	z = current_origin_z + _distance * sin(angle * vl_pi / 180);

	float y = bilinear(x, z);
	Vec3 tmove, ttri[3];

	tmove = proj(HTrans4(Vec3(x, y, z)) * HRot4(Vec3(0, -1, 0), angle / 180 * vl_pi) * Vec4(move, 1));
	for(int i = 0; i < 3; i++){
		ttri[i] = proj(HTrans4(Vec3(x, 0, z)) * HRot4(Vec3(0, -1, 0), angle / 180 * vl_pi) * Vec4(tri[i], 1));
		ttri[i][1] = bilinear(ttri[i][0], ttri[i][2]);
	}

	// car configuration
	Vec3 xx, yy, zz, tmp;

	tmp = ttri[1] - (ttri[0] + ttri[2]) / 2;
	tmp[1] = 0;
	yy = norm(cross((ttri[0] - ttri[2]), (ttri[1] - ttri[2])));
	xx = norm(tmp - dot(yy, tmp) * yy);
	zz = cross(xx, yy);

	float mat[16] = {xx[0], xx[1], xx[2], 0.0, 
					 yy[0], yy[1], yy[2], 0.0, 
					 zz[0], zz[1], zz[2], 0.0,
					 x, y + 4.5, z, 1.0};

	// testing
	/*
	cout << "ttri[0] = " << ttri[0] << endl << "ttri[1] = " << ttri[1] << endl << "ttri[2] = " << ttri[2] << endl;
	cout << "ttri[0] - ttri[2] = " << ttri[0] - ttri[2] << endl << "ttri[1] - ttri[2] = " << ttri[1] - ttri[2] << endl;
	cout << "cross((ttri[0] - ttri[2]), (ttri[1] - ttri[2])) = " << cross((ttri[0] - ttri[2]), (ttri[1] - ttri[2])) << endl;
	cout << "yy = norm(cross((ttri[0] - ttri[2]), (ttri[1] - ttri[2])))\n = " << norm(cross((ttri[0] - ttri[2]), (ttri[1] - ttri[2]))) << endl << endl;

	printf("(%f, %f, %f)\nxx = (%f, %f, %f)\nyy = (%f, %f, %f)\nzz = (%f, %f, %f)\n", x, y, z, xx[0], xx[1], xx[2], yy[0], yy[1], yy[2], zz[0], zz[1], zz[2]);
	printf("ttri = (%f, %f, %f)\n", ttri[0][0], ttri[0][1], ttri[0][2]);
	printf("tmp = (%f, %f, %f)\n", tmp[0], tmp[1], tmp[2]);
	system("CLS");
	*/
	
	gluLookAt(0, 100, 150, 0, 0, 0, 0, 1, 0);

	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glDisable(GL_LIGHTING);

	glColor3f (1,1,1);
	terrain();

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glPushMatrix();
	glMultMatrixf(mat);
	glRotatef(-90, 0, -1, 0);
	glmDraw(car, GLM_MATERIAL | GLM_SMOOTH);
	glPopMatrix();
	glDisable(GL_LIGHTING);
#endif
#if 1
	// map
	glViewport(gw / 5 * 4 + 1, gh / 5 * 4 + 1, gw / 5, gh / 5);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(80, 1, 1, 400);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	gluLookAt(0, 150, 1, 0, 0, 0, 0, 1, 0);

	glColor3f (1,1,1);
	terrain();
	
	glPushAttrib(GL_ENABLE_BIT);
	glColor3f(1, 0, 0);
	glPointSize(7);
	glDisable(GL_TEXTURE_2D);
	glEnable(GL_POINT_SMOOTH);
	glBegin(GL_POINTS);
	glVertex3dv(tmove.Ref());
	glEnd();
	glPopAttrib();
#endif

	glutSwapBuffers();
}
Ejemplo n.º 28
0
int main()
{
	GameManager newManager;

	newManager.Initialize();

	//Load and create objects
	ResourceManager* resourceManager = newManager.GetResourceManager();

	//Loads the meshes from the model file into a
	//simple gameobject hierarchy and returns the root game object
	//Returns null if the model wasn't found
	/*
	GameObject* dwarfObject = newManager.CreateGameObjectsFromModel("data/dwarf2.b3d");
	if(dwarfObject != NULL)
	{
		dwarfObject->GetTransform().SetScale(0.05f,0.05f,0.05f);
		dwarfObject->GetTransform().SetPosition(-3.0f,0.0f,0.0f);
		newManager.AddComponentToGameObject(dwarfObject, new RotateObject(dwarfObject));
	}
	*/
	
	/*
	resourceManager->StoreAndInitMaterial("terrainMaterial", 
										new Diffuse(resourceManager->GetShaderProgram("Diffuse", "../data/Diffuse.vert", "../data/Diffuse.frag"),
										resourceManager->GetTexture2D("data/heightmap4.bmp")));
	
	TerrainHeightMap newTerrain;
	newTerrain.CreateHeightMap(resourceManager->GetTexture2D("data/heightmap4.bmp"), 128);

	//Test
	int numberOfTerrainPatches = newTerrain.GetNumberOfPatches();
	for(int i = 0; i < numberOfTerrainPatches; i++)
	{
		GameObject* terrainObject = new GameObject();
		terrainObject->AddComponent(new MeshRenderer(terrainObject,newTerrain.GetTerrainMeshes()[i], resourceManager->GetMaterial("terrainMaterial")));
		newManager.AddGameObject(terrainObject);
	}
	*/

	
	//TEST 2D OBJECT & Material
	/*
	resourceManager->StoreAndInitMaterial("2DMaterial", 
										new Diffuse2D(resourceManager->GetShaderProgram("Diffuse2D", "../data/Diffuse2D.vert", "../data/Diffuse2D.frag"),
										resourceManager->GetTexture2D("../data/test.bmp")));
	GameObject* cubeObject = new GameObject();
	cubeObject->GetTransform().SetScale(128,128,1);
	cubeObject->GetTransform().SetPosition(Vector3(500,300,0));
	cubeObject->AddComponent(new MeshRenderer(cubeObject,resourceManager->GetPrimitive(PLANE_PRIMITIVE),
	resourceManager->GetMaterial("2DMaterial"), ComponentUpdateStep::Render2DUpdate()));
	newManager.AddGameObject(cubeObject);
	*/
	
	//CDLOD TERRAIN	
	
	resourceManager->StoreAndInitMaterial("TerrainMaterial", 
										new TerrainMaterial(resourceManager->GetShaderProgram("TerrainShader", 
										"../data/Terrain.vert", "../data/Terrain.frag"),resourceManager->GetTexture2D("data/heightmap4.bmp")));

	TerrainCDLOD terrain((Camera*)newManager.GetMainCameraObject()->GetComponent(typeid(Camera)),resourceManager->GetTexture2D("data/heightmap4.bmp"));
	GameObject* terrainObject = new GameObject();
	terrainObject->AddComponent(new TerrainRenderer(terrainObject, &terrain, (TerrainMaterial*)resourceManager->GetMaterial("TerrainMaterial"),newManager.GetGraphicsDevice()));
	newManager.AddGameObject(terrainObject);
	
	
	//Add a movement script to the camera
	GameObject* cameraObject = newManager.GetMainCameraObject();
	newManager.AddComponentToGameObject(cameraObject, new FreeLookCamera(cameraObject));

	newManager.Update();
	newManager.Shutdown();
}
std::string default_map_generator_job::default_generate_map(generator_data data, std::map<map_location,std::string>* labels, const config& cfg)
{
	log_scope("map generation");

	// Odd widths are nasty
	VALIDATE(is_even(data.width), _("Random maps with an odd width aren't supported."));

	// Try to find configuration for castles
	const config& castle_config = cfg.child("castle");

	int ticks = SDL_GetTicks();

	// We want to generate a map that is 9 times bigger than the actual size desired.
	// Only the middle part of the map will be used, but the rest is so that the map we
	// end up using can have a context (e.g. rivers flowing from out of the map into the map,
	// same for roads, etc.)
	data.width  *= 3;
	data.height *= 3;

	config naming;

	if(cfg.has_child("naming")) {
		naming = game_config_.child("naming");
		naming.append_attributes(cfg.child("naming"));
	}

	// If the [naming] child is empty, we cannot provide good names.
	std::map<map_location,std::string>* misc_labels = naming.empty() ? nullptr : labels;

	std::shared_ptr<name_generator>
		base_name_generator, river_name_generator, lake_name_generator,
		road_name_generator, bridge_name_generator, mountain_name_generator,
		forest_name_generator, swamp_name_generator;

	if(misc_labels != nullptr) {
		name_generator_factory base_generator_factory{ naming, {"male", "base", "bridge", "road", "river", "forest", "lake", "mountain", "swamp"} };

		naming.get_old_attribute("base_names", "male_names", "[naming]male_names= is deprecated, use base_names= instead");
		//Due to the attribute detection feature of the factory we also support male_name_generator= but keep it undocumented.

		base_name_generator = base_generator_factory.get_name_generator( (naming.has_attribute("base_names") || naming.has_attribute("base_name_generator")) ? "base" : "male" );
		river_name_generator    = base_generator_factory.get_name_generator("river");
		lake_name_generator     = base_generator_factory.get_name_generator("lake");
		road_name_generator     = base_generator_factory.get_name_generator("road");
		bridge_name_generator   = base_generator_factory.get_name_generator("bridge");
		mountain_name_generator = base_generator_factory.get_name_generator("mountain");
		forest_name_generator   = base_generator_factory.get_name_generator("forest");
		swamp_name_generator    = base_generator_factory.get_name_generator("swamp");
	}

	// Generate the height of everything.
	const height_map heights = generate_height_map(data.width, data.height, data.iterations, data.hill_size, data.island_size, data.island_off_center);

	LOG_NG << "Done generating height map. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	ticks = SDL_GetTicks();

	// Find out what the 'flatland' on this map is, i.e. grassland.
	std::string flatland = cfg["default_flatland"];
	if(flatland.empty()) {
		flatland = t_translation::write_terrain_code(t_translation::GRASS_LAND);
	}

	const t_translation::terrain_code grassland = t_translation::read_terrain_code(flatland);

	std::vector<terrain_height_mapper> height_conversion;
	for(const config& h : cfg.child_range("height")) {
		height_conversion.emplace_back(h);
	}

	terrain_map terrain(data.width, data.height, grassland);
	for(size_t x = 0; x != heights.size(); ++x) {
		for(size_t y = 0; y != heights[x].size(); ++y) {
			for(auto i : height_conversion) {
				if(i.convert_terrain(heights[x][y])) {
					terrain[x][y] = i.convert_to();
					break;
				}
			}
		}
	}

	t_translation::starting_positions starting_positions;
	LOG_NG << output_map(terrain, starting_positions);
	LOG_NG << "Placed landforms. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	ticks = SDL_GetTicks();

	/* Now that we have our basic set of flatland/hills/mountains/water,
	 * we can place lakes and rivers on the map.
	 * All rivers are sourced at a lake.
	 * Lakes must be in high land - at least 'min_lake_height'.
	 * (Note that terrain below a certain altitude may be made into bodies of water
	 *  in the code above - i.e. 'sea', but these are not considered 'lakes',
	 *  because they are not sources of rivers).
	 *
	 * We attempt to place 'max_lakes' lakes.
	 * Each lake will be placed at a random location, if that random location meets theminimum
	 * terrain requirements for a lake. We will also attempt to source a river from each lake.
	 */
	std::set<map_location> lake_locs;

	std::map<map_location, std::string> river_names, lake_names, road_names, bridge_names, mountain_names, forest_names, swamp_names;

	const size_t nlakes = data.max_lakes > 0 ? (rng_()%data.max_lakes) : 0;
	for(size_t lake = 0; lake != nlakes; ++lake) {
		for(int tries = 0; tries != 100; ++tries) {
			const int x = rng_()%data.width;
			const int y = rng_()%data.height;

			if(heights[x][y] <= cfg["min_lake_height"].to_int()) {
				continue;
			}

			std::vector<map_location> river = generate_river(heights, terrain, x, y, cfg["river_frequency"]);

			if(!river.empty() && misc_labels != nullptr) {
				const std::string base_name = base_name_generator->generate();
				const std::string& name = river_name_generator->generate({{"base",  base_name}});
				LOG_NG << "Named river '" << name << "'\n";

				size_t name_frequency = 20;
				for(std::vector<map_location>::const_iterator r = river.begin(); r != river.end(); ++r) {
					const map_location loc(r->x-data.width/3,r->y-data.height/3);

					if(((r - river.begin())%name_frequency) == name_frequency/2) {
						misc_labels->emplace(loc, name);
					}

					river_names.emplace(loc, base_name);
				}
			}

			LOG_NG << "Generating lake...\n";

			std::set<map_location> locs;
			if(generate_lake(terrain, x, y, cfg["lake_size"], locs) && misc_labels != nullptr) {
				bool touches_other_lake = false;

				std::string base_name = base_name_generator->generate();
				const std::string& name = lake_name_generator->generate({{"base",  base_name}});

				// Only generate a name if the lake hasn't touched any other lakes,
				// so that we don't end up with one big lake with multiple names.
				for(auto i : locs) {
					if(lake_locs.count(i) != 0) {
						touches_other_lake = true;

						// Reassign the name of this lake to be the same as the other lake
						const map_location loc(i.x-data.width/3,i.y-data.height/3);
						const std::map<map_location,std::string>::const_iterator other_name = lake_names.find(loc);
						if(other_name != lake_names.end()) {
							base_name = other_name->second;
						}
					}

					lake_locs.insert(i);
				}

				if(!touches_other_lake) {
					const map_location loc(x-data.width/3,y-data.height/3);
					misc_labels->erase(loc);
					misc_labels->emplace(loc, name);
				}

				for(auto i : locs) {
					const map_location loc(i.x-data.width/3,i.y-data.height/3);
					lake_names.emplace(loc, base_name);
				}
			}

			break;
		}
	}

	LOG_NG << "Generated rivers. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	ticks = SDL_GetTicks();

	const size_t default_dimensions = 40*40*9;

	/*
	 * Convert grassland terrain to other types of flat terrain.
	 *
	 * We generate a 'temperature map' which uses the height generation
	 * algorithm to generate the temperature levels all over the map.  Then we
	 * can use a combination of height and terrain to divide terrain up into
	 * more interesting types than the default.
	 */
	const height_map temperature_map = generate_height_map(data.width,data.height,
		cfg["temperature_iterations"].to_int() * data.width * data.height / default_dimensions,
		cfg["temperature_size"], 0, 0);

	LOG_NG << "Generated temperature map. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	ticks = SDL_GetTicks();

	std::vector<terrain_converter> converters;
	for(const config& cv : cfg.child_range("convert")) {
		converters.emplace_back(cv);
	}

	LOG_NG << "Created terrain converters. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	ticks = SDL_GetTicks();

	// Iterate over every flatland tile, and determine what type of flatland it is, based on our [convert] tags.
	for(int x = 0; x != data.width; ++x) {
		for(int y = 0; y != data.height; ++y) {
			for(auto i : converters) {
				if(i.convert_terrain(terrain[x][y],heights[x][y],temperature_map[x][y])) {
					terrain[x][y] = i.convert_to();
					break;
				}
			}
		}
	}

	LOG_NG << "Placing castles...\n";

	/*
	 * Attempt to place castles at random.
	 *
	 * After they are placed, we run a sanity check to make sure no two castles
	 * are closer than 'min_distance' hexes apart, and that they appear on a
	 * terrain listed in 'valid_terrain'.
	 *
	 * If not, we attempt to place them again.
	 */
	std::vector<map_location> castles;
	std::set<map_location> failed_locs;

	if(castle_config) {
		/*
		 * Castle configuration tag contains a 'valid_terrain' attribute which is a
		 * list of terrains that the castle may appear on.
		 */
		const t_translation::ter_list list = t_translation::read_list(castle_config["valid_terrain"]);

		const is_valid_terrain terrain_tester(terrain, list);

		for(int player = 0; player != data.nplayers; ++player) {
			LOG_NG << "placing castle for " << player << "\n";
			lg::scope_logger inner_scope_logging_object__(lg::general(), "placing castle");
			const int min_x = data.width/3 + 3;
			const int min_y = data.height/3 + 3;
			const int max_x = (data.width/3)*2 - 4;
			const int max_y = (data.height/3)*2 - 4;
			int min_distance = castle_config["min_distance"];

			map_location best_loc;
			int best_ranking = 0;
			for(int x = min_x; x != max_x; ++x) {
				for(int y = min_y; y != max_y; ++y) {
					const map_location loc(x,y);
					if(failed_locs.count(loc)) {
						continue;
					}

					const int ranking = rank_castle_location(x, y, terrain_tester, min_x, max_x, min_y, max_y, min_distance, castles, best_ranking);
					if(ranking <= 0) {
						failed_locs.insert(loc);
					}

					if(ranking > best_ranking) {
						best_ranking = ranking;
						best_loc = loc;
					}
				}
			}

			if(best_ranking == 0) {
				ERR_NG << "No castle location found, aborting." << std::endl;
				const std::string error = _("No valid castle location found. Too many or too few mountain hexes? (please check the 'max hill size' parameter)");
				throw mapgen_exception(error);
			}

			assert(std::find(castles.begin(), castles.end(), best_loc) == castles.end());
			castles.push_back(best_loc);

			// Make sure the location can't get a second castle.
			failed_locs.insert(best_loc);
		}

		LOG_NG << "Placed castles. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	}
	LOG_NG << "Placing roads...\n";
	ticks = SDL_GetTicks();

	// Place roads.
	// We select two tiles at random locations on the borders of the map
	// and try to build roads between them.
	int nroads = cfg["roads"];
	if(data.link_castles) {
		nroads += castles.size()*castles.size();
	}

	std::set<map_location> bridges;

	road_path_calculator calc(terrain, cfg, rng_());
	for(int road = 0; road != nroads; ++road) {
		lg::scope_logger another_inner_scope_logging_object__(lg::general(), "creating road");

		/*
		 * We want the locations to be on the portion of the map we're actually
		 * going to use, since roads on other parts of the map won't have any
		 * influence, and doing it like this will be quicker.
		 */
		map_location src = random_point_at_side(data.width/3 + 2,data.height/3 + 2);
		map_location dst = random_point_at_side(data.width/3 + 2,data.height/3 + 2);

		src.x += data.width/3 - 1;
		src.y += data.height/3 - 1;
		dst.x += data.width/3 - 1;
		dst.y += data.height/3 - 1;

		if(data.link_castles && road < int(castles.size() * castles.size())) {
			const size_t src_castle = road/castles.size();
			const size_t dst_castle = road%castles.size();
			if(src_castle >= dst_castle) {
				continue;
			}

			src = castles[src_castle];
			dst = castles[dst_castle];
		} else if(src.x == dst.x || src.y == dst.y) {
			// If the road isn't very interesting (on the same border), don't draw it.
			continue;
		}

		if(calc.cost(src, 0.0) >= 1000.0 || calc.cost(dst, 0.0) >= 1000.0) {
			continue;
		}

		// Search a path out for the road
		pathfind::plain_route rt = pathfind::a_star_search(src, dst, 10000.0, calc, data.width, data.height);

		const std::string& road_base_name = misc_labels != nullptr
			? base_name_generator->generate()
			: "";
		const std::string& road_name = misc_labels != nullptr
			? road_name_generator->generate({{"base", road_base_name}})
			: "";
		const int name_frequency = 20;
		int name_count = 0;

		bool on_bridge = false;

		// Draw the road.
		// If the search failed, rt.steps will simply be empty.
		for(std::vector<map_location>::const_iterator step = rt.steps.begin();
				step != rt.steps.end(); ++step) {

			const int x = step->x;
			const int y = step->y;

			if(x < 0 || y < 0 || x >= static_cast<long>(data.width) || y >= static_cast<long>(data.height)) {
				continue;
			}

			// Find the configuration which tells us what to convert this tile to, to make it into a road.
			const config& child = cfg.find_child("road_cost", "terrain", t_translation::write_terrain_code(terrain[x][y]));
			if(child.empty()){
				continue;
			}

			/* Convert to bridge means that we want to convert depending on the direction of the road.
			 * Typically it will be in a format like convert_to_bridge = \,|,/
			 * '|' will be used if the road is going north-south
			 * '/' will be used if the road is going south west-north east
			 * '\' will be used if the road is going south east-north west
			 * The terrain will be left unchanged otherwise (if there is no clear direction).
			 */
			const std::string& convert_to_bridge = child["convert_to_bridge"];
			if(!convert_to_bridge.empty()) {
				if(step == rt.steps.begin() || step+1 == rt.steps.end()) {
					continue;
				}

				const map_location& last = *(step-1);
				const map_location& next = *(step+1);

				map_location adj[6];
				get_adjacent_tiles(*step,adj);

				int direction = -1;

				// If we are going north-south
				if((last == adj[0] && next == adj[3]) || (last == adj[3] && next == adj[0])) {
					direction = 0;
				}

				// If we are going south west-north east
				else if((last == adj[1] && next == adj[4]) || (last == adj[4] && next == adj[1])) {
					direction = 1;
				}

				// If we are going south east-north west
				else if((last == adj[2] && next == adj[5]) || (last == adj[5] && next == adj[2])) {
					direction = 2;
				}

				if(misc_labels != nullptr && !on_bridge) {
					on_bridge = true;
					std::string bridge_base_name = base_name_generator->generate();
					const std::string& name = bridge_name_generator->generate({{"base",  bridge_base_name}});
					const map_location loc(x - data.width / 3, y-data.height/3);
					misc_labels->emplace(loc, name);
					bridge_names.emplace(loc, bridge_base_name); //add to use for village naming
					bridges.insert(loc);
				}

				if(direction != -1) {
					const std::vector<std::string> items = utils::split(convert_to_bridge);
					if(size_t(direction) < items.size() && !items[direction].empty()) {
						terrain[x][y] = t_translation::read_terrain_code(items[direction]);
					}

					continue;
				}
			} else {
				on_bridge = false;
			}

			// Just a plain terrain substitution for a road
			const std::string& convert_to = child["convert_to"];
			if(!convert_to.empty()) {
				const t_translation::terrain_code letter = t_translation::read_terrain_code(convert_to);
				if(misc_labels != nullptr && terrain[x][y] != letter && name_count++ == name_frequency && !on_bridge) {
					misc_labels->emplace(map_location(x - data.width / 3, y - data.height / 3), road_name);
					name_count = 0;
				}

				terrain[x][y] = letter;
				if(misc_labels != nullptr) {
					const map_location loc(x - data.width / 3, y - data.height / 3); //add to use for village naming
					if(!road_base_name.empty())
						road_names.emplace(loc, road_base_name);
				}
			}
		}
	}

	// Now that road drawing is done, we can plonk down the castles.
	for(std::vector<map_location>::const_iterator c = castles.begin(); c != castles.end(); ++c) {
		if(!c->valid()) {
			continue;
		}

		const int x = c->x;
		const int y = c->y;
		const int player = c - castles.begin() + 1;
		const t_translation::coordinate coord(x, y);
		starting_positions.insert(t_translation::starting_positions::value_type(std::to_string(player), coord));
		terrain[x][y] = t_translation::HUMAN_KEEP;

		const int castle_array[13][2] {
			{-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {0, 1}, {-1, 1},
			{-2, 1}, {-2, 0}, {-2, -1}, {-1, -2}, {0, -2}, {1, -2}
		};

		for(int i = 0; i < data.castle_size - 1; i++) {
			terrain[x+ castle_array[i][0]][y+ castle_array[i][1]] = t_translation::HUMAN_CASTLE;
		}

		// Remove all labels under the castle tiles
		if(labels != nullptr) {
			labels->erase(map_location(x-data.width/3,y-data.height/3));
			for(int i = 0; i < data.castle_size - 1; i++) {
				labels->erase(map_location(x+ castle_array[i][0]-data.width/3, y+ castle_array[i][1]-data.height/3));
			}
		}
	}

	LOG_NG << "Placed roads. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	ticks = SDL_GetTicks();

	/* Random naming for landforms: mountains, forests, swamps, hills
	 * we name these now that everything else is placed (as e.g., placing
	 * roads could split a forest)
	 */
	if(misc_labels != nullptr) {
		for(int x = data.width / 3; x < (data.width / 3)*2; x++) {
			for(int y = data.height / 3; y < (data.height / 3) * 2;y++) {
				//check the terrain of the tile
				const map_location loc(x - data.width / 3, y - data.height / 3);
				const t_translation::terrain_code terr = terrain[x][y];
				std::string name, base_name;
				std::set<std::string> used_names;

				if(t_translation::terrain_matches(terr, t_translation::ALL_MOUNTAINS)) {
					//name every 15th mountain
					if((rng_() % 15) == 0) {
						for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
							base_name = base_name_generator->generate();
							name = mountain_name_generator->generate({{"base",  base_name}});
						}
						misc_labels->emplace(loc, name);
						mountain_names.emplace(loc, base_name);
					}
				} else if(t_translation::terrain_matches(terr, t_translation::ALL_FORESTS)) {
					// If the forest tile is not named yet, name it
					const std::map<map_location, std::string>::const_iterator forest_name = forest_names.find(loc);
					if(forest_name == forest_names.end()) {
						for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
							base_name = base_name_generator->generate();
							name = forest_name_generator->generate({{"base",  base_name}});
						}
						forest_names.emplace(loc, base_name);
						// name all connected forest tiles accordingly
						flood_name(loc, base_name, forest_names, t_translation::ALL_FORESTS, terrain, data.width, data.height, 0, misc_labels, name);
					}
				} else if(t_translation::terrain_matches(terr, t_translation::ALL_SWAMPS)) {
					// If the swamp tile is not named yet, name it
					const std::map<map_location, std::string>::const_iterator swamp_name = swamp_names.find(loc);
					if(swamp_name == swamp_names.end()) {
						for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
							base_name = base_name_generator->generate();
							name = swamp_name_generator->generate({{"base",  base_name}});
						}
						swamp_names.emplace(loc, base_name);
						// name all connected swamp tiles accordingly
						flood_name(loc, base_name, swamp_names, t_translation::ALL_SWAMPS, terrain, data.width, data.height, 0, misc_labels, name);
					}
				}
			}
		}
	}

	LOG_NG << "Named landforms. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";
	LOG_NG << "Placing villages...\n";
	ticks = SDL_GetTicks();

	/*
	 * Place villages in a 'grid', to make placing fair, but with villages
	 * displaced from their position according to terrain and randomness, to
	 * add some variety.
	 */
	std::set<map_location> villages;

	if(data.nvillages > 0) {

		// First we work out the size of the x and y distance between villages
		const size_t tiles_per_village = ((data.width*data.height)/9)/data.nvillages;
		size_t village_x = 1, village_y = 1;

		// Alternate between incrementing the x and y value.
		// When they are high enough to equal or exceed the tiles_per_village,
		// then we have them to the value we want them at.
		while(village_x*village_y < tiles_per_village) {
			if(village_x < village_y) {
				++village_x;
			} else {
				++village_y;
			}
		}

		std::set<std::string> used_names;
		tcode_list_cache adj_liked_cache;

		config village_naming = game_config_.child("village_naming");

		if(cfg.has_child("village_naming")) {
			village_naming.append_attributes(cfg.child("village_naming"));
		}

		// If the [village_naming] child is empty, we cannot provide good names.
		std::map<map_location,std::string>* village_labels = village_naming.empty() ? nullptr : labels;

		for(int vx = 0; vx < data.width; vx += village_x) {
			LOG_NG << "village at " << vx << "\n";

			for(int vy = rng_()%village_y; vy < data.height; vy += village_y) {
				const size_t add = rng_()%3;
				const size_t x = (vx + add) - 1;
				const size_t y = (vy + add) - 1;

				const map_location res = place_village(terrain, x, y, 2, cfg, adj_liked_cache);

				if(res.x  < static_cast<long>(data.width     ) / 3 ||
				   res.x >= static_cast<long>(data.width  * 2) / 3 ||
				   res.y  < static_cast<long>(data.height    ) / 3 ||
				   res.y >= static_cast<long>(data.height * 2) / 3) {
					continue;
				}

				const std::string str = t_translation::write_terrain_code(terrain[res.x][res.y]);

				const std::string& convert_to = cfg.find_child("village", "terrain", str)["convert_to"].str();
				if(convert_to.empty()) {
					continue;
				}

				terrain[res.x][res.y] = t_translation::read_terrain_code(convert_to);

				villages.insert(res);

				if(village_labels == nullptr) {
					continue;
				}

				name_generator_factory village_name_generator_factory{ village_naming,
					{"base", "male", "village", "lake", "river", "bridge", "grassland", "forest", "hill", "mountain", "mountain_anon", "road", "swamp"} };

				village_naming.get_old_attribute("base_names", "male_names", "[village_naming]male_names= is deprecated, use base_names= instead");
				//Due to the attribute detection feature of the factory we also support male_name_generator= but keep it undocumented.

				base_name_generator = village_name_generator_factory.get_name_generator(
					(village_naming.has_attribute("base_names") || village_naming.has_attribute("base_name_generator")) ? "base" : "male" );

				const map_location loc(res.x-data.width/3,res.y-data.height/3);

				map_location adj[6];
				get_adjacent_tiles(loc,adj);

				std::string name_type = "village";
				const t_translation::ter_list
					field	 = t_translation::ter_list(1, t_translation::GRASS_LAND),
					forest   = t_translation::ter_list(1, t_translation::FOREST),
					mountain = t_translation::ter_list(1, t_translation::MOUNTAIN),
					hill	 = t_translation::ter_list(1, t_translation::HILL);

				size_t field_count = 0, forest_count = 0, mountain_count = 0, hill_count = 0;

				std::map<std::string,std::string> symbols;

				size_t n;
				for(n = 0; n != 6; ++n) {
					const std::map<map_location,std::string>::const_iterator road_name = road_names.find(adj[n]);
					if(road_name != road_names.end()) {
						symbols["road"] = road_name->second;
						name_type = "road";
						break;
					}

					const std::map<map_location,std::string>::const_iterator river_name = river_names.find(adj[n]);
					if(river_name != river_names.end()) {
						symbols["river"] = river_name->second;
						name_type = "river";

						const std::map<map_location,std::string>::const_iterator bridge_name = bridge_names.find(adj[n]);
						if(bridge_name != bridge_names.end()) {
							//we should always end up here, since if there is an adjacent bridge, there has to be an adjacent river too
							symbols["bridge"] = bridge_name->second;
							name_type = "river_bridge";
						}

						break;
					}

					const std::map<map_location,std::string>::const_iterator forest_name = forest_names.find(adj[n]);
					if(forest_name != forest_names.end()) {
						symbols["forest"] = forest_name->second;
						name_type = "forest";
						break;
					}

					const std::map<map_location,std::string>::const_iterator lake_name = lake_names.find(adj[n]);
					if(lake_name != lake_names.end()) {
						symbols["lake"] = lake_name->second;
						name_type = "lake";
						break;
					}

					const std::map<map_location,std::string>::const_iterator mountain_name = mountain_names.find(adj[n]);
					if(mountain_name != mountain_names.end()) {
						symbols["mountain"] = mountain_name->second;
						name_type = "mountain";
						break;
					}

					const std::map<map_location,std::string>::const_iterator swamp_name = swamp_names.find(adj[n]);
					if(swamp_name != swamp_names.end()) {
						symbols["swamp"] = swamp_name->second;
						name_type = "swamp";
						break;
					}

					const t_translation::terrain_code terr = terrain[adj[n].x+data.width/3][adj[n].y+data.height/3];

					if(std::count(field.begin(),field.end(),terr) > 0) {
						++field_count;
					} else if(std::count(forest.begin(),forest.end(),terr) > 0) {
						++forest_count;
					} else if(std::count(hill.begin(),hill.end(),terr) > 0) {
						++hill_count;
					} else if(std::count(mountain.begin(),mountain.end(),terr) > 0) {
						++mountain_count;
					}
				}

				if(n == 6) {
					if(field_count == 6) {
						name_type = "grassland";
					} else if(forest_count >= 2) {
						name_type = "forest";
					} else if(mountain_count >= 1) {
						name_type = "mountain_anon";
					} else if(hill_count >= 2) {
						name_type = "hill";
					}
				}

				std::string name;

				symbols["base"] = base_name_generator->generate();
				std::shared_ptr<name_generator> village_name_generator = village_name_generator_factory.get_name_generator(name_type);

				for(size_t ntry = 0; ntry != 30 && (ntry == 0 || used_names.count(name) > 0); ++ntry) {
					name = village_name_generator->generate(symbols);
				}

				used_names.insert(name);
				village_labels->emplace(loc, name);
			}
		}
	}

	LOG_NG << "Placed villages. " << (SDL_GetTicks() - ticks) << " ticks elapsed" << "\n";

	return output_map(terrain, starting_positions);
}