00001
00006 #include <global.h>
00007 #include <random_map.h>
00008 #include <math.h>
00009
00010 typedef struct {
00011 int x;
00012 int y;
00013
00014 int sx;
00015 int sy;
00016 int ax, ay, zx, zy;
00017
00018 int rtype;
00019 } Room;
00020
00021 static int roguelike_place_room(Room *Rooms, int xsize, int ysize, int nrooms);
00022 static void roguelike_make_rooms(Room *Rooms, char **maze, int options);
00023 static void roguelike_link_rooms(Room *Rooms, char **maze, int xsize, int ysize);
00024
00044 int surround_check(char **layout, int i, int j, int Xsize, int Ysize) {
00045 int surround_index = 0;
00046
00047 if ((i > 0) && (layout[i-1][j] != 0 && layout[i-1][j] != '.'))
00048 surround_index += 1;
00049 if ((i < Xsize-1) && (layout[i+1][j] != 0 && layout[i+1][j] != '.'))
00050 surround_index += 2;
00051 if ((j > 0) && (layout[i][j-1] != 0 && layout[i][j-1] != '.'))
00052 surround_index += 4;
00053 if ((j < Ysize-1) && (layout[i][j+1] != 0 && layout[i][j+1] != '.'))
00054 surround_index += 8;
00055 return surround_index;
00056 }
00057
00069 char **roguelike_layout_gen(int xsize, int ysize, int options) {
00070 int i, j;
00071 Room *Rooms = NULL;
00072 Room *walk;
00073 int nrooms = 0;
00074 int tries = 0;
00075
00076
00077 char **maze = (char **)malloc(sizeof(char *)*xsize);
00078 for (i = 0; i < xsize; i++) {
00079 maze[i] = (char *)malloc(sizeof(char)*ysize);
00080 for (j = 0; j < ysize; j++)
00081 maze[i][j] = '#';
00082 }
00083
00084
00085
00086
00087
00088 if (xsize < 11 || ysize < 11) {
00089 for (i = 1; i < xsize-1; i++)
00090 for (j = 1; j < ysize-1; j++)
00091 maze[i][j] = 0;
00092 maze[(xsize-1)/2][(ysize-1)/2] = '>';
00093 maze[(xsize-1)/2][(ysize-1)/2+1] = '<';
00094 return maze;
00095 }
00096
00097
00098 nrooms = RANDOM()%10+6;
00099 Rooms = (Room *)calloc(nrooms+1, sizeof(Room));
00100
00101
00102 i = 0;
00103 while (tries < 450 && i < nrooms) {
00104
00105 if (!roguelike_place_room(Rooms, xsize, ysize, nrooms))
00106 tries++;
00107 else
00108 i++;
00109 }
00110
00111 if (i == 0) {
00112 for (i = 1; i < xsize-1; i++)
00113 for (j = 1; j < ysize-1; j++)
00114 maze[i][j] = 0;
00115 maze[(xsize-1)/2][(ysize-1)/2] = '>';
00116 maze[(xsize-1)/2][(ysize-1)/2+1] = '<';
00117 free(Rooms);
00118 return maze;
00119 }
00120
00121
00122 roguelike_make_rooms(Rooms, maze, options);
00123
00124 roguelike_link_rooms(Rooms, maze, xsize, ysize);
00125
00126
00127
00128 maze[Rooms->x][Rooms->y] = '<';
00129
00130 for (walk = Rooms; walk->x != 0; walk++)
00131 ;
00132
00133 walk--;
00134 if (walk == Rooms) {
00135
00136
00137
00138
00139
00140 if (maze[walk->x][walk->y+1] == '.')
00141 maze[walk->x][walk->y+1] = '>';
00142 else
00143 maze[walk->x][walk->y-1] = '>';
00144 } else
00145 maze[walk->x][walk->y] = '>';
00146
00147
00148 for (i = 0; i < xsize; i++)
00149 for (j = 0; j < ysize; j++) {
00150 if (maze[i][j] == '.')
00151 maze[i][j] = 0;
00152 if (maze[i][j] == 'D') {
00153 int si = surround_check(maze, i, j, xsize, ysize);
00154
00155 if (si != 3 && si != 12) {
00156 maze[i][j] = 0;
00157
00158 i = 0;
00159 j = 0;
00160 }
00161 }
00162 }
00163
00164 free(Rooms);
00165 return maze;
00166 }
00167
00180 static int roguelike_place_room(Room *Rooms, int xsize, int ysize, int nrooms) {
00181 int tx, ty;
00182 int sx, sy;
00183 int ax, ay;
00184 int zx, zy;
00185 int x_basesize;
00186 int y_basesize;
00187 Room *walk;
00188
00189
00190
00191 x_basesize = xsize/isqrt(nrooms);
00192 y_basesize = ysize/isqrt(nrooms);
00193
00194
00195 tx = RANDOM()%xsize;
00196 ty = RANDOM()%ysize;
00197
00198
00199 sx = (RANDOM()%x_basesize)+(RANDOM()%x_basesize)+(RANDOM()%x_basesize);
00200 sy = (RANDOM()%y_basesize)+(RANDOM()%y_basesize)+(RANDOM()%y_basesize);
00201 sy = (int)(sy*.5);
00202
00203
00204 ax = tx-sx/2;
00205 zx = tx+sx/2+sx%2;
00206
00207 ay = ty-sy/2;
00208 zy = ty+sy/2+sy%2;
00209
00210
00211 if (zx > xsize-1 || ax < 1)
00212 return 0;
00213 if (zy > ysize-1 || ay < 1)
00214 return 0;
00215
00216
00217 if (sx < 3 || sy < 3)
00218 return 0;
00219
00220
00221 for (walk = Rooms; walk->x != 0; walk++) {
00222 int dx = abs(tx-walk->x);
00223 int dy = abs(ty-walk->y);
00224
00225 if ((dx < (walk->sx+sx)/2+2) && (dy < (walk->sy+sy)/2+2))
00226 return 0;
00227 }
00228
00229
00230
00231
00232 for (walk = Rooms; walk->x != 0; walk++)
00233 ;
00234 walk->x = tx;
00235 walk->y = ty;
00236 walk->sx = sx;
00237 walk->sy = sy;
00238 walk->ax = ax;
00239 walk->ay = ay;
00240 walk->zx = zx;
00241 walk->zy = zy;
00242 return 1;
00243 }
00244
00254 static void roguelike_make_rooms(Room *Rooms, char **maze, int options) {
00255 int making_circle = 0;
00256 int i, j;
00257 int R;
00258 Room *walk;
00259
00260 for (walk = Rooms; walk->x != 0; walk++) {
00261
00262 switch (options) {
00263 case 1:
00264 making_circle = 0;
00265 break;
00266
00267 case 2:
00268 making_circle = 1;
00269 break;
00270
00271 default:
00272 making_circle = ((RANDOM()%3 == 0) ? 1 : 0);
00273 break;
00274 }
00275
00276 if (walk->sx < walk->sy)
00277 R = walk->sx/2;
00278 else
00279 R = walk->sy/2;
00280
00281
00282 for (i = walk->ax; i < walk->zx; i++)
00283 for (j = walk->ay; j < walk->zy; j++) {
00284 if (!making_circle || ((int)(0.5+hypot(walk->x-i, walk->y-j))) <= R)
00285 maze[i][j] = '.';
00286 }
00287 }
00288 }
00289
00300 static void roguelike_link_rooms(Room *Rooms, char **maze, int xsize, int ysize) {
00301 Room *walk;
00302 int i, j;
00303
00304
00305 if (Rooms[1].x == 0)
00306 return;
00307
00308 for (walk = Rooms+1; walk->x != 0; walk++) {
00309 int x1 = walk->x;
00310 int y1 = walk->y;
00311 int x2 = (walk-1)->x;
00312 int y2 = (walk-1)->y;
00313 int in_wall = 0;
00314
00315 if (RANDOM()%2) {
00316
00317
00318
00319 if (x2 < x1) {
00320 int tx = x2, ty = y2;
00321 x2 = x1;
00322 y2 = y1;
00323 x1 = tx;
00324 y1 = ty;
00325 }
00326
00327 j = y1;
00328 for (i = x1; i < x2; i++) {
00329 if (in_wall == 0 && maze[i][j] == '#') {
00330 in_wall = 1;
00331 maze[i][j] = 'D';
00332 } else if (in_wall && maze[i][j] == '.') {
00333 in_wall = 0;
00334 maze[i-1][j] = 'D';
00335 } else if (maze[i][j] != 'D' && maze[i][j] != '.')
00336 maze[i][j] = 0;
00337 }
00338 j = MIN(y1, y2);
00339 if (maze[i][j] == '.')
00340 in_wall = 0;
00341 if (maze[i][j] == 0 || maze[i][j] == '#')
00342 in_wall = 1;
00343 for (; j < MAX(y1, y2); j++) {
00344 if (in_wall == 0 && maze[i][j] == '#') {
00345 in_wall = 1;
00346 maze[i][j] = 'D';
00347 } else if (in_wall && maze[i][j] == '.') {
00348 in_wall = 0;
00349 maze[i][j-1] = 'D';
00350 } else if (maze[i][j] != 'D' && maze[i][j] != '.')
00351 maze[i][j] = 0;
00352 }
00353 } else {
00354 in_wall = 0;
00355
00356 if (y2 < y1) {
00357 int tx = x2, ty = y2;
00358 x2 = x1;
00359 y2 = y1;
00360 x1 = tx;
00361 y1 = ty;
00362 }
00363 i = x1;
00364
00365 for (j = y1; j < y2; j++) {
00366 if (in_wall == 0 && maze[i][j] == '#') {
00367 in_wall = 1;
00368 maze[i][j] = 'D';
00369 } else if (in_wall && maze[i][j] == '.') {
00370 in_wall = 0;
00371 maze[i][j-1] = 'D';
00372 } else if (maze[i][j] != 'D' && maze[i][j] != '.')
00373 maze[i][j] = 0;
00374 }
00375
00376 i = MIN(x1, x2);
00377 if (maze[i][j] == '.')
00378 in_wall = 0;
00379 if (maze[i][j] == 0 || maze[i][j] == '#')
00380 in_wall = 1;
00381 for (; i < MAX(x1, x2); i++) {
00382 if (in_wall == 0 && maze[i][j] == '#') {
00383 in_wall = 1;
00384 maze[i][j] = 'D';
00385 } else if (in_wall && maze[i][j] == '.') {
00386 in_wall = 0;
00387 maze[i-1][j] = 'D';
00388 } else
00389 if (maze[i][j] != 'D' && maze[i][j] != '.')
00390 maze[i][j] = 0;
00391
00392 }
00393 }
00394 }
00395 }