/*
* new_level:
* Dig and draw a new level
*
* @(#)new_level.c 4.19 (Berkeley) 1/12/82
*
* Rogue: Exploring the Dungeons of Doom
* Copyright (C) 1980, 1981, 1982 Michael Toy, Ken Arnold and Glenn Wichman
* All rights reserved.
*
* See the file LICENSE.TXT for full copyright and licensing information.
*/
#include <stdlib.h>
#include <time.h>
#include <curses.h>
#include <string.h>
#include "rogue.h"
#define TREAS_ROOM 20 /* one chance in TREAS_ROOM for a treasure room */
#define MAXTREAS 10 /* maximum number of treasures in a treasure room */
#define MINTREAS 2 /* minimum number of treasures in a treasure room */
void put_things(void);
void treas_room(void);
void
new_level(void)
{
register int rm, i;
register THING *tp;
register char *sp;
register THING **mp;
register int index;
coord stairs;
player.t_flags &= ~ISHELD; /* unhold when you go down just in case */
if (level > max_level)
max_level = level;
/*
* Clean things off from last level
*/
clear();
for (sp = _level; sp < &_level[MAXCOLS*MAXLINES]; )
*sp++ = ' ';
for (sp = _flags; sp < &_flags[MAXCOLS*MAXLINES]; )
*sp++ = F_REAL;
for (mp = _monst; mp < &_monst[MAXCOLS*MAXLINES]; )
*mp++ = NULL;
clear();
/*
* Free up the monsters on the last level
*/
for (tp = mlist; tp != NULL; tp = next(tp))
free_list(tp->t_pack);
free_list(mlist);
/*
* Throw away stuff left on the previous level (if anything)
*/
free_list(lvl_obj);
do_rooms(); /* Draw rooms */
do_passages(); /* Draw passages */
no_food++;
put_things(); /* Place objects (if any) */
/*
* Place the staircase down.
*/
i = 0;
do {
rm = rnd_room();
rnd_pos(&rooms[rm], &stairs);
index = INDEX(stairs.y, stairs.x);
if (i++ > 100)
{
i = 0;
srand(md_random_seed());
}
} until (_level[index] == FLOOR);
_level[index] = STAIRS;
/*
* Place the traps
*/
if (rnd(10) < level)
{
ntraps = rnd(level / 4) + 1;
if (ntraps > MAXTRAPS)
ntraps = MAXTRAPS;
i = ntraps;
while (i--)
{
do
{
rm = rnd_room();
rnd_pos(&rooms[rm], &stairs);
index = INDEX(stairs.y, stairs.x);
} until (_level[index] == FLOOR && (_flags[index] & F_REAL));
sp = &_flags[index];
*sp &= ~(F_REAL | F_TMASK);
*sp |= rnd(NTRAPS);
}
}
do
{
rm = rnd_room();
rnd_pos(&rooms[rm], &hero);
index = INDEX(hero.y, hero.x);
} until (_level[index] == FLOOR && (_flags[index] & F_REAL)
&& _monst[index] == NULL);
enter_room(&hero);
move(hero.y, hero.x);
addch(PLAYER);
if (on(player, SEEMONST))
turn_see(FALSE);
}
/*
* rnd_room:
* Pick a room that is really there
*/
int
rnd_room(void)
{
register int rm;
do
{
rm = rnd(MAXROOMS);
} while (rooms[rm].r_flags & ISGONE);
return rm;
}
/*
* put_things:
* Put potions and scrolls on this level
*/
void
put_things(void)
{
register int i;
register THING *cur;
register int rm;
coord tp;
/*
* Once you have found the amulet, the only way to get new stuff is
* go down into the dungeon.
*/
if (amulet && level < max_level)
return;
/*
* check for treasure rooms, and if so, put it in.
*/
if (rnd(TREAS_ROOM) == 0)
treas_room();
/*
* Do MAXOBJ attempts to put things on a level
*/
for (i = 0; i < MAXOBJ; i++)
if (rnd(100) < 35)
{
/*
* Pick a new object and link it in the list
*/
cur = new_thing();
attach(lvl_obj, cur);
/*
* Put it somewhere
*/
do {
rm = rnd_room();
rnd_pos(&rooms[rm], &tp);
} until (chat(tp.y, tp.x) == FLOOR);
chat(tp.y, tp.x) = cur->o_type;
cur->o_pos = tp;
}
/*
* If he is really deep in the dungeon and he hasn't found the
* amulet yet, put it somewhere on the ground
*/
if (level >= AMULETLEVEL && !amulet)
{
cur = new_item();
attach(lvl_obj, cur);
cur->o_hplus = cur->o_dplus = 0;
strcpy(cur->o_damage,"0d0");
strcpy(cur->o_hurldmg,"0d0");
cur->o_ac = 11;
cur->o_type = AMULET;
/*
* Put it somewhere
*/
do {
rm = rnd_room();
rnd_pos(&rooms[rm], &tp);
} until (winat(tp.y, tp.x) == FLOOR);
chat(tp.y, tp.x) = AMULET;
cur->o_pos = tp;
}
}
/*
* treas_room:
* Add a treasure room
*/
#define MAXTRIES 10 /* max number of tries to put down a monster */
void
treas_room(void)
{
register int nm, index;
register THING *tp;
register struct room *rp;
register int spots, num_monst;
coord mp;
rp = &rooms[rnd_room()];
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2) - MINTREAS;
if (spots > (MAXTREAS - MINTREAS))
spots = (MAXTREAS - MINTREAS);
num_monst = nm = rnd(spots) + MINTREAS;
while (nm--)
{
do
{
rnd_pos(rp, &mp);
index = INDEX(mp.y, mp.x);
} until (_level[index] == FLOOR);
tp = new_thing();
tp->o_pos = mp;
attach(lvl_obj, tp);
_level[index] = tp->o_type;
}
/*
* fill up room with monsters from the next level down
*/
if ((nm = rnd(spots) + MINTREAS) < num_monst + 2)
nm = num_monst + 2;
spots = (rp->r_max.y - 2) * (rp->r_max.x - 2);
if (nm > spots)
nm = spots;
level++;
while (nm--)
{
spots = 0;
do
{
rnd_pos(rp, &mp);
index = INDEX(mp.y, mp.x);
spots++;
} until (_monst[index] == NULL || spots > MAXTRIES);
if (_monst[index] == NULL)
{
tp = new_item();
new_monster(tp, randmonster(FALSE), &mp);
tp->t_flags |= ISMEAN; /* no sloughers in THIS room */
give_pack(tp);
}
}
level--;
}