#include #include "vars.h" #include "dice.h" #include "pline.h" #include "digdungeon.h" #include "digspecial.h" extern const char *underworld_quarters[]; extern const char *hell_quarters[]; #define PAUSE() ((int)refresh(),(int)getch()) static LOC *avoidloc; static int ckgateok(LOC *lc) { int iscave[8]; int i; int j; if ((lc->type != LOC_CAVE) || (lc->cavetype != LOC_JUSTCAVE)) { return(0); } if (lc->on->flags & LVF_WRAPAROUND) { return(1); } for (i=0;i<8;i++) { iscave[i] = (lc->on->cells[lc->x+delta[i][0]][lc->y+delta[i][1]].type == LOC_CAVE); } j = 0; for (i=0;i<8;i++) { if (iscave[i] != iscave[(i+1)%8]) { j ++; } } return(j==2); } static int ckavoid(LOC *lc) { int dx; int dy; if ((lc->type != LOC_CAVE) || (lc->cavetype != LOC_JUSTCAVE)) { return(0); } dx = lc->x - avoidloc->x; if (dx < 0) dx = - dx; dy = lc->y - avoidloc->y; if (dy < 0) dy = - dy; if (dx+dy < 20) { return(0); } return(1); } static int ckflag(LOC *lc) { return( (lc->type == LOC_CAVE) && (lc->cavetype == LOC_JUSTCAVE) && (lc->flags & LF_FLAG) ); } static int ckavflag(LOC *lc) { int dx; int dy; if ( (lc->type != LOC_CAVE) || (lc->cavetype != LOC_JUSTCAVE) || !(lc->flags & LF_FLAG) ) return(0); dx = lc->x - avoidloc->x; if (dx < 0) dx = - dx; dy = lc->y - avoidloc->y; if (dy < 0) dy = - dy; if (dx+dy < 20) { return(0); } return(1); } LOC *randomloc(LEVEL *lv, int (*ckf)(LOC *), int maxl) { LOC *lc; do { lc = &lv->cells[rnd(LEV_X)][rnd(LEV_Y)]; } while (ckf && !(*ckf)(lc) && (--maxl != 0)); return(lc); } static void make_earth(void) { LEVEL *lp; lp = &levels[L_EARTH]; lp->levelno = L_EARTH; lp->index = L_EARTH; lp->shortname = "Earth"; lp->longname = "Plane of Earth"; lp->flags = LVF_WRAPAROUND; lp->visibility = 2; clearlevel(lp,LOC_CAVE); } static void make_air(void) { LEVEL *lp; lp = &levels[L_AIR]; lp->levelno = L_AIR; lp->index = L_AIR; lp->shortname = "Air"; lp->longname = "Plane of Air"; lp->flags = LVF_WRAPAROUND | LVF_DRIFT; lp->visibility = 10; clearlevel(lp,LOC_CAVE); /* make clouds */ } static void make_water(void) { LEVEL *lp; lp = &levels[L_WATER]; lp->levelno = L_WATER; lp->index = L_WATER; lp->shortname = "Water"; lp->longname = "Plane of Water"; lp->flags = LVF_WRAPAROUND | LVF_DRIFT; lp->visibility = 3; clearlevel(lp,LOC_CAVE); } static void make_fire(void) { LEVEL *lp; lp = &levels[L_FIRE]; lp->levelno = L_FIRE; lp->index = L_FIRE; lp->shortname = "Fire"; lp->longname = "Plane of Fire"; lp->flags = LVF_WRAPAROUND; lp->visibility = 6; clearlevel(lp,LOC_CAVE); } static void make_underworld(void) { LEVEL *lp; lp = &levels[L_UNDERWORLD]; lp->levelno = L_UNDERWORLD; lp->index = L_UNDERWORLD; lp->shortname = "Underworld"; lp->longname = "Underworld"; lp->visibility = 7; } static void make_hell(void) { LEVEL *lp; lp = &levels[L_HELL]; lp->levelno = L_HELL; lp->index = L_HELL; lp->shortname = "Hell"; lp->longname = "Hell"; lp->visibility = 7; } static void level_from_quarters(LEVEL *lv, const char **qs) { static int xreset[4] = { 0, 0, LEV_X-1, LEV_X-1 }; static int yreset[4] = { 0, LEV_Y-1, 0, LEV_Y-1 }; static int xinc[4] = { 1, 1, -1, -1 }; static int yinc[4] = { 1, -1, 1, -1 }; int qnos[4]; int nq; int i; int j; int x; int y; int dx; int dy; int xc; int yc; const char *qp; clearlevel(lv,LOC_ROCK); for (nq=0;qs[nq];nq++) ; if (nq < 4) { panic("Not enough quarters in level_from_quarters"); } for (i=0;i<4;i++) { qnos[i] = rnd(nq-i); } for (i=3;i>0;i--) { for (j=i-1;j>=0;j--) { if (qnos[i] >= qnos[j]) { qnos[i] ++; } } } for (i=3;i>0;i--) { for (j=i-1;j>=0;j--) { if (qnos[i] == qnos[j]) { panic("identical quarters chosen: %d %d %d %d", qnos[0],qnos[1],qnos[2],qnos[3]); } } } for (i=0;i<4;i++) { qp = qs[qnos[i]]; dx = xinc[i]; dy = yinc[i]; y = yreset[i]; for (yc=LEV_Y/2;yc>0;yc--) { x = xreset[i]; for (xc=LEV_X/2;xc>0;xc--) { switch (*qp++) { case 'O': lv->cells[x][y].flags &= ~LF_FLAGB; break; case 'N': lv->cells[x][y].flags |= LF_FLAGB; break; case '#': digcell(lv,x,y); lv->cells[x][y].flags &= ~LF_FLAG; lv->cells[x][y].flags |= LF_FLAGB; lv->cells[x][y].type = LOC_SDOOR; lv->cells[x][y].walldoor = LOC_UWALL; break; case '.': digcell(lv,x,y); lv->cells[x][y].flags &= ~(LF_FLAG|LF_FLAGB); break; case '_': digcell(lv,x,y); lv->cells[x][y].flags |= LF_FLAG; lv->cells[x][y].flags &= ~LF_FLAGB; break; default: panic("Bad character 0%o in quarter",0xff&(int)qp[-1]); break; } x += dx; } y += dy; } } } static void makegate(LOC *ob, LOC *ib) { ob->on->gate_ob = ob; ib->on->gate_ib = ib; ob->type = LOC_GATE; ob->gatetype = LOC_GATE_IN; ob->to = ib; ib->type = LOC_GATE; ib->gatetype = LOC_GATE_OUT; ib->to = ob; } void makespeciallevels(void) { static int lvshuffle[4] = { L_EARTH, L_AIR, L_FIRE, L_WATER }; int i; LEVEL *llv; LEVEL *lv; LOC *g1; LOC *g2; make_earth(); make_air(); make_water(); make_fire(); for (i=0;i<4;i++) { int j; j = rnd(4); if (j != i) { int t; t = lvshuffle[i]; lvshuffle[i] = lvshuffle[j]; lvshuffle[j] = t; } } llv = &levels[GATE_LEVEL-1]; g1 = randomloc(llv,&ckgateok,-1); for (i=0;i<4;i++) { lv = &levels[lvshuffle[i]]; g2 = randomloc(lv,0,-1); makegate(g1,g2); avoidloc = g2; g1 = randomloc(lv,&ckavoid,-1); } make_underworld(); lv = &levels[L_UNDERWORLD]; level_from_quarters(lv,underworld_quarters); g2 = randomloc(lv,&ckflag,-1); makegate(g1,g2); avoidloc = g2; g1 = randomloc(lv,&ckavflag,-1); make_hell(); lv = &levels[L_HELL]; level_from_quarters(lv,hell_quarters); g2 = randomloc(lv,&ckflag,-1); makegate(g1,g2); }