added in 'landform' setting to map generator

This commit is contained in:
Dave White 2004-03-27 20:31:43 +00:00
parent 00e44b11ea
commit 4baca7de7f
6 changed files with 117 additions and 33 deletions

View file

@ -67,16 +67,42 @@ typedef std::vector<std::vector<char> > terrain_map;
//we generate 'iterations' hills in total.
//the range of heights is normalized to 0-1000
//'island_size' controls whether or not the map should tend toward an island shape, and if
//so, how large the island should be. Hills will not have centers that are more than 'island_size'
//away from the center of the map. 'island_size' as 0 will allow hills anywhere.
//so, how large the island should be. Hills with centers that are more than 'island_size'
//away from the center of the map will be inverted (i.e. be valleys).
//'island_size' as 0 indicates no island
height_map generate_height_map(size_t width, size_t height,
size_t iterations, size_t hill_size,
size_t island_size)
size_t island_size, size_t island_off_center)
{
height_map res(width,std::vector<int>(height,0));
const size_t center_x = width/2;
const size_t center_y = height/2;
size_t center_x = width/2;
size_t center_y = height/2;
std::cerr << "off-centering...\n";
if(island_off_center != 0) {
switch(rand()%4) {
case 0:
center_x += island_off_center;
break;
case 1:
center_y += island_off_center;
break;
case 2:
if(center_x < island_off_center)
center_x = 0;
else
center_x -= island_off_center;
break;
case 3:
if(center_y < island_off_center)
center_y = 0;
else
center_y -= island_off_center;
break;
}
}
for(size_t i = 0; i != iterations; ++i) {
@ -89,25 +115,22 @@ height_map generate_height_map(size_t width, size_t height,
//a rectangle that contains all the positive values for this formula --
//the rectangle is given by min_x,max_x,min_y,max_y
int x1 = 0, y1 = 0, tries = 0;
bool valid_values = false;
//is this a negative hill? (i.e. a valley)
bool is_valley = false;
while(!valid_values && tries < 20) {
x1 = island_size > 0 ? center_x - island_size + (rand()%(island_size*2)) :
int x1 = island_size > 0 ? center_x - island_size + (rand()%(island_size*2)) :
int(rand()%width);
y1 = island_size > 0 ? center_y - island_size + (rand()%(island_size*2)) :
std::cerr << "y\n";
int y1 = island_size > 0 ? center_y - island_size + (rand()%(island_size*2)) :
int(rand()%height);
if(island_size == 0) {
valid_values = true;
} else {
const size_t diffx = abs(x1 - center_x);
const size_t diffy = abs(y1 - center_y);
const size_t dist = size_t(sqrt(double(diffx*diffx + diffy*diffy)));
valid_values = dist < island_size;
}
std::cerr << "z\n";
++tries;
//we have to check whether this is actually a valley
if(island_size != 0) {
const size_t diffx = abs(x1 - center_x);
const size_t diffy = abs(y1 - center_y);
const size_t dist = size_t(sqrt(double(diffx*diffx + diffy*diffy)));
is_valley = dist > island_size;
}
const int radius = rand()%hill_size + 1;
@ -117,13 +140,23 @@ height_map generate_height_map(size_t width, size_t height,
const int min_y = y1 - radius > 0 ? y1 - radius : 0;
const int max_y = y1 + radius < res.front().size() ? y1 + radius : res.front().size();
for(int x2 = min_x; size_t(x2) != max_x; ++x2) {
for(int y2 = min_y; size_t(y2) != max_y; ++y2) {
for(int x2 = min_x; x2 < max_x; ++x2) {
for(int y2 = min_y; y2 < max_y; ++y2) {
const int xdiff = (x2-x1);
const int ydiff = (y2-y1);
const int height = radius - int(sqrt(double(xdiff*xdiff + ydiff*ydiff)));
if(height > 0) {
res[x2][y2] += height;
if(is_valley) {
if(height > res[x2][y2]) {
res[x2][y2] = 0;
} else {
res[x2][y2] -= height;
}
} else {
res[x2][y2] += height;
}
}
}
}
@ -477,7 +510,7 @@ void place_castles(std::vector<gamemap::location>& castles, const std::set<gamem
}
//function to generate the map.
std::string default_generate_map(size_t width, size_t height, size_t island_size,
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 nplayers,
const config& cfg)
@ -503,8 +536,10 @@ std::string default_generate_map(size_t width, size_t height, size_t island_size
width *= 3;
height *= 3;
std::cerr << "generating height map...\n";
//generate the height of everything.
const height_map heights = generate_height_map(width,height,iterations,hill_size,20);
const height_map heights = generate_height_map(width,height,iterations,hill_size,island_size,island_off_center);
std::cerr << "done generating height map...\n";
//the configuration file should contain a number of [height] tags:
//[height]
@ -560,7 +595,7 @@ std::string default_generate_map(size_t width, size_t height, size_t island_size
//of height and terrain to divide flatland up into more interesting types than the default
const height_map temperature_map = generate_height_map(width,height,
atoi(cfg["temperature_iterations"].c_str()),
atoi(cfg["temperature_size"].c_str()),0);
atoi(cfg["temperature_size"].c_str()),0,0);
std::cerr << "generated temperature map...\n";

View file

@ -35,7 +35,7 @@ public:
map_generator* create_map_generator(const std::string& name, const config* cfg);
std::string default_generate_map(size_t width, size_t height, size_t island_size,
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 nplayers,
const config& cfg);

View file

@ -10,6 +10,11 @@
#include "widgets/button.hpp"
#include "widgets/slider.hpp"
namespace {
const size_t max_island = 10;
const size_t max_coastal = 5;
}
default_map_generator::default_map_generator(const config* cfg)
: width_(40), height_(40), island_size_(0), iterations_(1000), hill_size_(10), max_lakes_(20),
nvillages_(25), nplayers_(2), cfg_(cfg)
@ -168,7 +173,7 @@ void default_map_generator::user_config(display& disp)
villages_slider.set_value(nvillages_);
const int min_landform = 0;
const int max_landform = 10;
const int max_landform = int(max_island);
slider_rect.y = landform_rect.y;
gui::slider landform_slider(disp,slider_rect);
landform_slider.set_min(min_landform);
@ -218,6 +223,7 @@ void default_map_generator::user_config(display& disp)
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,iterations_label,iterations_rect.x,iterations_rect.y);
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,hillsize_label,hillsize_rect.x,hillsize_rect.y);
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,villages_label,villages_rect.x,villages_rect.y);
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,landform_label,landform_rect.x,landform_rect.y);
std::stringstream players_str;
players_str << nplayers_;
@ -240,7 +246,7 @@ void default_map_generator::user_config(display& disp)
slider_right+horz_margin,villages_rect.y);
std::stringstream landform_str;
landform_str << string_table[island_size_ == 0 ? "inland" : (island_size_ < 5 ? "coastal" : "island")];
landform_str << string_table[island_size_ == 0 ? "inland" : (island_size_ < max_coastal ? "coastal" : "island")];
font::draw_text(&disp,disp.screen_area(),14,font::NORMAL_COLOUR,landform_str.str(),
slider_right+horz_margin,landform_rect.y);
@ -258,11 +264,31 @@ std::string default_map_generator::name() const { return "default"; }
std::string default_map_generator::create_map(const std::vector<std::string>& args)
{
//many less iterations for an island, to make the island shaped
const size_t iterations = island_size_ > 0 ? iterations_/10 : iterations_;
const size_t island_size = island_size_ == 0 ? 0 : 120 - island_size_*10;
size_t iterations = iterations_;
size_t island_size = 0;
size_t island_off_center = 0;
size_t max_lakes = max_lakes_;
if(island_size_ >= max_coastal) {
//islands look good with much fewer iterations than normal, and fewer lakes
iterations /= 10;
max_lakes /= 9;
//the radius of the island should be up to half the width of the map
const size_t island_radius = 50 + ((max_island - island_size_)*50)/(max_island - max_coastal);
island_size = (island_radius*(width_/2))/100;
} else if(island_size_ > 0) {
std::cerr << "coastal...\n";
//the radius of the island should be up to twice the width of the map
const size_t island_radius = 40 + ((max_coastal - island_size_)*40)/max_coastal;
island_size = (island_radius*width_*2)/100;
island_off_center = minimum<size_t>(width_,height_);
std::cerr << "calculated coastal params...\n";
}
if(cfg_ != NULL)
return default_generate_map(width_,height_,island_size,iterations,hill_size_,max_lakes_,(nvillages_*width_*height_)/1000,nplayers_,*cfg_);
return default_generate_map(width_,height_,island_size,island_off_center,iterations,hill_size_,max_lakes,(nvillages_*width_*height_)/1000,nplayers_,*cfg_);
else
return "";
}

View file

@ -420,6 +420,24 @@ void send_data_all_except(const config& cfg, connection connection_num, size_t m
}
}
std::string ip_address(connection connection_num)
{
std::stringstream str;
const IPaddress* const ip = SDLNet_TCP_GetPeerAddress(connection_num);
if(ip != NULL) {
const unsigned char* buf = reinterpret_cast<const unsigned char*>(&ip->host);
for(int i = 0; i != sizeof(ip->host); ++i) {
str << int(buf[i]);
if(i+1 != sizeof(ip->host)) {
str << '.';
}
}
}
return str.str();
}
std::pair<int,int> current_transfer_stats()
{
if(current_connection == received_data.end())

View file

@ -92,6 +92,9 @@ void process_send_queue(connection connection_num=0, size_t max_size=0);
//function to send data to all peers except 'connection_num'
void send_data_all_except(const config& cfg, connection connection_num, size_t max_size=0);
//function to get the remote ip address of a socket
std::string ip_address(connection connection_num);
//function to see the number of bytes being processed on the current socket
std::pair<int,int> current_transfer_stats();

View file

@ -130,6 +130,8 @@ void server::run()
//send other players in the lobby the update that the player has joined
lobby_players_.send_data(sync_initial_response(),sock);
std::cout << "'" << username << "' (" << network::ip_address(sock) << ") has logged on\n";
} else if(lobby_players_.is_member(sock)) {
const config* const create_game = data.child("create_game");
if(create_game != NULL) {