Mercurial > hg > early-roguelike
diff urogue/rooms.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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/urogue/rooms.c Tue Jan 31 19:56:04 2017 -0500 @@ -0,0 +1,315 @@ +/* + rooms.c - Draw the nine rooms on the screen + + 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. +*/ + +#include <stdlib.h> +#include "rogue.h" + +void +do_rooms(void) +{ + int i; + struct room *rp; + struct linked_list *item; + struct thing *tp; + int left_out; + coord top; + coord bsze; + coord mp; + + /* bsze is the maximum room size */ + + bsze.x = COLS / 3; + bsze.y = (LINES - 2) / 3; + + /* Clear things for a new level */ + + for (rp = rooms; rp < &rooms[MAXROOMS]; rp++) + rp->r_nexits = rp->r_flags = rp->r_fires = 0; + + /* Put the gone rooms, if any, on the level */ + + left_out = rnd(3); + + 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++) + { + int has_gold = FALSE; + + /* Find upper left corner of box that this room goes in */ + + top.x = (i % 3) * bsze.x; + top.y = i / 3 * bsze.y + 1; + + 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; + } + while (rp->r_pos.y < 1 || rp->r_pos.y > LINES - 3); + + continue; + } + + if (rnd(40) < level - 5) + 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); + } + while (rp->r_pos.y == 0); + + /* Draw the room */ + + draw_room(rp); + + /* Put the gold in */ + + if (rnd(10) < 3 && (!has_artifact || level >= max_level)) + { + struct linked_list *itm; + struct object *cur; + coord tpos; + + has_gold = TRUE; /* This room has gold in it */ + + itm = spec_item(GOLD, 0, 0, 0); + cur = OBJPTR(itm); + + /* Put it somewhere */ + + rnd_pos(rp, &tpos); + cur->o_pos = tpos; + + /* Put the gold into the level list of items */ + + add_obj(itm, tpos.y, tpos.x); + + if (roomin(tpos) != rp) + { + endwin(); + abort(); + } + } + + /* Put the monster in */ + + if (rnd(100) < (has_gold ? 80 : 40)) + { + int which; + int n, cnt; + + item = new_item(sizeof *tp); + tp = THINGPTR(item); + + do + rnd_pos(rp, &mp); + while (mvwinch(stdscr, mp.y, mp.x) != FLOOR); + + which = randmonster(NOWANDER, NOGRAB); + new_monster(item, which, &mp, NOMAXSTATS); + + /* See if we want to give it a treasure to carry around. */ + + if (rnd(100) < monsters[tp->t_index].m_carry) + attach(tp->t_pack, new_thing()); + + /* If it has a fire, mark it */ + + if (on(*tp, HASFIRE)) + { + rp->r_flags |= HASFIRE; + rp->r_fires++; + } + + /* If it carries gold, give it some */ + + if (on(*tp, CARRYGOLD)) + { + struct object *cur; + + item = spec_item(GOLD, 0, 0, 0); + cur = OBJPTR(item); + cur->o_count = GOLDCALC + GOLDCALC + GOLDCALC; + cur->o_pos = tp->t_pos; + attach(tp->t_pack, item); + } + + n = rnd(7); + + if (on(*tp, ISSWARM) && n < 5) + cnt = roll(2, 4); + else if (on(*tp, ISFLOCK) && n < 5) + cnt = roll(1, 4); + else + cnt = 0; + + for (n = 1; n <= cnt; n++) + { + coord pos; + + if (place_mons(mp.y, mp.x, &pos)!= FALSE) + { + struct linked_list *nitem; + + nitem = new_item(sizeof(struct thing)); + new_monster(nitem, which, &pos, NOMAXSTATS); + + /* If the monster is on a trap, trap it */ + + if (isatrap(mvinch(pos.y, pos.x))) + be_trapped(THINGPTR(nitem), mp); + + if (on(*tp, ISFRIENDLY)) + turn_on(*(THINGPTR(nitem)), ISFRIENDLY); + else + turn_off(*(THINGPTR(nitem)), ISFRIENDLY); + } + } + + if (cnt > 0) + { + int boost = rnd(3) + 1; + + if (on(*tp, LOWCAST) || on(*tp, MEDCAST) || on(*tp, HIGHCAST)) + turn_on(*tp, CANCAST); + + tp->t_stats.s_hpt += 3 * boost; + tp->t_stats.s_arm -= 2 * boost; + tp->t_stats.s_lvl += 2 * boost; + tp->t_stats.s_str += 2 * boost; + tp->t_stats.s_intel += 2 * boost; + tp->t_stats.s_exp += 4 * boost * monsters[which].m_add_exp; + } + } + } +} + +/* + draw_room() + Draw a box around a room +*/ + +void +draw_room(struct room *rp) +{ + 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); + } +} + +/* + horiz() + draw a horizontal line +*/ + +void +horiz(int cnt) +{ + while(cnt--) + addch('-'); +} + +/* + vert() + draw a vertical line +*/ + +void +vert(int cnt) +{ + int x, y; + + getyx(stdscr, y, x); + + x--; + + while(cnt--) + { + move(++y, x); + addch('|'); + } +} + +/* + 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; +} + +/* + rnd_room() + Pick a room that is really there +*/ + +int +rnd_room(void) +{ + int rm; + + if (levtype != NORMLEV) + rm = 0; + else + do + { + rm = rnd(MAXROOMS); + } + while (rooms[rm].r_flags & ISGONE); + + return(rm); +}