Annotation of early-roguelike/arogue5/new_level.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * new_level: Dig and draw a new level
! 3: *
! 4: * Advanced Rogue
! 5: * Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
! 6: * All rights reserved.
! 7: *
! 8: * Based on "Rogue: Exploring the Dungeons of Doom"
! 9: * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 10: * All rights reserved.
! 11: *
! 12: * See the file LICENSE.TXT for full copyright and licensing information.
! 13: */
! 14:
! 15: #include "curses.h"
! 16: #include "rogue.h"
! 17: #define TERRASAVE 3
! 18:
! 19: void put_things(LEVTYPE ltype);
! 20:
! 21: /* ltype designates type of level to create */
! 22: void
! 23: new_level(LEVTYPE ltype)
! 24: {
! 25: register int rm = 0, i, cnt;
! 26: register char ch;
! 27: register struct linked_list *item;
! 28: register struct thing *tp;
! 29: register struct object *obj;
! 30: int waslit = 0; /* Was the previous outside level lit? */
! 31: int starty = 0, startx = 0, deltay = 0, deltax = 0;
! 32: bool fresh=TRUE, vert = 0, top;
! 33: struct room *rp;
! 34: struct linked_list *nitem, *savmonst=NULL, *savitems=NULL;
! 35: coord stairs = { 0, 0 };
! 36:
! 37: if (wizard) {
! 38: msg("Turns: %d", turns); /* Number of turns for last level */
! 39: mpos = 0;
! 40: }
! 41:
! 42: /* Start player off right */
! 43: turn_off(player, ISHELD);
! 44: turn_off(player, ISFLEE);
! 45: extinguish(suffocate);
! 46: hold_count = 0;
! 47: trap_tries = 0;
! 48:
! 49: /* Are we just entering a dungeon? If so, how big is it? */
! 50: if (ltype != OUTSIDE && nfloors < 0) nfloors = HARDER+10 + rnd(11);
! 51:
! 52: if (level > max_level)
! 53: max_level = level;
! 54:
! 55: /* Are we starting a new outside level? */
! 56: if (ltype == OUTSIDE) {
! 57: register int i, j;
! 58:
! 59: /* Save some information prior to clearing the screen */
! 60: if (level == -1 || mvinch(hero.y, hero.x) == '-') vert = TRUE;
! 61: else vert = FALSE;
! 62:
! 63: if (level == -1) {
! 64: fresh = TRUE;
! 65: starty = 2;
! 66: startx = 1;
! 67: deltay = deltax = 1;
! 68: level = 0; /* Restore the level */
! 69: }
! 70: else { /* Copy several lines of the terrain to the other end */
! 71: char cch; /* Copy character */
! 72:
! 73: /* Was the area dark (not magically lit)? */
! 74: if (!(rooms[0].r_flags & ISDARK)) waslit = 1;
! 75:
! 76: fresh = FALSE;
! 77: if ((vert && hero.y == 1) || (!vert && hero.x == 0)) top = TRUE;
! 78: else top = FALSE;
! 79: for (i=0; i<TERRASAVE; i++) {
! 80: if (vert)
! 81: for (j=1; j<COLS-1; j++) {
! 82: if (top) {
! 83: cch = CCHAR( mvinch(i+2, j) );
! 84: mvaddch(LINES-6+i, j, cch);
! 85: }
! 86: else {
! 87: cch = CCHAR( mvinch(LINES-4-i, j) );
! 88: mvaddch(4-i, j, cch);
! 89: }
! 90: }
! 91: else
! 92: for (j=2; j<LINES-3; j++) {
! 93: if (top) {
! 94: cch = CCHAR( mvinch(j, i+1) );
! 95: mvaddch(j, COLS-4+i, cch);
! 96: }
! 97: else {
! 98: cch = CCHAR( mvinch(j, COLS-2-i) );
! 99: mvaddch(j, 3-i, cch);
! 100: }
! 101: }
! 102: }
! 103:
! 104: if (vert) {
! 105: startx = deltax = 1;
! 106: if (top) {
! 107: starty = LINES-4-TERRASAVE;
! 108: deltay = -1;
! 109: }
! 110: else {
! 111: starty = TERRASAVE + 2;
! 112: deltay = 1;
! 113: }
! 114: }
! 115: else {
! 116: starty = 2;
! 117: deltay = 1;
! 118: if (top) {
! 119: startx = COLS-2-TERRASAVE;
! 120: deltax = -1;
! 121: }
! 122: else {
! 123: deltax = 1;
! 124: startx = TERRASAVE + 1;
! 125: }
! 126: }
! 127:
! 128: /* Check if any monsters should be saved */
! 129: for (item = mlist; item != NULL; item = nitem) {
! 130: nitem = next(item);
! 131: tp = THINGPTR(item);
! 132: if (vert) {
! 133: if (top) {
! 134: if (tp->t_pos.y < TERRASAVE + 2)
! 135: tp->t_pos.y += LINES - 5 - TERRASAVE;
! 136: else continue;
! 137: }
! 138: else {
! 139: if (tp->t_pos.y > LINES - 4 - TERRASAVE)
! 140: tp->t_pos.y += 5 + TERRASAVE - LINES;
! 141: else continue;
! 142: }
! 143: }
! 144: else {
! 145: if (top) {
! 146: if (tp->t_pos.x < TERRASAVE + 1)
! 147: tp->t_pos.x += COLS - 2 - TERRASAVE;
! 148: else continue;
! 149: }
! 150: else {
! 151: if (tp->t_pos.x > COLS - 2 - TERRASAVE)
! 152: tp->t_pos.x += 2 + TERRASAVE - COLS;
! 153: else continue;
! 154: }
! 155: }
! 156: detach(mlist, item);
! 157: attach(savmonst, item);
! 158: }
! 159:
! 160: /* Check if any treasure should be saved */
! 161: for (item = lvl_obj; item != NULL; item = nitem) {
! 162: nitem = next(item);
! 163: obj = OBJPTR(item);
! 164: if (vert) {
! 165: if (top) {
! 166: if (obj->o_pos.y < TERRASAVE + 2)
! 167: obj->o_pos.y += LINES - 5 - TERRASAVE;
! 168: else continue;
! 169: }
! 170: else {
! 171: if (obj->o_pos.y > LINES - 4 - TERRASAVE)
! 172: obj->o_pos.y += 5 + TERRASAVE - LINES;
! 173: else continue;
! 174: }
! 175: }
! 176: else {
! 177: if (top) {
! 178: if (obj->o_pos.x < TERRASAVE + 1)
! 179: obj->o_pos.x += COLS - 2 - TERRASAVE;
! 180: else continue;
! 181: }
! 182: else {
! 183: if (obj->o_pos.x > COLS - 2 - TERRASAVE)
! 184: obj->o_pos.x += 2 + TERRASAVE - COLS;
! 185: else continue;
! 186: }
! 187: }
! 188: detach(lvl_obj, item);
! 189: attach(savitems, item);
! 190: }
! 191: }
! 192: }
! 193:
! 194:
! 195: wclear(cw);
! 196: wclear(mw);
! 197: if (fresh) clear();
! 198: /*
! 199: * check to see if he missed a UNIQUE, If he did then put it back
! 200: * in the monster table for next time
! 201: */
! 202: for (item = mlist; item != NULL; item = next(item)) {
! 203: tp = THINGPTR(item);
! 204: if (on(*tp, ISUNIQUE))
! 205: monsters[tp->t_index].m_normal = TRUE;
! 206: }
! 207: /*
! 208: * Free up the monsters on the last level
! 209: */
! 210: t_free_list(monst_dead);
! 211: t_free_list(mlist);
! 212: o_free_list(lvl_obj); /* Free up previous objects (if any) */
! 213: for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
! 214: t_free_list(rp->r_exit); /* Free up the exit lists */
! 215:
! 216: levtype = ltype;
! 217: foods_this_level = 0; /* food for hero this level */
! 218: if (ltype == POSTLEV) {
! 219: do_post(); /* do post stuff */
! 220: }
! 221: else if (ltype == MAZELEV) {
! 222: do_maze();
! 223: no_food++;
! 224: put_things(ltype); /* Place objects (if any) */
! 225: }
! 226: else if (ltype == OUTSIDE) {
! 227: init_terrain();
! 228: do_terrain(starty, startx, deltay, deltax, (bool) (fresh || !vert));
! 229: no_food++;
! 230: put_things(ltype);
! 231:
! 232: /* Should we magically light this area? */
! 233: if (waslit) rooms[0].r_flags &= ~ISDARK;
! 234: }
! 235: else {
! 236: do_rooms(); /* Draw rooms */
! 237: do_passages(); /* Draw passages */
! 238: no_food++;
! 239: put_things(ltype); /* Place objects (if any) */
! 240: }
! 241: /*
! 242: * Place the staircase down. Only a small chance for an outside stairway.
! 243: */
! 244: if (ltype != OUTSIDE || roll(1, 4) == 4) {
! 245: cnt = 0;
! 246: do {
! 247: rm = rnd_room();
! 248: rnd_pos(&rooms[rm], &stairs);
! 249: } until (mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
! 250: addch(STAIRS);
! 251: }
! 252: /*
! 253: * maybe add a trading post
! 254: */
! 255: if (level > 5 && rnd(11) == 7 && ltype == NORMLEV) {
! 256: cnt = 0;
! 257: do {
! 258: rm = rnd_room();
! 259: if (rooms[rm].r_flags & ISTREAS)
! 260: continue;
! 261: rnd_pos(&rooms[rm], &stairs);
! 262: } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
! 263: addch(POST);
! 264: }
! 265: if (ltype != POSTLEV) { /* Add monsters that fell through */
! 266: nitem = tlist;
! 267: while (nitem != NULL) {
! 268: item = nitem;
! 269: nitem = next(item); /* because detach and attach mess up ptrs */
! 270: tp = THINGPTR(item);
! 271: cnt = 0;
! 272: do {
! 273: rm = rnd_room();
! 274: rnd_pos(&rooms[rm], &tp->t_pos);
! 275: } until (cnt++ > 5000 || winat(tp->t_pos.y, tp->t_pos.x) == FLOOR);
! 276: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
! 277: tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
! 278:
! 279: /*
! 280: * If it has a fire, mark it
! 281: */
! 282: if (on(*tp, HASFIRE)) {
! 283: register struct linked_list *fire_item;
! 284:
! 285: fire_item = creat_item();
! 286: ldata(fire_item) = (char *) tp;
! 287: attach(rooms[rm].r_fires, fire_item);
! 288: rooms[rm].r_flags |= HASFIRE;
! 289: }
! 290: turn_off(*tp, ISELSEWHERE);
! 291: detach(tlist, item);
! 292: attach(mlist, item);
! 293: }
! 294: }
! 295:
! 296: /* Restore any saved monsters */
! 297: for (item = savmonst; item != NULL; item = nitem) {
! 298: nitem = next(item);
! 299: tp = THINGPTR(item);
! 300: mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, tp->t_type);
! 301: tp->t_oldch = CCHAR( mvwinch(cw, tp->t_pos.y, tp->t_pos.x) );
! 302:
! 303: /*
! 304: * If it has a fire, mark it
! 305: */
! 306: if (on(*tp, HASFIRE)) {
! 307: register struct linked_list *fire_item;
! 308:
! 309: fire_item = creat_item();
! 310: ldata(fire_item) = (char *) tp;
! 311: attach(rooms[rm].r_fires, fire_item);
! 312: rooms[rm].r_flags |= HASFIRE;
! 313: }
! 314:
! 315: detach(savmonst, item);
! 316: attach(mlist, item);
! 317: }
! 318:
! 319: /* Restore any saved objects */
! 320: for(item = savitems; item != NULL; item = nitem) {
! 321: nitem = next(item);
! 322: obj = OBJPTR(item);
! 323: mvaddch(obj->o_pos.y, obj->o_pos.x, obj->o_type);
! 324: detach(savitems, item);
! 325: attach(lvl_obj, item);
! 326: }
! 327:
! 328:
! 329: /*
! 330: * Place the traps (except for trading post)
! 331: */
! 332: ntraps = 0; /* No traps yet */
! 333: if (levtype == NORMLEV) {
! 334: if (rnd(10) < vlevel) {
! 335: ntraps = rnd(vlevel/4)+1;
! 336: if (ntraps > MAXTRAPS)
! 337: ntraps = MAXTRAPS;
! 338: i = ntraps;
! 339: while (i--)
! 340: {
! 341: cnt = 0;
! 342: do {
! 343: rm = rnd_room();
! 344: if (rooms[rm].r_flags & ISTREAS)
! 345: continue;
! 346: rnd_pos(&rooms[rm], &stairs);
! 347: } until (winat(stairs.y, stairs.x) == FLOOR || cnt++ > 5000);
! 348:
! 349: traps[i].tr_flags = 0;
! 350:
! 351: /* If we are at the bottom, we can't set a trap door */
! 352: if (level >= nfloors) ch = (char) rnd(7) + 1;
! 353: else ch = (char) rnd(8);
! 354:
! 355: switch((int) ch) {
! 356: case 0: ch = TRAPDOOR;
! 357: when 1: ch = BEARTRAP;
! 358: when 2: ch = SLEEPTRAP;
! 359: when 3: ch = ARROWTRAP;
! 360: when 4: ch = TELTRAP;
! 361: when 5: ch = DARTTRAP;
! 362: when 6: ch = POOL;
! 363: traps[i].tr_flags = ISFOUND;
! 364: when 7: ch = MAZETRAP;
! 365: }
! 366: addch(ch);
! 367: traps[i].tr_type = ch;
! 368: traps[i].tr_show = FLOOR;
! 369: traps[i].tr_pos = stairs;
! 370: }
! 371: }
! 372: }
! 373: if (fresh) { /* A whole new picture */
! 374: cnt = 0;
! 375: do {
! 376: rm = rnd_room();
! 377: if (rooms[rm].r_flags & ISTREAS)
! 378: continue;
! 379: rnd_pos(&rooms[rm], &hero);
! 380: } until( cnt++ > 5000 ||
! 381: (winat(hero.y, hero.x) == FLOOR &&
! 382: DISTANCE(hero.y, hero.x, stairs.y, stairs.x) > 16));
! 383: }
! 384: else { /* We're extending into an adjacent outside plane */
! 385: rm = 0;
! 386: if (vert) {
! 387: if (hero.y == 1) hero.y = LINES - 3 - TERRASAVE; /* Top to bottom */
! 388: else hero.y = TERRASAVE + 1; /* Bottom to top */
! 389: }
! 390: else {
! 391: if (hero.x == 0) hero.x = COLS - 1 - TERRASAVE; /* Right to left */
! 392: else hero.x = TERRASAVE; /* Left to right */
! 393: }
! 394: }
! 395: oldrp = &rooms[rm]; /* Set the current room */
! 396: player.t_oldpos = player.t_pos; /* Set the current position */
! 397: if (ISWEARING(R_AGGR) ||
! 398: (cur_misc[WEAR_JEWEL] != NULL &&
! 399: cur_misc[WEAR_JEWEL]->o_which == MM_JEWEL))
! 400: aggravate();
! 401: light(&hero);
! 402: wmove(cw, hero.y, hero.x);
! 403: waddch(cw, PLAYER);
! 404:
! 405: if (level > cur_max)
! 406: cur_max = level;
! 407:
! 408: status(TRUE);
! 409: }
! 410:
! 411: /*
! 412: * Pick a room that is really there
! 413: */
! 414:
! 415: int
! 416: rnd_room(void)
! 417: {
! 418: register int rm;
! 419:
! 420: if (levtype != NORMLEV)
! 421: rm = 0;
! 422: else do
! 423: {
! 424: rm = rnd(MAXROOMS);
! 425: } while (rooms[rm].r_flags & ISGONE);
! 426: return rm;
! 427: }
! 428:
! 429: /*
! 430: * put_things:
! 431: * put potions and scrolls on this level
! 432: * ltype: designates type of level to create
! 433: */
! 434:
! 435: void
! 436: put_things(LEVTYPE ltype)
! 437: {
! 438: register int i, rm, cnt;
! 439: register struct object *cur;
! 440: register struct linked_list *item, *exitptr;
! 441: bool got_unique = FALSE;
! 442: int length, width;
! 443: coord tp, *exit;
! 444:
! 445: /*
! 446: * The only way to get new stuff is to go down into the dungeon.
! 447: */
! 448: if (level <= cur_max)
! 449: return;
! 450:
! 451: /*
! 452: * There is a chance that there is a treasure room on this level
! 453: * Increasing chance after level 9
! 454: */
! 455: if (ltype != MAZELEV && rnd(HARDER) < level - 8) {
! 456: register int j;
! 457: register struct room *rp;
! 458:
! 459: /* Count the number of free spaces */
! 460: i = 0; /* 0 tries */
! 461: do {
! 462: rp = &rooms[rnd_room()];
! 463: width = rp->r_max.y - 2;
! 464: length = rp->r_max.x - 2;
! 465: } until ((width*length >= MAXTREAS) || (i++ > MAXROOMS*4));
! 466:
! 467: /* Mark the room as a treasure room */
! 468: rp->r_flags |= ISTREAS;
! 469:
! 470: /* Make all the doors secret doors */
! 471: for (exitptr = rp->r_exit; exitptr; exitptr = next(exitptr)) {
! 472: exit = DOORPTR(exitptr);
! 473: move(exit->y, exit->x);
! 474: addch(SECRETDOOR);
! 475: }
! 476:
! 477: /*
! 478: * check to see if there are any monsters in room already
! 479: */
! 480: for (item = mlist; item != NULL; item = next(item)) {
! 481: register struct thing *tp;
! 482:
! 483: tp = THINGPTR(item);
! 484: if (rp == roomin(&tp->t_pos)) {
! 485: turn_on(*tp, ISMEAN);
! 486: if (off(*tp, CANINWALL)) {
! 487: tp->t_dest = &hero;
! 488: turn_on(*tp, ISRUN);
! 489: }
! 490: if (on(*tp, ISUNIQUE))
! 491: got_unique = TRUE;
! 492:
! 493: /* If it is a mimic, undisguise it */
! 494: if (on(*tp, ISDISGUISE))
! 495: turn_off(*tp, ISDISGUISE);
! 496: }
! 497: }
! 498:
! 499:
! 500: /* Put in the monsters and treasures */
! 501: for (j=1; j<rp->r_max.y-1; j++)
! 502: for (i=1; i<rp->r_max.x-1; i++) {
! 503: coord trp;
! 504:
! 505: trp.y = rp->r_pos.y+j;
! 506: trp.x = rp->r_pos.x+i;
! 507:
! 508: /* Monsters */
! 509: if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
! 510: (mvwinch(mw, rp->r_pos.y+j, rp->r_pos.x+i) == ' ')) {
! 511: register struct thing *tp;
! 512:
! 513: /* Make a monster */
! 514: item = new_item(sizeof *tp);
! 515: tp = THINGPTR(item);
! 516:
! 517: /*
! 518: * Put it there and aggravate it (unless it can escape)
! 519: * only put one UNIQUE per treasure room at most
! 520: */
! 521: if (got_unique)
! 522: new_monster(item,randmonster(FALSE, TRUE),&trp,TRUE);
! 523: else
! 524: new_monster(item,randmonster(FALSE, FALSE),&trp,TRUE);
! 525: if (on(*tp, ISUNIQUE)) {
! 526: got_unique = TRUE;
! 527: carry_obj(tp, monsters[tp->t_index].m_carry);
! 528: }
! 529: turn_on(*tp, ISMEAN);
! 530: if (off(*tp, CANINWALL)) {
! 531: tp->t_dest = &hero;
! 532: turn_on(*tp, ISRUN);
! 533: }
! 534:
! 535: /* If it is a mimic, undisguise it */
! 536: if (on(*tp, ISDISGUISE))
! 537: turn_off(*tp, ISDISGUISE);
! 538:
! 539: if (on(*tp, HASFIRE)) {
! 540: register struct linked_list *fire_item;
! 541:
! 542: fire_item = creat_item();
! 543: ldata(fire_item) = (char *) tp;
! 544: attach(rp->r_fires, fire_item);
! 545: rp->r_flags |= HASFIRE;
! 546: }
! 547: }
! 548:
! 549: /* Treasures */
! 550: if ((rnd(100) < (MAXTREAS*100)/(width*length)) &&
! 551: (mvinch(rp->r_pos.y+j, rp->r_pos.x+i) == FLOOR)) {
! 552: item = new_thing(ALL);
! 553: attach(lvl_obj, item);
! 554: cur = OBJPTR(item);
! 555:
! 556: mvaddch(trp.y, trp.x, cur->o_type);
! 557: cur->o_pos = trp;
! 558: }
! 559: }
! 560: }
! 561:
! 562: /*
! 563: * Do MAXOBJ attempts to put things on a level
! 564: */
! 565: for (i = 0; i < MAXOBJ; i++)
! 566: if (rnd(100) < 45) {
! 567: /*
! 568: * Pick a new object and link it in the list
! 569: */
! 570: item = new_thing(ALL);
! 571: attach(lvl_obj, item);
! 572: cur = OBJPTR(item);
! 573: /*
! 574: * Put it somewhere
! 575: */
! 576: cnt = 0;
! 577: do {
! 578: rm = rnd_room();
! 579: rnd_pos(&rooms[rm], &tp);
! 580: } until (winat(tp.y, tp.x) == FLOOR || cnt++ > 500);
! 581: mvaddch(tp.y, tp.x, cur->o_type);
! 582: cur->o_pos = tp;
! 583: }
! 584: }
CVSweb