Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

dll/bigmap.c

Go to the documentation of this file.
00001 /* {{{
00002  * CalcRogue, a roguelike game for PCs, calculators and PDAs
00003  * Copyright (C) 2003 Jim Babcock
00004  * 
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018  * }}} */
00019 // bigmap.c
00022 
00023 #include "crogue.h"
00024 #include "dll.h"
00025 
00026 #define ROOMCONN_RETRIES 2
00027 #define CORRIDOREND_RETRIES 10
00028 #define CORRIDORBRANCH_RETRIES 2
00029 #define ROOMSIZE_MAX_X 8
00030 #define ROOMSIZE_MIN_X 4
00031 #define ROOMSIZE_MAX_Y 8
00032 #define ROOMSIZE_MIN_Y 4
00033 #define CORRIDOR_MAX_LEN 10
00034 #define CORRIDOR_MIN_LEN 4
00035 
00036 #define TFLAG_CLEAN          1
00037 #define TFLAG_RECEPTACLE     2
00038 #define TFLAG_JUNCTION       4  /* Later, might put a door here */
00039 //{{{
00040 typedef struct mark
00041 {
00042     scoord pos;
00043     unsigned char direction;
00044     unsigned char retries;
00045 } mark;
00046 //}}}
00047 //{{{
00048 typedef union feature_info
00049 {
00050     short length;
00051     
00052     struct {
00053         scoord size;
00054         short offset;
00055     } room;
00056     
00057     struct {
00058         short vaultid;
00059     } vault;
00060 } feature_info;
00061 //}}}
00062 //{{{
00063 typedef struct feature
00064 {
00065     scoord pos;
00066     feature_info ext;
00067     short type;
00068     short direction;
00069 } feature;
00070 //}}}
00071 #define NUM_TYPES 2
00072 #define FEATURE_ROOM       0
00073 #define FEATURE_CORRIDOR   1
00074 #define FEATURE_VAULT      2
00075 //{{{
00076 typedef struct vaultdesc
00077 {
00078     scoord size;
00079     scoord offset;
00080     const char *content;
00081 } vaultdesc;
00082 //}}}
00083 
00084 #define NUM_VAULT_TYPES 12
00085 
00086 #define VAULTCHAR_BLANK      '/'  /* A tile that's not part of the vault     */
00087 #define VAULTCHAR_WALL_HARD  '#'  /* A 'hard' wall cannot be replaced        */
00088 #define VAULTCHAR_WALL_SOFT  '$'  /* A 'soft' wall could be connected to a   */
00089                                   /* corridor if something else generates it */
00090 #define VAULTCHAR_DOOR       '+'
00091 #define VAULTCHAR_MARK_DOWN  '2'  /* These correspond to the num pad         */
00092 #define VAULTCHAR_MARK_LEFT  '4'
00093 #define VAULTCHAR_MARK_RIGHT '6'
00094 #define VAULTCHAR_MARK_UP    '8'
00095 
00096 const vaultdesc vaults[] =
00097     {
00098 //{{{
00099         { {7,7}, {4,0},  // 5x5 Circular room
00100           "/## ##/"
00101           "##   ##"
00102           "#     #"
00103           "4     6"
00104           "#     #"
00105           "##   ##"
00106           "/##2##/"
00107         },
00108 //}}}
00109 //{{{
00110         { {9,9}, {4,0},  // 7x7 Circular room
00111           "//## ##//"
00112           "/##   ##/"
00113           "##     ##"
00114           "#       #"
00115           "4       6"
00116           "#       #"
00117           "##     ##"
00118           "/##   ##/"
00119           "//##2##//"
00120         },
00121 //}}}
00122 //{{{
00123         { {11,11}, {5,0},// 9x9 Circular room
00124           "//### ###//"
00125           "/##     ##/"
00126           "##       ##"
00127           "#         #"
00128           "#         #"
00129           "4         6"
00130           "#         #"
00131           "#         #"
00132           "##       ##"
00133           "/##     ##/"
00134           "//###2###//"
00135         },
00136 //}}}
00137 //{{{
00138         { {9,9}, {4,0},  // 7x7 Cross-shaped room
00139           "//## ##//"
00140           "//#   #//"
00141           "###   ###"
00142           "#       #"
00143           "4       6"
00144           "#       #"
00145           "###   ###"
00146           "//#   #//"
00147           "//##2##//"
00148         },
00149 //}}}
00150 //{{{
00151         { {13,13}, {8,0},// 11x11 star
00152           "
00153           "
00154           "
00155           "
00156           "/###     ###/"
00157           "##         ##"
00158           "4           6"
00159           "##         ##"
00160           "/###     ###/"
00161           "
00162           "
00163           "
00164           "
00165         },
00166 //}}}
00167 //{{{
00168         { {15,15}, {8,0},// 13x13 star
00169           "
00170           "
00171           "
00172           "
00173           "
00174           "/####     ####/"
00175           "##           ##"
00176           "4             6"
00177           "##           ##"
00178           "/####     ####/"
00179           "
00180           "
00181           "
00182           "
00183           "
00184         },
00185 //}}}
00186 //{{{
00187         { {9,9}, {4,0},  // 7x7 rotary
00188           "//## ##//"
00189           "/##   ##/"
00190           "##     ##"
00191           "#  ###  #"
00192           "4  ###  6"
00193           "#  ###  #"
00194           "##     ##"
00195           "/##   ##/"
00196           "//##2##//"
00197         },
00198 //}}}
00199 //{{{
00200         { {11,11}, {5,0},// 9x9 rotary
00201           "//### ###//"
00202           "/##     ##/"
00203           "##  ###  ##"
00204           "#  #####  #"
00205           "# ####### #"
00206           "4 ####### 6"
00207           "# ####### #"
00208           "#  #####  #"
00209           "##  ###  ##"
00210           "/##     ##/"
00211           "//###2###//"
00212         },
00213 //}}}
00214 //{{{
00215         { {13,13}, {8,0},// 11x11 rotary
00216           "
00217           "//##     ##//"
00218           "/##       ##/"
00219           "##   ###   ##"
00220           "#   #####   #"
00221           "#  #######  #"
00222           "4  #######  6"
00223           "#  #######  #"
00224           "#   #####   #"
00225           "##   ###   ##"
00226           "/##       ##/"
00227           "//##     ##//"
00228           "
00229         },
00230 //}}}
00231 //{{{
00232         { {17,17}, {8,0},// 15x15 rotary
00233           "
00234           "
00235           "//##         ##//"
00236           "/##    ###    ##/"
00237           "/#   #######   #/"
00238           "##  #########  ##"
00239           "#   #########   #"
00240           "#  ###########  #"
00241           "4  ###########  6"
00242           "#  ###########  #"
00243           "#   #########   #"
00244           "##  #########  ##"
00245           "/#   #######   #/"
00246           "/##    ###    ##/"
00247           "//##         ##//"
00248           "
00249           "
00250         },
00251 //}}}
00252 //{{{
00253         { {15,15}, {3,0},  // Wizard's tower (ala NetHack)
00254           "### ###########"
00255           "#             #"
00256           "#             #"
00257           "4             6"
00258           "#             #"
00259           "#     ###     #"
00260           "#    ## ##    #"
00261           "4    #   #    6"
00262           "#    ## ##    #"
00263           "#     ###     #"
00264           "#             #"
00265           "4             6"
00266           "#             #"
00267           "#             #"
00268           "###2###2###2###"
00269         },
00270 //}}}
00271 //{{{
00272         { {13,11}, {6,0},  // Moria-style rooms
00273           "###### ######"
00274           "#           #"
00275           "# ######### #"
00276           "# +   #   + #"
00277           "# #   #   # #"
00278           "4 ######### 6"
00279           "# #   #   # #"
00280           "# +   #   + #"
00281           "# ######### #"
00282           "#           #"
00283           "######2######"
00284         },
00285 //}}}
00286     };
00287 
00288 //{{{
00289 scoord directions[4] =
00290     {
00291         {  1,  0 },
00292         {  0, -1 },
00293         { -1,  0 },
00294         {  0,  1 }
00295     };
00296 //}}}
00297 #define DIR_RIGHT 0
00298 #define DIR_UP    1
00299 #define DIR_LEFT  2
00300 #define DIR_DOWN  3
00301 
00302 static void bigmap_prepass(void);
00303 static int bigmap_postpass(void);
00304 static void bigmap_fill(void);
00305 static int bigmap_place_feature(feature *feature, mark *marks, int *marks_pending);
00306 static int bigmap_place_corridor(feature *feature, int dry, mark *marks, int *marks_pending);
00307 static int bigmap_place_room(feature *feature, int dry, mark *marks, int *pending);
00308 static int bigmap_place_vault(feature *feature, int dry, mark *marks, int *pending);
00309 static void rand_feature(feature *feature, mark *m);
00310 static void add_mark(int x, int y, int dir, mark *marks, int *pending, int retries);
00311 
00312 //{{{
00313 int mkmap_big(void)
00314 {
00315     bigmap_prepass();
00316     bigmap_fill();
00317     return bigmap_postpass();
00318 }
00319 //}}}
00320 //{{{
00321 static int is_in_bounds(scoord pos)
00322 {
00323     if(pos.x<=0 || pos.y<=0 || pos.x>=MAPSIZE_X-1 || pos.y>=MAPSIZE_Y-1)
00324         return 0;
00325     else
00326         return 1;
00327 }
00328 //}}}
00329 //{{{
00330 static void bigmap_prepass(void)
00331 {
00332     int xi, yi;
00333     for(yi=0; yi<MAPSIZE_Y; yi++)
00334     for(xi=0; xi<MAPSIZE_X; xi++)
00335         w->t[yi][xi].flags = TFLAG_CLEAN;
00336 }
00337 //}}}
00338 //{{{
00339 static int bigmap_postpass(void)
00340 {
00341     int xi, yi;
00342     unsigned filled=0, empty=0;
00343     for(yi=1; yi<MAPSIZE_Y-1; yi++)
00344     for(xi=1; xi<MAPSIZE_X-1; xi++)
00345     {
00346         if(w->t[yi][xi].type == TILE_FLOOR)
00347             empty++;
00348         else
00349             filled++;
00350         if(w->t[yi][xi].flags & TFLAG_JUNCTION && make_door(xi, yi))
00351         {
00352             if(nrandom(15,0)==0)
00353                 w->t[yi][xi].type = TILE_SDOOR;
00354             else
00355                 w->t[yi][xi].type = TILE_CDOOR;
00356         }
00357     }
00358     
00359     for(yi=0; yi<MAPSIZE_Y; yi++)
00360     for(xi=0; xi<MAPSIZE_X; xi++)
00361         w->t[yi][xi].flags = 0;
00362     
00363     if(empty < 100)
00364         return 0;
00365     else
00366         return 1;
00367 }
00368 //}}}
00369 //{{{
00370 static void bigmap_fill(void)
00371 {
00372     mark marks[512];
00373     int marks_pending = 0;
00374     int current_mark;
00375     feature current_feature;
00376     
00377     add_mark(MAPSIZE_X/2, MAPSIZE_Y/2, nrandom(3,0), marks, &marks_pending,255);
00378     
00379     while(marks_pending > 0)
00380     {
00381         // Pick a random mark
00382         current_mark = nrandom(marks_pending-1, 0);
00383         
00384         // Pick a type
00385         rand_feature(&current_feature, &marks[current_mark]);
00386         
00387         // Check for fit
00388         if( bigmap_place_feature(&current_feature, marks, &marks_pending) ) {
00389             marks[current_mark] = marks[--marks_pending];
00390         } else {
00391             marks[current_mark].retries --;
00392             if(marks[current_mark].retries == 0)
00393                 marks[current_mark] = marks[--marks_pending];
00394         }
00395     }
00396 }
00397 //}}}
00398 //{{{
00399 static int bigmap_place_feature(feature *feature, mark *marks, int *pending)
00400 {
00401     switch(feature->type)
00402     {
00403         case FEATURE_CORRIDOR:
00404             // Dry run: See if it fits first, then try to place it
00405             if(bigmap_place_corridor(feature, 1, marks, pending))
00406                  return bigmap_place_corridor(feature, 0, marks, pending);
00407             else return 0;
00408         default:
00409         case FEATURE_ROOM:
00410             // Dry run: See if it fits first, then try to place it
00411             if(bigmap_place_room(feature, 1, marks, pending))
00412                  return bigmap_place_room(feature, 0, marks, pending);
00413             else return 0;
00414         case FEATURE_VAULT:
00415             if(bigmap_place_vault(feature, 1, marks, pending))
00416                  return bigmap_place_vault(feature, 0, marks, pending);
00417             else return 0;
00418     }
00419 }
00420 //}}}
00421 //{{{
00422 static int bigmap_place_corridor(feature *feature, int dry,
00423     mark *marks, int *marks_pending)
00424 {
00425     int ii;
00426     scoord pos = feature->pos;
00427     scoord delta = directions[feature->direction];
00428     scoord perpendicular = directions[ (feature->direction+1)%4 ];
00429     scoord tmp;
00430     int branch_direction = (feature->direction+1)%4;
00431     
00432     for(ii=0; ii<feature->ext.length; ii++)
00433     {
00434         // OPTIMIZEME: This bounds check should be outside the loop
00435         if(!is_in_bounds(pos)) return 0;
00436         
00437         if(dry)
00438         {
00439             if(w->t[pos.y][pos.x].flags & TFLAG_RECEPTACLE)
00440                     // Hit another room, but in a spot where it doesn't mind
00441                     // having a corridor sticking out
00442                 return 1;
00443             if(w->t[pos.y][pos.x].flags & TFLAG_CLEAN)
00444                     // Tunneling through new ground
00445                 continue;
00446             return 0;
00447         }
00448         else
00449         {
00450             if(w->t[pos.y][pos.x].flags & TFLAG_CLEAN)
00451             {
00452                 w->t[pos.y][pos.x].type = TILE_FLOOR;
00453                 w->t[pos.y][pos.x].flags &= ~TFLAG_CLEAN;
00454                 
00455                 // 1 in 9 chance: Put a mark here
00456                 if(nrandom(8,0)==0)
00457                 {
00458                     if(nrandom(1,0)) // Random side
00459                     {
00460                         perpendicular.x = -perpendicular.x;
00461                         perpendicular.y = -perpendicular.y;
00462                         branch_direction = (branch_direction+2)%4;
00463                     }
00464                     tmp.x = pos.x + perpendicular.x;
00465                     tmp.y = pos.y + perpendicular.y;
00466                     add_mark(tmp.x, tmp.y, branch_direction,
00467                         marks, marks_pending, CORRIDORBRANCH_RETRIES);
00468                 }
00469             }
00470             else if(w->t[pos.y][pos.x].flags & TFLAG_RECEPTACLE)
00471             {
00472                 w->t[pos.y][pos.x].type = TILE_FLOOR;
00473                 return 1;
00474             }
00475             else
00476             {
00477                 pos.x -= delta.x;
00478                 pos.y -= delta.y;
00479                 w->t[pos.y][pos.x].flags |= TFLAG_JUNCTION;
00480                 return 1;
00481             }
00482         }
00483         
00484         pos.x += delta.x;
00485         pos.y += delta.y;
00486     }
00487     // Put a mark at the end
00488     if(!dry) {
00489         add_mark(pos.x, pos.y, feature->direction,
00490             marks, marks_pending, CORRIDOREND_RETRIES);
00491     }
00492     
00493         // Disappeared into the ether, making a dead end
00494     return 1;
00495 }
00496 //}}}
00497 //{{{
00498 static int bigmap_place_room(feature *feature, int dry,
00499     mark *marks, int *pending)
00500 {
00501     scoord next_cell, next_row;
00502     scoord pos;
00503     int xi, yi;
00504     int min_x, max_x, min_y, max_y;
00505     int intersections = 0;
00506     
00507     next_cell.x = directions[(feature->direction+1)%4].x;
00508     next_cell.y = directions[(feature->direction+1)%4].y;
00509     next_row.x  = directions[feature->direction].x
00510                   - next_cell.x*feature->ext.room.size.x;
00511     next_row.y  = directions[feature->direction].y
00512                   - next_cell.y*feature->ext.room.size.x;
00513     
00514     if(dry) {
00515         if(!(w->t[feature->pos.y][feature->pos.x].flags & TFLAG_CLEAN))
00516             return 0;
00517     } else {
00518         w->t[feature->pos.y][feature->pos.x].flags &= ~TFLAG_CLEAN;
00519         w->t[feature->pos.y][feature->pos.x].type = TILE_FLOOR;
00520     }
00521     
00522     pos.x = feature->pos.x + directions[feature->direction].x;
00523     pos.y = feature->pos.y + directions[feature->direction].y;
00524     pos.x -= next_cell.x * feature->ext.room.offset;
00525     pos.y -= next_cell.y * feature->ext.room.offset;
00526     min_x = max_x = pos.x;
00527     min_y = max_y = pos.y;
00528     
00529     for(yi=0; yi<feature->ext.room.size.y; yi++)
00530     {
00531         for(xi=0; xi<feature->ext.room.size.x; xi++)
00532         {
00533             // OPTIMIZEME: This bounds check should be outside the loop
00534             if(!is_in_bounds(pos)) return 0;
00535             
00536             if(dry) {
00537                 if(!(w->t[pos.y][pos.x].flags & TFLAG_CLEAN))
00538                     return 0;
00539             } else {
00540                 w->t[pos.y][pos.x].type = TILE_FLOOR;
00541                 w->t[pos.y][pos.x].flags &= ~TFLAG_CLEAN;
00542             }
00543             // OPTIMIZEME: This really ought to be hoisted
00544             if(pos.x < min_x) min_x = pos.x;
00545             if(pos.x > max_x) max_x = pos.x;
00546             if(pos.y < min_y) min_y = pos.y;
00547             if(pos.y > max_y) max_y = pos.y;
00548             pos.x += next_cell.x;
00549             pos.y += next_cell.y;
00550         }
00551         pos.x += next_row.x;
00552         pos.y += next_row.y;
00553     }
00554     
00555     if(dry)
00556     {
00557         // Expand by 1, since multiple non-walls there would indicate a
00558         // collision. Testing isn't done when the border falls outside the
00559         // or onto the map's outer boundary, since that area is guaranteed to
00560         // be wall, but not TILE_WALL.
00561         min_x --; max_x ++;
00562         min_y --; max_y ++;
00563         
00564         // Check walls
00565         // OPTIMIZEME: Checking bounds *inside* the loop here is just bad
00566         for(xi=min_x; xi<=max_x; xi++) {
00567             if(min_y>0 && w->t[min_y][xi].type != TILE_WALL)
00568                 intersections++;
00569             if(max_y<MAPSIZE_Y-1 && w->t[max_y][xi].type != TILE_WALL)
00570                 intersections++;
00571         }
00572         for(yi=min_y; yi<=max_y; yi++) {
00573             if(min_x>0 && w->t[yi][min_x].type != TILE_WALL)
00574                 intersections++;
00575             if(max_x<MAPSIZE_X-1 && w->t[yi][max_x].type != TILE_WALL)
00576                 intersections++;
00577         }
00578         if(intersections>1) // More collisions than just where it came in
00579             return 0;
00580     }
00581     else
00582     {
00583         add_mark(nrandom(max_x, min_x), max_y+1, DIR_DOWN,
00584             marks, pending, ROOMCONN_RETRIES);
00585         add_mark(nrandom(max_x, min_x), min_y-1, DIR_UP,
00586             marks, pending, ROOMCONN_RETRIES);
00587         add_mark(min_x-1, nrandom(max_y, min_y), DIR_LEFT,
00588             marks, pending, ROOMCONN_RETRIES);
00589         add_mark(max_x+1, nrandom(max_y, min_y), DIR_RIGHT,
00590             marks, pending, ROOMCONN_RETRIES);
00591     }
00592     
00593     return 1;
00594 }
00595 //}}}
00596 //{{{
00597 static int bigmap_place_vault(feature *feature, int dry,
00598     mark *marks, int *pending)
00599 {
00600     scoord next_cell, next_row;
00601     scoord perpendicular_cell;
00602     scoord pos;
00603     int xi, yi;
00604     int direction = feature->direction;
00605     const vaultdesc *desc = &vaults[feature->ext.vault.vaultid];
00606     
00607     next_cell.x = directions[(feature->direction+1)%4].x;
00608     next_cell.y = directions[(feature->direction+1)%4].y;
00609     next_row.x  = directions[feature->direction].x
00610                   - next_cell.x*desc->size.x;
00611     next_row.y  = directions[feature->direction].y
00612                   - next_cell.y*desc->size.x;
00613     perpendicular_cell.x = directions[feature->direction].x;
00614     perpendicular_cell.y = directions[feature->direction].y;
00615     
00616     pos.x = feature->pos.x + directions[feature->direction].x;
00617     pos.y = feature->pos.y + directions[feature->direction].y;
00618     pos.x -= next_cell.x * desc->offset.x;
00619     pos.y -= next_cell.y * desc->offset.x;
00620     pos.x -= perpendicular_cell.x * desc->offset.y;
00621     pos.y -= perpendicular_cell.y * desc->offset.y;
00622     
00623     for(yi=0; yi<desc->size.y; yi++)
00624     {
00625         for(xi=0; xi<desc->size.x; xi++)
00626         {
00627             // OPTIMIZEME: This bounds check should be outside the loop
00628             if(!is_in_bounds(pos)) return 0;
00629             
00630             if(dry) {
00631                 if(desc->content[yi*desc->size.x + xi] != '/')
00632                 {
00633                     if(w->t[pos.y][pos.x].type != TILE_WALL)
00634                         return 0;
00635                 }
00636             } else {
00637                 switch(desc->content[ yi*desc->size.x + xi ])
00638                 {
00639                     case '/':
00640                         break;
00641                     case '2':
00642                         add_mark(pos.x, pos.y, (DIR_DOWN+direction+1)%4,
00643                             marks, pending, ROOMCONN_RETRIES);
00644                         break;
00645                     case '4':
00646                         add_mark(pos.x, pos.y, (DIR_LEFT+direction+1)%4,
00647                             marks, pending, ROOMCONN_RETRIES);
00648                         break;
00649                     case '6':
00650                         add_mark(pos.x, pos.y, (DIR_RIGHT+direction+1)%4,
00651                             marks, pending, ROOMCONN_RETRIES);
00652                         break;
00653                     case '8':
00654                         add_mark(pos.x, pos.y, (DIR_UP+direction+1)%4,
00655                             marks, pending, ROOMCONN_RETRIES);
00656                         break;
00657                     case '#':
00658                         w->t[pos.y][pos.x].flags &= ~TFLAG_CLEAN;
00659                         break;
00660                     case ' ':
00661                         w->t[pos.y][pos.x].type = TILE_FLOOR;
00662                         w->t[pos.y][pos.x].flags &= ~TFLAG_CLEAN;
00663                         break;
00664                     case '+':
00665                         w->t[pos.y][pos.x].type = TILE_CDOOR;
00666                         w->t[pos.y][pos.x].flags &= ~TFLAG_CLEAN;
00667                 }
00668             }
00669             pos.x += next_cell.x;
00670             pos.y += next_cell.y;
00671         }
00672         pos.x += next_row.x;
00673         pos.y += next_row.y;
00674     }
00675     return 1;
00676 }
00677 //}}}
00678 //{{{
00679 static void rand_feature(feature *feature, mark *m)
00680 {
00681     const vaultdesc *vault_desc;
00682     
00683     feature->pos = m->pos;
00684     feature->direction = m->direction;
00685     if(nrandom(5,1)==1)
00686         feature->type = FEATURE_CORRIDOR;
00687     else if(nrandom(2,1)==1)
00688         feature->type = FEATURE_ROOM;
00689     else
00690         feature->type = FEATURE_VAULT;
00691     
00692     switch(feature->type)
00693     {
00694         case FEATURE_CORRIDOR:
00695             feature->ext.length = nrandom(CORRIDOR_MAX_LEN, CORRIDOR_MIN_LEN);
00696             break;
00697         case FEATURE_ROOM:
00698             feature->ext.room.size.x = nrandom(ROOMSIZE_MAX_X, ROOMSIZE_MIN_Y);
00699             feature->ext.room.size.y = nrandom(ROOMSIZE_MAX_X, ROOMSIZE_MIN_Y);
00700             feature->ext.room.offset = nrandom(feature->ext.room.size.x-1, 0);
00701             break;
00702         case FEATURE_VAULT:
00703             feature->ext.vault.vaultid = nrandom(NUM_VAULT_TYPES-1, 0);
00704             vault_desc = &vaults[feature->ext.vault.vaultid];
00705             break;
00706     }
00707 }
00708 //}}}
00709 //{{{
00710 static void add_mark(int x, int y, int dir, mark *marks, int *pending,
00711     int retries)
00712 {
00713     if(*pending >= 512) return;
00714     marks[*pending].pos.x = x;
00715     marks[*pending].pos.y = y;
00716     marks[*pending].direction = dir;
00717     marks[*pending].retries = retries;
00718     w->t[y][x].flags |= TFLAG_JUNCTION;
00719     (*pending)++;
00720 }
00721 //}}}
00722 

Generated on Thu May 20 13:12:09 2004 for CalcRogue by doxygen 1.3.6