227 lines
4.7 KiB
C++
227 lines
4.7 KiB
C++
#include <map.h>
|
|
#include <cstdlib> // rand
|
|
#include <cstring> // memset
|
|
|
|
// g++ -shared biome.cpp -o biome.dll -I../src
|
|
// g++ -shared biome.cpp -o biome.so -I../src -fPIC
|
|
|
|
#define MAX_POWER 10
|
|
#define MAX_EPICENTER_BY_TYPE 7
|
|
#define DIST_MIN_INTER_EPICENTRE 50
|
|
#define MIN_RADIUS 25
|
|
#define OFFSET_RADIUS 50
|
|
|
|
//map type ----> not used for now
|
|
enum{
|
|
FLAT, VALLEY
|
|
};
|
|
|
|
//biome type
|
|
enum{
|
|
VILLAGE, PLAINS, FOREST,MOUNTAINS,NB_BIOMES
|
|
};
|
|
|
|
// probability for each biomes
|
|
// in following order {GRASS,TREE,BERRIES, ROCK, IRON_ORE}
|
|
char proba_table[NB_BIOMES][5] = {{97,2,1,0,0},{85,13,2,0,0},{40,40,20,0,0},{0,0,0,80,20}};
|
|
|
|
typedef struct{
|
|
int x;
|
|
int y;
|
|
int type;
|
|
int power;
|
|
int radius;
|
|
} t_biome;
|
|
|
|
// variables
|
|
t_biome* l_biomes;
|
|
int size_biomes;
|
|
int nb_plains, nb_forests, nb_mountains;
|
|
int cpt_biome;
|
|
int width, height, n;
|
|
|
|
// functions
|
|
int distance_manhattan(int x1,int y1, int x2, int y2);
|
|
void set_spawns(Map &map);
|
|
void create_biome(int x, int y, int type);
|
|
void create_biome_random(Map &map, int type);
|
|
int check_nears_biomes(int x, int y);
|
|
int check_nears_spawn(Map &map, int x, int y);
|
|
int in_radius(int x,int y,t_biome e);
|
|
PixelType generate(int x, int y);
|
|
void init_generator();
|
|
|
|
extern "C" void generate(Map *mapPtr)
|
|
{
|
|
Map &map = *mapPtr;
|
|
width = map.getWidth();
|
|
height = map.getHeight();
|
|
n = map.getNbTeams();
|
|
int i,j;
|
|
|
|
//biome variable
|
|
|
|
init_generator();
|
|
|
|
//Epicenters generation
|
|
// random choice for numbers of biomes
|
|
nb_plains = (rand()%MAX_EPICENTER_BY_TYPE)+3;
|
|
nb_forests = (rand()%MAX_EPICENTER_BY_TYPE)+3;
|
|
nb_mountains = (rand()%MAX_EPICENTER_BY_TYPE)+3;
|
|
|
|
size_biomes = nb_plains+ nb_forests + nb_mountains + n;
|
|
|
|
l_biomes = (t_biome*)malloc(sizeof(t_biome)*size_biomes);
|
|
cpt_biome = 0;
|
|
|
|
// Spawn generations
|
|
set_spawns(map);
|
|
|
|
for(i=0;i<nb_plains;i++)
|
|
create_biome_random(map, PLAINS);
|
|
|
|
for(i=0;i<nb_forests;i++)
|
|
create_biome_random(map, FOREST);
|
|
|
|
for(i=0;i<nb_mountains;i++)
|
|
create_biome_random(map, MOUNTAINS);
|
|
// */
|
|
//génération de la carte
|
|
|
|
for (i=0;i<width;i++){
|
|
for(j=0;j<height;j++)
|
|
map[i][j].type = generate(i, j);
|
|
}
|
|
|
|
for(i=0; i<n; ++i)
|
|
{
|
|
map[map.team(i)].type = SPAWN;
|
|
map[map.team(i)].data.teamId = i;
|
|
}
|
|
|
|
free(l_biomes);
|
|
}
|
|
|
|
void init_generator(){
|
|
|
|
}
|
|
|
|
void set_spawns(Map &map){
|
|
int i;
|
|
int tier_w, tier_h;
|
|
|
|
tier_w = width/6;
|
|
tier_h = height/3;
|
|
|
|
for(i=0; i<n; ++i) // TODO : update spawn location initialisation
|
|
{
|
|
map.team(i) = Coord((rand()%tier_w)+tier_w, (rand()%tier_h)+tier_h);
|
|
create_biome(map.team(i).x, map.team(i).y, VILLAGE);
|
|
}
|
|
|
|
// sp_x[1] = width-sp_x[0];
|
|
// sp_y[1] = height-sp_y[0];
|
|
}
|
|
|
|
void create_biome(int x, int y, int type){
|
|
t_biome *biome = l_biomes + cpt_biome++;
|
|
|
|
biome->x=x;
|
|
biome->y=y;
|
|
biome->type = type;
|
|
|
|
switch(type){
|
|
case VILLAGE:
|
|
biome->power = (rand()%MAX_POWER)+1;
|
|
biome->radius = (rand()%(25-10))+10;
|
|
break;
|
|
case PLAINS:
|
|
case FOREST:
|
|
case MOUNTAINS:
|
|
default:
|
|
biome->power = (rand()%MAX_POWER)+1;
|
|
biome->radius = (rand()%(OFFSET_RADIUS))+MIN_RADIUS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void create_biome_random(Map &map, int type){
|
|
int x,y;
|
|
do {
|
|
x=rand()%width;
|
|
y=rand()%height;
|
|
} while ((check_nears_biomes(x,y) != 0) || (check_nears_spawn(map, x,y) != 0)); //prevent biome superposition
|
|
|
|
create_biome(x,y,type);
|
|
}
|
|
|
|
int check_nears_biomes(int x, int y){
|
|
int i, c=0;
|
|
for(i=0;i<cpt_biome;i++){
|
|
if (in_radius(x,y,l_biomes[i]) != -1) c++;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
int check_nears_spawn(Map &map, int x, int y){
|
|
int i,c = 0;
|
|
for(i=0;i<n;i++)
|
|
if (map.team(i).dist(x,y) < 75)
|
|
++c;
|
|
return c;
|
|
}
|
|
|
|
int in_radius(int x,int y,t_biome e){
|
|
int d = distance_manhattan(x,y,e.x,e.y);
|
|
return d < e.radius ? d : -1;
|
|
}
|
|
|
|
PixelType generate(int x, int y){
|
|
int i, j;
|
|
int proba[5];
|
|
int sum, dist, ratio, val, seuil=0;
|
|
t_biome biome;
|
|
|
|
memset(&proba,0,sizeof(int)*5);
|
|
sum=0;
|
|
|
|
for(i=0;i<size_biomes;i++){
|
|
biome = l_biomes[i];
|
|
if ((dist=in_radius(x,y,biome)) != -1){
|
|
ratio=(((biome.radius-dist)*100)/biome.radius);
|
|
//ne marche pas correctement, besoin de fractale à la place
|
|
/* if (biome.type == MOUNTAINS && (ratio < 20)){
|
|
sum += biome.power*ratio*100;
|
|
proba[0] += biome.power*ratio*20;
|
|
proba[3] += biome.power*ratio*75;
|
|
proba[4] += biome.power*ratio*5;
|
|
}else{*/
|
|
sum += biome.power*ratio*100;
|
|
for(j=0;j<5;j++){
|
|
proba[j]+=(proba_table[biome.type][j])*(biome.power)*ratio;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sum!=0){
|
|
val = rand()%sum;
|
|
for (i=0;i<5;i++){
|
|
seuil += proba[i];
|
|
if(val < seuil)
|
|
return PixelType(i+1);
|
|
}
|
|
}else{
|
|
val = rand()%100;
|
|
if (val <95){
|
|
return GRASS;
|
|
}else{
|
|
return TREE;
|
|
}
|
|
}
|
|
return GRASS;
|
|
}
|
|
|
|
int distance_manhattan(int x1,int y1, int x2, int y2){
|
|
return Coord::dist(Coord(x1, y1), Coord(x2, y2));
|
|
}
|