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 
281  if (strstr(RP->layoutstyle, "crawl")) {
283  }
284  /* No style found - choose one ranomdly */
285  if (RP->map_layout_style == 0) {
286  RP->map_layout_style = (RANDOM()%NROFLAYOUTS)+1;
287  }
288 
289  switch (RP->map_layout_style) {
290  case ONION_LAYOUT:
291  maze = map_gen_onion(RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
292  if (!(RANDOM()%3) && !(RP->layoutoptions1&OPT_WALLS_ONLY)) {
293  roomify_layout(maze, RP);
294  }
295  break;
296 
297  case MAZE_LAYOUT:
298  maze = maze_gen(RP->Xsize, RP->Ysize, RANDOM()%2,/* unused: */0);
299  if (!(RANDOM()%2)) {
300  doorify_layout(maze, RP);
301  }
302  break;
303 
304  case SPIRAL_LAYOUT:
305  maze = map_gen_spiral(RP->Xsize, RP->Ysize, RP->layoutoptions1,/* unused: */0);
306  if (!(RANDOM()%2)) {
307  doorify_layout(maze, RP);
308  }
309  break;
310 
311  case ROGUELIKE_LAYOUT:
312  /* Don't put symmetry in rogue maps. There isn't much reason to
313  * do so in the first place (doesn't make it any more interesting),
314  * but more importantly, the symmetry code presumes we are symmetrizing
315  * spirals, or maps with lots of passages - making a symmetric rogue
316  * map fails because its likely that the passages the symmetry process
317  * creates may not connect the rooms.
318  */
319  RP->symmetry_used = NO_SYM;
320  RP->Ysize = oysize;
321  RP->Xsize = oxsize;
322  maze = roguelike_layout_gen(RP->Xsize, RP->Ysize, RP->layoutoptions1, 0/*unused*/);
323  /* no doorifying... done already */
324  break;
325 
326  case SNAKE_LAYOUT:
327  maze = make_snake_layout(RP->Xsize, RP->Ysize,/* unused: */0,0);
328  if (RANDOM()%2) {
329  roomify_layout(maze, RP);
330  }
331  break;
332 
334  maze = make_square_spiral_layout(RP->Xsize, RP->Ysize,/* unused: */0,0);
335  if (RANDOM()%2) {
336  roomify_layout(maze, RP);
337  }
338  break;
339 
340  case CRAWL_LAYOUT:
341  // No symmetry in the crawl layout
342  // Like the rogue layout, it is just not a
343  // good idea to symmetrize.
344  RP->symmetry_used = NO_SYM;
345  // Undo the symmetry resize
346  RP->Ysize = oysize;
347  RP->Xsize = oxsize;
348  maze = map_gen_crawl(RP->Xsize, RP->Ysize, 0, 0);
349  // Only rarely add doors
350  // They tend to un-maze the layout, so don't do it often
351  if (RANDOM()%4 == 0) {
352  doorify_layout(maze, RP);
353  }
354  break;
355  }
356 
357  maze = symmetrize_layout(maze, RP->symmetry_used, RP);
358 #ifdef RMAP_DEBUG
359  dump_layout(maze, RP);
360 #endif
361  if (RP->expand2x) {
362  maze = expand2x(maze, RP->Xsize, RP->Ysize);
363  RP->Xsize = RP->Xsize*2-1;
364  RP->Ysize = RP->Ysize*2-1;
365  }
366  return maze;
367 }
368 
381 char **symmetrize_layout(char **maze, int sym, RMParms *RP)
382 {
383  int i, j;
384  char **sym_maze;
385  int Xsize_orig, Ysize_orig;
386 
387  Xsize_orig = RP->Xsize;
388  Ysize_orig = RP->Ysize;
389  RP->symmetry_used = sym; /* tell everyone else what sort of symmetry is used.*/
390  if (sym == NO_SYM) {
391  RP->Xsize = Xsize_orig;
392  RP->Ysize = Ysize_orig;
393  return maze;
394  }
395  /* pick new sizes */
396  RP->Xsize = ((sym == X_SYM || sym == XY_SYM) ? RP->Xsize*2-3 : RP->Xsize);
397  RP->Ysize = ((sym == Y_SYM || sym == XY_SYM) ? RP->Ysize*2-3 : RP->Ysize);
398 
399  sym_maze = (char **)calloc(sizeof(char *), RP->Xsize);
400  for (i = 0; i < RP->Xsize; i++) {
401  sym_maze[i] = (char *)calloc(sizeof(char), RP->Ysize);
402  }
403 
404  if (sym == X_SYM)
405  for (i = 0; i < RP->Xsize/2+1; i++)
406  for (j = 0; j < RP->Ysize; j++) {
407  sym_maze[i][j] = maze[i][j];
408  sym_maze[RP->Xsize-i-1][j] = maze[i][j];
409  };
410  if (sym == Y_SYM)
411  for (i = 0; i < RP->Xsize; i++)
412  for (j = 0; j < RP->Ysize/2+1; j++) {
413  sym_maze[i][j] = maze[i][j];
414  sym_maze[i][RP->Ysize-j-1] = maze[i][j];
415  }
416  if (sym == XY_SYM)
417  for (i = 0; i < RP->Xsize/2+1; i++)
418  for (j = 0; j < RP->Ysize/2+1; j++) {
419  sym_maze[i][j] = maze[i][j];
420  sym_maze[i][RP->Ysize-j-1] = maze[i][j];
421  sym_maze[RP->Xsize-i-1][j] = maze[i][j];
422  sym_maze[RP->Xsize-i-1][RP->Ysize-j-1] = maze[i][j];
423  }
424 
425  /* delete the old maze */
426  for (i = 0; i < Xsize_orig; i++) {
427  free(maze[i]);
428  }
429  free(maze);
430 
431  /* reconnect disjointed spirals */
432  if (RP->map_layout_style == SPIRAL_LAYOUT) {
433  connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
434  }
435  /* reconnect disjointed nethackmazes: the routine for
436  * spirals will do the trick?
437  */
438  if (RP->map_layout_style == ROGUELIKE_LAYOUT) {
439  connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
440  }
441 
442  return sym_maze;
443 }
444 
462 char **rotate_layout(char **maze, int rotation, RMParms *RP)
463 {
464  char **new_maze;
465  int i, j;
466 
467  switch (rotation) {
468  case 0:
469  return maze;
470 
471  case 2: { /* a reflection */
472  char *rotated = static_cast<char *>(malloc(sizeof(char)*RP->Xsize*RP->Ysize));
473 
474  for (i = 0; i < RP->Xsize; i++) { /* make a copy */
475  for (j = 0; j < RP->Ysize; j++) {
476  rotated[i*RP->Ysize+j] = maze[i][j];
477  }
478  }
479  for (i = 0; i < RP->Xsize; i++) { /* copy a reflection back */
480  for (j = 0; j < RP->Ysize; j++) {
481  maze[i][j] = rotated[(RP->Xsize-i-1)*RP->Ysize+RP->Ysize-j-1];
482  }
483  }
484  free(rotated);
485  return maze;
486  }
487 
488  case 1:
489  case 3: {
490  int swap;
491 
492  new_maze = (char **)calloc(sizeof(char *), RP->Ysize);
493  for (i = 0; i < RP->Ysize; i++) {
494  new_maze[i] = (char *)calloc(sizeof(char), RP->Xsize);
495  }
496  if (rotation == 1) /* swap x and y */
497  for (i = 0; i < RP->Xsize; i++)
498  for (j = 0; j < RP->Ysize; j++) {
499  new_maze[j][i] = maze[i][j];
500  }
501 
502  if (rotation == 3) { /* swap x and y */
503  for (i = 0; i < RP->Xsize; i++)
504  for (j = 0; j < RP->Ysize; j++) {
505  new_maze[j][i] = maze[RP->Xsize-i-1][RP->Ysize-j-1];
506  }
507  }
508 
509  /* delete the old layout */
510  for (i = 0; i < RP->Xsize; i++) {
511  free(maze[i]);
512  }
513  free(maze);
514 
515  swap = RP->Ysize;
516  RP->Ysize = RP->Xsize;
517  RP->Xsize = swap;
518  return new_maze;
519  }
520  }
521  return NULL;
522 }
523 
531 void roomify_layout(char **maze, RMParms *RP)
532 {
533  int tries = RP->Xsize*RP->Ysize/30;
534  int ti;
535 
536  for (ti = 0; ti < tries; ti++) {
537  int dx, dy; /* starting location for looking at creating a door */
538  int cx, cy; /* results of checking on creating walls. */
539 
540  dx = RANDOM()%RP->Xsize;
541  dy = RANDOM()%RP->Ysize;
542  cx = can_make_wall(maze, dx, dy, 0, RP); /* horizontal */
543  cy = can_make_wall(maze, dx, dy, 1, RP); /* vertical */
544  if (cx == -1) {
545  if (cy != -1) {
546  make_wall(maze, dx, dy, 1);
547  }
548  continue;
549  }
550  if (cy == -1) {
551  make_wall(maze, dx, dy, 0);
552  continue;
553  }
554  if (cx < cy) {
555  make_wall(maze, dx, dy, 0);
556  } else {
557  make_wall(maze, dx, dy, 1);
558  }
559  }
560 }
561 
579 int can_make_wall(char **maze, int dx, int dy, int dir, RMParms *RP)
580 {
581  int i1;
582  int length = 0;
583 
584  /* dont make walls if we're on the edge. */
585  if (dx == 0 || dx == (RP->Xsize-1) || dy == 0 || dy == (RP->Ysize-1)) {
586  return -1;
587  }
588 
589  /* don't make walls if we're ON a wall. */
590  if (maze[dx][dy] != 0) {
591  return -1;
592  }
593 
594  if (dir == 0) {
595  /* horizontal */
596  int y = dy;
597 
598  for (i1 = dx-1; i1 > 0; i1--) {
599  int sindex = surround_flag2(maze, i1, y, RP);
600 
601  if (sindex == 1) {
602  break;
603  }
604  if (sindex != 0) {
605  return -1; /* can't make horiz. wall here */
606  }
607  if (maze[i1][y] != 0) {
608  return -1; /* can't make horiz. wall here */
609  }
610  length++;
611  }
612 
613  for (i1 = dx+1; i1 < RP->Xsize-1; i1++) {
614  int sindex = surround_flag2(maze, i1, y, RP);
615 
616  if (sindex == 2) {
617  break;
618  }
619  if (sindex != 0) {
620  return -1; /* can't make horiz. wall here */
621  }
622  if (maze[i1][y] != 0) {
623  return -1; /* can't make horiz. wall here */
624  }
625  length++;
626  }
627  return length;
628  } else {
629  /* vertical */
630  int x = dx;
631 
632  for (i1 = dy-1; i1 > 0; i1--) {
633  int sindex = surround_flag2(maze, x, i1, RP);
634 
635  if (sindex == 4) {
636  break;
637  }
638  if (sindex != 0) {
639  return -1; /* can't make vert. wall here */
640  }
641  if (maze[x][i1] != 0) {
642  return -1; /* can't make horiz. wall here */
643  }
644  length++;
645  }
646 
647  for (i1 = dy+1; i1 < RP->Ysize-1; i1++) {
648  int sindex = surround_flag2(maze, x, i1, RP);
649 
650  if (sindex == 8) {
651  break;
652  }
653  if (sindex != 0) {
654  return -1; /* can't make verti. wall here */
655  }
656  if (maze[x][i1] != 0) {
657  return -1; /* can't make horiz. wall here */
658  }
659  length++;
660  }
661  return length;
662  }
663 }
664 
679 int make_wall(char **maze, int x, int y, int dir)
680 {
681  maze[x][y] = 'D'; /* mark a door */
682  switch (dir) {
683  case 0: { /* horizontal */
684  int i1;
685 
686  for (i1 = x-1; maze[i1][y] == 0; i1--) {
687  maze[i1][y] = '#';
688  }
689  for (i1 = x+1; maze[i1][y] == 0; i1++) {
690  maze[i1][y] = '#';
691  }
692  break;
693  }
694 
695  case 1: { /* vertical */
696  int i1;
697 
698  for (i1 = y-1; maze[x][i1] == 0; i1--) {
699  maze[x][i1] = '#';
700  }
701  for (i1 = y+1; maze[x][i1] == 0; i1++) {
702  maze[x][i1] = '#';
703  }
704  break;
705  }
706  }
707 
708  return 0;
709 }
710 
718 void doorify_layout(char **maze, RMParms *RP)
719 {
720  int ndoors = RP->Xsize*RP->Ysize/60; /* reasonable number of doors. */
721  int *doorlist_x;
722  int *doorlist_y;
723  int doorlocs = 0; /* # of available doorlocations */
724  int i, j;
725 
726  doorlist_x = static_cast<int *>(malloc(sizeof(int)*RP->Xsize*RP->Ysize));
727  doorlist_y = static_cast<int *>(malloc(sizeof(int)*RP->Xsize*RP->Ysize));
728 
729 
730  /* make a list of possible door locations */
731  for (i = 1; i < RP->Xsize-1; i++)
732  for (j = 1; j < RP->Ysize-1; j++) {
733  int sindex = surround_flag(maze, i, j, RP);
734  if (sindex == 3 || sindex == 12) {
735  /* these are possible door sindex*/
736  doorlist_x[doorlocs] = i;
737  doorlist_y[doorlocs] = j;
738  doorlocs++;
739  }
740  }
741 
742  while (ndoors > 0 && doorlocs > 0) {
743  int di;
744  int sindex;
745 
746  di = RANDOM()%doorlocs;
747  i = doorlist_x[di];
748  j = doorlist_y[di];
749  sindex = surround_flag(maze, i, j, RP);
750  if (sindex == 3 || sindex == 12) { /* these are possible door sindex*/
751  maze[i][j] = 'D';
752  ndoors--;
753  }
754  /* reduce the size of the list */
755  doorlocs--;
756  doorlist_x[di] = doorlist_x[doorlocs];
757  doorlist_y[di] = doorlist_y[doorlocs];
758  }
759  free(doorlist_x);
760  free(doorlist_y);
761 }
762 
771 {
772  StringBuffer *buf;
773 
774  buf = stringbuffer_new();
775  stringbuffer_append_printf(buf, "xsize %d\nysize %d\n", RP->Xsize, RP->Ysize);
776 
777  if (RP->wallstyle[0]) {
778  stringbuffer_append_printf(buf, "wallstyle %s\n", RP->wallstyle);
779  }
780 
781  if (RP->floorstyle[0]) {
782  stringbuffer_append_printf(buf, "floorstyle %s\n", RP->floorstyle);
783  }
784 
785  if (RP->monsterstyle[0]) {
786  stringbuffer_append_printf(buf, "monsterstyle %s\n", RP->monsterstyle);
787  }
788 
789  if (RP->treasurestyle[0]) {
790  stringbuffer_append_printf(buf, "treasurestyle %s\n", RP->treasurestyle);
791  }
792 
793  if (RP->layoutstyle[0]) {
794  stringbuffer_append_printf(buf, "layoutstyle %s\n", RP->layoutstyle);
795  }
796 
797  if (RP->decorstyle[0]) {
798  stringbuffer_append_printf(buf, "decorstyle %s\n", RP->decorstyle);
799  }
800 
801  if (RP->doorstyle[0]) {
802  stringbuffer_append_printf(buf, "doorstyle %s\n", RP->doorstyle);
803  }
804 
805  if (RP->exitstyle[0]) {
806  stringbuffer_append_printf(buf, "exitstyle %s\n", RP->exitstyle);
807  }
808 
809  if (RP->cheststyle[0]) {
810  stringbuffer_append_printf(buf, "cheststyle %s\n", RP->cheststyle);
811  }
812 
813  if (RP->final_map[0]) {
814  stringbuffer_append_printf(buf, "final_map %s\n", RP->final_map);
815  }
816 
817  if (RP->final_exit_archetype[0]) {
818  stringbuffer_append_printf(buf, "final_exit_archetype %s\n", RP->final_exit_archetype);
819  }
820 
821  if (RP->exit_on_final_map[0]) {
822  stringbuffer_append_printf(buf, "exit_on_final_map %s\n", RP->exit_on_final_map);
823  }
824 
825  if (RP->this_map[0]) {
826  stringbuffer_append_printf(buf, "origin_map %s\n", RP->this_map);
827  }
828 
829  if (RP->expand2x) {
830  stringbuffer_append_printf(buf, "expand2x %d\n", RP->expand2x);
831  }
832 
833  if (RP->layoutoptions1) {
834  stringbuffer_append_printf(buf, "layoutoptions1 %d\n", RP->layoutoptions1);
835  }
836 
837  if (RP->layoutoptions2) {
838  stringbuffer_append_printf(buf, "layoutoptions2 %d\n", RP->layoutoptions2);
839  }
840 
841  if (RP->symmetry) {
842  stringbuffer_append_printf(buf, "symmetry %d\n", RP->symmetry);
843  }
844 
845  if (RP->difficulty && RP->difficulty_given) {
846  stringbuffer_append_printf(buf, "difficulty %d\n", RP->difficulty);
847  }
848 
849  if (RP->difficulty_increase != 1.0) {
850  stringbuffer_append_printf(buf, "difficulty_increase %f\n", RP->difficulty_increase);
851  }
852 
853  stringbuffer_append_printf(buf, "dungeon_level %d\n", RP->dungeon_level);
854 
855  if (RP->dungeon_depth) {
856  stringbuffer_append_printf(buf, "dungeon_depth %d\n", RP->dungeon_depth);
857  }
858 
859  if (RP->dungeon_name[0]) {
860  stringbuffer_append_printf(buf, "dungeon_name %s\n", RP->dungeon_name);
861  }
862 
863  if (RP->decoroptions) {
864  stringbuffer_append_printf(buf, "decoroptions %d\n", RP->decoroptions);
865  }
866 
867  if (RP->orientation) {
868  stringbuffer_append_printf(buf, "orientation %d\n", RP->orientation);
869  }
870 
871  if (RP->origin_x) {
872  stringbuffer_append_printf(buf, "origin_x %d\n", RP->origin_x);
873  }
874 
875  if (RP->origin_y) {
876  stringbuffer_append_printf(buf, "origin_y %d\n", RP->origin_y);
877  }
878  if (RP->random_seed) {
879  /* Add one so that the next map is a bit different */
880  stringbuffer_append_printf(buf, "random_seed %d\n", RP->random_seed+1);
881  }
882 
883  if (RP->treasureoptions) {
884  stringbuffer_append_printf(buf, "treasureoptions %d\n", RP->treasureoptions);
885  }
886 
887  if (RP->multiple_floors) {
888  stringbuffer_append_printf(buf, "multiple_floors %d\n", RP->multiple_floors);
889  }
890 
891  if (RP->darkness) {
892  stringbuffer_append_printf(buf, "darkness %d\n", RP->darkness);
893  }
894 
895  if (RP->outdoor) {
896  stringbuffer_append_printf(buf, "outdoor 1\n");
897  }
898 
899  if (RP->link_source_map) {
900  stringbuffer_append_printf(buf, "link_source_map 1\n");
901  }
902 
903  return buf;
904 }
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:324
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:338
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:336
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:679
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:629
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:579
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:137
roomify_layout
void roomify_layout(char **maze, RMParms *RP)
Take a layout and make some rooms in it.
Definition: random_map.cpp:531
mapstruct::path
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:361
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:1564
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:373
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:260
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:770
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)
Share a string.
Definition: shstr.cpp:137
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:2032
MIN_RANDOM_MAP_SIZE
#define MIN_RANDOM_MAP_SIZE
Minimal size a random should have to actually be generated.
Definition: random_map.h:155
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:718
NO_SYM
#define NO_SYM
No symmetry.
Definition: random_map.h:148
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:462
mapstruct::reset_group
sstring reset_group
For reset purpose, all maps in the same group reset at the same time.
Definition: map.h:332
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
map_gen_crawl
char ** map_gen_crawl(int xsize, int ysize, int iter, int hallway)
Generator of the crawl maze.
Definition: room_gen_crawl.cpp:139
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:362
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:149
RANDOM
#define RANDOM()
Definition: define.h:628
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:381
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:320
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:357
CRAWL_LAYOUT
#define CRAWL_LAYOUT
Definition: random_map.h:119
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:1934
RMParms::layoutoptions1
int layoutoptions1
Definition: random_map.h:77
NROFLAYOUTS
#define NROFLAYOUTS
Definition: random_map.h:120
XY_SYM
#define XY_SYM
Reflection.
Definition: random_map.h:151
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:150
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:147
RMParms::symmetry_used
int symmetry_used
Definition: random_map.h:95