Crossfire Server, Trunk  1.75.0
random_map.cpp
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 <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/time.h>
27 #include <time.h>
28 
29 #include "global.h"
30 #include "maze_gen.h"
31 #include "random_map.h"
32 #include "room_gen.h"
33 #include "rproto.h"
34 #include "sproto.h"
35 
43 void dump_layout(char **layout, RMParms *RP)
44 {
45  int i, j;
46 
47  for (i = 0; i < RP->Xsize; i++) {
48  for (j = 0; j < RP->Ysize; j++) {
49  if (layout[i][j] == 0) {
50  layout[i][j] = ' ';
51  }
52  printf("%c", layout[i][j]);
53  if (layout[i][j] == ' ') {
54  layout[i][j] = 0;
55  }
56  }
57  printf("\n");
58  }
59  printf("\n");
60 }
61 
75 mapstruct *generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout, sstring reset_group)
76 {
77  char **layout, *buf;
78  mapstruct *theMap;
79  int i;
80 
81  /* pick a random seed, or use the one from the input file */
82  if (RP->random_seed == 0) {
83  RP->random_seed = time(NULL);
84  }
85 
86  SRANDOM(RP->random_seed);
87 
89 
90  if (RP->difficulty == 0) {
91  RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty */
92  if (RP->difficulty_increase > 0.001) {
93  RP->difficulty = (int)((float)RP->dungeon_level*RP->difficulty_increase);
94  if (RP->difficulty < 1) {
95  RP->difficulty = 1;
96  }
97  }
98  } else {
99  RP->difficulty_given = 1;
100  }
101 
102  if (!use_layout) {
103  if (RP->Xsize < MIN_RANDOM_MAP_SIZE) {
104  RP->Xsize = MIN_RANDOM_MAP_SIZE+RANDOM()%25+5;
105  }
106  if (RP->Ysize < MIN_RANDOM_MAP_SIZE) {
107  RP->Ysize = MIN_RANDOM_MAP_SIZE+RANDOM()%25+5;
108  }
109 
110  if (RP->expand2x > 0) {
111  RP->Xsize /= 2;
112  RP->Ysize /= 2;
113  }
114 
115  layout = layoutgen(RP);
116 
117 #ifdef RMAP_DEBUG
118  dump_layout(layout, RP);
119 #endif
120 
121  if (RP->map_layout_style != ROGUELIKE_LAYOUT) {
122  /* rotate the layout randomly */
123  layout = rotate_layout(layout, RANDOM()%4, RP);
124 #ifdef RMAP_DEBUG
125  dump_layout(layout, RP);
126 #endif
127  }
128  } else {
129  layout = use_layout;
130  }
131 
132  /* increment these for the current map */
133  RP->dungeon_level += 1;
134 
135  /* allocate the map and set the floor */
136  theMap = make_map_floor(layout, RP->floorstyle, RP);
137 
138  /* set the name of the map. */
139  safe_strncpy(theMap->path, OutFileName, sizeof(theMap->path));
140 
141  if (reset_group) {
142  theMap->reset_group = add_string(reset_group);
143  } else {
144  theMap->reset_group = add_string(OutFileName);
145  }
146 
147  /* set region */
148  theMap->region = RP->region;
149 
150  /* create walls unless the wallstyle is "none" */
151  if (strcmp(RP->wallstyle, "none")) {
152  make_map_walls(theMap, layout, RP->wallstyle, RP);
153 
154  /* place doors unless doorstyle or wallstyle is "none"*/
155  if (strcmp(RP->doorstyle, "none")) {
156  put_doors(theMap, layout, RP->doorstyle, RP);
157  }
158  }
159 
160  /* create exits unless the exitstyle is "none" */
161  if (strcmp(RP->exitstyle, "none")) {
162  place_exits(theMap, layout, RP->exitstyle, RP->orientation, RP);
163  }
164 
165  if (RP->map_layout_style != ROGUELIKE_LAYOUT) {
166  place_specials_in_map(theMap, layout, RP);
167  }
168 
169  /* create monsters unless the monsterstyle is "none" */
170  if (strcmp(RP->monsterstyle, "none")) {
171  place_monsters(theMap, RP->monsterstyle, RP->difficulty, RP);
172  }
173 
174  /* treasures needs to have a proper difficulty set for the map. */
175  theMap->difficulty = calculate_difficulty(theMap);
176 
177  /* create treasure unless the treasurestyle is "none" */
178  if (strcmp(RP->treasurestyle, "none")) {
179  place_treasure(theMap, layout, RP->treasurestyle, RP->treasureoptions, RP);
180  }
181 
182  /* create decor unless the decorstyle is "none" */
183  if (strcmp(RP->decorstyle, "none")) {
184  put_decor(theMap, layout, RP->decorstyle, RP->decoroptions, RP);
185  }
186 
187  /* generate treasures, etc. */
188  apply_auto_fix(theMap);
189 
190  unblock_exits(theMap, layout, RP);
191 
192  /* free the layout unless it was given by caller */
193  if (!use_layout) {
194  for (i = 0; i < RP->Xsize; i++) {
195  free(layout[i]);
196  }
197  free(layout);
198  }
199 
200  theMap->msg = buf;
201 
202  theMap->outdoor = RP->outdoor;
203  if (theMap->outdoor) {
204  set_darkness_map(theMap);
205  } else {
206  change_map_light(theMap, RP->darkness);
207  }
208 
209  /* We set the reset time at this, so town portal works on the map. */
210  theMap->last_reset_time = seconds();
211  return theMap;
212 }
213 
226 char **layoutgen(RMParms *RP)
227 {
228  char **maze = NULL;
229  int oxsize = RP->Xsize, oysize = RP->Ysize;
230 
231  if (RP->symmetry == RANDOM_SYM) {
232  RP->symmetry_used = (RANDOM()%(XY_SYM))+1;
233  } else {
234  RP->symmetry_used = RP->symmetry;
235  }
236 
237  if (RP->symmetry_used == Y_SYM || RP->symmetry_used == XY_SYM) {
238  RP->Ysize = RP->Ysize/2+1;
239  }
240  if (RP->symmetry_used == X_SYM || RP->symmetry_used == XY_SYM) {
241  RP->Xsize = RP->Xsize/2+1;
242  }
243 
244  if (RP->Xsize < MIN_RANDOM_MAP_SIZE) {
245  RP->Xsize = MIN_RANDOM_MAP_SIZE+RANDOM()%5;
246  }
247  if (RP->Ysize < MIN_RANDOM_MAP_SIZE) {
248  RP->Ysize = MIN_RANDOM_MAP_SIZE+RANDOM()%5;
249  }
250  RP->map_layout_style = 0;
251 
252  /* Redo this - there was a lot of redundant code of checking for preset
253  * layout style and then random layout style. Instead, figure out
254  * the numeric layoutstyle, so there is only one area that actually
255  * calls the code to make the maps.
256  */
257  if (strstr(RP->layoutstyle, "onion")) {
259  }
260 
261  if (strstr(RP->layoutstyle, "maze")) {
263  }
264 
265  if (strstr(RP->layoutstyle, "spiral")) {
267  }
268 
269  if (strstr(RP->layoutstyle, "rogue")) {
271  }
272 
273  if (strstr(RP->layoutstyle, "snake")) {
275  }
276 
277  if (strstr(RP->layoutstyle, "squarespiral")) {
279  }
280  /* No style found - choose one ranomdly */
281  if (RP->map_layout_style == 0) {
282  RP->map_layout_style = (RANDOM()%NROFLAYOUTS)+1;
283  }
284 
285  switch (RP->map_layout_style) {
286  case ONION_LAYOUT:
287  maze = map_gen_onion(RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
288  if (!(RANDOM()%3) && !(RP->layoutoptions1&OPT_WALLS_ONLY)) {
289  roomify_layout(maze, RP);
290  }
291  break;
292 
293  case MAZE_LAYOUT:
294  maze = maze_gen(RP->Xsize, RP->Ysize, RANDOM()%2,/* unused: */0);
295  if (!(RANDOM()%2)) {
296  doorify_layout(maze, RP);
297  }
298  break;
299 
300  case SPIRAL_LAYOUT:
301  maze = map_gen_spiral(RP->Xsize, RP->Ysize, RP->layoutoptions1,/* unused: */0);
302  if (!(RANDOM()%2)) {
303  doorify_layout(maze, RP);
304  }
305  break;
306 
307  case ROGUELIKE_LAYOUT:
308  /* Don't put symmetry in rogue maps. There isn't much reason to
309  * do so in the first place (doesn't make it any more interesting),
310  * but more importantly, the symmetry code presumes we are symmetrizing
311  * spirals, or maps with lots of passages - making a symmetric rogue
312  * map fails because its likely that the passages the symmetry process
313  * creates may not connect the rooms.
314  */
315  RP->symmetry_used = NO_SYM;
316  RP->Ysize = oysize;
317  RP->Xsize = oxsize;
318  maze = roguelike_layout_gen(RP->Xsize, RP->Ysize, RP->layoutoptions1, 0/*unused*/);
319  /* no doorifying... done already */
320  break;
321 
322  case SNAKE_LAYOUT:
323  maze = make_snake_layout(RP->Xsize, RP->Ysize,/* unused: */0,0);
324  if (RANDOM()%2) {
325  roomify_layout(maze, RP);
326  }
327  break;
328 
330  maze = make_square_spiral_layout(RP->Xsize, RP->Ysize,/* unused: */0,0);
331  if (RANDOM()%2) {
332  roomify_layout(maze, RP);
333  }
334  break;
335  }
336 
337  maze = symmetrize_layout(maze, RP->symmetry_used, RP);
338 #ifdef RMAP_DEBUG
339  dump_layout(maze, RP);
340 #endif
341  if (RP->expand2x) {
342  maze = expand2x(maze, RP->Xsize, RP->Ysize);
343  RP->Xsize = RP->Xsize*2-1;
344  RP->Ysize = RP->Ysize*2-1;
345  }
346  return maze;
347 }
348 
361 char **symmetrize_layout(char **maze, int sym, RMParms *RP)
362 {
363  int i, j;
364  char **sym_maze;
365  int Xsize_orig, Ysize_orig;
366 
367  Xsize_orig = RP->Xsize;
368  Ysize_orig = RP->Ysize;
369  RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used.*/
370  if (sym == NO_SYM) {
371  RP->Xsize = Xsize_orig;
372  RP->Ysize = Ysize_orig;
373  return maze;
374  }
375  /* pick new sizes */
376  RP->Xsize = ((sym == X_SYM || sym == XY_SYM) ? RP->Xsize*2-3 : RP->Xsize);
377  RP->Ysize = ((sym == Y_SYM || sym == XY_SYM) ? RP->Ysize*2-3 : RP->Ysize);
378 
379  sym_maze = (char **)calloc(sizeof(char *), RP->Xsize);
380  for (i = 0; i < RP->Xsize; i++) {
381  sym_maze[i] = (char *)calloc(sizeof(char), RP->Ysize);
382  }
383 
384  if (sym == X_SYM)
385  for (i = 0; i < RP->Xsize/2+1; i++)
386  for (j = 0; j < RP->Ysize; j++) {
387  sym_maze[i][j] = maze[i][j];
388  sym_maze[RP->Xsize-i-1][j] = maze[i][j];
389  };
390  if (sym == Y_SYM)
391  for (i = 0; i < RP->Xsize; i++)
392  for (j = 0; j < RP->Ysize/2+1; j++) {
393  sym_maze[i][j] = maze[i][j];
394  sym_maze[i][RP->Ysize-j-1] = maze[i][j];
395  }
396  if (sym == XY_SYM)
397  for (i = 0; i < RP->Xsize/2+1; i++)
398  for (j = 0; j < RP->Ysize/2+1; j++) {
399  sym_maze[i][j] = maze[i][j];
400  sym_maze[i][RP->Ysize-j-1] = maze[i][j];
401  sym_maze[RP->Xsize-i-1][j] = maze[i][j];
402  sym_maze[RP->Xsize-i-1][RP->Ysize-j-1] = maze[i][j];
403  }
404 
405  /* delete the old maze */
406  for (i = 0; i < Xsize_orig; i++) {
407  free(maze[i]);
408  }
409  free(maze);
410 
411  /* reconnect disjointed spirals */
412  if (RP->map_layout_style == SPIRAL_LAYOUT) {
413  connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
414  }
415  /* reconnect disjointed nethackmazes: the routine for
416  * spirals will do the trick?
417  */
418  if (RP->map_layout_style == ROGUELIKE_LAYOUT) {
419  connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
420  }
421 
422  return sym_maze;
423 }
424 
442 char **rotate_layout(char **maze, int rotation, RMParms *RP)
443 {
444  char **new_maze;
445  int i, j;
446 
447  switch (rotation) {
448  case 0:
449  return maze;
450 
451  case 2: { /* a reflection */
452  char *rotated = static_cast<char *>(malloc(sizeof(char)*RP->Xsize*RP->Ysize));
453 
454  for (i = 0; i < RP->Xsize; i++) { /* make a copy */
455  for (j = 0; j < RP->Ysize; j++) {
456  rotated[i*RP->Ysize+j] = maze[i][j];
457  }
458  }
459  for (i = 0; i < RP->Xsize; i++) { /* copy a reflection back */
460  for (j = 0; j < RP->Ysize; j++) {
461  maze[i][j] = rotated[(RP->Xsize-i-1)*RP->Ysize+RP->Ysize-j-1];
462  }
463  }
464  free(rotated);
465  return maze;
466  }
467 
468  case 1:
469  case 3: {
470  int swap;
471 
472  new_maze = (char **)calloc(sizeof(char *), RP->Ysize);
473  for (i = 0; i < RP->Ysize; i++) {
474  new_maze[i] = (char *)calloc(sizeof(char), RP->Xsize);
475  }
476  if (rotation == 1) /* swap x and y */
477  for (i = 0; i < RP->Xsize; i++)
478  for (j = 0; j < RP->Ysize; j++) {
479  new_maze[j][i] = maze[i][j];
480  }
481 
482  if (rotation == 3) { /* swap x and y */
483  for (i = 0; i < RP->Xsize; i++)
484  for (j = 0; j < RP->Ysize; j++) {
485  new_maze[j][i] = maze[RP->Xsize-i-1][RP->Ysize-j-1];
486  }
487  }
488 
489  /* delete the old layout */
490  for (i = 0; i < RP->Xsize; i++) {
491  free(maze[i]);
492  }
493  free(maze);
494 
495  swap = RP->Ysize;
496  RP->Ysize = RP->Xsize;
497  RP->Xsize = swap;
498  return new_maze;
499  }
500  }
501  return NULL;
502 }
503 
511 void roomify_layout(char **maze, RMParms *RP)
512 {
513  int tries = RP->Xsize*RP->Ysize/30;
514  int ti;
515 
516  for (ti = 0; ti < tries; ti++) {
517  int dx, dy; /* starting location for looking at creating a door */
518  int cx, cy; /* results of checking on creating walls. */
519 
520  dx = RANDOM()%RP->Xsize;
521  dy = RANDOM()%RP->Ysize;
522  cx = can_make_wall(maze, dx, dy, 0, RP); /* horizontal */
523  cy = can_make_wall(maze, dx, dy, 1, RP); /* vertical */
524  if (cx == -1) {
525  if (cy != -1) {
526  make_wall(maze, dx, dy, 1);
527  }
528  continue;
529  }
530  if (cy == -1) {
531  make_wall(maze, dx, dy, 0);
532  continue;
533  }
534  if (cx < cy) {
535  make_wall(maze, dx, dy, 0);
536  } else {
537  make_wall(maze, dx, dy, 1);
538  }
539  }
540 }
541 
559 int can_make_wall(char **maze, int dx, int dy, int dir, RMParms *RP)
560 {
561  int i1;
562  int length = 0;
563 
564  /* dont make walls if we're on the edge. */
565  if (dx == 0 || dx == (RP->Xsize-1) || dy == 0 || dy == (RP->Ysize-1)) {
566  return -1;
567  }
568 
569  /* don't make walls if we're ON a wall. */
570  if (maze[dx][dy] != 0) {
571  return -1;
572  }
573 
574  if (dir == 0) {
575  /* horizontal */
576  int y = dy;
577 
578  for (i1 = dx-1; i1 > 0; i1--) {
579  int sindex = surround_flag2(maze, i1, y, RP);
580 
581  if (sindex == 1) {
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 
593  for (i1 = dx+1; i1 < RP->Xsize-1; i1++) {
594  int sindex = surround_flag2(maze, i1, y, RP);
595 
596  if (sindex == 2) {
597  break;
598  }
599  if (sindex != 0) {
600  return -1; /* can't make horiz. wall here */
601  }
602  if (maze[i1][y] != 0) {
603  return -1; /* can't make horiz. wall here */
604  }
605  length++;
606  }
607  return length;
608  } else {
609  /* vertical */
610  int x = dx;
611 
612  for (i1 = dy-1; i1 > 0; i1--) {
613  int sindex = surround_flag2(maze, x, i1, RP);
614 
615  if (sindex == 4) {
616  break;
617  }
618  if (sindex != 0) {
619  return -1; /* can't make vert. wall here */
620  }
621  if (maze[x][i1] != 0) {
622  return -1; /* can't make horiz. wall here */
623  }
624  length++;
625  }
626 
627  for (i1 = dy+1; i1 < RP->Ysize-1; i1++) {
628  int sindex = surround_flag2(maze, x, i1, RP);
629 
630  if (sindex == 8) {
631  break;
632  }
633  if (sindex != 0) {
634  return -1; /* can't make verti. wall here */
635  }
636  if (maze[x][i1] != 0) {
637  return -1; /* can't make horiz. wall here */
638  }
639  length++;
640  }
641  return length;
642  }
643 }
644 
659 int make_wall(char **maze, int x, int y, int dir)
660 {
661  maze[x][y] = 'D'; /* mark a door */
662  switch (dir) {
663  case 0: { /* horizontal */
664  int i1;
665 
666  for (i1 = x-1; maze[i1][y] == 0; i1--) {
667  maze[i1][y] = '#';
668  }
669  for (i1 = x+1; maze[i1][y] == 0; i1++) {
670  maze[i1][y] = '#';
671  }
672  break;
673  }
674 
675  case 1: { /* vertical */
676  int i1;
677 
678  for (i1 = y-1; maze[x][i1] == 0; i1--) {
679  maze[x][i1] = '#';
680  }
681  for (i1 = y+1; maze[x][i1] == 0; i1++) {
682  maze[x][i1] = '#';
683  }
684  break;
685  }
686  }
687 
688  return 0;
689 }
690 
698 void doorify_layout(char **maze, RMParms *RP)
699 {
700  int ndoors = RP->Xsize*RP->Ysize/60; /* reasonable number of doors. */
701  int *doorlist_x;
702  int *doorlist_y;
703  int doorlocs = 0; /* # of available doorlocations */
704  int i, j;
705 
706  doorlist_x = static_cast<int *>(malloc(sizeof(int)*RP->Xsize*RP->Ysize));
707  doorlist_y = static_cast<int *>(malloc(sizeof(int)*RP->Xsize*RP->Ysize));
708 
709 
710  /* make a list of possible door locations */
711  for (i = 1; i < RP->Xsize-1; i++)
712  for (j = 1; j < RP->Ysize-1; j++) {
713  int sindex = surround_flag(maze, i, j, RP);
714  if (sindex == 3 || sindex == 12) {
715  /* these are possible door sindex*/
716  doorlist_x[doorlocs] = i;
717  doorlist_y[doorlocs] = j;
718  doorlocs++;
719  }
720  }
721 
722  while (ndoors > 0 && doorlocs > 0) {
723  int di;
724  int sindex;
725 
726  di = RANDOM()%doorlocs;
727  i = doorlist_x[di];
728  j = doorlist_y[di];
729  sindex = surround_flag(maze, i, j, RP);
730  if (sindex == 3 || sindex == 12) { /* these are possible door sindex*/
731  maze[i][j] = 'D';
732  ndoors--;
733  }
734  /* reduce the size of the list */
735  doorlocs--;
736  doorlist_x[di] = doorlist_x[doorlocs];
737  doorlist_y[di] = doorlist_y[doorlocs];
738  }
739  free(doorlist_x);
740  free(doorlist_y);
741 }
742 
751 {
752  StringBuffer *buf;
753 
754  buf = stringbuffer_new();
755  stringbuffer_append_printf(buf, "xsize %d\nysize %d\n", RP->Xsize, RP->Ysize);
756 
757  if (RP->wallstyle[0]) {
758  stringbuffer_append_printf(buf, "wallstyle %s\n", RP->wallstyle);
759  }
760 
761  if (RP->floorstyle[0]) {
762  stringbuffer_append_printf(buf, "floorstyle %s\n", RP->floorstyle);
763  }
764 
765  if (RP->monsterstyle[0]) {
766  stringbuffer_append_printf(buf, "monsterstyle %s\n", RP->monsterstyle);
767  }
768 
769  if (RP->treasurestyle[0]) {
770  stringbuffer_append_printf(buf, "treasurestyle %s\n", RP->treasurestyle);
771  }
772 
773  if (RP->layoutstyle[0]) {
774  stringbuffer_append_printf(buf, "layoutstyle %s\n", RP->layoutstyle);
775  }
776 
777  if (RP->decorstyle[0]) {
778  stringbuffer_append_printf(buf, "decorstyle %s\n", RP->decorstyle);
779  }
780 
781  if (RP->doorstyle[0]) {
782  stringbuffer_append_printf(buf, "doorstyle %s\n", RP->doorstyle);
783  }
784 
785  if (RP->exitstyle[0]) {
786  stringbuffer_append_printf(buf, "exitstyle %s\n", RP->exitstyle);
787  }
788 
789  if (RP->cheststyle[0]) {
790  stringbuffer_append_printf(buf, "cheststyle %s\n", RP->cheststyle);
791  }
792 
793  if (RP->final_map[0]) {
794  stringbuffer_append_printf(buf, "final_map %s\n", RP->final_map);
795  }
796 
797  if (RP->final_exit_archetype[0]) {
798  stringbuffer_append_printf(buf, "final_exit_archetype %s\n", RP->final_exit_archetype);
799  }
800 
801  if (RP->exit_on_final_map[0]) {
802  stringbuffer_append_printf(buf, "exit_on_final_map %s\n", RP->exit_on_final_map);
803  }
804 
805  if (RP->this_map[0]) {
806  stringbuffer_append_printf(buf, "origin_map %s\n", RP->this_map);
807  }
808 
809  if (RP->expand2x) {
810  stringbuffer_append_printf(buf, "expand2x %d\n", RP->expand2x);
811  }
812 
813  if (RP->layoutoptions1) {
814  stringbuffer_append_printf(buf, "layoutoptions1 %d\n", RP->layoutoptions1);
815  }
816 
817  if (RP->layoutoptions2) {
818  stringbuffer_append_printf(buf, "layoutoptions2 %d\n", RP->layoutoptions2);
819  }
820 
821  if (RP->symmetry) {
822  stringbuffer_append_printf(buf, "symmetry %d\n", RP->symmetry);
823  }
824 
825  if (RP->difficulty && RP->difficulty_given) {
826  stringbuffer_append_printf(buf, "difficulty %d\n", RP->difficulty);
827  }
828 
829  if (RP->difficulty_increase != 1.0) {
830  stringbuffer_append_printf(buf, "difficulty_increase %f\n", RP->difficulty_increase);
831  }
832 
833  stringbuffer_append_printf(buf, "dungeon_level %d\n", RP->dungeon_level);
834 
835  if (RP->dungeon_depth) {
836  stringbuffer_append_printf(buf, "dungeon_depth %d\n", RP->dungeon_depth);
837  }
838 
839  if (RP->dungeon_name[0]) {
840  stringbuffer_append_printf(buf, "dungeon_name %s\n", RP->dungeon_name);
841  }
842 
843  if (RP->decoroptions) {
844  stringbuffer_append_printf(buf, "decoroptions %d\n", RP->decoroptions);
845  }
846 
847  if (RP->orientation) {
848  stringbuffer_append_printf(buf, "orientation %d\n", RP->orientation);
849  }
850 
851  if (RP->origin_x) {
852  stringbuffer_append_printf(buf, "origin_x %d\n", RP->origin_x);
853  }
854 
855  if (RP->origin_y) {
856  stringbuffer_append_printf(buf, "origin_y %d\n", RP->origin_y);
857  }
858  if (RP->random_seed) {
859  /* Add one so that the next map is a bit different */
860  stringbuffer_append_printf(buf, "random_seed %d\n", RP->random_seed+1);
861  }
862 
863  if (RP->treasureoptions) {
864  stringbuffer_append_printf(buf, "treasureoptions %d\n", RP->treasureoptions);
865  }
866 
867  if (RP->multiple_floors) {
868  stringbuffer_append_printf(buf, "multiple_floors %d\n", RP->multiple_floors);
869  }
870 
871  if (RP->darkness) {
872  stringbuffer_append_printf(buf, "darkness %d\n", RP->darkness);
873  }
874 
875  if (RP->outdoor) {
876  stringbuffer_append_printf(buf, "outdoor 1\n");
877  }
878 
879  if (RP->link_source_map) {
880  stringbuffer_append_printf(buf, "link_source_map 1\n");
881  }
882 
883  return buf;
884 }
map_gen_onion
char ** map_gen_onion(int xsize, int ysize, int option, int layers)
Generates an onion layout.
Definition: room_gen_onion.cpp:70
generate_random_map
mapstruct * generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout, sstring reset_group)
Main random map routine.
Definition: random_map.cpp:75
RMParms::layoutstyle
char layoutstyle[RM_SIZE]
Contains the layout type to generate, see layoutgen() for valid types.
Definition: random_map.h:41
global.h
mapstruct::region
struct region * region
What jurisdiction in the game world this map is ruled by points to the struct containing all the prop...
Definition: map.h:319
random_map.h
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
roguelike_layout_gen
char ** roguelike_layout_gen(int xsize, int ysize, int options, int _unused_layers)
Actually make the rogue layout.
Definition: rogue_layout.cpp:309
layout
Definition: main.cpp:84
RMParms::orientation
int orientation
Definition: random_map.h:87
RMParms::symmetry
int symmetry
Definition: random_map.h:79
mapstruct::difficulty
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:333
RMParms::difficulty_given
int difficulty_given
If non zero, this means the difficulty was not zero initially.
Definition: random_map.h:82
RMParms::multiple_floors
int multiple_floors
If non zero, then the map will have multiple floors, else only one floor will be used.
Definition: random_map.h:101
MAZE_LAYOUT
#define MAZE_LAYOUT
Definition: random_map.h:114
mapstruct::outdoor
uint32_t outdoor
True if an outdoor map.
Definition: map.h:331
make_wall
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.cpp:659
ONION_LAYOUT
#define ONION_LAYOUT
Definition: random_map.h:113
stringbuffer_append_printf
void stringbuffer_append_printf(StringBuffer *sb, const char *format,...)
Append a formatted string to a string buffer instance.
Definition: stringbuffer.cpp:138
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.cpp:57
RMParms::Ysize
int Ysize
Definition: random_map.h:75
RMParms::dungeon_depth
int dungeon_depth
Definition: random_map.h:85
SRANDOM
#define SRANDOM(seed)
Definition: define.h:639
make_square_spiral_layout
char ** make_square_spiral_layout(int xsize, int ysize, int _unused_options, int _unused_layers)
Generates a square-spiral layout.
Definition: square_spiral.cpp:80
time
non standard information is not specified or uptime this means how long since the executable has been started A particular host may have been running a server for quite a long time
Definition: arch-handbook.txt:206
SPIRAL_LAYOUT
#define SPIRAL_LAYOUT
Definition: random_map.h:115
room_gen.h
can_make_wall
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,...
Definition: random_map.cpp:559
maze_gen
char ** maze_gen(int xsize, int ysize, int option, int _unused_layers)
This function generates a random blocked maze with the property that there is only one path from one ...
Definition: maze_gen.cpp:59
RMParms::origin_y
int origin_y
Definition: random_map.h:88
RMParms::dungeon_level
int dungeon_level
Definition: random_map.h:84
maze_gen.h
OPT_WALLS_ONLY
#define OPT_WALLS_ONLY
Only walls.
Definition: random_map.h:136
roomify_layout
void roomify_layout(char **maze, RMParms *RP)
Take a layout and make some rooms in it.
Definition: random_map.cpp:511
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:355
map_gen_spiral
char ** map_gen_spiral(int xsize, int ysize, int option, int _unused_layers)
Generates a spiral layout.
Definition: room_gen_spiral.cpp:62
surround_flag2
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.cpp:77
buf
StringBuffer * buf
Definition: readable.cpp:1565
RMParms
Random map parameters.
Definition: random_map.h:14
unblock_exits
void unblock_exits(mapstruct *map, char **maze, RMParms *RP)
This function unblocks the exits.
Definition: exit.cpp:401
RMParms::origin_x
int origin_x
Definition: random_map.h:89
set_darkness_map
void set_darkness_map(mapstruct *m)
Set the darkness level for a map, based on the time of the day.
Definition: main.cpp:371
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.cpp:76
apply_auto_fix
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.cpp:258
SQUARE_SPIRAL_LAYOUT
#define SQUARE_SPIRAL_LAYOUT
Definition: random_map.h:118
place_specials_in_map
void place_specials_in_map(mapstruct *map, char **layout, RMParms *RP)
Main function for specials.
Definition: special.cpp:396
write_map_parameters_to_string
StringBuffer * write_map_parameters_to_string(const RMParms *RP)
Creates a suitable message for exit from RP.
Definition: random_map.cpp:750
RMParms::this_map
char this_map[RM_SIZE]
Path of the map from which the random map(s) were created.
Definition: random_map.h:65
RMParms::decorstyle
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
make_map_walls
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 '#' marks.
Definition: wall.cpp:184
RMParms::darkness
int darkness
Map darkness.
Definition: random_map.h:102
RMParms::final_map
char final_map[RM_SIZE]
If not empty, the path of the final map this whole maze leads to.
Definition: random_map.h:57
dump_layout
void dump_layout(char **layout, RMParms *RP)
Dumps specified layout using printf().
Definition: random_map.cpp:43
add_string
sstring add_string(const char *str)
This will add 'str' to the hash table.
Definition: shstr.cpp:124
surround_flag
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.cpp:40
change_map_light
int change_map_light(mapstruct *m, int change)
Used to change map light level (darkness) up or down.
Definition: map.cpp:2024
MIN_RANDOM_MAP_SIZE
#define MIN_RANDOM_MAP_SIZE
Minimal size a random should have to actually be generated.
Definition: random_map.h:154
RMParms::expand2x
int expand2x
Definition: random_map.h:76
doorify_layout
void doorify_layout(char **maze, RMParms *RP)
Puts doors at appropriate locations in a layout.
Definition: random_map.cpp:698
NO_SYM
#define NO_SYM
No symmetry.
Definition: random_map.h:147
expand2x
char ** expand2x(char **layout, int xsize, int ysize)
Expands the layout be a factor 2.
Definition: expand2x.cpp:43
rotate_layout
char ** rotate_layout(char **maze, int rotation, RMParms *RP)
Takes a map and rotates it.
Definition: random_map.cpp:442
mapstruct::reset_group
sstring reset_group
For reset purpose, all maps in the same group reset at the same time.
Definition: map.h:327
rproto.h
RMParms::wallstyle
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
sproto.h
ROGUELIKE_LAYOUT
#define ROGUELIKE_LAYOUT
Definition: random_map.h:116
RMParms::doorstyle
char doorstyle[RM_SIZE]
Name of the doors style file, in /styles/doorstyles, see put_doors().
Definition: random_map.h:43
mapstruct::last_reset_time
long last_reset_time
A timestamp of the last original map loading.
Definition: map.h:356
seconds
long seconds(void)
Return wall clock time in seconds.
Definition: time.cpp:348
X_SYM
#define X_SYM
Vertical symmetry.
Definition: random_map.h:148
RANDOM
#define RANDOM()
Definition: define.h:638
symmetrize_layout
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.cpp:361
StringBuffer
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.cpp:25
RMParms::difficulty
int difficulty
Definition: random_map.h:80
RMParms::final_exit_archetype
char final_exit_archetype[RM_SIZE]
If not empty, the archetype name of the exit leading to the final map.
Definition: random_map.h:59
place_treasure
void place_treasure(mapstruct *map, char **layout, char *treasure_style, int treasureoptions, RMParms *RP)
Place treasures in the map.
Definition: treasure.cpp:92
connect_spirals
void connect_spirals(int xsize, int ysize, int sym, char **layout)
Connects disjoint spirals which may result from the symmetrization process.
Definition: room_gen_spiral.cpp:159
SNAKE_LAYOUT
#define SNAKE_LAYOUT
Definition: random_map.h:117
RMParms::cheststyle
char cheststyle[RM_SIZE]
Name of the chests style file, in /styles/cheststyles, can be an empty string in which case a random ...
Definition: random_map.h:53
RMParms::random_seed
int random_seed
Definition: random_map.h:90
RMParms::outdoor
int outdoor
Whether generated map is outdoor or not.
Definition: random_map.h:103
mapstruct
This is a game-map.
Definition: map.h:315
sstring
const typedef char * sstring
Definition: sstring.h:2
place_exits
void place_exits(mapstruct *map, char **maze, char *exitstyle, int orientation, RMParms *RP)
Place exits in the map.
Definition: exit.cpp:144
put_doors
void put_doors(mapstruct *the_map, char **maze, const char *doorstyle, RMParms *RP)
Add doors to a map.
Definition: door.cpp:73
place_monsters
void place_monsters(mapstruct *map, char *monsterstyle, int difficulty, RMParms *RP)
Place some monsters into the map.
Definition: monster.cpp:38
RMParms::exit_on_final_map
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:70
RMParms::treasurestyle
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
RMParms::treasureoptions
int treasureoptions
Definition: random_map.h:94
RMParms::dungeon_name
char dungeon_name[RM_SIZE]
If not empty, will be used in the name of the random keys.
Definition: random_map.h:72
make_snake_layout
char ** make_snake_layout(int xsize, int ysize, int _unused_options, int _unused_layers)
Generate a snake-like layout.
Definition: snake.cpp:36
make_map_floor
mapstruct * make_map_floor(char **layout, char *floorstyle, RMParms *RP)
Creates the Crossfire mapstruct object from the layout, and adds the floor.
Definition: floor.cpp:75
RMParms::floorstyle
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
mapstruct::msg
char * msg
Message map creator may have left.
Definition: map.h:351
RMParms::map_layout_style
int map_layout_style
Definition: random_map.h:91
put_decor
void put_decor(mapstruct *map, char **maze, char *decorstyle, int decor_option, RMParms *RP)
Put the decor into the map.
Definition: decor.cpp:65
RMParms::monsterstyle
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
calculate_difficulty
int calculate_difficulty(mapstruct *m)
This routine is supposed to find out the difficulty of the map.
Definition: map.cpp:1926
RMParms::layoutoptions1
int layoutoptions1
Definition: random_map.h:77
NROFLAYOUTS
#define NROFLAYOUTS
Definition: random_map.h:119
XY_SYM
#define XY_SYM
Reflection.
Definition: random_map.h:150
RMParms::decoroptions
int decoroptions
Definition: random_map.h:86
RMParms::exitstyle
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:63
RMParms::region
struct region * region
Definition: random_map.h:96
Y_SYM
#define Y_SYM
Horizontal symmetry.
Definition: random_map.h:149
RMParms::Xsize
int Xsize
Definition: random_map.h:74
RMParms::layoutoptions2
int layoutoptions2
Definition: random_map.h:78
RMParms::link_source_map
bool link_source_map
Whether to set the reset group (if not already defined) of the source map for this random map.
Definition: random_map.h:104
RMParms::difficulty_increase
float difficulty_increase
Definition: random_map.h:83
layoutgen
char ** layoutgen(RMParms *RP)
This function builds the actual layout.
Definition: random_map.cpp:226
RANDOM_SYM
#define RANDOM_SYM
Random symmetry.
Definition: random_map.h:146
RMParms::symmetry_used
int symmetry_used
Definition: random_map.h:95