Annotation of early-roguelike/urogue/newlvl.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: newlvl.c - Dig and draw a new level
! 3:
! 4: UltraRogue: The Ultimate Adventure in the Dungeons of Doom
! 5: Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong
! 6: All rights reserved.
! 7:
! 8: Based on "Advanced Rogue"
! 9: Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka
! 10: All rights reserved.
! 11:
! 12: Based on "Rogue: Exploring the Dungeons of Doom"
! 13: Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
! 14: All rights reserved.
! 15:
! 16: See the file LICENSE.TXT for full copyright and licensing information.
! 17: */
! 18:
! 19: /*
! 20: Notes
! 21:
! 22: Add treasure room code from Rogue 5.2,
! 23: put in #ifdef 0/#endif bracket at end of code
! 24: */
! 25:
! 26: #include "rogue.h"
! 27:
! 28: /*
! 29: new_level()
! 30: Dig and draw a new level
! 31: */
! 32:
! 33: void
! 34: new_level(LEVTYPE ltype, int special)
! 35: {
! 36: int rm, i, cnt;
! 37: struct linked_list *item, *nitem;
! 38: struct thing *tp;
! 39: struct linked_list *fpack = NULL;
! 40: int going_down = TRUE;
! 41: coord stairs;
! 42:
! 43: /* Start player off right */
! 44:
! 45: turn_off(player, ISHELD);
! 46: turn_off(player, ISFLEE);
! 47: extinguish_fuse(FUSE_SUFFOCATE);
! 48: hold_count = 0;
! 49: trap_tries = 0;
! 50: no_food++;
! 51:
! 52: if (level >= max_level)
! 53: max_level = level;
! 54: else
! 55: going_down = FALSE;
! 56:
! 57: /* Free up the monsters on the last level */
! 58:
! 59: if (fam_ptr != NULL) /* save what familiar is carrying */
! 60: {
! 61: fpack = (THINGPTR(fam_ptr))->t_pack;
! 62: (THINGPTR(fam_ptr))->t_pack = NULL;
! 63: fam_ptr = NULL; /* just in case */
! 64: }
! 65:
! 66: for (i = 1; i <= mons_summoned; i++)
! 67: extinguish_fuse(FUSE_UNSUMMON);
! 68:
! 69: mons_summoned = 0;
! 70:
! 71: for (item = mlist; item != NULL; item = nitem)
! 72: {
! 73: tp = THINGPTR(item);
! 74: nitem = next(item);
! 75:
! 76: if (on(*tp, ISUNIQUE)) /* Put alive UNIQUE on next level */
! 77: monsters[tp->t_index].m_normal = TRUE;
! 78:
! 79: killed(NULL, item, NOMESSAGE, NOPOINTS);
! 80: }
! 81:
! 82: free_list(lvl_obj); /* Free up previous objects (if any) */
! 83:
! 84: wclear(cw);
! 85: wclear(mw);
! 86: clear();
! 87: refresh();
! 88: levtype = ltype;
! 89:
! 90: switch (ltype)
! 91: {
! 92: case THRONE:
! 93: do_throne(special); /* do monster throne stuff */
! 94: break;
! 95:
! 96: case MAZELEV:
! 97: do_maze();
! 98: break;
! 99:
! 100: case POSTLEV:
! 101: do_post();
! 102: levtype = ltype = NORMLEV;
! 103: level++;
! 104:
! 105: default:
! 106: do_rooms(); /* Draw rooms */
! 107: do_passages(); /* Draw passages */
! 108: break;
! 109: }
! 110:
! 111: /* Place the staircase down. */
! 112:
! 113: cnt = 0;
! 114:
! 115: do
! 116: {
! 117: rm = rnd_room();
! 118: rnd_pos(&rooms[rm], &stairs);
! 119: }
! 120: while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000));
! 121:
! 122: addch(STAIRS);
! 123:
! 124: put_things(ltype); /* Place objects (if any) */
! 125:
! 126: if (has_artifact && level == 1)
! 127: create_lucifer(&stairs);
! 128:
! 129: /* Place the traps */
! 130:
! 131: ntraps = 0; /* No traps yet */
! 132:
! 133: if (levtype == NORMLEV)
! 134: {
! 135: if (rnd(10) < level)
! 136: {
! 137: char ch = 0;
! 138:
! 139: i = ntraps = min(MAXTRAPS, rnd(level / 2) + 1);
! 140:
! 141: /* maybe a lair */
! 142:
! 143: if (level > 35 && ltype == NORMLEV && rnd(wizard ? 3 : 10) == 0)
! 144: {
! 145: cnt = 0;
! 146:
! 147: do
! 148: {
! 149: rm = rnd_room();
! 150:
! 151: if (rooms[rm].r_flags & ISTREAS)
! 152: continue;
! 153:
! 154: rnd_pos(&rooms[rm], &stairs);
! 155: }
! 156: while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000));
! 157:
! 158: addch(LAIR);
! 159: i--;
! 160: traps[i].tr_flags = 0;
! 161: traps[i].tr_type = LAIR;
! 162: traps[i].tr_show = FLOOR;
! 163: traps[i].tr_pos = stairs;
! 164: }
! 165:
! 166: while (i--)
! 167: {
! 168: cnt = 0;
! 169:
! 170: do
! 171: {
! 172: rm = rnd_room();
! 173:
! 174: if (rooms[rm].r_flags & ISTREAS)
! 175: continue;
! 176:
! 177: rnd_pos(&rooms[rm], &stairs);
! 178: }
! 179: while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000));
! 180:
! 181: traps[i].tr_flags = 0;
! 182:
! 183: switch (rnd(11))
! 184: {
! 185: case 0:
! 186: ch = TRAPDOOR;
! 187: break;
! 188:
! 189: case 1:
! 190: ch = BEARTRAP;
! 191: break;
! 192:
! 193: case 2:
! 194: ch = SLEEPTRAP;
! 195: break;
! 196:
! 197: case 3:
! 198: ch = ARROWTRAP;
! 199: break;
! 200:
! 201: case 4:
! 202: ch = TELTRAP;
! 203: break;
! 204:
! 205: case 5:
! 206: ch = DARTTRAP;
! 207: break;
! 208:
! 209: case 6:
! 210: ch = POOL;
! 211:
! 212: if (rnd(10))
! 213: traps[i].tr_flags = ISFOUND;
! 214:
! 215: break;
! 216:
! 217: case 7:
! 218: ch = MAZETRAP;
! 219: break;
! 220:
! 221: case 8:
! 222: ch = FIRETRAP;
! 223: break;
! 224:
! 225: case 9:
! 226: ch = POISONTRAP;
! 227: break;
! 228:
! 229: case 10:
! 230: ch = RUSTTRAP;
! 231: break;
! 232: }
! 233:
! 234: addch(ch);
! 235: traps[i].tr_type = ch;
! 236: traps[i].tr_show = FLOOR;
! 237: traps[i].tr_pos = stairs;
! 238: }
! 239: }
! 240: }
! 241:
! 242: do /* Position hero */
! 243: {
! 244: rm = rnd_room();
! 245:
! 246: if (levtype != THRONE && (rooms[rm].r_flags & ISTREAS))
! 247: continue;
! 248:
! 249: rnd_pos(&rooms[rm], &hero);
! 250: }
! 251: while(!(winat(hero.y, hero.x) == FLOOR &&
! 252: DISTANCE(hero, stairs) > 16));
! 253:
! 254: oldrp = &rooms[rm]; /* Set the current room */
! 255: player.t_oldpos = player.t_pos; /* Set the current position */
! 256:
! 257: if (levtype != POSTLEV && levtype != THRONE)
! 258: {
! 259: if (on(player, BLESSMAP) && rnd(5) == 0)
! 260: {
! 261: read_scroll(&player, S_MAP, ISNORMAL);
! 262:
! 263: if (rnd(3) == 0)
! 264: turn_off(player, BLESSMAP);
! 265: }
! 266:
! 267: if (player.t_ctype == C_THIEF || on(player, BLESSGOLD) && rnd(5) == 0)
! 268: {
! 269: read_scroll(&player, S_GFIND, ISNORMAL);
! 270:
! 271: if (rnd(3) == 0)
! 272: turn_off(player, BLESSGOLD);
! 273: }
! 274:
! 275: if (player.t_ctype == C_RANGER || on(player, BLESSFOOD) && rnd(5) == 0)
! 276: {
! 277: read_scroll(&player, S_FOODDET, ISNORMAL);
! 278:
! 279: if (rnd(3) == 0)
! 280: turn_off(player, BLESSFOOD);
! 281: }
! 282:
! 283: if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_ILLUSION ||
! 284: on(player, BLESSMAGIC) && rnd(5) == 0)
! 285: {
! 286: quaff(&player, P_TREASDET, ISNORMAL);
! 287:
! 288: if (rnd(3) == 0)
! 289: turn_off(player, BLESSMAGIC);
! 290: }
! 291:
! 292: if (player.t_ctype == C_DRUID || on(player, BLESSMONS) && rnd(5) == 0)
! 293: {
! 294: quaff(&player, P_MONSTDET, ISNORMAL);
! 295:
! 296: if (rnd(3) == 0)
! 297: turn_off(player, BLESSMONS);
! 298: }
! 299: else if (player.t_ctype == C_CLERIC ||
! 300: player.t_ctype == C_PALADIN || is_wearing(R_PIETY))
! 301: undead_sense();
! 302: }
! 303:
! 304: if (is_wearing(R_AGGR))
! 305: aggravate();
! 306:
! 307: if (is_wearing(R_ADORNMENT) ||
! 308: cur_armor != NULL && cur_armor->o_which == MITHRIL)
! 309: {
! 310: int greed = FALSE;
! 311:
! 312: for (item = mlist; item != NULL; item = next(item))
! 313: {
! 314: tp = THINGPTR(item);
! 315:
! 316: if (on(*tp, ISGREED))
! 317: {
! 318: turn_on(*tp, ISRUN);
! 319: turn_on(*tp, ISMEAN);
! 320: tp->t_ischasing = TRUE;
! 321: tp->t_chasee = &player;
! 322: greed = TRUE;
! 323: }
! 324: }
! 325:
! 326: if (greed)
! 327: msg("An uneasy feeling comes over you.");
! 328: }
! 329:
! 330: if (is_carrying(TR_PALANTIR)) /* Palantir shows all */
! 331: {
! 332: msg("The Palantir reveals all!");
! 333:
! 334: overlay(stdscr, cw); /* Wizard mode 'f' command */
! 335: overlay(mw, cw); /* followed by 'm' command */
! 336: }
! 337:
! 338: if (is_carrying(TR_PHIAL)) /* Phial lights your way */
! 339: {
! 340: if (!is_carrying(TR_PALANTIR))
! 341: msg("The Phial banishes the darkness!");
! 342:
! 343: for (i = 0; i < MAXROOMS; i++)
! 344: rooms[i].r_flags &= ~ISDARK;
! 345: }
! 346:
! 347: if (is_carrying(TR_AMULET)) /* Amulet describes the level */
! 348: {
! 349: level_eval();
! 350: }
! 351:
! 352:
! 353: wmove(cw, hero.y, hero.x);
! 354: waddch(cw, PLAYER);
! 355: light(&hero);
! 356:
! 357: /* Summon familiar if player has one */
! 358:
! 359: if (on(player, HASFAMILIAR))
! 360: {
! 361: summon_monster((short) fam_type, FAMILIAR, MESSAGE);
! 362:
! 363: if (fam_ptr != NULL) /* add old pack to new */
! 364: {
! 365: tp = THINGPTR(fam_ptr);
! 366:
! 367: if (tp->t_pack == NULL)
! 368: tp->t_pack = fpack;
! 369: else if (fpack != NULL)
! 370: {
! 371: for (item = tp->t_pack; item->l_next != NULL;item = next(item))
! 372: ;
! 373:
! 374: item->l_next = fpack;
! 375: debug("new_level: l_prev = %p",item);
! 376: fpack->l_prev = item;
! 377: }
! 378: }
! 379: else
! 380: free_list(fpack);
! 381: }
! 382:
! 383: mem_check(__FILE__,__LINE__);
! 384: status(TRUE);
! 385: }
! 386:
! 387: /*
! 388: put_things()
! 389: put potions and scrolls on this level
! 390: */
! 391:
! 392: void
! 393: put_things(LEVTYPE ltype)
! 394: {
! 395: int i, rm, cnt;
! 396: struct linked_list *item;
! 397: struct object *cur;
! 398: int got_unique = FALSE;
! 399: int length, width, maxobjects;
! 400: coord tp;
! 401:
! 402: /*
! 403: * Once you have found an artifact, the only way to get new stuff is
! 404: * go down into the dungeon.
! 405: */
! 406:
! 407: if (has_artifact && level < max_level && ltype != THRONE)
! 408: return;
! 409:
! 410: /*
! 411: * There is a chance that there is a treasure room on this level
! 412: * Increasing chance after level 10
! 413: */
! 414:
! 415: if (ltype != MAZELEV && rnd(50) < level - 10)
! 416: {
! 417: int n, j;
! 418: struct room *rp;
! 419:
! 420: /* Count the number of free spaces */
! 421: n = 0; /* 0 tries */
! 422:
! 423: do
! 424: {
! 425: rp = &rooms[rnd_room()];
! 426: width = rp->r_max.y - 2;
! 427: length = rp->r_max.x - 2;
! 428: }
! 429: while(!((width * length <= MAXTREAS) || (n++ > MAXROOMS * 4)));
! 430:
! 431: /* Mark the room as a treasure room */
! 432:
! 433: rp->r_flags |= ISTREAS;
! 434:
! 435: /* Make all the doors secret doors */
! 436:
! 437: for (n = 0; n < rp->r_nexits; n++)
! 438: {
! 439: move(rp->r_exit[n].y, rp->r_exit[n].x);
! 440: addch(SECRETDOOR);
! 441: }
! 442:
! 443: /* Put in the monsters and treasures */
! 444:
! 445: for (j = 1; j < rp->r_max.y - 1; j++)
! 446: for (n = 1; n < rp->r_max.x - 1; n++)
! 447: {
! 448: coord trp;
! 449:
! 450: trp.y = rp->r_pos.y + j;
! 451: trp.x = rp->r_pos.x + n;
! 452:
! 453: /* Monsters */
! 454:
! 455: if ((rnd(100) < (MAXTREAS * 100) /
! 456: (width * length)) &&
! 457: (mvwinch(mw, rp->r_pos.y + j,
! 458: rp->r_pos.x + n) == ' '))
! 459: {
! 460: struct thing *th;
! 461:
! 462: /* Make a monster */
! 463:
! 464: item = new_item(sizeof *th);
! 465: th = THINGPTR(item);
! 466:
! 467: /*
! 468: * Put it there and aggravate it
! 469: * (unless it can escape) only put
! 470: * one UNIQUE per treasure room at
! 471: * most
! 472: */
! 473:
! 474: if (got_unique)
! 475: new_monster(item, randmonster(NOWANDER, GRAB), &trp,
! 476: NOMAXSTATS);
! 477: else
! 478: {
! 479: new_monster(item, randmonster(NOWANDER, NOGRAB), &trp,
! 480: NOMAXSTATS);
! 481:
! 482: if (on(*th, ISUNIQUE))
! 483: got_unique = TRUE;
! 484: }
! 485:
! 486: turn_off(*th, ISFRIENDLY);
! 487: turn_on(*th, ISMEAN);
! 488:
! 489: if (off(*th, CANINWALL))
! 490: {
! 491: th->t_ischasing = TRUE;
! 492: th->t_chasee = &player;
! 493: turn_on(*th, ISRUN);
! 494: }
! 495: }
! 496:
! 497: /* Treasures */
! 498:
! 499: if ((rnd(100) < (MAXTREAS * 100) /
! 500: (width * length)) &&
! 501: (mvinch(rp->r_pos.y + j,
! 502: rp->r_pos.x + n) == FLOOR))
! 503: {
! 504: item = new_thing();
! 505: cur = OBJPTR(item);
! 506: cur->o_pos = trp;
! 507: add_obj(item, trp.y, trp.x);
! 508: }
! 509: }
! 510: }
! 511:
! 512: /* Do MAXOBJ attempts to put things on a level, maybe */
! 513:
! 514: maxobjects = (ltype == THRONE) ? rnd(3 * MAXOBJ) + 35 : MAXOBJ;
! 515:
! 516: for (i = 0; i < maxobjects; i++)
! 517: if (rnd(100) < 40 || ltype == THRONE)
! 518: {
! 519: /* Pick a new object and link it in the list */
! 520:
! 521: item = new_thing();
! 522: cur = OBJPTR(item);
! 523:
! 524: /* Put it somewhere */
! 525:
! 526: cnt = 0;
! 527:
! 528: do
! 529: {
! 530: rm = rnd_room();
! 531: rnd_pos(&rooms[rm], &tp);
! 532: }
! 533: while(!(winat(tp.y, tp.x) == FLOOR || cnt++ > 500));
! 534:
! 535: cur->o_pos = tp;
! 536: add_obj(item, tp.y, tp.x);
! 537: }
! 538:
! 539: /*
! 540: * If he is really deep in the dungeon and he hasn't found an
! 541: * artifact yet, put it somewhere on the ground
! 542: */
! 543:
! 544: if (make_artifact())
! 545: {
! 546: item = new_item(sizeof *cur);
! 547: cur = OBJPTR(item);
! 548: new_artifact(-1, cur);
! 549: cnt = 0;
! 550:
! 551: do
! 552: {
! 553: rm = rnd_room();
! 554: rnd_pos(&rooms[rm], &tp);
! 555: }
! 556: while(!(winat(tp.y, tp.x) == FLOOR || cnt++ > 500));
! 557:
! 558: cur->o_pos = tp;
! 559: add_obj(item, tp.y, tp.x);
! 560: }
! 561: }
! 562:
! 563: /*
! 564: do_throne()
! 565: Put a monster's throne room and monsters on the screen
! 566: */
! 567:
! 568: void
! 569: do_throne(int special)
! 570: {
! 571: coord mp;
! 572: int save_level;
! 573: int i;
! 574: struct room *rp;
! 575: struct thing *tp;
! 576: struct linked_list *item;
! 577: int throne_monster;
! 578:
! 579: for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
! 580: {
! 581: rp->r_nexits = 0; /* no exits */
! 582: rp->r_flags = ISGONE; /* kill all rooms */
! 583: }
! 584:
! 585: rp = &rooms[0]; /* point to only room */
! 586: rp->r_flags = 0; /* this room NOT gone */
! 587: rp->r_max.x = 40;
! 588: rp->r_max.y = 10; /* 10 * 40 room */
! 589: rp->r_pos.x = (COLS - rp->r_max.x) / 2; /* center horizontal */
! 590: rp->r_pos.y = 3; /* 2nd line */
! 591: draw_room(rp); /* draw the only room */
! 592:
! 593: save_level = level;
! 594: level = max(2 * level, level + roll(4, 6));
! 595:
! 596: if (special == 0) /* Who has he offended? */
! 597: do
! 598: throne_monster = nummonst - roll(1, NUMSUMMON);
! 599: while(!monsters[throne_monster].m_normal);
! 600: else
! 601: throne_monster = special;
! 602:
! 603: /* Create summoning monster */
! 604:
! 605: item = new_item(sizeof *tp);
! 606:
! 607: tp = THINGPTR(item);
! 608:
! 609: do
! 610: {
! 611: rnd_pos(rp, &mp);
! 612: }
! 613: while(mvwinch(stdscr, mp.y, mp.x) != FLOOR);
! 614:
! 615: new_monster(item, throne_monster, &mp, MAXSTATS);
! 616: turn_on(*tp, CANSEE);
! 617: turn_off(*tp, ISFRIENDLY);
! 618:
! 619: if (on(*tp, CANSUMMON)) /* summon his helpers */
! 620: summon_help(tp, FORCE);
! 621: else
! 622: {
! 623: for (i = roll(4, 10); i >= 0; i--)
! 624: {
! 625: item = new_item(sizeof *tp);
! 626: tp = THINGPTR(item);
! 627:
! 628: do
! 629: {
! 630: rnd_pos(rp, &mp);
! 631: }
! 632: while(mvwinch(stdscr, mp.y, mp.x) != FLOOR);
! 633:
! 634: new_monster(item, randmonster(NOWANDER, NOGRAB), &mp, MAXSTATS);
! 635: turn_on(*tp, CANSEE);
! 636: turn_off(*tp, ISFRIENDLY);
! 637: }
! 638: }
! 639:
! 640: level = save_level + roll(2, 3); /* send the hero down */
! 641: aggravate();
! 642: }
! 643:
! 644: /*
! 645: create_lucifer()
! 646: special surprise on the way back up create Lucifer
! 647: with more than the usual god abilities
! 648: */
! 649:
! 650: void
! 651: create_lucifer(coord *stairs)
! 652: {
! 653: struct linked_list *item = new_item(sizeof(struct thing));
! 654: struct thing *tp = THINGPTR(item);
! 655:
! 656: new_monster(item, nummonst + 1, stairs, MAXSTATS);
! 657: turn_on(*tp, CANINWALL);
! 658: turn_on(*tp, CANHUH);
! 659: turn_on(*tp, CANBLINK);
! 660: turn_on(*tp, CANSNORE);
! 661: turn_on(*tp, CANDISEASE);
! 662: turn_on(*tp, NOCOLD);
! 663: turn_on(*tp, TOUCHFEAR);
! 664: turn_on(*tp, BMAGICHIT);
! 665: turn_on(*tp, NOFIRE);
! 666: turn_on(*tp, NOBOLT);
! 667: turn_on(*tp, CANBLIND);
! 668: turn_on(*tp, CANINFEST);
! 669: turn_on(*tp, CANSMELL);
! 670: turn_on(*tp, CANPARALYZE);
! 671: turn_on(*tp, CANSTINK);
! 672: turn_on(*tp, CANCHILL);
! 673: turn_on(*tp, CANFRIGHTEN);
! 674: turn_on(*tp, CANHOLD);
! 675: turn_on(*tp, CANBRANDOM);
! 676: }
CVSweb