Mercurial > hg > early-roguelike
diff urogue/newlvl.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
author | John "Elwin" Edwards |
---|---|
date | Tue, 31 Jan 2017 19:56:04 -0500 |
parents | |
children | e52a8a7ad4c5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/newlvl.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,676 @@ +/* + newlvl.c - Dig and draw a new level + + UltraRogue: The Ultimate Adventure in the Dungeons of Doom + Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +/* + Notes + + Add treasure room code from Rogue 5.2, + put in #ifdef 0/#endif bracket at end of code +*/ + +#include "rogue.h" + +/* + new_level() + Dig and draw a new level +*/ + +void +new_level(LEVTYPE ltype, int special) +{ + int rm, i, cnt; + struct linked_list *item, *nitem; + struct thing *tp; + struct linked_list *fpack = NULL; + int going_down = TRUE; + coord stairs; + + /* Start player off right */ + + turn_off(player, ISHELD); + turn_off(player, ISFLEE); + extinguish_fuse(FUSE_SUFFOCATE); + hold_count = 0; + trap_tries = 0; + no_food++; + + if (level >= max_level) + max_level = level; + else + going_down = FALSE; + + /* Free up the monsters on the last level */ + + if (fam_ptr != NULL) /* save what familiar is carrying */ + { + fpack = (THINGPTR(fam_ptr))->t_pack; + (THINGPTR(fam_ptr))->t_pack = NULL; + fam_ptr = NULL; /* just in case */ + } + + for (i = 1; i <= mons_summoned; i++) + extinguish_fuse(FUSE_UNSUMMON); + + mons_summoned = 0; + + for (item = mlist; item != NULL; item = nitem) + { + tp = THINGPTR(item); + nitem = next(item); + + if (on(*tp, ISUNIQUE)) /* Put alive UNIQUE on next level */ + monsters[tp->t_index].m_normal = TRUE; + + killed(NULL, item, NOMESSAGE, NOPOINTS); + } + + free_list(lvl_obj); /* Free up previous objects (if any) */ + + wclear(cw); + wclear(mw); + clear(); + refresh(); + levtype = ltype; + + switch (ltype) + { + case THRONE: + do_throne(special); /* do monster throne stuff */ + break; + + case MAZELEV: + do_maze(); + break; + + case POSTLEV: + do_post(); + levtype = ltype = NORMLEV; + level++; + + default: + do_rooms(); /* Draw rooms */ + do_passages(); /* Draw passages */ + break; + } + + /* Place the staircase down. */ + + cnt = 0; + + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &stairs); + } + while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000)); + + addch(STAIRS); + + put_things(ltype); /* Place objects (if any) */ + + if (has_artifact && level == 1) + create_lucifer(&stairs); + + /* Place the traps */ + + ntraps = 0; /* No traps yet */ + + if (levtype == NORMLEV) + { + if (rnd(10) < level) + { + char ch = 0; + + i = ntraps = min(MAXTRAPS, rnd(level / 2) + 1); + + /* maybe a lair */ + + if (level > 35 && ltype == NORMLEV && rnd(wizard ? 3 : 10) == 0) + { + cnt = 0; + + do + { + rm = rnd_room(); + + if (rooms[rm].r_flags & ISTREAS) + continue; + + rnd_pos(&rooms[rm], &stairs); + } + while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000)); + + addch(LAIR); + i--; + traps[i].tr_flags = 0; + traps[i].tr_type = LAIR; + traps[i].tr_show = FLOOR; + traps[i].tr_pos = stairs; + } + + while (i--) + { + cnt = 0; + + do + { + rm = rnd_room(); + + if (rooms[rm].r_flags & ISTREAS) + continue; + + rnd_pos(&rooms[rm], &stairs); + } + while (!(mvinch(stairs.y, stairs.x) == FLOOR || cnt++ > 5000)); + + traps[i].tr_flags = 0; + + switch (rnd(11)) + { + case 0: + ch = TRAPDOOR; + break; + + case 1: + ch = BEARTRAP; + break; + + case 2: + ch = SLEEPTRAP; + break; + + case 3: + ch = ARROWTRAP; + break; + + case 4: + ch = TELTRAP; + break; + + case 5: + ch = DARTTRAP; + break; + + case 6: + ch = POOL; + + if (rnd(10)) + traps[i].tr_flags = ISFOUND; + + break; + + case 7: + ch = MAZETRAP; + break; + + case 8: + ch = FIRETRAP; + break; + + case 9: + ch = POISONTRAP; + break; + + case 10: + ch = RUSTTRAP; + break; + } + + addch(ch); + traps[i].tr_type = ch; + traps[i].tr_show = FLOOR; + traps[i].tr_pos = stairs; + } + } + } + + do /* Position hero */ + { + rm = rnd_room(); + + if (levtype != THRONE && (rooms[rm].r_flags & ISTREAS)) + continue; + + rnd_pos(&rooms[rm], &hero); + } + while(!(winat(hero.y, hero.x) == FLOOR && + DISTANCE(hero, stairs) > 16)); + + oldrp = &rooms[rm]; /* Set the current room */ + player.t_oldpos = player.t_pos; /* Set the current position */ + + if (levtype != POSTLEV && levtype != THRONE) + { + if (on(player, BLESSMAP) && rnd(5) == 0) + { + read_scroll(&player, S_MAP, ISNORMAL); + + if (rnd(3) == 0) + turn_off(player, BLESSMAP); + } + + if (player.t_ctype == C_THIEF || on(player, BLESSGOLD) && rnd(5) == 0) + { + read_scroll(&player, S_GFIND, ISNORMAL); + + if (rnd(3) == 0) + turn_off(player, BLESSGOLD); + } + + if (player.t_ctype == C_RANGER || on(player, BLESSFOOD) && rnd(5) == 0) + { + read_scroll(&player, S_FOODDET, ISNORMAL); + + if (rnd(3) == 0) + turn_off(player, BLESSFOOD); + } + + if (player.t_ctype == C_MAGICIAN || player.t_ctype == C_ILLUSION || + on(player, BLESSMAGIC) && rnd(5) == 0) + { + quaff(&player, P_TREASDET, ISNORMAL); + + if (rnd(3) == 0) + turn_off(player, BLESSMAGIC); + } + + if (player.t_ctype == C_DRUID || on(player, BLESSMONS) && rnd(5) == 0) + { + quaff(&player, P_MONSTDET, ISNORMAL); + + if (rnd(3) == 0) + turn_off(player, BLESSMONS); + } + else if (player.t_ctype == C_CLERIC || + player.t_ctype == C_PALADIN || is_wearing(R_PIETY)) + undead_sense(); + } + + if (is_wearing(R_AGGR)) + aggravate(); + + if (is_wearing(R_ADORNMENT) || + cur_armor != NULL && cur_armor->o_which == MITHRIL) + { + int greed = FALSE; + + for (item = mlist; item != NULL; item = next(item)) + { + tp = THINGPTR(item); + + if (on(*tp, ISGREED)) + { + turn_on(*tp, ISRUN); + turn_on(*tp, ISMEAN); + tp->t_ischasing = TRUE; + tp->t_chasee = &player; + greed = TRUE; + } + } + + if (greed) + msg("An uneasy feeling comes over you."); + } + + if (is_carrying(TR_PALANTIR)) /* Palantir shows all */ + { + msg("The Palantir reveals all!"); + + overlay(stdscr, cw); /* Wizard mode 'f' command */ + overlay(mw, cw); /* followed by 'm' command */ + } + + if (is_carrying(TR_PHIAL)) /* Phial lights your way */ + { + if (!is_carrying(TR_PALANTIR)) + msg("The Phial banishes the darkness!"); + + for (i = 0; i < MAXROOMS; i++) + rooms[i].r_flags &= ~ISDARK; + } + + if (is_carrying(TR_AMULET)) /* Amulet describes the level */ + { + level_eval(); + } + + + wmove(cw, hero.y, hero.x); + waddch(cw, PLAYER); + light(&hero); + + /* Summon familiar if player has one */ + + if (on(player, HASFAMILIAR)) + { + summon_monster((short) fam_type, FAMILIAR, MESSAGE); + + if (fam_ptr != NULL) /* add old pack to new */ + { + tp = THINGPTR(fam_ptr); + + if (tp->t_pack == NULL) + tp->t_pack = fpack; + else if (fpack != NULL) + { + for (item = tp->t_pack; item->l_next != NULL;item = next(item)) + ; + + item->l_next = fpack; + debug("new_level: l_prev = %p",item); + fpack->l_prev = item; + } + } + else + free_list(fpack); + } + + mem_check(__FILE__,__LINE__); + status(TRUE); +} + +/* + put_things() + put potions and scrolls on this level +*/ + +void +put_things(LEVTYPE ltype) +{ + int i, rm, cnt; + struct linked_list *item; + struct object *cur; + int got_unique = FALSE; + int length, width, maxobjects; + coord tp; + + /* + * Once you have found an artifact, the only way to get new stuff is + * go down into the dungeon. + */ + + if (has_artifact && level < max_level && ltype != THRONE) + return; + + /* + * There is a chance that there is a treasure room on this level + * Increasing chance after level 10 + */ + + if (ltype != MAZELEV && rnd(50) < level - 10) + { + int n, j; + struct room *rp; + + /* Count the number of free spaces */ + n = 0; /* 0 tries */ + + do + { + rp = &rooms[rnd_room()]; + width = rp->r_max.y - 2; + length = rp->r_max.x - 2; + } + while(!((width * length <= MAXTREAS) || (n++ > MAXROOMS * 4))); + + /* Mark the room as a treasure room */ + + rp->r_flags |= ISTREAS; + + /* Make all the doors secret doors */ + + for (n = 0; n < rp->r_nexits; n++) + { + move(rp->r_exit[n].y, rp->r_exit[n].x); + addch(SECRETDOOR); + } + + /* Put in the monsters and treasures */ + + for (j = 1; j < rp->r_max.y - 1; j++) + for (n = 1; n < rp->r_max.x - 1; n++) + { + coord trp; + + trp.y = rp->r_pos.y + j; + trp.x = rp->r_pos.x + n; + + /* Monsters */ + + if ((rnd(100) < (MAXTREAS * 100) / + (width * length)) && + (mvwinch(mw, rp->r_pos.y + j, + rp->r_pos.x + n) == ' ')) + { + struct thing *th; + + /* Make a monster */ + + item = new_item(sizeof *th); + th = THINGPTR(item); + + /* + * Put it there and aggravate it + * (unless it can escape) only put + * one UNIQUE per treasure room at + * most + */ + + if (got_unique) + new_monster(item, randmonster(NOWANDER, GRAB), &trp, + NOMAXSTATS); + else + { + new_monster(item, randmonster(NOWANDER, NOGRAB), &trp, + NOMAXSTATS); + + if (on(*th, ISUNIQUE)) + got_unique = TRUE; + } + + turn_off(*th, ISFRIENDLY); + turn_on(*th, ISMEAN); + + if (off(*th, CANINWALL)) + { + th->t_ischasing = TRUE; + th->t_chasee = &player; + turn_on(*th, ISRUN); + } + } + + /* Treasures */ + + if ((rnd(100) < (MAXTREAS * 100) / + (width * length)) && + (mvinch(rp->r_pos.y + j, + rp->r_pos.x + n) == FLOOR)) + { + item = new_thing(); + cur = OBJPTR(item); + cur->o_pos = trp; + add_obj(item, trp.y, trp.x); + } + } + } + + /* Do MAXOBJ attempts to put things on a level, maybe */ + + maxobjects = (ltype == THRONE) ? rnd(3 * MAXOBJ) + 35 : MAXOBJ; + + for (i = 0; i < maxobjects; i++) + if (rnd(100) < 40 || ltype == THRONE) + { + /* Pick a new object and link it in the list */ + + item = new_thing(); + cur = OBJPTR(item); + + /* Put it somewhere */ + + cnt = 0; + + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &tp); + } + while(!(winat(tp.y, tp.x) == FLOOR || cnt++ > 500)); + + cur->o_pos = tp; + add_obj(item, tp.y, tp.x); + } + + /* + * If he is really deep in the dungeon and he hasn't found an + * artifact yet, put it somewhere on the ground + */ + + if (make_artifact()) + { + item = new_item(sizeof *cur); + cur = OBJPTR(item); + new_artifact(-1, cur); + cnt = 0; + + do + { + rm = rnd_room(); + rnd_pos(&rooms[rm], &tp); + } + while(!(winat(tp.y, tp.x) == FLOOR || cnt++ > 500)); + + cur->o_pos = tp; + add_obj(item, tp.y, tp.x); + } +} + +/* + do_throne() + Put a monster's throne room and monsters on the screen +*/ + +void +do_throne(int special) +{ + coord mp; + int save_level; + int i; + struct room *rp; + struct thing *tp; + struct linked_list *item; + int throne_monster; + + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + { + rp->r_nexits = 0; /* no exits */ + rp->r_flags = ISGONE; /* kill all rooms */ + } + + rp = &rooms[0]; /* point to only room */ + rp->r_flags = 0; /* this room NOT gone */ + rp->r_max.x = 40; + rp->r_max.y = 10; /* 10 * 40 room */ + rp->r_pos.x = (COLS - rp->r_max.x) / 2; /* center horizontal */ + rp->r_pos.y = 3; /* 2nd line */ + draw_room(rp); /* draw the only room */ + + save_level = level; + level = max(2 * level, level + roll(4, 6)); + + if (special == 0) /* Who has he offended? */ + do + throne_monster = nummonst - roll(1, NUMSUMMON); + while(!monsters[throne_monster].m_normal); + else + throne_monster = special; + + /* Create summoning monster */ + + item = new_item(sizeof *tp); + + tp = THINGPTR(item); + + do + { + rnd_pos(rp, &mp); + } + while(mvwinch(stdscr, mp.y, mp.x) != FLOOR); + + new_monster(item, throne_monster, &mp, MAXSTATS); + turn_on(*tp, CANSEE); + turn_off(*tp, ISFRIENDLY); + + if (on(*tp, CANSUMMON)) /* summon his helpers */ + summon_help(tp, FORCE); + else + { + for (i = roll(4, 10); i >= 0; i--) + { + item = new_item(sizeof *tp); + tp = THINGPTR(item); + + do + { + rnd_pos(rp, &mp); + } + while(mvwinch(stdscr, mp.y, mp.x) != FLOOR); + + new_monster(item, randmonster(NOWANDER, NOGRAB), &mp, MAXSTATS); + turn_on(*tp, CANSEE); + turn_off(*tp, ISFRIENDLY); + } + } + + level = save_level + roll(2, 3); /* send the hero down */ + aggravate(); +} + +/* + create_lucifer() + special surprise on the way back up create Lucifer + with more than the usual god abilities +*/ + +void +create_lucifer(coord *stairs) +{ + struct linked_list *item = new_item(sizeof(struct thing)); + struct thing *tp = THINGPTR(item); + + new_monster(item, nummonst + 1, stairs, MAXSTATS); + turn_on(*tp, CANINWALL); + turn_on(*tp, CANHUH); + turn_on(*tp, CANBLINK); + turn_on(*tp, CANSNORE); + turn_on(*tp, CANDISEASE); + turn_on(*tp, NOCOLD); + turn_on(*tp, TOUCHFEAR); + turn_on(*tp, BMAGICHIT); + turn_on(*tp, NOFIRE); + turn_on(*tp, NOBOLT); + turn_on(*tp, CANBLIND); + turn_on(*tp, CANINFEST); + turn_on(*tp, CANSMELL); + turn_on(*tp, CANPARALYZE); + turn_on(*tp, CANSTINK); + turn_on(*tp, CANCHILL); + turn_on(*tp, CANFRIGHTEN); + turn_on(*tp, CANHOLD); + turn_on(*tp, CANBRANDOM); +}