/*
* Draw the nine rooms on the screen
*
* @(#)rooms.c 9.0 (rdk) 7/17/84
*
* Super-Rogue
* Copyright (C) 1984 Robert D. Kindelberger
* 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.
*/
#include "rogue.h"
#include "rogue.ext"
void horiz(int cnt);
void vert(int cnt);
/*
* do_rooms:
* Place the rooms in the dungeon
*/
void
do_rooms(void)
{
int mloops, mchance, nummons, left_out, roomtries;
bool treas = FALSE;
reg int i;
reg struct room *rp;
reg struct linked_list *item;
reg struct thing *tp;
struct coord top, bsze, mp;
/*
* bsze is the maximum room size
*/
bsze.x = COLS / 3;
bsze.y = (LINES - 1) / 3;
/*
* Clear things for a new level
*/
for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
rp->r_goldval = rp->r_nexits = rp->r_flags = 0;
/*
* Put the gone rooms, if any, on the level
*/
left_out = rnd(4);
for (i = 0; i < left_out; i++)
rooms[rnd_room()].r_flags |= ISGONE;
/*
* dig and populate all the rooms on the level
*/
for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++) {
/*
* Find upper left corner of box that this room goes in
*/
top.x = (i%3) * bsze.x + 1;
top.y = i/3 * bsze.y;
if (rf_on(rp,ISGONE)) {
/*
* Place a gone room. Make certain that there is a
* blank line for passage drawing.
*/
roomtries = 0;
do {
rp->r_pos.x = top.x + rnd(bsze.x-2) + 1;
rp->r_pos.y = top.y + rnd(bsze.y-2) + 1;
rp->r_max.x = -COLS;
rp->r_max.x = -LINES;
if (++roomtries > 250)
fatal("failed to place a gone room");
} until(rp->r_pos.y > 0 && rp->r_pos.y < LINES-2);
continue;
}
if (rnd(10) < level-1)
rp->r_flags |= ISDARK;
/*
* Find a place and size for a random room
*/
roomtries = 0;
do {
rp->r_max.x = rnd(bsze.x - 4) + 4;
rp->r_max.y = rnd(bsze.y - 4) + 4;
rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
if (++roomtries > 250) {
fatal("failed to place a good room");
}
} until (rp->r_pos.y != 0);
if (level < max_level)
mchance = 30; /* 30% when going up (all monsters) */
else
mchance = 3; /* 3% when going down */
treas = FALSE;
if (rnd(100) < mchance && (rp->r_max.x * rp->r_max.y) >
((bsze.x * bsze.y * 55) / 100)) {
treas = TRUE;
rp->r_flags |= ISTREAS;
rp->r_flags |= ISDARK;
}
/*
* Put the gold in
*/
if ((rnd(100) < 50 || treas) && (!amulet || level >= max_level)) {
rp->r_goldval = GOLDCALC;
if (treas)
rp->r_goldval += 200 + (15 * (rnd(level) + 2));
rp->r_gold.y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
rp->r_gold.x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
}
draw_room(rp);
/*
* Put the monster in
*/
if (treas) {
mloops = rnd(level / 3) + 6;
mchance = 1;
}
else {
mloops = 1;
mchance = 100;
}
for (nummons = 0; nummons < mloops; nummons++) {
if (rnd(mchance) < (rp->r_goldval > 0 ? 80 : 25))
add_mon(rp, treas);
}
}
}
/*
* add_mon:
* Add a monster to a room
*/
void
add_mon(struct room *rm, bool treas)
{
reg struct thing *tp;
reg struct linked_list *item;
struct coord mp;
int chance;
mp = *rnd_pos(rm);
item = new_monster(rnd_mon(FALSE,FALSE), &mp, treas);
tp = THINGPTR(item);
chance = rnd(100);
if (levtype == MAZELEV)
chance = rnd(50);
/*
* See if monster has a treasure
*/
if (levtype == MAZELEV && rnd(100) < 20) {
reg struct linked_list *fd;
fd = new_thing(FALSE, FOOD, 0);
attach(tp->t_pack, fd);
}
else {
if (chance < monsters[tp->t_indx].m_carry)
attach(tp->t_pack, new_thing(FALSE, ANYTHING));
}
}
/*
* draw_room:
* Draw a box around a room
*/
void
draw_room(struct room *rp)
{
reg int j, k;
move(rp->r_pos.y, rp->r_pos.x+1);
vert(rp->r_max.y-2); /* Draw left side */
move(rp->r_pos.y+rp->r_max.y-1, rp->r_pos.x);
horiz(rp->r_max.x); /* Draw bottom */
move(rp->r_pos.y, rp->r_pos.x);
horiz(rp->r_max.x); /* Draw top */
vert(rp->r_max.y-2); /* Draw right side */
/*
* Put the floor down
*/
for (j = 1; j < rp->r_max.y - 1; j++) {
move(rp->r_pos.y + j, rp->r_pos.x + 1);
for (k = 1; k < rp->r_max.x - 1; k++) {
addch(FLOOR);
}
}
/*
* Put the gold there
*/
if (rp->r_goldval > 0)
mvaddch(rp->r_gold.y, rp->r_gold.x, GOLD);
}
/*
* horiz:
* draw a horizontal line
*/
void
horiz(int cnt)
{
while (cnt-- > 0)
addch('-');
}
/*
* vert:
* draw a vertical line
*/
void
vert(int cnt)
{
reg int x, y;
getyx(stdscr, y, x);
x--;
while (cnt-- > 0) {
move(++y, x);
addch('|');
}
}
/*
* rnd_pos:
* pick a random spot in a room
*/
struct coord *
rnd_pos(struct room *rp)
{
reg int y, x, i;
static struct coord spot;
i = 0;
do {
x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
i += 1;
} while(winat(y, x) != FLOOR && i < 1000);
spot.x = x;
spot.y = y;
return &spot;
}
/*
* rf_on:
* Returns TRUE if flag is set for room stuff
*/
bool
rf_on(struct room *rm, long bit)
{
return (rm->r_flags & bit);
}