-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWorld.cpp
More file actions
158 lines (136 loc) · 4.61 KB
/
World.cpp
File metadata and controls
158 lines (136 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* Licensed under GNU GPL v2
* Author(s): Adam Nyberg, Emil Österlund, Christofer Oden
* Created on: 09102?
*/
#include "World.h"
void World::generate(int row_count, int col_count, TileType default_tile)
{
my_row_count = row_count;
my_col_count = col_count;
my_default_tile = default_tile;
// When setting values at tiles, use 'set_tile()', it has bounds checking
printf("Initializing terrain matrix\n");
for( int i = 0; i < my_row_count; ++i ) {
for( int j = 0; j < my_col_count; ++j ) {
my_tiles.push_back( Tile( i, j, my_default_tile ) );
}
}
printf("Randomizing landscape\n");
// Generate a random landscape
// Instead of putting water at the borders, we refrain from putting
// anything else there
for (int row = 1; row < my_row_count - 1; ++row) {
for (int col = 1; col < my_col_count - 1; ++col) {
if (CHANCE(0.20)) set_tile_type(row, col, TILE_GRASS);
else if (CHANCE(0.70)) set_tile_type(row, col, TILE_TREES);
}
}
// If a land tile is neighbouring a water tile, replace it with water
// with the probability pWater
// Probability for replacement decreases with every successful attempt
// and increases for every failed attempt
printf("Expanding water areas\n");
double pWater = 0.0;
for (int row = 1; row < my_row_count - 1; ++row) {
for (int col = 1; col < my_col_count - 1; ++col) {
if (get_tile_type(row, col) == TILE_WATER)
continue;
if (
get_tile_type(row - 1, col) == TILE_WATER ||
get_tile_type(row, col - 1) == TILE_WATER ||
get_tile_type(row + 1, col) == TILE_WATER ||
get_tile_type(row, col + 1) == TILE_WATER
) {
if (CHANCE(pWater)) {
set_tile_type(row, col, TILE_WATER);
pWater -= 1.0;
}
else {
pWater += 0.0;
}
}
}
}
// Put water at single land tiles surrounded by water or
// land tiles lying between two water tiles horizontally or
// vertically to create lakes and rivers
printf( "Joining water tiles close to each other\n" );
for( int row = 1; row < my_row_count - 1; ++row ) {
for( int col = 1; col < my_col_count - 1; ++col ) {
if( get_tile_type(row, col) == TILE_WATER )
continue;
if( (get_tile_type(row + 1, col) == TILE_WATER &&
get_tile_type(row - 1, col) == TILE_WATER) ||
(get_tile_type(row, col + 1) == TILE_WATER &&
get_tile_type(row, col - 1) == TILE_WATER) )
{
set_tile_type( row, col, TILE_WATER );
}
}
}
printf( "Removing single water tiles\n" );
for( int row = 1; row < my_row_count - 1; ++row ) {
for( int col = 1; col < my_col_count - 1; ++col ) {
if( get_tile_type(row, col) == TILE_GRASS )
continue;
if( get_tile_type(row + 1, col) != TILE_WATER
&& get_tile_type(row - 1, col) != TILE_WATER
&& get_tile_type(row, col + 1) != TILE_WATER
&& get_tile_type(row, col - 1) != TILE_WATER )
{
set_tile_type(row, col, TILE_GRASS);
}
}
}
}
void World::load( const char *path ) {
FILE *fp = NULL;
char c = 0;
my_row_count = 0;
my_col_count = 0;
fp = fopen( path, "r" );
if( fp == NULL ) {
perror( "fopen" );
return;
}
while( c != EOF ) {
int col = 0;
while( (c = fgetc(fp) ) != '\n' ) {
if( c == EOF )
break;
my_tiles.push_back( Tile( my_row_count, col, TileType(c) ) );
++col;
}
++my_row_count;
if( col > my_col_count )
my_col_count = col;
}
fclose( fp );
}
inline
bool World::is_out_of_bounds( int row, int col ) {
if (row < 0 || row >= my_row_count || col < 0 || col >= my_col_count)
return true;
else
return false;
}
inline
TileType World::get_tile_type( int row, int col )
{
if( is_out_of_bounds( row, col ) ) {
//fprintf(stderr, "World tile out of bounds at (%d, %d)\n", row, col);
return my_default_tile;
}
else
return my_tiles[ row * my_col_count + col ].get_type();
}
inline
void World::set_tile_type( int row, int col, TileType tile_type )
{
// If out of bounds do nothing
if( is_out_of_bounds( row, col ) )
return;
else
my_tiles[ row * my_col_count + col ].set_type( tile_type );
}