/* * Dig shops. * * Shops are very stylized in this version: they are all * single-rectangle areas with a door from which a straight corridor * leads to somewhere accessible. * * Arguably, a shop should be any suitably-sized piece of the dungeon * that has a cutpoint we can put a door at to separate it from the * rest of the level; this then opens the door to multi-level shops * and the like. I'm not sure whether I like that idea; I may * implement it and see what the results look like. */ #include #include #include "vars.h" #include "dice.h" #include "pline.h" #include "structs.h" #include "digdoors.h" #include "digdungeon.h" #include "digshops.h" #if 0 /* * These are debugger assist. The #if 0 code below is more debugger * assist. The blocks saying "base64 -d | gunzip" are compressed (and * encoded to make them safe for a #if 0 block); that command decodes * and decompresses them. */ static WINDOW *ss; static void PAUSE(void) { refresh(); getch(); } static void mach(int x, int y, char c) { mvaddch(x,y,c); } #endif /* * Return true if there are no shop cells on the direct line from (x,y) * in direction (dx,dy) before reaching (tx,ty). It is the caller's * responsibility to ensure that (tx,ty)-(x,y) is a positive integer * multiple of (dx,dy). * * This is used to test shop door positions; see shopok(), below. */ static int shopdoorok(LEVEL *lp, int x, int y, int dx, int dy, int tx, int ty) { LOC *l; while ((x != tx) || (y != ty)) { l = &lp->cells[x][y]; if (l->flags & LF_SHOP) return(0); x += dx; y += dy; } return(1); } /* * Test whether position (xp,yp) size (sx,sy) is suitable for a shop; * if so, set *dpxp and *dpyp to a suitable door position. * * The door position is chosen randomly from among all positions for * which shopdoorok returns true. If there are no such positions, we * return zero. * * A door position is acceptable if a line run straight from it away * from the shop reaches non-shop cave before reaching another shop or * the edge of the level; this is tested by looking for CAVE cells on * an orthogonal away from the shop and seeing if there are any for * which no SHOP cells occur between the putative door location and * the CAVE cell. (This is what shopdoorok is designed to test.) */ static int shopok(LEVEL *lp, int sx, int sy, int xp, int yp, int *dpxp, int *dpyp) { int x; int y; int n; int dx; int dy; n = 1; #if 0 base64 -d | gunzip H4sIADqiBDoCAysuScxLyS8t0dC05sotS0xJSc7QqCzQqSjQUddTRxHTNQSKAgl1 B3V0tdrFFSAJbBrAUtqYurSLK8HyGLrAEto47ILpwm4hQiuqrcUgP6bmpYD8GOAY GuwKYpQWpKRkFhcYaajlFOjaJafm5BRHVxTERlcWxOoY4pTXNQSpAJJ41IBUgJ1C 2CCoi/EpBHuFkLOg/iXsNrhpBB2IZCSKKwHHoU4OMQIAAA== #endif for (x=0;xcells[x][y+yp].type == LOC_CAVE) { if (shopdoorok(lp,x,y+yp,(xcells[x+xp][y].type == LOC_CAVE) { if (shopdoorok(lp,x+xp,y,0,(y= xp+sx) { *dpxp = xp + sx; *dpyp = dy; } else if (dy < yp) { *dpxp = dx; *dpyp = yp - 1; } else if (dy >= yp+sy) { *dpxp = dx; *dpyp = yp + sy; } else { panic("impossible (dx,dy) in shopok"); } #if 0 base64 -d | gunzip H4sIAGuiBDoCAysuScxLyS8t0dC05sotS0xJSc7QqCzQqSjQUddTRxHTNQSKAgl1 B3V0tdrFFSAJbBrAUtqYurSLK8HyGLrAEto47ILpwm4hQit2W7VSCoDOBZIga5VB MsUg36fmpYB8H+AYGuwKYpQWpKRkFhcYaajlFOjaJafm5BRHgzXFRoNNiNUxxKEK pAS/vK4hSAWQJGAG2CuEDYL6GJ9CcFAQchY0vAi7DW4aQQciGYniSgAFxNRbcQIA AA== #endif return(1); } /* * Given a position (xp,yp), size (sx,sy), and doorway location * (doorx,doory), dig a shop. The caller is responsible for making * sure the shop size, position, and doorway location are suitable for * the level. This also digs corridor from the shop door out to the * nearest CAVE cell. It is the caller's responsibility to ensure * there is such a CAVE cell (this is one thing shopok() tests). */ static void digshop(LEVEL *lp, int sx, int sy, int xp, int yp, int doorx, int doory) { int x; int y; SHOP *s; s = malloc(sizeof(SHOP)); s->link = lp->shops; lp->shops = s; s->on = lp; s->shkname = "Foo"; s->type = SHOP_BASETYPE + rnd(SHOP_NTYPES); s->pos.x = xp; s->pos.y = yp; s->size.x = sx; s->size.y = sy; s->door.x = doorx; s->door.y = doory; if ((xp < 1) || (yp < 1) || (xp+sx >= LEV_X) || (yp+sy >= LEV_Y)) panic("bad location in digshop"); for (x=0;xcells[xp+x][yp+y].flags |= LF_SHOP; if (doorx < xp) { sx = -1; sy = 0; } else if (doorx >= xp+sx) { sx = 1; sy = 0; } else if (doory < yp) { sx = 0; sy = -1; } else if (doory >= yp+sy) { sx = 0; sy = 1; } else { panic("impossible door position in digshop"); } x = doorx; y = doory; while (1) { if (lp->cells[x][y].type == LOC_CAVE) break; digcell(lp,x,y); if ( (lp->cells[x+sy][y+sx].type == LOC_CAVE) || (lp->cells[x-sy][y-sx].type == LOC_CAVE) ) break; x += sx; y += sy; } digdoor(lp,doorx,doory,0,onein(3)); lp->cells[doorx][doory].flags |= LF_SHOP; #if 0 lvdisp(lp);PAUSE(); #endif } /* * Dig shops on a level. Some levels shouldn't have shops at all; for * other levels, loop, randomly picking a shop size and then, up to a * fixed number of tries, looking for a spot for it. */ static void digshops(LEVEL *lv) { /* no shops on elemental planes, underworld, hell */ if ((lv->index < 0) || (lv->index >= DUNGEON_LEVELS)) return; while (onein(2)) { int x; int y; int sx; int sy; int nt; int dpx; int dpy; #if 0 lvdisp(lv);PAUSE(); #endif do { sx = roll("2d5"); sy = roll("d4+1"); } while (sx+sy < 6); for (nt=20;nt>0;nt--) { x = 1 + rnd(LEV_X-2-sx); y = 1 + rnd(LEV_Y-2-sy); #if 0 /* base64 -d | gunzip */ H4sIAJ7CIToCAysuScxLyS8t0dC05sotS0xJSc7QqNSp0FHXUkcW0TXUqQBiNFGd Cu1iLMIgxWAJbQwp7WKwLFZhbax2QHVgtQiuDdW2YpCfUvNSQH4qSk0rSi3OADFL C1JSMosLjDTUcsp07ZJTc3KKoytioytjdQxxyeoaAuWBBG4VQHmwKwgZAnUqHmVg P+B3DtSbhNwEM4mQwxDGobgOAAfRVA4TAgAA #endif if (solidrock(lv,sx,sy,x,y) && shopok(lv,sx,sy,x,y,&dpx,&dpy)) { digshop(lv,sx,sy,x,y,dpx,dpy); break; } } } } /* * Create shops as appropriate throughout the dungeon. */ void makeshops(void) { int l; #if 0 ss = stdscr; #endif for (l=0;l