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:92
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:337
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:335
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
time
same as sound ncom command like but with extra the client want tick commands so it knows animation timing the client wants to be informed of pickup mode changes Mode will be sent when the player successfully logs and afterward any time the value is but over time
Definition: protocol.txt:416
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
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:360
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:379
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:266
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:2015
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:145
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:361
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:356
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:1917
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