Crossfire Server, Branch 1.12  R12190
random_map.c
Go to the documentation of this file.
00001 /*
00002  * static char *rcsid_random_map_c =
00003  *   "$Id: random_map.c 11578 2009-02-23 22:02:27Z lalo $";
00004  */
00005 
00006 /*
00007     CrossFire, A Multiplayer game for X-windows
00008 
00009     Copyright (C) 2001 Mark Wedel & Crossfire Development Team
00010     Copyright (C) 1992 Frank Tore Johansen
00011 
00012     This program is free software; you can redistribute it and/or modify
00013     it under the terms of the GNU General Public License as published by
00014     the Free Software Foundation; either version 2 of the License, or
00015     (at your option) any later version.
00016 
00017     This program is distributed in the hope that it will be useful,
00018     but WITHOUT ANY WARRANTY; without even the implied warranty of
00019     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020     GNU General Public License for more details.
00021 
00022     You should have received a copy of the GNU General Public License
00023     along with this program; if not, write to the Free Software
00024     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00025 
00026     The authors can be reached via e-mail at crossfire-devel@real-time.com
00027 */
00028 
00036 #include <stdlib.h>
00037 #include <time.h>
00038 #include <stdio.h>
00039 #include <global.h>
00040 #include <maze_gen.h>
00041 #include <room_gen.h>
00042 #include <random_map.h>
00043 #include <rproto.h>
00044 #include <sproto.h>
00045 
00053 void dump_layout(char **layout, RMParms *RP) {
00054     int i, j;
00055 
00056     for (i = 0; i < RP->Xsize; i++) {
00057         for (j = 0; j < RP->Ysize; j++) {
00058             if (layout[i][j] == 0)
00059                 layout[i][j] = ' ';
00060             printf("%c", layout[i][j]);
00061             if (layout[i][j] == ' ')
00062                 layout[i][j] = 0;
00063         }
00064         printf("\n");
00065     }
00066     printf("\n");
00067 }
00068 
00080 mapstruct *generate_random_map(const char *OutFileName, RMParms *RP, char **use_layout) {
00081     char **layout, buf[HUGE_BUF];
00082     mapstruct *theMap;
00083     int i;
00084 
00085     /* pick a random seed, or use the one from the input file */
00086     if (RP->random_seed == 0)
00087         RP->random_seed = time(NULL);
00088 
00089     SRANDOM(RP->random_seed);
00090 
00091     write_map_parameters_to_string(RP, buf, sizeof(buf));
00092 
00093     if (RP->difficulty == 0) {
00094         RP->difficulty = RP->dungeon_level; /* use this instead of a map difficulty  */
00095         if (RP->difficulty_increase > 0.001) {
00096             RP->difficulty = (int)((float)RP->dungeon_level*RP->difficulty_increase);
00097             if (RP->difficulty < 1)
00098                 RP->difficulty = 1;
00099         }
00100     } else
00101         RP->difficulty_given = 1;
00102 
00103     if (!use_layout) {
00104         if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
00105             RP->Xsize = MIN_RANDOM_MAP_SIZE+RANDOM()%25+5;
00106         if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
00107             RP->Ysize = MIN_RANDOM_MAP_SIZE+RANDOM()%25+5;
00108 
00109         if (RP->expand2x > 0) {
00110             RP->Xsize /= 2;
00111             RP->Ysize /= 2;
00112         }
00113 
00114         layout = layoutgen(RP);
00115 
00116 #ifdef RMAP_DEBUG
00117         dump_layout(layout, RP);
00118 #endif
00119 
00120         /*  rotate the layout randomly */
00121         layout = rotate_layout(layout, RANDOM()%4, RP);
00122 #ifdef RMAP_DEBUG
00123         dump_layout(layout, RP);
00124 #endif
00125     } else
00126         layout = use_layout;
00127 
00128     /* increment these for the current map */
00129     RP->dungeon_level += 1;
00130 
00131     /* allocate the map and set the floor */
00132     theMap = make_map_floor(layout, RP->floorstyle, RP);
00133 
00134     /* set the name of the map. */
00135     strncpy(theMap->path, OutFileName, sizeof(theMap->path));
00136 
00137     /* set region */
00138     theMap->region = RP->region;
00139 
00140     /* create walls unless the wallstyle is "none" */
00141     if (strcmp(RP->wallstyle, "none")) {
00142         make_map_walls(theMap, layout, RP->wallstyle, RP);
00143 
00144         /* place doors unless doorstyle or wallstyle is "none"*/
00145         if (strcmp(RP->doorstyle, "none"))
00146             put_doors(theMap, layout, RP->doorstyle, RP);
00147 
00148     }
00149 
00150     /* create exits unless the exitstyle is "none" */
00151     if (strcmp(RP->exitstyle, "none"))
00152         place_exits(theMap, layout, RP->exitstyle, RP->orientation, RP);
00153 
00154     place_specials_in_map(theMap, layout, RP);
00155 
00156     /* create monsters unless the monsterstyle is "none" */
00157     if (strcmp(RP->monsterstyle, "none"))
00158         place_monsters(theMap, RP->monsterstyle, RP->difficulty, RP);
00159 
00160     /* treasures needs to have a proper difficulty set for the map. */
00161     theMap->difficulty = calculate_difficulty(theMap);
00162 
00163     /* create treasure unless the treasurestyle is "none" */
00164     if (strcmp(RP->treasurestyle, "none"))
00165         place_treasure(theMap, layout, RP->treasurestyle, RP->treasureoptions, RP);
00166 
00167     /* create decor unless the decorstyle is "none" */
00168     if (strcmp(RP->decorstyle, "none"))
00169         put_decor(theMap, layout, RP->decorstyle, RP->decoroptions, RP);
00170 
00171     /* generate treasures, etc. */
00172     fix_auto_apply(theMap);
00173 
00174     unblock_exits(theMap, layout, RP);
00175 
00176     /* free the layout unless it was given by caller */
00177     if (!use_layout) {
00178         for (i = 0; i < RP->Xsize; i++)
00179             free(layout[i]);
00180         free(layout);
00181     }
00182 
00183     theMap->msg = strdup_local(buf);
00184 
00185     /* We set the reset time at this, so town portal works on the map. */
00186     gettimeofday(&(theMap->last_reset_time), NULL);
00187 
00188     return theMap;
00189 }
00190 
00203 char **layoutgen(RMParms *RP) {
00204     char **maze = NULL;
00205     int oxsize = RP->Xsize, oysize = RP->Ysize;
00206 
00207     if (RP->symmetry == RANDOM_SYM)
00208         RP->symmetry_used = (RANDOM()%(XY_SYM))+1;
00209     else
00210         RP->symmetry_used = RP->symmetry;
00211 
00212     if (RP->symmetry_used == Y_SYM || RP->symmetry_used == XY_SYM)
00213         RP->Ysize = RP->Ysize/2+1;
00214     if (RP->symmetry_used == X_SYM || RP->symmetry_used == XY_SYM)
00215         RP->Xsize = RP->Xsize/2+1;
00216 
00217     if (RP->Xsize < MIN_RANDOM_MAP_SIZE)
00218         RP->Xsize = MIN_RANDOM_MAP_SIZE+RANDOM()%5;
00219     if (RP->Ysize < MIN_RANDOM_MAP_SIZE)
00220         RP->Ysize = MIN_RANDOM_MAP_SIZE+RANDOM()%5;
00221     RP->map_layout_style = 0;
00222 
00223     /* Redo this - there was a lot of redundant code of checking for preset
00224      * layout style and then random layout style.  Instead, figure out
00225      * the numeric layoutstyle, so there is only one area that actually
00226      * calls the code to make the maps.
00227      */
00228     if (strstr(RP->layoutstyle, "onion")) {
00229         RP->map_layout_style = ONION_LAYOUT;
00230     }
00231 
00232     if (strstr(RP->layoutstyle, "maze")) {
00233         RP->map_layout_style = MAZE_LAYOUT;
00234     }
00235 
00236     if (strstr(RP->layoutstyle, "spiral")) {
00237         RP->map_layout_style = SPIRAL_LAYOUT;
00238     }
00239 
00240     if (strstr(RP->layoutstyle, "rogue")) {
00241         RP->map_layout_style = ROGUELIKE_LAYOUT;
00242     }
00243 
00244     if (strstr(RP->layoutstyle, "snake")) {
00245         RP->map_layout_style = SNAKE_LAYOUT;
00246     }
00247 
00248     if (strstr(RP->layoutstyle, "squarespiral")) {
00249         RP->map_layout_style = SQUARE_SPIRAL_LAYOUT;
00250     }
00251     /* No style found - choose one ranomdly */
00252     if (RP->map_layout_style == 0) {
00253         RP->map_layout_style = (RANDOM()%NROFLAYOUTS)+1;
00254     }
00255 
00256     switch (RP->map_layout_style) {
00257     case ONION_LAYOUT:
00258         maze = map_gen_onion(RP->Xsize, RP->Ysize, RP->layoutoptions1, RP->layoutoptions2);
00259         if (!(RANDOM()%3)&& !(RP->layoutoptions1&OPT_WALLS_ONLY))
00260             roomify_layout(maze, RP);
00261         break;
00262 
00263     case MAZE_LAYOUT:
00264         maze = maze_gen(RP->Xsize, RP->Ysize, RANDOM()%2);
00265         if (!(RANDOM()%2))
00266             doorify_layout(maze, RP);
00267         break;
00268 
00269     case SPIRAL_LAYOUT:
00270         maze = map_gen_spiral(RP->Xsize, RP->Ysize, RP->layoutoptions1);
00271         if (!(RANDOM()%2))
00272             doorify_layout(maze, RP);
00273         break;
00274 
00275     case ROGUELIKE_LAYOUT:
00276         /* Don't put symmetry in rogue maps.  There isn't much reason to
00277          * do so in the first place (doesn't make it any more interesting),
00278          * but more importantly, the symmetry code presumes we are symmetrizing
00279          * spirals, or maps with lots of passages - making a symmetric rogue
00280          * map fails because its likely that the passages the symmetry process
00281          * creates may not connect the rooms.
00282          */
00283         RP->symmetry_used = NO_SYM;
00284         RP->Ysize = oysize;
00285         RP->Xsize = oxsize;
00286         maze = roguelike_layout_gen(RP->Xsize, RP->Ysize, RP->layoutoptions1);
00287         /* no doorifying...  done already */
00288         break;
00289 
00290     case SNAKE_LAYOUT:
00291         maze = make_snake_layout(RP->Xsize, RP->Ysize);
00292         if (RANDOM()%2)
00293             roomify_layout(maze, RP);
00294         break;
00295 
00296     case SQUARE_SPIRAL_LAYOUT:
00297         maze = make_square_spiral_layout(RP->Xsize, RP->Ysize);
00298         if (RANDOM()%2)
00299             roomify_layout(maze, RP);
00300         break;
00301     }
00302 
00303     maze = symmetrize_layout(maze, RP->symmetry_used, RP);
00304 #ifdef RMAP_DEBUG
00305     dump_layout(maze, RP);
00306 #endif
00307     if (RP->expand2x) {
00308         maze = expand2x(maze, RP->Xsize, RP->Ysize);
00309         RP->Xsize = RP->Xsize*2-1;
00310         RP->Ysize = RP->Ysize*2-1;
00311     }
00312     return maze;
00313 }
00314 
00327 char **symmetrize_layout(char **maze, int sym, RMParms *RP) {
00328     int i, j;
00329     char **sym_maze;
00330     int Xsize_orig, Ysize_orig;
00331 
00332     Xsize_orig = RP->Xsize;
00333     Ysize_orig = RP->Ysize;
00334     RP->symmetry_used = sym;  /* tell everyone else what sort of symmetry is used.*/
00335     if (sym == NO_SYM) {
00336         RP->Xsize = Xsize_orig;
00337         RP->Ysize = Ysize_orig;
00338         return maze;
00339     }
00340     /* pick new sizes */
00341     RP->Xsize = ((sym == X_SYM || sym == XY_SYM) ? RP->Xsize*2-3 : RP->Xsize);
00342     RP->Ysize = ((sym == Y_SYM || sym == XY_SYM) ? RP->Ysize*2-3 : RP->Ysize);
00343 
00344     sym_maze = (char **)calloc(sizeof(char *), RP->Xsize);
00345     for (i = 0; i < RP->Xsize; i++)
00346         sym_maze[i] = (char *)calloc(sizeof(char), RP->Ysize);
00347 
00348     if (sym == X_SYM)
00349         for (i = 0; i < RP->Xsize/2+1; i++)
00350             for (j = 0; j < RP->Ysize; j++) {
00351                 sym_maze[i][j] = maze[i][j];
00352                 sym_maze[RP->Xsize-i-1][j] = maze[i][j];
00353             };
00354     if (sym == Y_SYM)
00355         for (i = 0; i < RP->Xsize; i++)
00356             for (j = 0; j < RP->Ysize/2+1; j++) {
00357                 sym_maze[i][j] = maze[i][j];
00358                 sym_maze[i][RP->Ysize-j-1] = maze[i][j];
00359             }
00360     if (sym == XY_SYM)
00361         for (i = 0; i < RP->Xsize/2+1; i++)
00362             for (j = 0; j < RP->Ysize/2+1; j++) {
00363                 sym_maze[i][j] = maze[i][j];
00364                 sym_maze[i][RP->Ysize-j-1] = maze[i][j];
00365                 sym_maze[RP->Xsize-i-1][j] = maze[i][j];
00366                 sym_maze[RP->Xsize-i-1][RP->Ysize-j-1] = maze[i][j];
00367             }
00368 
00369     /* delete the old maze */
00370     for (i = 0; i < Xsize_orig; i++)
00371         free(maze[i]);
00372     free(maze);
00373 
00374     /* reconnect disjointed spirals */
00375     if (RP->map_layout_style == SPIRAL_LAYOUT)
00376         connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
00377     /* reconnect disjointed nethackmazes:  the routine for
00378      * spirals will do the trick?
00379      */
00380     if (RP->map_layout_style == ROGUELIKE_LAYOUT)
00381         connect_spirals(RP->Xsize, RP->Ysize, sym, sym_maze);
00382 
00383     return sym_maze;
00384 }
00385 
00403 char **rotate_layout(char **maze, int rotation, RMParms *RP) {
00404     char **new_maze;
00405     int i, j;
00406 
00407     switch (rotation) {
00408     case 0:
00409         return maze;
00410         break;
00411 
00412     case 2: { /* a reflection */
00413             char *new = malloc(sizeof(char)*RP->Xsize*RP->Ysize);
00414 
00415             for (i = 0; i < RP->Xsize; i++) { /* make a copy */
00416                 for (j = 0; j < RP->Ysize; j++) {
00417                     new[i*RP->Ysize+j] = maze[i][j];
00418             }
00419             }
00420             for (i = 0; i < RP->Xsize; i++) { /* copy a reflection back */
00421                 for (j = 0; j < RP->Ysize; j++) {
00422                     maze[i][j] = new[(RP->Xsize-i-1)*RP->Ysize+RP->Ysize-j-1];
00423                 }
00424             }
00425             free(new);
00426             return maze;
00427             break;
00428         }
00429 
00430     case 1:
00431     case 3: {
00432             int swap;
00433 
00434             new_maze = (char **)calloc(sizeof(char *), RP->Ysize);
00435             for (i = 0; i < RP->Ysize; i++) {
00436                 new_maze[i] = (char *)calloc(sizeof(char), RP->Xsize);
00437             }
00438             if (rotation == 1) /* swap x and y */
00439                 for (i = 0; i < RP->Xsize; i++)
00440                     for (j = 0; j < RP->Ysize; j++)
00441                         new_maze[j][i] = maze[i][j];
00442 
00443             if (rotation == 3) { /* swap x and y */
00444                 for (i = 0; i < RP->Xsize; i++)
00445                     for (j = 0; j < RP->Ysize; j++)
00446                         new_maze[j][i] = maze[RP->Xsize-i-1][RP->Ysize-j-1];
00447             }
00448 
00449             /* delete the old layout */
00450             for (i = 0; i < RP->Xsize; i++)
00451                 free(maze[i]);
00452             free(maze);
00453 
00454             swap = RP->Ysize;
00455             RP->Ysize = RP->Xsize;
00456             RP->Xsize = swap;
00457             return new_maze;
00458             break;
00459         }
00460     }
00461     return NULL;
00462 }
00463 
00471 void roomify_layout(char **maze, RMParms *RP) {
00472     int tries = RP->Xsize*RP->Ysize/30;
00473     int ti;
00474 
00475     for (ti = 0; ti < tries; ti++) {
00476         int dx, dy;  /* starting location for looking at creating a door */
00477         int cx, cy;  /* results of checking on creating walls. */
00478 
00479         dx = RANDOM()%RP->Xsize;
00480         dy = RANDOM()%RP->Ysize;
00481         cx = can_make_wall(maze, dx, dy, 0, RP);  /* horizontal */
00482         cy = can_make_wall(maze, dx, dy, 1, RP);  /* vertical */
00483         if (cx == -1) {
00484             if (cy != -1)
00485                 make_wall(maze, dx, dy, 1);
00486             continue;
00487         }
00488         if (cy == -1) {
00489             make_wall(maze, dx, dy, 0);
00490             continue;
00491         }
00492         if (cx < cy)
00493             make_wall(maze, dx, dy, 0);
00494         else
00495             make_wall(maze, dx, dy, 1);
00496     }
00497 }
00498 
00516 int can_make_wall(char **maze, int dx, int dy, int dir, RMParms *RP) {
00517     int i1;
00518     int length = 0;
00519 
00520     /* dont make walls if we're on the edge. */
00521     if (dx == 0 || dx == (RP->Xsize-1) || dy == 0 || dy == (RP->Ysize-1))
00522         return -1;
00523 
00524     /* don't make walls if we're ON a wall. */
00525     if (maze[dx][dy] != 0)
00526         return -1;
00527 
00528     if (dir == 0) {
00529         /* horizontal */
00530         int y = dy;
00531 
00532         for (i1 = dx-1; i1 > 0; i1--) {
00533             int sindex = surround_flag2(maze, i1, y, RP);
00534 
00535             if (sindex == 1)
00536                 break;
00537             if (sindex != 0)
00538                 return -1; /* can't make horiz.  wall here */
00539             if (maze[i1][y] != 0)
00540                 return -1; /* can't make horiz.  wall here */
00541             length++;
00542         }
00543 
00544         for (i1 = dx+1; i1 < RP->Xsize-1; i1++) {
00545             int sindex = surround_flag2(maze, i1, y, RP);
00546 
00547             if (sindex == 2)
00548                 break;
00549             if (sindex != 0)
00550                 return -1;  /* can't make horiz.  wall here */
00551             if (maze[i1][y] != 0)
00552                 return -1; /* can't make horiz.  wall here */
00553             length++;
00554         }
00555         return length;
00556     } else {
00557         /* vertical */
00558         int x = dx;
00559 
00560         for (i1 = dy-1; i1 > 0; i1--) {
00561             int sindex = surround_flag2(maze, x, i1, RP);
00562 
00563             if (sindex == 4)
00564                 break;
00565             if (sindex != 0)
00566                 return -1; /* can't make vert. wall here */
00567             if (maze[x][i1] != 0)
00568                 return -1; /* can't make horiz.  wall here */
00569             length++;
00570         }
00571 
00572         for (i1 = dy+1; i1 < RP->Ysize-1; i1++) {
00573             int sindex = surround_flag2(maze, x, i1, RP);
00574 
00575             if (sindex == 8)
00576                 break;
00577             if (sindex != 0)
00578                 return -1; /* can't make verti. wall here */
00579             if (maze[x][i1] != 0)
00580                 return -1; /* can't make horiz.  wall here */
00581             length++;
00582         }
00583         return length;
00584     }
00585     return -1;
00586 }
00587 
00602 int make_wall(char **maze, int x, int y, int dir) {
00603     maze[x][y] = 'D'; /* mark a door */
00604     switch (dir) {
00605     case 0: { /* horizontal */
00606             int i1;
00607 
00608             for (i1 = x-1; maze[i1][y] == 0; i1--)
00609                 maze[i1][y] = '#';
00610             for (i1 = x+1; maze[i1][y] == 0; i1++)
00611                 maze[i1][y] = '#';
00612             break;
00613     }
00614 
00615     case 1: { /* vertical */
00616             int i1;
00617 
00618             for (i1 = y-1; maze[x][i1] == 0; i1--)
00619                 maze[x][i1] = '#';
00620             for (i1 = y+1; maze[x][i1] == 0; i1++)
00621                 maze[x][i1] = '#';
00622             break;
00623         }
00624     }
00625 
00626     return 0;
00627 }
00628 
00636 void doorify_layout(char **maze, RMParms *RP) {
00637     int ndoors = RP->Xsize*RP->Ysize/60;  /* reasonable number of doors. */
00638     int *doorlist_x;
00639     int *doorlist_y;
00640     int doorlocs = 0;  /* # of available doorlocations */
00641     int i, j;
00642 
00643     doorlist_x = malloc(sizeof(int)*RP->Xsize*RP->Ysize);
00644     doorlist_y = malloc(sizeof(int)*RP->Xsize*RP->Ysize);
00645 
00646 
00647     /* make a list of possible door locations */
00648     for (i = 1; i < RP->Xsize-1; i++)
00649         for (j = 1; j < RP->Ysize-1; j++) {
00650             int sindex = surround_flag(maze, i, j, RP);
00651             if (sindex == 3 || sindex == 12) {
00652                 /* these are possible door sindex*/
00653                 doorlist_x[doorlocs] = i;
00654                 doorlist_y[doorlocs] = j;
00655                 doorlocs++;
00656             }
00657         }
00658 
00659     while (ndoors > 0 && doorlocs > 0) {
00660         int di;
00661         int sindex;
00662 
00663         di = RANDOM()%doorlocs;
00664         i = doorlist_x[di];
00665         j = doorlist_y[di];
00666         sindex = surround_flag(maze, i, j, RP);
00667         if (sindex == 3 || sindex == 12) { /* these are possible door sindex*/
00668             maze[i][j] = 'D';
00669             ndoors--;
00670         }
00671         /* reduce the size of the list */
00672         doorlocs--;
00673         doorlist_x[di] = doorlist_x[doorlocs];
00674         doorlist_y[di] = doorlist_y[doorlocs];
00675     }
00676     free(doorlist_x);
00677     free(doorlist_y);
00678 }
00679 
00689 void write_map_parameters_to_string(RMParms *RP, char *buf, int bufsize) {
00690     char small_buf[256];
00691     snprintf(buf, bufsize, "xsize %d\nysize %d\n", RP->Xsize, RP->Ysize);
00692 
00693     /* Since we'll be using strncat, just plya it safe and keep space for final 0. */
00694     bufsize--;
00695     buf[bufsize] = '\0';
00696 
00697     if (RP->wallstyle[0]) {
00698         snprintf(small_buf, sizeof(small_buf), "wallstyle %s\n", RP->wallstyle);
00699         strncat(buf, small_buf, bufsize);
00700     }
00701 
00702     if (RP->floorstyle[0]) {
00703         snprintf(small_buf, sizeof(small_buf), "floorstyle %s\n", RP->floorstyle);
00704         strncat(buf, small_buf, bufsize);
00705     }
00706 
00707     if (RP->monsterstyle[0]) {
00708         snprintf(small_buf, sizeof(small_buf), "monsterstyle %s\n", RP->monsterstyle);
00709         strncat(buf, small_buf, bufsize);
00710     }
00711 
00712     if (RP->treasurestyle[0]) {
00713         snprintf(small_buf, sizeof(small_buf), "treasurestyle %s\n", RP->treasurestyle);
00714         strncat(buf, small_buf, bufsize);
00715     }
00716 
00717     if (RP->layoutstyle[0]) {
00718         snprintf(small_buf, sizeof(small_buf), "layoutstyle %s\n", RP->layoutstyle);
00719         strncat(buf, small_buf, bufsize);
00720     }
00721 
00722     if (RP->decorstyle[0]) {
00723         snprintf(small_buf, sizeof(small_buf), "decorstyle %s\n", RP->decorstyle);
00724         strncat(buf, small_buf, bufsize);
00725     }
00726 
00727     if (RP->doorstyle[0]) {
00728         snprintf(small_buf, sizeof(small_buf), "doorstyle %s\n", RP->doorstyle);
00729         strncat(buf, small_buf, bufsize);
00730     }
00731 
00732     if (RP->exitstyle[0]) {
00733         snprintf(small_buf, sizeof(small_buf), "exitstyle %s\n", RP->exitstyle);
00734         strncat(buf, small_buf, bufsize);
00735     }
00736 
00737     if (RP->final_map[0]) {
00738         snprintf(small_buf, sizeof(small_buf), "final_map %s\n", RP->final_map);
00739         strncat(buf, small_buf, bufsize);
00740     }
00741 
00742     if (RP->final_exit_archetype[0]) {
00743         snprintf(small_buf, sizeof(small_buf), "final_exit_archetype %s\n", RP->final_exit_archetype);
00744         strncat(buf, small_buf, bufsize);
00745     }
00746 
00747     if (RP->exit_on_final_map[0]) {
00748         snprintf(small_buf, sizeof(small_buf), "exit_on_final_map %s\n", RP->exit_on_final_map);
00749         strncat(buf, small_buf, bufsize);
00750     }
00751 
00752     if (RP->this_map[0]) {
00753         snprintf(small_buf, sizeof(small_buf), "origin_map %s\n", RP->this_map);
00754         strncat(buf, small_buf, bufsize);
00755     }
00756 
00757     if (RP->expand2x) {
00758         snprintf(small_buf, sizeof(small_buf), "expand2x %d\n", RP->expand2x);
00759         strncat(buf, small_buf, bufsize);
00760     }
00761 
00762     if (RP->layoutoptions1) {
00763         snprintf(small_buf, sizeof(small_buf), "layoutoptions1 %d\n", RP->layoutoptions1);
00764         strncat(buf, small_buf, bufsize);
00765     }
00766 
00767     if (RP->layoutoptions2) {
00768         snprintf(small_buf, sizeof(small_buf), "layoutoptions2 %d\n", RP->layoutoptions2);
00769         strncat(buf, small_buf, bufsize);
00770     }
00771 
00772     if (RP->layoutoptions3) {
00773         snprintf(small_buf, sizeof(small_buf), "layoutoptions3 %d\n", RP->layoutoptions3);
00774         strncat(buf, small_buf, bufsize);
00775     }
00776 
00777     if (RP->symmetry) {
00778         snprintf(small_buf, sizeof(small_buf), "symmetry %d\n", RP->symmetry);
00779         strncat(buf, small_buf, bufsize);
00780     }
00781 
00782     if (RP->difficulty && RP->difficulty_given) {
00783         snprintf(small_buf, sizeof(small_buf), "difficulty %d\n", RP->difficulty);
00784         strncat(buf, small_buf, bufsize);
00785     }
00786 
00787     if (RP->difficulty_increase != 1.0) {
00788         snprintf(small_buf, sizeof(small_buf), "difficulty_increase %f\n", RP->difficulty_increase);
00789         strncat(buf, small_buf, bufsize);
00790     }
00791 
00792     snprintf(small_buf, sizeof(small_buf), "dungeon_level %d\n", RP->dungeon_level);
00793     strncat(buf, small_buf, bufsize);
00794 
00795     if (RP->dungeon_depth) {
00796         snprintf(small_buf, sizeof(small_buf), "dungeon_depth %d\n", RP->dungeon_depth);
00797         strncat(buf, small_buf, bufsize);
00798     }
00799 
00800     if (RP->dungeon_name[0]) {
00801         snprintf(small_buf, sizeof(small_buf), "dungeon_name %s\n", RP->dungeon_name);
00802         strncat(buf, small_buf, bufsize);
00803     }
00804 
00805     if (RP->decoroptions) {
00806         snprintf(small_buf, sizeof(small_buf), "decoroptions %d\n", RP->decoroptions);
00807         strncat(buf, small_buf, bufsize);
00808     }
00809 
00810     if (RP->orientation) {
00811         snprintf(small_buf, sizeof(small_buf), "orientation %d\n", RP->orientation);
00812         strncat(buf, small_buf, bufsize);
00813     }
00814 
00815     if (RP->origin_x) {
00816         snprintf(small_buf, sizeof(small_buf), "origin_x %d\n", RP->origin_x);
00817         strncat(buf, small_buf, bufsize);
00818     }
00819 
00820     if (RP->origin_y) {
00821         snprintf(small_buf, sizeof(small_buf), "origin_y %d\n", RP->origin_y);
00822         strncat(buf, small_buf, bufsize);
00823     }
00824     if (RP->random_seed) {
00825         /* Add one so that the next map is a bit different */
00826         snprintf(small_buf, sizeof(small_buf), "random_seed %d\n", RP->random_seed+1);
00827         strncat(buf, small_buf, bufsize);
00828     }
00829 
00830     if (RP->treasureoptions) {
00831         snprintf(small_buf, sizeof(small_buf), "treasureoptions %d\n", RP->treasureoptions);
00832         strncat(buf, small_buf, bufsize);
00833     }
00834 
00835     if (RP->multiple_floors) {
00836         snprintf(small_buf, sizeof(small_buf), "multiple_floors %d\n", RP->multiple_floors);
00837         strncat(buf, small_buf, bufsize);
00838     }
00839 }
00840 
00877 void write_parameters_to_string(char *buf,
00878                                 int xsize_n,
00879                                 int ysize_n,
00880                                 const char *wallstyle_n,
00881                                 const char *floorstyle_n,
00882                                 const char *monsterstyle_n,
00883                                 const char *treasurestyle_n,
00884                                 const char *layoutstyle_n,
00885                                 const char *decorstyle_n,
00886                                 const char *doorstyle_n,
00887                                 const char *exitstyle_n,
00888                                 const char *final_map_n,
00889                                 const char *exit_on_final_map_n,
00890                                 const char *this_map_n,
00891                                 int layoutoptions1_n,
00892                                 int layoutoptions2_n,
00893                                 int layoutoptions3_n,
00894                                 int symmetry_n,
00895                                 int dungeon_depth_n,
00896                                 int dungeon_level_n,
00897                                 int difficulty_n,
00898                                 int difficulty_given_n,
00899                                 int decoroptions_n,
00900                                 int orientation_n,
00901                                 int origin_x_n,
00902                                 int origin_y_n,
00903                                 int random_seed_n,
00904                                 int treasureoptions_n,
00905                                 float difficulty_increase) {
00906     char small_buf[256];
00907     sprintf(buf, "xsize %d\nysize %d\n", xsize_n, ysize_n);
00908 
00909     if (wallstyle_n && wallstyle_n[0]) {
00910         snprintf(small_buf, sizeof(small_buf), "wallstyle %s\n", wallstyle_n);
00911         strcat(buf, small_buf);
00912     }
00913 
00914     if (floorstyle_n && floorstyle_n[0]) {
00915         snprintf(small_buf, sizeof(small_buf), "floorstyle %s\n", floorstyle_n);
00916         strcat(buf, small_buf);
00917     }
00918 
00919     if (monsterstyle_n && monsterstyle_n[0]) {
00920         snprintf(small_buf, sizeof(small_buf), "monsterstyle %s\n", monsterstyle_n);
00921         strcat(buf, small_buf);
00922     }
00923 
00924     if (treasurestyle_n && treasurestyle_n[0]) {
00925         snprintf(small_buf, sizeof(small_buf), "treasurestyle %s\n", treasurestyle_n);
00926         strcat(buf, small_buf);
00927     }
00928 
00929     if (layoutstyle_n &&layoutstyle_n[0]) {
00930         snprintf(small_buf, sizeof(small_buf), "layoutstyle %s\n", layoutstyle_n);
00931         strcat(buf, small_buf);
00932     }
00933 
00934     if (decorstyle_n && decorstyle_n[0]) {
00935         snprintf(small_buf, sizeof(small_buf), "decorstyle %s\n", decorstyle_n);
00936         strcat(buf, small_buf);
00937     }
00938 
00939     if (doorstyle_n && doorstyle_n[0]) {
00940         snprintf(small_buf, sizeof(small_buf), "doorstyle %s\n", doorstyle_n);
00941         strcat(buf, small_buf);
00942     }
00943 
00944     if (exitstyle_n && exitstyle_n[0]) {
00945         snprintf(small_buf, sizeof(small_buf), "exitstyle %s\n", exitstyle_n);
00946         strcat(buf, small_buf);
00947     }
00948 
00949     if (final_map_n && final_map_n[0]) {
00950         snprintf(small_buf, sizeof(small_buf), "final_map %s\n", final_map_n);
00951         strcat(buf, small_buf);
00952     }
00953 
00954     if (exit_on_final_map_n && exit_on_final_map_n[0]) {
00955         snprintf(small_buf, sizeof(small_buf), "exit_on_final_map %s\n", exit_on_final_map_n);
00956         strcat(buf, small_buf);
00957     }
00958 
00959     if (this_map_n && this_map_n[0]) {
00960         snprintf(small_buf, sizeof(small_buf), "origin_map %s\n", this_map_n);
00961         strcat(buf, small_buf);
00962     }
00963 
00964     if (layoutoptions1_n) {
00965         snprintf(small_buf, sizeof(small_buf), "layoutoptions1 %d\n", layoutoptions1_n);
00966         strcat(buf, small_buf);
00967     }
00968 
00969 
00970     if (layoutoptions2_n) {
00971         snprintf(small_buf, sizeof(small_buf), "layoutoptions2 %d\n", layoutoptions2_n);
00972         strcat(buf, small_buf);
00973     }
00974 
00975 
00976     if (layoutoptions3_n) {
00977         snprintf(small_buf, sizeof(small_buf), "layoutoptions3 %d\n", layoutoptions3_n);
00978         strcat(buf, small_buf);
00979     }
00980 
00981     if (symmetry_n) {
00982         snprintf(small_buf, sizeof(small_buf), "symmetry %d\n", symmetry_n);
00983         strcat(buf, small_buf);
00984     }
00985 
00986 
00987     if (difficulty_n && difficulty_given_n) {
00988         snprintf(small_buf, sizeof(small_buf), "difficulty %d\n", difficulty_n);
00989         strcat(buf, small_buf);
00990     }
00991 
00992     if (difficulty_increase > 0.001) {
00993         snprintf(small_buf, sizeof(small_buf), "difficulty_increase %f\n", difficulty_increase);
00994         strcat(buf, small_buf);
00995     }
00996 
00997     snprintf(small_buf, sizeof(small_buf), "dungeon_level %d\n", dungeon_level_n);
00998     strcat(buf, small_buf);
00999 
01000     if (dungeon_depth_n) {
01001         snprintf(small_buf, sizeof(small_buf), "dungeon_depth %d\n", dungeon_depth_n);
01002         strcat(buf, small_buf);
01003     }
01004 
01005     if (decoroptions_n) {
01006         snprintf(small_buf, sizeof(small_buf), "decoroptions %d\n", decoroptions_n);
01007         strcat(buf, small_buf);
01008     }
01009 
01010     if (orientation_n) {
01011         snprintf(small_buf, sizeof(small_buf), "orientation %d\n", orientation_n);
01012         strcat(buf, small_buf);
01013     }
01014 
01015     if (origin_x_n) {
01016         snprintf(small_buf, sizeof(small_buf), "origin_x %d\n", origin_x_n);
01017         strcat(buf, small_buf);
01018     }
01019 
01020     if (origin_y_n) {
01021         snprintf(small_buf, sizeof(small_buf), "origin_y %d\n", origin_y_n);
01022         strcat(buf, small_buf);
01023     }
01024 
01025     if (random_seed_n) {
01026         /* Add one so that the next map is a bit different */
01027         snprintf(small_buf, sizeof(small_buf), "random_seed %d\n", random_seed_n+1);
01028         strcat(buf, small_buf);
01029     }
01030 
01031     if (treasureoptions_n) {
01032         snprintf(small_buf, sizeof(small_buf), "treasureoptions %d\n", treasureoptions_n);
01033         strcat(buf, small_buf);
01034     }
01035 }