Crossfire Server, Trunk  R20513
random_map.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
23 #include "global.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/time.h>
29 #include <time.h>
30 
31 #include "maze_gen.h"
32 #include "random_map.h"
33 #include "room_gen.h"
34 #include "rproto.h"
35 #include "sproto.h"
36 
44 void dump_layout(char **layout, RMParms *RP)
45 {
46  int i, j;
47 
48  for (i = 0; i < RP->Xsize; i++) {
49  for (j = 0; j < RP->Ysize; j++) {
50  if (layout[i][j] == 0) {
51  layout[i][j] = ' ';
52  }
53  printf("%c", layout[i][j]);
54  if (layout[i][j] == ' ') {
55  layout[i][j] = 0;
56  }
57  }
58  printf("\n");
59  }
60  printf("\n");
61 }
62 
74 mapstruct *generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout)
75 {
76  char **layout, *buf;
77  mapstruct *theMap;
78  int i;
79 
80  /* pick a random seed, or use the one from the input file */
81  if (RP->random_seed == 0) {
82  RP->random_seed = time(NULL);
83  }
84 
85  SRANDOM(RP->random_seed);
86 
88 
89  if (RP->difficulty == 0) {
90  RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
91  if (RP->difficulty_increase > 0.001) {
92  RP->difficulty = (int)((float)RP->dungeon_level*RP->difficulty_increase);
93  if (RP->difficulty < 1) {
94  RP->difficulty = 1;
95  }
96  }
97  } else {
98  RP->difficulty_given = 1;
99  }
100 
101  if (!use_layout) {
102  if (RP->Xsize < MIN_RANDOM_MAP_SIZE) {
103  RP->Xsize = MIN_RANDOM_MAP_SIZE+RANDOM()%25+5;
104  }
105  if (RP->Ysize < MIN_RANDOM_MAP_SIZE) {
106  RP->Ysize = MIN_RANDOM_MAP_SIZE+RANDOM()%25+5;
107  }
108 
109  if (RP->expand2x > 0) {
110  RP->Xsize /= 2;
111  RP->Ysize /= 2;
112  }
113 
114  layout = layoutgen(RP);
115 
116 #ifdef RMAP_DEBUG
117  dump_layout(layout, RP);
118 #endif
119 
120  /* rotate the layout randomly */
121  layout = rotate_layout(layout, RANDOM()%4, RP);
122 #ifdef RMAP_DEBUG
123  dump_layout(layout, RP);
124 #endif
125  } else {
126  layout = use_layout;
127  }
128 
129  /* increment these for the current map */
130  RP->dungeon_level += 1;
131 
132  /* allocate the map and set the floor */
133  theMap = make_map_floor(layout, RP->floorstyle, RP);
134 
135  /* set the name of the map. */
136  safe_strncpy(theMap->path, OutFileName, sizeof(theMap->path));
137 
138  /* set region */
139  theMap->region = RP->region;
140 
141  /* create walls unless the wallstyle is "none" */
142  if (strcmp(RP->wallstyle, "none")) {
143  make_map_walls(theMap, layout, RP->wallstyle, RP);
144 
145  /* place doors unless doorstyle or wallstyle is "none"*/
146  if (strcmp(RP->doorstyle, "none")) {
147  put_doors(theMap, layout, RP->doorstyle, RP);
148  }
149  }
150 
151  /* create exits unless the exitstyle is "none" */
152  if (strcmp(RP->exitstyle, "none")) {
153  place_exits(theMap, layout, RP->exitstyle, RP->orientation, RP);
154  }
155 
156  place_specials_in_map(theMap, layout, RP);
157 
158  /* create monsters unless the monsterstyle is "none" */
159  if (strcmp(RP->monsterstyle, "none")) {
160  place_monsters(theMap, RP->monsterstyle, RP->difficulty, RP);
161  }
162 
163  /* treasures needs to have a proper difficulty set for the map. */
164  theMap->difficulty = calculate_difficulty(theMap);
165 
166  /* create treasure unless the treasurestyle is "none" */
167  if (strcmp(RP->treasurestyle, "none")) {
168  place_treasure(theMap, layout, RP->treasurestyle, RP->treasureoptions, RP);
169  }
170 
171  /* create decor unless the decorstyle is "none" */
172  if (strcmp(RP->decorstyle, "none")) {
173  put_decor(theMap, layout, RP->decorstyle, RP->decoroptions, RP);
174  }
175 
176  /* generate treasures, etc. */
177  apply_auto_fix(theMap);
178 
179  unblock_exits(theMap, layout, RP);
180 
181  /* free the layout unless it was given by caller */
182  if (!use_layout) {
183  for (i = 0; i < RP->Xsize; i++) {
184  free(layout[i]);
185  }
186  free(layout);
187  }
188 
189  theMap->msg = buf;
190 
191  /* We set the reset time at this, so town portal works on the map. */
192  theMap->last_reset_time = seconds();
193  return theMap;
194 }
195 
208 char **layoutgen(RMParms *RP)
209 {
210  char **maze = NULL;
211  int oxsize = RP->Xsize, oysize = RP->Ysize;
212 
213  if (RP->symmetry == RANDOM_SYM) {
214  RP->symmetry_used = (RANDOM()%(XY_SYM))+1;
215  } else {
216  RP->symmetry_used = RP->symmetry;
217  }
218 
219  if (RP->symmetry_used == Y_SYM || RP->symmetry_used == XY_SYM) {
220  RP->Ysize = RP->Ysize/2+1;
221  }
222  if (RP->symmetry_used == X_SYM || RP->symmetry_used == XY_SYM) {
223  RP->Xsize = RP->Xsize/2+1;
224  }
225 
226  if (RP->Xsize < MIN_RANDOM_MAP_SIZE) {
227  RP->Xsize = MIN_RANDOM_MAP_SIZE+RANDOM()%5;
228  }
229  if (RP->Ysize < MIN_RANDOM_MAP_SIZE) {
230  RP->Ysize = MIN_RANDOM_MAP_SIZE+RANDOM()%5;
231  }
232  RP->map_layout_style = 0;
233 
234  /* Redo this - there was a lot of redundant code of checking for preset
235  * layout style and then random layout style. Instead, figure out
236  * the numeric layoutstyle, so there is only one area that actually
237  * calls the code to make the maps.
238  */
239  if (strstr(RP->layoutstyle, "onion")) {
241  }
242 
243  if (strstr(RP->layoutstyle, "maze")) {
245  }
246 
247  if (strstr(RP->layoutstyle, "spiral")) {
249  }
250 
251  if (strstr(RP->layoutstyle, "rogue")) {
253  }
254 
255  if (strstr(RP->layoutstyle, "snake")) {
257  }
258 
259  if (strstr(RP->layoutstyle, "squarespiral")) {
261  }
262  /* No style found - choose one ranomdly */
263  if (RP->map_layout_style == 0) {
264  RP->map_layout_style = (RANDOM()%NROFLAYOUTS)+1;
265  }
266 
267  switch (RP->map_layout_style) {
268  case ONION_LAYOUT:
269  maze = map_gen_onion(RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
270  if (!(RANDOM()%3) && !(RP->layoutoptions1&OPT_WALLS_ONLY)) {
271  roomify_layout(maze, RP);
272  }
273  break;
274 
275  case MAZE_LAYOUT:
276  maze = maze_gen(RP->Xsize, RP->Ysize, RANDOM()%2);
277  if (!(RANDOM()%2)) {
278  doorify_layout(maze, RP);
279  }
280  break;
281 
282  case SPIRAL_LAYOUT:
283  maze = map_gen_spiral(RP->Xsize, RP->Ysize, RP->layoutoptions1);
284  if (!(RANDOM()%2)) {
285  doorify_layout(maze, RP);
286  }
287  break;
288 
289  case ROGUELIKE_LAYOUT:
290  /* Don't put symmetry in rogue maps. There isn't much reason to
291  * do so in the first place (doesn't make it any more interesting),
292  * but more importantly, the symmetry code presumes we are symmetrizing
293  * spirals, or maps with lots of passages - making a symmetric rogue
294  * map fails because its likely that the passages the symmetry process
295  * creates may not connect the rooms.
296  */
297  RP->symmetry_used = NO_SYM;
298  RP->Ysize = oysize;
299  RP->Xsize = oxsize;
300  maze = roguelike_layout_gen(RP->Xsize, RP->Ysize, RP->layoutoptions1);
301  /* no doorifying... done already */
302  break;
303 
304  case SNAKE_LAYOUT:
305  maze = make_snake_layout(RP->Xsize, RP->Ysize);
306  if (RANDOM()%2) {
307  roomify_layout(maze, RP);
308  }
309  break;
310 
312  maze = make_square_spiral_layout(RP->Xsize, RP->Ysize);
313  if (RANDOM()%2) {
314  roomify_layout(maze, RP);
315  }
316  break;
317  }
318 
319  maze = symmetrize_layout(maze, RP->symmetry_used, RP);
320 #ifdef RMAP_DEBUG
321  dump_layout(maze, RP);
322 #endif
323  if (RP->expand2x) {
324  maze = expand2x(maze, RP->Xsize, RP->Ysize);
325  RP->Xsize = RP->Xsize*2-1;
326  RP->Ysize = RP->Ysize*2-1;
327  }
328  return maze;
329 }
330 
343 char **symmetrize_layout(char **maze, int sym, RMParms *RP)
344 {
345  int i, j;
346  char **sym_maze;
347  int Xsize_orig, Ysize_orig;
348 
349  Xsize_orig = RP->Xsize;
350  Ysize_orig = RP->Ysize;
351  RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used.*/
352  if (sym == NO_SYM) {
353  RP->Xsize = Xsize_orig;
354  RP->Ysize = Ysize_orig;
355  return maze;
356  }
357  /* pick new sizes */
358  RP->Xsize = ((sym == X_SYM || sym == XY_SYM) ? RP->Xsize*2-3 : RP->Xsize);
359  RP->Ysize = ((sym == Y_SYM || sym == XY_SYM) ? RP->Ysize*2-3 : RP->Ysize);
360 
361  sym_maze = (char **)calloc(sizeof(char *), RP->Xsize);
362  for (i = 0; i < RP->Xsize; i++) {
363  sym_maze[i] = (char *)calloc(sizeof(char), RP->Ysize);
364  }
365 
366  if (sym == X_SYM)
367  for (i = 0; i < RP->Xsize/2+1; i++)
368  for (j = 0; j < RP->Ysize; j++) {
369  sym_maze[i][j] = maze[i][j];
370  sym_maze[RP->Xsize-i-1][j] = maze[i][j];
371  };
372  if (sym == Y_SYM)
373  for (i = 0; i < RP->Xsize; i++)
374  for (j = 0; j < RP->Ysize/2+1; j++) {
375  sym_maze[i][j] = maze[i][j];
376  sym_maze[i][RP->Ysize-j-1] = maze[i][j];
377  }
378  if (sym == XY_SYM)
379  for (i = 0; i < RP->Xsize/2+1; i++)
380  for (j = 0; j < RP->Ysize/2+1; j++) {
381  sym_maze[i][j] = maze[i][j];
382  sym_maze[i][RP->Ysize-j-1] = maze[i][j];
383  sym_maze[RP->Xsize-i-1][j] = maze[i][j];
384  sym_maze[RP->Xsize-i-1][RP->Ysize-j-1] = maze[i][j];
385  }
386 
387  /* delete the old maze */
388  for (i = 0; i < Xsize_orig; i++) {
389  free(maze[i]);
390  }
391  free(maze);
392 
393  /* reconnect disjointed spirals */
394  if (RP->map_layout_style == SPIRAL_LAYOUT) {
395  connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
396  }
397  /* reconnect disjointed nethackmazes: the routine for
398  * spirals will do the trick?
399  */
400  if (RP->map_layout_style == ROGUELIKE_LAYOUT) {
401  connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
402  }
403 
404  return sym_maze;
405 }
406 
424 char **rotate_layout(char **maze, int rotation, RMParms *RP)
425 {
426  char **new_maze;
427  int i, j;
428 
429  switch (rotation) {
430  case 0:
431  return maze;
432  break;
433 
434  case 2: { /* a reflection */
435  char *new = malloc(sizeof(char)*RP->Xsize*RP->Ysize);
436 
437  for (i = 0; i < RP->Xsize; i++) { /* make a copy */
438  for (j = 0; j < RP->Ysize; j++) {
439  new[i*RP->Ysize+j] = maze[i][j];
440  }
441  }
442  for (i = 0; i < RP->Xsize; i++) { /* copy a reflection back */
443  for (j = 0; j < RP->Ysize; j++) {
444  maze[i][j] = new[(RP->Xsize-i-1)*RP->Ysize+RP->Ysize-j-1];
445  }
446  }
447  free(new);
448  return maze;
449  break;
450  }
451 
452  case 1:
453  case 3: {
454  int swap;
455 
456  new_maze = (char **)calloc(sizeof(char *), RP->Ysize);
457  for (i = 0; i < RP->Ysize; i++) {
458  new_maze[i] = (char *)calloc(sizeof(char), RP->Xsize);
459  }
460  if (rotation == 1) /* swap x and y */
461  for (i = 0; i < RP->Xsize; i++)
462  for (j = 0; j < RP->Ysize; j++) {
463  new_maze[j][i] = maze[i][j];
464  }
465 
466  if (rotation == 3) { /* swap x and y */
467  for (i = 0; i < RP->Xsize; i++)
468  for (j = 0; j < RP->Ysize; j++) {
469  new_maze[j][i] = maze[RP->Xsize-i-1][RP->Ysize-j-1];
470  }
471  }
472 
473  /* delete the old layout */
474  for (i = 0; i < RP->Xsize; i++) {
475  free(maze[i]);
476  }
477  free(maze);
478 
479  swap = RP->Ysize;
480  RP->Ysize = RP->Xsize;
481  RP->Xsize = swap;
482  return new_maze;
483  break;
484  }
485  }
486  return NULL;
487 }
488 
496 void roomify_layout(char **maze, RMParms *RP)
497 {
498  int tries = RP->Xsize*RP->Ysize/30;
499  int ti;
500 
501  for (ti = 0; ti < tries; ti++) {
502  int dx, dy; /* starting location for looking at creating a door */
503  int cx, cy; /* results of checking on creating walls. */
504 
505  dx = RANDOM()%RP->Xsize;
506  dy = RANDOM()%RP->Ysize;
507  cx = can_make_wall(maze, dx, dy, 0, RP); /* horizontal */
508  cy = can_make_wall(maze, dx, dy, 1, RP); /* vertical */
509  if (cx == -1) {
510  if (cy != -1) {
511  make_wall(maze, dx, dy, 1);
512  }
513  continue;
514  }
515  if (cy == -1) {
516  make_wall(maze, dx, dy, 0);
517  continue;
518  }
519  if (cx < cy) {
520  make_wall(maze, dx, dy, 0);
521  } else {
522  make_wall(maze, dx, dy, 1);
523  }
524  }
525 }
526 
544 int can_make_wall(char **maze, int dx, int dy, int dir, RMParms *RP)
545 {
546  int i1;
547  int length = 0;
548 
549  /* dont make walls if we're on the edge. */
550  if (dx == 0 || dx == (RP->Xsize-1) || dy == 0 || dy == (RP->Ysize-1)) {
551  return -1;
552  }
553 
554  /* don't make walls if we're ON a wall. */
555  if (maze[dx][dy] != 0) {
556  return -1;
557  }
558 
559  if (dir == 0) {
560  /* horizontal */
561  int y = dy;
562 
563  for (i1 = dx-1; i1 > 0; i1--) {
564  int sindex = surround_flag2(maze, i1, y, RP);
565 
566  if (sindex == 1) {
567  break;
568  }
569  if (sindex != 0) {
570  return -1; /* can't make horiz. wall here */
571  }
572  if (maze[i1][y] != 0) {
573  return -1; /* can't make horiz. wall here */
574  }
575  length++;
576  }
577 
578  for (i1 = dx+1; i1 < RP->Xsize-1; i1++) {
579  int sindex = surround_flag2(maze, i1, y, RP);
580 
581  if (sindex == 2) {
582  break;
583  }
584  if (sindex != 0) {
585  return -1; /* can't make horiz. wall here */
586  }
587  if (maze[i1][y] != 0) {
588  return -1; /* can't make horiz. wall here */
589  }
590  length++;
591  }
592  return length;
593  } else {
594  /* vertical */
595  int x = dx;
596 
597  for (i1 = dy-1; i1 > 0; i1--) {
598  int sindex = surround_flag2(maze, x, i1, RP);
599 
600  if (sindex == 4) {
601  break;
602  }
603  if (sindex != 0) {
604  return -1; /* can't make vert. wall here */
605  }
606  if (maze[x][i1] != 0) {
607  return -1; /* can't make horiz. wall here */
608  }
609  length++;
610  }
611 
612  for (i1 = dy+1; i1 < RP->Ysize-1; i1++) {
613  int sindex = surround_flag2(maze, x, i1, RP);
614 
615  if (sindex == 8) {
616  break;
617  }
618  if (sindex != 0) {
619  return -1; /* can't make verti. wall here */
620  }
621  if (maze[x][i1] != 0) {
622  return -1; /* can't make horiz. wall here */
623  }
624  length++;
625  }
626  return length;
627  }
628 }
629 
644 int make_wall(char **maze, int x, int y, int dir)
645 {
646  maze[x][y] = 'D'; /* mark a door */
647  switch (dir) {
648  case 0: { /* horizontal */
649  int i1;
650 
651  for (i1 = x-1; maze[i1][y] == 0; i1--) {
652  maze[i1][y] = '#';
653  }
654  for (i1 = x+1; maze[i1][y] == 0; i1++) {
655  maze[i1][y] = '#';
656  }
657  break;
658  }
659 
660  case 1: { /* vertical */
661  int i1;
662 
663  for (i1 = y-1; maze[x][i1] == 0; i1--) {
664  maze[x][i1] = '#';
665  }
666  for (i1 = y+1; maze[x][i1] == 0; i1++) {
667  maze[x][i1] = '#';
668  }
669  break;
670  }
671  }
672 
673  return 0;
674 }
675 
683 void doorify_layout(char **maze, RMParms *RP)
684 {
685  int ndoors = RP->Xsize*RP->Ysize/60; /* reasonable number of doors. */
686  int *doorlist_x;
687  int *doorlist_y;
688  int doorlocs = 0; /* # of available doorlocations */
689  int i, j;
690 
691  doorlist_x = malloc(sizeof(int)*RP->Xsize*RP->Ysize);
692  doorlist_y = malloc(sizeof(int)*RP->Xsize*RP->Ysize);
693 
694 
695  /* make a list of possible door locations */
696  for (i = 1; i < RP->Xsize-1; i++)
697  for (j = 1; j < RP->Ysize-1; j++) {
698  int sindex = surround_flag(maze, i, j, RP);
699  if (sindex == 3 || sindex == 12) {
700  /* these are possible door sindex*/
701  doorlist_x[doorlocs] = i;
702  doorlist_y[doorlocs] = j;
703  doorlocs++;
704  }
705  }
706 
707  while (ndoors > 0 && doorlocs > 0) {
708  int di;
709  int sindex;
710 
711  di = RANDOM()%doorlocs;
712  i = doorlist_x[di];
713  j = doorlist_y[di];
714  sindex = surround_flag(maze, i, j, RP);
715  if (sindex == 3 || sindex == 12) { /* these are possible door sindex*/
716  maze[i][j] = 'D';
717  ndoors--;
718  }
719  /* reduce the size of the list */
720  doorlocs--;
721  doorlist_x[di] = doorlist_x[doorlocs];
722  doorlist_y[di] = doorlist_y[doorlocs];
723  }
724  free(doorlist_x);
725  free(doorlist_y);
726 }
727 
736 {
737  StringBuffer *buf;
738 
739  buf = stringbuffer_new();
740  stringbuffer_append_printf(buf, "xsize %d\nysize %d\n", RP->Xsize, RP->Ysize);
741 
742  if (RP->wallstyle[0]) {
743  stringbuffer_append_printf(buf, "wallstyle %s\n", RP->wallstyle);
744  }
745 
746  if (RP->floorstyle[0]) {
747  stringbuffer_append_printf(buf, "floorstyle %s\n", RP->floorstyle);
748  }
749 
750  if (RP->monsterstyle[0]) {
751  stringbuffer_append_printf(buf, "monsterstyle %s\n", RP->monsterstyle);
752  }
753 
754  if (RP->treasurestyle[0]) {
755  stringbuffer_append_printf(buf, "treasurestyle %s\n", RP->treasurestyle);
756  }
757 
758  if (RP->layoutstyle[0]) {
759  stringbuffer_append_printf(buf, "layoutstyle %s\n", RP->layoutstyle);
760  }
761 
762  if (RP->decorstyle[0]) {
763  stringbuffer_append_printf(buf, "decorstyle %s\n", RP->decorstyle);
764  }
765 
766  if (RP->doorstyle[0]) {
767  stringbuffer_append_printf(buf, "doorstyle %s\n", RP->doorstyle);
768  }
769 
770  if (RP->exitstyle[0]) {
771  stringbuffer_append_printf(buf, "exitstyle %s\n", RP->exitstyle);
772  }
773 
774  if (RP->final_map[0]) {
775  stringbuffer_append_printf(buf, "final_map %s\n", RP->final_map);
776  }
777 
778  if (RP->final_exit_archetype[0]) {
779  stringbuffer_append_printf(buf, "final_exit_archetype %s\n", RP->final_exit_archetype);
780  }
781 
782  if (RP->exit_on_final_map[0]) {
783  stringbuffer_append_printf(buf, "exit_on_final_map %s\n", RP->exit_on_final_map);
784  }
785 
786  if (RP->this_map[0]) {
787  stringbuffer_append_printf(buf, "origin_map %s\n", RP->this_map);
788  }
789 
790  if (RP->expand2x) {
791  stringbuffer_append_printf(buf, "expand2x %d\n", RP->expand2x);
792  }
793 
794  if (RP->layoutoptions1) {
795  stringbuffer_append_printf(buf, "layoutoptions1 %d\n", RP->layoutoptions1);
796  }
797 
798  if (RP->layoutoptions2) {
799  stringbuffer_append_printf(buf, "layoutoptions2 %d\n", RP->layoutoptions2);
800  }
801 
802  if (RP->symmetry) {
803  stringbuffer_append_printf(buf, "symmetry %d\n", RP->symmetry);
804  }
805 
806  if (RP->difficulty && RP->difficulty_given) {
807  stringbuffer_append_printf(buf, "difficulty %d\n", RP->difficulty);
808  }
809 
810  if (RP->difficulty_increase != 1.0) {
811  stringbuffer_append_printf(buf, "difficulty_increase %f\n", RP->difficulty_increase);
812  }
813 
814  stringbuffer_append_printf(buf, "dungeon_level %d\n", RP->dungeon_level);
815 
816  if (RP->dungeon_depth) {
817  stringbuffer_append_printf(buf, "dungeon_depth %d\n", RP->dungeon_depth);
818  }
819 
820  if (RP->dungeon_name[0]) {
821  stringbuffer_append_printf(buf, "dungeon_name %s\n", RP->dungeon_name);
822  }
823 
824  if (RP->decoroptions) {
825  stringbuffer_append_printf(buf, "decoroptions %d\n", RP->decoroptions);
826  }
827 
828  if (RP->orientation) {
829  stringbuffer_append_printf(buf, "orientation %d\n", RP->orientation);
830  }
831 
832  if (RP->origin_x) {
833  stringbuffer_append_printf(buf, "origin_x %d\n", RP->origin_x);
834  }
835 
836  if (RP->origin_y) {
837  stringbuffer_append_printf(buf, "origin_y %d\n", RP->origin_y);
838  }
839  if (RP->random_seed) {
840  /* Add one so that the next map is a bit different */
841  stringbuffer_append_printf(buf, "random_seed %d\n", RP->random_seed+1);
842  }
843 
844  if (RP->treasureoptions) {
845  stringbuffer_append_printf(buf, "treasureoptions %d\n", RP->treasureoptions);
846  }
847 
848  if (RP->multiple_floors) {
849  stringbuffer_append_printf(buf, "multiple_floors %d\n", RP->multiple_floors);
850  }
851 
852  return buf;
853 }
char ** roguelike_layout_gen(int xsize, int ysize, int options)
Actually make the rogue layout.
Definition: rogue_layout.c:332
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
char final_exit_archetype[RM_SIZE]
If not empty, the archetype name of the exit leading to the final map.
Definition: random_map.h:54
Random map parameters.
Definition: random_map.h:14
mapstruct * make_map_floor(char **layout, char *floorstyle, RMParms *RP)
Creates the Crossfire mapstruct object from the layout, and adds the floor.
Definition: floor.c:75
int make_wall(char **maze, int x, int y, int dir)
Cuts the layout horizontally or vertically by a wall with a door.
Definition: random_map.c:644
int decoroptions
Definition: random_map.h:81
#define ONION_LAYOUT
Definition: random_map.h:105
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout)
Main random map routine.
Definition: random_map.c:74
void place_treasure(mapstruct *map, char **layout, char *treasure_style, int treasureoptions, RMParms *RP)
Place treasures in the map.
Definition: treasure.c:92
void unblock_exits(mapstruct *map, char **maze, RMParms *RP)
This function unblocks the exits.
Definition: exit.c:385
char floorstyle[RM_SIZE]
Name of the floor style file, in /styles/floors, can be an empty string in which case a random one is...
Definition: random_map.h:29
char final_map[RM_SIZE]
If not empty, the path of the final map this whole maze leads to.
Definition: random_map.h:52
char ** make_snake_layout(int xsize, int ysize)
Generate a snake-like layout.
Definition: snake.c:34
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
#define SNAKE_LAYOUT
Definition: random_map.h:109
void place_monsters(mapstruct *map, char *monsterstyle, int difficulty, RMParms *RP)
Place some monsters into the map.
Definition: monster.c:38
char exit_on_final_map[RM_SIZE]
If this is "no", then no exit will be made to the final map from the previous random map...
Definition: random_map.h:65
Random map related variables.
int calculate_difficulty(mapstruct *m)
This routine is supposed to find out the difficulty of the map.
Definition: map.c:1913
void dump_layout(char **layout, RMParms *RP)
Dumps specified layout using printf().
Definition: random_map.c:44
int difficulty_given
If non zero, this means the difficulty was not zero initially.
Definition: random_map.h:77
char doorstyle[RM_SIZE]
Name of the doors style file, in /styles/doorstyles, see put_doors().
Definition: random_map.h:43
char ** layoutgen(RMParms *RP)
This function builds the actual layout.
Definition: random_map.c:208
void make_map_walls(mapstruct *map, char **layout, char *w_style, RMParms *RP)
takes a map and a layout, and puts walls in the map (picked from w_style) at &#39;#&#39; marks.
Definition: wall.c:184
int random_seed
Definition: random_map.h:85
Global type definitions and header inclusions.
#define safe_strncpy
Definition: compat.h:23
int multiple_floors
If non zero, then the map will have multiple floors, else only one floor will be used.
Definition: random_map.h:96
#define SRANDOM(seed)
Definition: define.h:680
void roomify_layout(char **maze, RMParms *RP)
Take a layout and make some rooms in it.
Definition: random_map.c:496
int expand2x
Definition: random_map.h:71
#define SPIRAL_LAYOUT
Definition: random_map.h:107
char ** make_square_spiral_layout(int xsize, int ysize)
Generates a square-spiral layout.
Definition: square_spiral.c:78
#define NROFLAYOUTS
Definition: random_map.h:111
void connect_spirals(int xsize, int ysize, int sym, char **layout)
Connects disjoint spirals which may result from the symmetrization process.
int map_layout_style
Definition: random_map.h:86
int layoutoptions2
Definition: random_map.h:73
int symmetry
Definition: random_map.h:74
char monsterstyle[RM_SIZE]
Name of the monster style directory, in /styles/monsters, can be an empty string in which case a rand...
Definition: random_map.h:34
void doorify_layout(char **maze, RMParms *RP)
Puts doors at appropriate locations in a layout.
Definition: random_map.c:683
void put_doors(mapstruct *the_map, char **maze, const char *doorstyle, RMParms *RP)
Add doors to a map.
Definition: door.c:73
int layoutoptions1
Definition: random_map.h:72
int surround_flag2(char **layout, int i, int j, RMParms *RP)
Given a layout and a coordinate, tell me which squares up/down/right/left are occupied by walls...
Definition: wall.c:77
int orientation
Definition: random_map.h:82
int treasureoptions
Definition: random_map.h:89
char * msg
Message map creator may have left.
Definition: map.h:361
char ** rotate_layout(char **maze, int rotation, RMParms *RP)
Takes a map and rotates it.
Definition: random_map.c:424
StringBuffer * write_map_parameters_to_string(const RMParms *RP)
Creates a suitable message for exit from RP.
Definition: random_map.c:735
long seconds(void)
Return wall clock time in seconds.
Definition: time.c:344
char dungeon_name[RM_SIZE]
If not empty, will be used in the name of the random keys.
Definition: random_map.h:67
#define ROGUELIKE_LAYOUT
Definition: random_map.h:108
int dungeon_level
Definition: random_map.h:79
#define MIN_RANDOM_MAP_SIZE
Minimal size a random should have to actually be generated.
Definition: random_map.h:146
char ** expand2x(char **layout, int xsize, int ysize)
Expands the layout be a factor 2.
Definition: expand2x.c:43
void place_exits(mapstruct *map, char **maze, char *exitstyle, int orientation, RMParms *RP)
Place exits in the map.
Definition: exit.c:144
int can_make_wall(char **maze, int dx, int dy, int dir, RMParms *RP)
Checks the layout to see if we can stick a horizontal (dir = 0) wall (or vertical, dir == 1) here which ends up on other walls sensibly.
Definition: random_map.c:544
char exitstyle[RM_SIZE]
Name of the exit style files, in /styles/exitstyles/{up,down}, can be an empty string in which case a...
Definition: random_map.h:58
char ** map_gen_spiral(int xsize, int ysize, int option)
Generates a spiral layout.
#define SQUARE_SPIRAL_LAYOUT
Definition: random_map.h:110
long last_reset_time
A timestamp of the last original map loading.
Definition: map.h:366
#define NO_SYM
No symmetry.
Definition: random_map.h:139
char layoutstyle[RM_SIZE]
Contains the layout type to generate, see layoutgen() for valid types.
Definition: random_map.h:41
int symmetry_used
Definition: random_map.h:90
char ** maze_gen(int xsize, int ysize, int option)
This function generates a random blocked maze with the property that there is only one path from one ...
Definition: maze_gen.c:58
int Ysize
Definition: random_map.h:70
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:343
void put_decor(mapstruct *map, char **maze, char *decorstyle, int decor_option, RMParms *RP)
Put the decor into the map.
Definition: decor.c:65
int Xsize
Definition: random_map.h:69
float difficulty_increase
Definition: random_map.h:78
char ** symmetrize_layout(char **maze, int sym, RMParms *RP)
Takes a map and makes it symmetric: adjusts Xsize and Ysize to produce a symmetric map...
Definition: random_map.c:343
#define RANDOM()
Definition: define.h:679
#define RANDOM_SYM
Random symmetry.
Definition: random_map.h:138
int origin_y
Definition: random_map.h:83
#define MAZE_LAYOUT
Definition: random_map.h:106
int dungeon_depth
Definition: random_map.h:80
char this_map[RM_SIZE]
Path of the map from which the random map(s) were created.
Definition: random_map.h:60
struct regiondef * region
Definition: random_map.h:91
void apply_auto_fix(mapstruct *m)
Go through the entire map (only the first time when an original map is loaded) and performs special a...
Definition: main.c:261
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.c:104
#define OPT_WALLS_ONLY
Only walls.
Definition: random_map.h:128
char ** map_gen_onion(int xsize, int ysize, int option, int layers)
Generates an onion layout.
void place_specials_in_map(mapstruct *map, char **layout, RMParms *RP)
Main function for specials.
Definition: special.c:393
int difficulty
Definition: random_map.h:75
char treasurestyle[RM_SIZE]
Name of the treasures style file, in /styles/treasurestyles, can be an empty string in which case a r...
Definition: random_map.h:39
int surround_flag(char **layout, int i, int j, RMParms *RP)
Given a layout and a coordinate, tell me which squares up/down/right/left are occupied.
Definition: wall.c:40
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
This is a game-map.
Definition: map.h:325
#define Y_SYM
Horizontal symmetry.
Definition: random_map.h:141
char decorstyle[RM_SIZE]
Name of the decor style file, in /styles/decorstyles, can be an empty string in which case a random o...
Definition: random_map.h:48
int origin_x
Definition: random_map.h:84
struct regiondef * region
What jurisdiction in the game world this map is ruled by points to the struct containing all the prop...
Definition: map.h:329
char wallstyle[RM_SIZE]
Name of the wall style file, in /styles/wallstyles, can be an empty string in which case a random one...
Definition: random_map.h:19
#define X_SYM
Vertical symmetry.
Definition: random_map.h:140
#define XY_SYM
Reflection.
Definition: random_map.h:142
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
Definition: main.c:88