/*
* Create the layout for the new level
*
* @(#)rooms.c 4.16 (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 <ctype.h>
#include <curses.h>
#include "rogue.h"
#define GOLDGRP 1
void draw_room(struct room *rp);
void vert(struct room *rp, int startx);
void horiz(struct room *rp, int starty);
/*
* do_rooms:
* Create rooms and corridors with a connectivity graph
*/
void
do_rooms(void)
{
register int i;
register struct room *rp;
register THING *tp;
register int left_out;
coord top;
coord bsze;
coord mp;
/*
* bsze is the maximum room size
*/
bsze.x = COLS/3;
bsze.y = LINES/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 (rp->r_flags & ISGONE)
{
/*
* Place a gone room. Make certain that there is a blank line
* for passage drawing.
*/
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;
} until (rp->r_pos.y > 0 && rp->r_pos.y < LINES-1);
continue;
}
if (rnd(10) < level - 1)
rp->r_flags |= ISDARK;
/*
* Find a place and size for a random room
*/
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);
} until (rp->r_pos.y != 0);
/*
* Put the gold in
*/
if (rnd(2) == 0 && (!amulet || level >= max_level))
{
register THING *gold;
gold = new_item();
gold->o_goldval = rp->r_goldval = GOLDCALC;
rnd_pos(rp, &rp->r_gold);
gold->o_pos = rp->r_gold;
gold->o_flags = ISMANY;
gold->o_group = GOLDGRP;
gold->o_type = GOLD;
attach(lvl_obj, gold);
}
draw_room(rp);
/*
* Put the monster in
*/
if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
{
tp = new_item();
do
{
rnd_pos(rp, &mp);
} until (winat(mp.y, mp.x) == FLOOR);
new_monster(tp, randmonster(FALSE), &mp);
give_pack(tp);
}
}
}
/*
* draw_room:
* Draw a box around a room and lay down the floor
*/
void
draw_room(struct room *rp)
{
register int y, x;
vert(rp, rp->r_pos.x); /* Draw left side */
vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */
horiz(rp, rp->r_pos.y); /* Draw top */
horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */
/*
* Put the floor down
*/
for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
/*strrep(&chat(rp->r_pos.y + 1, j), FLOOR, rp->r_max.y - rp->r_pos.y - 2);*/
for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
chat(y, x) = FLOOR;
/*
* Put the gold there
*/
if (rp->r_goldval)
chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
}
/*
* vert:
* Draw a vertical line
*/
void
vert(struct room *rp, int startx)
{
register int y;
for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
chat(y, startx) = '|';
}
/*
* horiz:
* Draw a horizontal line
*/
void
horiz(struct room *rp, int starty)
{
register int x;
for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
chat(starty, x) = '-';
}
/*
* rnd_pos:
* Pick a random spot in a room
*/
void
rnd_pos(struct room *rp, coord *cp)
{
cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
}
/*
* enter_room:
* Code that is executed whenver you appear in a room
*/
void
enter_room(coord *cp)
{
register struct room *rp;
register int y, x;
register THING *tp;
rp = proom = roomin(cp);
if (rp->r_flags & ISGONE)
{
msg("in a gone room");
return;
}
door_open(rp);
if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
{
move(y, rp->r_pos.x);
for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
{
tp = moat(y, x);
if (tp == NULL || !see_monst(tp))
addch(chat(y, x));
else
addch(tp->t_disguise);
}
}
}
/*
* leave_room:
* Code for when we exit a room
*/
void
leave_room(coord *cp)
{
register int y, x;
register struct room *rp;
register char floor;
register char ch;
rp = proom;
proom = &passages[flat(cp->y, cp->x) & F_PNUM];
floor = ((rp->r_flags & ISDARK) && !on(player, ISBLIND)) ? ' ' : FLOOR;
for (y = rp->r_pos.y + 1; y < rp->r_max.y + rp->r_pos.y - 1; y++)
for (x = rp->r_pos.x + 1; x < rp->r_max.x + rp->r_pos.x - 1; x++)
switch (ch = mvinch(y, x))
{
case ' ':
case TRAP:
case STAIRS:
break;
case FLOOR:
if (floor == ' ')
addch(' ');
break;
default:
/*
* to check for monster, we have to strip out
* standout bit
*/
if (isupper(toascii(ch)))
if (on(player, SEEMONST))
{
standout();
addch(ch);
standend();
break;
}
else
{
THING *tp = moat(y, x);
if (tp != NULL)
tp->t_oldch = floor;
#ifdef WIZARD
else
msg("couldn't find monster in leave_room at (%d,%d)", y, x);
#endif
}
addch(floor);
}
door_open(rp);
}