#include "vars.h" #include "dice.h" #include "structs.h" #include "areas.h" #define LEVEL_NOWATER 5 // level number, not level[] index #define MAX_WATER .6 // chance of water fill on DUNGEON_LEVELS-1 #define WATER_CHANCE(l) (((l-LEVEL_NOWATER)*MAX_WATER)/(DUNGEON_LEVELS-LEVEL_NOWATER)) /* * This flood-fills a cave region, like flagregion() in digdungeon.c, * except that it doesn't follow stairs, and it returns a boolean * indicating whether it found a LOC_STAIRS_D in the area. */ static int flagarea(LEVEL *lv, int x, int y) { LOC *l; int bits; #define U 0x00000001 #define L 0x00000002 #define D 0x00000004 #define R 0x00000008 #define DOWN 0x00000010 l = &lv->cells[x][y]; if (l->flags & LF_FLAG) return(0); switch (l->type) { case LOC_CAVE: case LOC_DOOR: case LOC_SDOOR: break; default: return(0); break; } if (l->cavetype == LOC_STAIRS_D) return(1); bits = 0; if (x >= 1) bits |= L; if (y >= 1) bits |= U; if (x < LEV_X-1) bits |= R; if (y < LEV_Y-1) bits |= D; l->flags |= LF_FLAG; lv->nunflagged --; if (bits & L) { if ((bits & U) && flagarea(lv,x-1,y-1)) bits |= DOWN; if (flagarea(lv,x-1,y)) bits |= DOWN; if ((bits & D) && flagarea(lv,x-1,y+1)) bits |= DOWN; } if (bits & R) { if ((bits & U) && flagarea(lv,x+1,y-1)) bits |= DOWN; if (flagarea(lv,x+1,y)) bits |= DOWN; if ((bits & D) && flagarea(lv,x+1,y+1)) bits |= DOWN; } if ((bits & U) && flagarea(lv,x,y-1)) bits |= DOWN; if ((bits & D) && flagarea(lv,x,y+1)) bits |= DOWN; return(bits&DOWN); #undef U #undef L #undef D #undef R } /* * Convert LF_FLAG to LF_FLAGB on lv. Used by makeareas(). */ static void flag_to_flagb(LEVEL *lv) { int x; int y; LOC *l; for (x=LEV_X-1;x>=0;x--) { l = &lv->cells[x][0]; for (y=LEV_Y-1;y>=0;y--) { if (l->flags & LF_FLAG) l->flags = (l->flags & ~LF_FLAG) | LF_FLAGB; l ++; } } } /* * Fill those areas of lv that are marked LF_FLAG. Used by * makeareas() to actually water-fill areas. */ static void waterfill_flagged(LEVEL *lv) { int x; int y; LOC *l; for (x=LEV_X-1;x>=0;x--) { l = &lv->cells[x][0]; for (y=LEV_Y-1;y>=0;y--) { if (l->flags & LF_FLAG) { l->flags |= LF_WATERFILL; l->flags &= ~LF_WATER_LOW; } l ++; } } } /* * Set up "areas", portions of the dungeon that are water-filled. We * look for areas with up stairs but no down stairs; each such area * has a chance, depending on its depth in the dungeon, of being * water-filled. * * The chance of an area, when found, being water-filled is zero * above/at LEVEL_NOWATER, increasing linearly to MAX_WATER at the * deepest level. * * We use LF_FLAG to mark an area we're working on, LF_FLAGB to mark an * area we've already looked at. */ void makeareas(void) { int x; int y; int z; LEVEL *lv; LOC *l; int ch; for (z=DUNGEON_LEVELS-1;z>=0;z--) { lv = &levels[z]; for (x=LEV_X-1;x>=0;x--) { l = &lv->cells[x][0]; for (y=LEV_Y-1;y>=0;y--) { l->flags &= ~ (LF_FLAG | LF_FLAGB); l ++; } } } for (z=DUNGEON_LEVELS-1;z>=0;z--) { lv = &levels[z]; if (lv->levelno <= LEVEL_NOWATER) continue; ch = 10000 * WATER_CHANCE(lv->levelno); for (x=LEV_X-1;x>=0;x--) { l = &lv->cells[x][LEV_Y]; for (y=LEV_Y-1;y>=0;y--) { l --; if ((l->type == LOC_CAVE) && !(l->flags & (LF_FLAG|LF_FLAGB))) { if (! flagarea(lv,x,y)) { if (rnd(10000) < ch) { waterfill_flagged(lv); } } flag_to_flagb(lv); } } } } }