Annotation of early-roguelike/rogue5/rooms.c, Revision 1.1
1.1 ! rubenllo 1: /*
! 2: * Create the layout for the new level
! 3: *
! 4: * @(#)rooms.c 4.45 (Berkeley) 02/05/99
! 5: *
! 6: * Rogue: Exploring the Dungeons of Doom
! 7: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
! 8: * All rights reserved.
! 9: *
! 10: * See the file LICENSE.TXT for full copyright and licensing information.
! 11: */
! 12:
! 13: #include <ctype.h>
! 14: #include <curses.h>
! 15: #include "rogue.h"
! 16:
! 17: typedef struct spot { /* position matrix for maze positions */
! 18: int nexits;
! 19: coord exits[4];
! 20: int used;
! 21: } SPOT;
! 22:
! 23: #define GOLDGRP 1
! 24:
! 25: /*
! 26: * do_rooms:
! 27: * Create rooms and corridors with a connectivity graph
! 28: */
! 29:
! 30: void
! 31: do_rooms(void)
! 32: {
! 33: int i;
! 34: struct room *rp;
! 35: THING *tp;
! 36: int left_out;
! 37: coord top;
! 38: coord bsze; /* maximum room size */
! 39: coord mp;
! 40:
! 41: bsze.x = NUMCOLS / 3;
! 42: bsze.y = NUMLINES / 3;
! 43: /*
! 44: * Clear things for a new level
! 45: */
! 46: for (rp = rooms; rp < &rooms[MAXROOMS]; rp++)
! 47: {
! 48: rp->r_goldval = 0;
! 49: rp->r_nexits = 0;
! 50: rp->r_flags = 0;
! 51: }
! 52: /*
! 53: * Put the gone rooms, if any, on the level
! 54: */
! 55: left_out = rnd(4);
! 56: for (i = 0; i < left_out; i++)
! 57: rooms[rnd_room()].r_flags |= ISGONE;
! 58: /*
! 59: * dig and populate all the rooms on the level
! 60: */
! 61: for (i = 0, rp = rooms; i < MAXROOMS; rp++, i++)
! 62: {
! 63: /*
! 64: * Find upper left corner of box that this room goes in
! 65: */
! 66: top.x = (i % 3) * bsze.x + 1;
! 67: top.y = (i / 3) * bsze.y;
! 68: if (rp->r_flags & ISGONE)
! 69: {
! 70: /*
! 71: * Place a gone room. Make certain that there is a blank line
! 72: * for passage drawing.
! 73: */
! 74: do
! 75: {
! 76: rp->r_pos.x = top.x + rnd(bsze.x - 2) + 1;
! 77: rp->r_pos.y = top.y + rnd(bsze.y - 2) + 1;
! 78: rp->r_max.x = -NUMCOLS;
! 79: rp->r_max.y = -NUMLINES;
! 80: } until (rp->r_pos.y > 0 && rp->r_pos.y < NUMLINES-1);
! 81: continue;
! 82: }
! 83: /*
! 84: * set room type
! 85: */
! 86: if (rnd(10) < level - 1)
! 87: {
! 88: rp->r_flags |= ISDARK; /* dark room */
! 89: if (rnd(15) == 0)
! 90: rp->r_flags = ISMAZE; /* maze room */
! 91: }
! 92: /*
! 93: * Find a place and size for a random room
! 94: */
! 95: if (rp->r_flags & ISMAZE)
! 96: {
! 97: rp->r_max.x = bsze.x - 1;
! 98: rp->r_max.y = bsze.y - 1;
! 99: if ((rp->r_pos.x = top.x) == 1)
! 100: rp->r_pos.x = 0;
! 101: if ((rp->r_pos.y = top.y) == 0)
! 102: {
! 103: rp->r_pos.y++;
! 104: rp->r_max.y--;
! 105: }
! 106: }
! 107: else
! 108: do
! 109: {
! 110: rp->r_max.x = rnd(bsze.x - 4) + 4;
! 111: rp->r_max.y = rnd(bsze.y - 4) + 4;
! 112: rp->r_pos.x = top.x + rnd(bsze.x - rp->r_max.x);
! 113: rp->r_pos.y = top.y + rnd(bsze.y - rp->r_max.y);
! 114: } until (rp->r_pos.y != 0);
! 115: draw_room(rp);
! 116: /*
! 117: * Put the gold in
! 118: */
! 119: if (rnd(2) == 0 && (!amulet || level >= max_level))
! 120: {
! 121: THING *gold;
! 122:
! 123: gold = new_item();
! 124: gold->o_goldval = rp->r_goldval = GOLDCALC;
! 125: find_floor(rp, &rp->r_gold, FALSE, FALSE);
! 126: gold->o_pos = rp->r_gold;
! 127: chat(rp->r_gold.y, rp->r_gold.x) = GOLD;
! 128: gold->o_flags = ISMANY;
! 129: gold->o_group = GOLDGRP;
! 130: gold->o_type = GOLD;
! 131: attach(lvl_obj, gold);
! 132: }
! 133: /*
! 134: * Put the monster in
! 135: */
! 136: if (rnd(100) < (rp->r_goldval > 0 ? 80 : 25))
! 137: {
! 138: tp = new_item();
! 139: find_floor(rp, &mp, FALSE, TRUE);
! 140: new_monster(tp, randmonster(FALSE), &mp);
! 141: give_pack(tp);
! 142: }
! 143: }
! 144: }
! 145:
! 146: /*
! 147: * draw_room:
! 148: * Draw a box around a room and lay down the floor for normal
! 149: * rooms; for maze rooms, draw maze.
! 150: */
! 151:
! 152: void
! 153: draw_room(const struct room *rp)
! 154: {
! 155: int y, x;
! 156:
! 157: if (rp->r_flags & ISMAZE)
! 158: do_maze(rp);
! 159: else
! 160: {
! 161: vert(rp, rp->r_pos.x); /* Draw left side */
! 162: vert(rp, rp->r_pos.x + rp->r_max.x - 1); /* Draw right side */
! 163: horiz(rp, rp->r_pos.y); /* Draw top */
! 164: horiz(rp, rp->r_pos.y + rp->r_max.y - 1); /* Draw bottom */
! 165:
! 166: /*
! 167: * Put the floor down
! 168: */
! 169: for (y = rp->r_pos.y + 1; y < rp->r_pos.y + rp->r_max.y - 1; y++)
! 170: for (x = rp->r_pos.x + 1; x < rp->r_pos.x + rp->r_max.x - 1; x++)
! 171: chat(y, x) = FLOOR;
! 172: }
! 173: }
! 174:
! 175: /*
! 176: * vert:
! 177: * Draw a vertical line
! 178: */
! 179:
! 180: void
! 181: vert(const struct room *rp, int startx)
! 182: {
! 183: int y;
! 184:
! 185: for (y = rp->r_pos.y + 1; y <= rp->r_max.y + rp->r_pos.y - 1; y++)
! 186: chat(y, startx) = '|';
! 187: }
! 188:
! 189: /*
! 190: * horiz:
! 191: * Draw a horizontal line
! 192: */
! 193:
! 194: void
! 195: horiz(const struct room *rp, int starty)
! 196: {
! 197: int x;
! 198:
! 199: for (x = rp->r_pos.x; x <= rp->r_pos.x + rp->r_max.x - 1; x++)
! 200: chat(starty, x) = '-';
! 201: }
! 202:
! 203: /*
! 204: * do_maze:
! 205: * Dig a maze
! 206: */
! 207:
! 208: static int Maxy, Maxx, Starty, Startx;
! 209:
! 210: static SPOT maze[NUMLINES/3+1][NUMCOLS/3+1];
! 211:
! 212:
! 213: void
! 214: do_maze(const struct room *rp)
! 215: {
! 216: SPOT *sp;
! 217: int starty, startx;
! 218: coord pos;
! 219:
! 220: for (sp = &maze[0][0]; sp <= &maze[NUMLINES / 3][NUMCOLS / 3]; sp++)
! 221: {
! 222: sp->used = FALSE;
! 223: sp->nexits = 0;
! 224: }
! 225:
! 226: Maxy = rp->r_max.y;
! 227: Maxx = rp->r_max.x;
! 228: Starty = rp->r_pos.y;
! 229: Startx = rp->r_pos.x;
! 230: starty = (rnd(rp->r_max.y) / 2) * 2;
! 231: startx = (rnd(rp->r_max.x) / 2) * 2;
! 232: pos.y = starty + Starty;
! 233: pos.x = startx + Startx;
! 234: putpass(&pos);
! 235: dig(starty, startx);
! 236: }
! 237:
! 238: /*
! 239: * dig:
! 240: * Dig out from around where we are now, if possible
! 241: */
! 242:
! 243: void
! 244: dig(int y, int x)
! 245: {
! 246: coord *cp;
! 247: int cnt, newy, newx, nexty = 0, nextx = 0;
! 248: coord pos;
! 249: coord del[4] = {
! 250: {2, 0}, {-2, 0}, {0, 2}, {0, -2}
! 251: };
! 252:
! 253: for (;;)
! 254: {
! 255: cnt = 0;
! 256: for (cp = del; cp <= &del[3]; cp++)
! 257: {
! 258: newy = y + cp->y;
! 259: newx = x + cp->x;
! 260: if (newy < 0 || newy > Maxy || newx < 0 || newx > Maxx)
! 261: continue;
! 262: if (flat(newy + Starty, newx + Startx) & F_PASS)
! 263: continue;
! 264: if (rnd(++cnt) == 0)
! 265: {
! 266: nexty = newy;
! 267: nextx = newx;
! 268: }
! 269: }
! 270: if (cnt == 0)
! 271: return;
! 272: accnt_maze(y, x, nexty, nextx);
! 273: accnt_maze(nexty, nextx, y, x);
! 274: if (nexty == y)
! 275: {
! 276: pos.y = y + Starty;
! 277: if (nextx - x < 0)
! 278: pos.x = nextx + Startx + 1;
! 279: else
! 280: pos.x = nextx + Startx - 1;
! 281: }
! 282: else
! 283: {
! 284: pos.x = x + Startx;
! 285: if (nexty - y < 0)
! 286: pos.y = nexty + Starty + 1;
! 287: else
! 288: pos.y = nexty + Starty - 1;
! 289: }
! 290: putpass(&pos);
! 291: pos.y = nexty + Starty;
! 292: pos.x = nextx + Startx;
! 293: putpass(&pos);
! 294: dig(nexty, nextx);
! 295: }
! 296: }
! 297:
! 298: /*
! 299: * accnt_maze:
! 300: * Account for maze exits
! 301: */
! 302:
! 303: void
! 304: accnt_maze(int y, int x, int ny, int nx)
! 305: {
! 306: SPOT *sp;
! 307: coord *cp;
! 308:
! 309: sp = &maze[y][x];
! 310: for (cp = sp->exits; cp < &sp->exits[sp->nexits]; cp++)
! 311: if (cp->y == ny && cp->x == nx)
! 312: return;
! 313: cp->y = ny;
! 314: cp->x = nx;
! 315: }
! 316:
! 317: /*
! 318: * rnd_pos:
! 319: * Pick a random spot in a room
! 320: */
! 321:
! 322: void
! 323: rnd_pos(const struct room *rp, coord *cp)
! 324: {
! 325: cp->x = rp->r_pos.x + rnd(rp->r_max.x - 2) + 1;
! 326: cp->y = rp->r_pos.y + rnd(rp->r_max.y - 2) + 1;
! 327: }
! 328:
! 329: /*
! 330: * find_floor:
! 331: * Find a valid floor spot in this room. If rp is NULL, then
! 332: * pick a new room each time around the loop.
! 333: */
! 334: int
! 335: find_floor(const struct room *rp, coord *cp, int limit, int monst)
! 336: {
! 337: PLACE *pp;
! 338: int cnt;
! 339: int compchar = 0;
! 340: int pickroom;
! 341:
! 342: pickroom = (rp == NULL);
! 343:
! 344: if (!pickroom)
! 345: compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR);
! 346: cnt = limit;
! 347: for (;;)
! 348: {
! 349: if (limit && cnt-- == 0)
! 350: return FALSE;
! 351: if (pickroom)
! 352: {
! 353: rp = &rooms[rnd_room()];
! 354: compchar = ((rp->r_flags & ISMAZE) ? PASSAGE : FLOOR);
! 355: }
! 356: rnd_pos(rp, cp);
! 357: pp = INDEX(cp->y, cp->x);
! 358: if (monst)
! 359: {
! 360: if (pp->p_monst == NULL && step_ok(pp->p_ch))
! 361: return TRUE;
! 362: }
! 363: else if (pp->p_ch == compchar)
! 364: return TRUE;
! 365: }
! 366: }
! 367:
! 368: /*
! 369: * enter_room:
! 370: * Code that is executed whenver you appear in a room
! 371: */
! 372:
! 373: void
! 374: enter_room(const coord *cp)
! 375: {
! 376: struct room *rp;
! 377: THING *tp;
! 378: int y, x;
! 379: chtype ch;
! 380:
! 381: rp = proom = roomin(cp);
! 382: door_open(rp);
! 383: if (!(rp->r_flags & ISDARK) && !on(player, ISBLIND))
! 384: for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
! 385: {
! 386: move(y, rp->r_pos.x);
! 387: for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
! 388: {
! 389: tp = moat(y, x);
! 390: ch = chat(y, x);
! 391: if (tp == NULL)
! 392: if (CCHAR(inch()) != ch)
! 393: addch(ch);
! 394: else
! 395: move(y, x + 1);
! 396: else
! 397: {
! 398: tp->t_oldch = ch;
! 399: if (!see_monst(tp))
! 400: if (on(player, SEEMONST))
! 401: {
! 402: standout();
! 403: addch(tp->t_disguise);
! 404: standend();
! 405: }
! 406: else
! 407: addch(ch);
! 408: else
! 409: addch(tp->t_disguise);
! 410: }
! 411: }
! 412: }
! 413: }
! 414:
! 415: /*
! 416: * leave_room:
! 417: * Code for when we exit a room
! 418: */
! 419:
! 420: void
! 421: leave_room(const coord *cp)
! 422: {
! 423: PLACE *pp;
! 424: struct room *rp;
! 425: int y, x;
! 426: int floor;
! 427: int ch;
! 428:
! 429: rp = proom;
! 430:
! 431: if (rp->r_flags & ISMAZE)
! 432: return;
! 433:
! 434: if (rp->r_flags & ISGONE)
! 435: floor = PASSAGE;
! 436: else if (!(rp->r_flags & ISDARK) || on(player, ISBLIND))
! 437: floor = FLOOR;
! 438: else
! 439: floor = ' ';
! 440:
! 441: proom = &passages[flat(cp->y, cp->x) & F_PNUM];
! 442: for (y = rp->r_pos.y; y < rp->r_max.y + rp->r_pos.y; y++)
! 443: for (x = rp->r_pos.x; x < rp->r_max.x + rp->r_pos.x; x++)
! 444: {
! 445: move(y, x);
! 446: switch ( ch = CCHAR(inch()) )
! 447: {
! 448: case FLOOR:
! 449: if (floor == ' ' && ch != ' ')
! 450: addch(' ');
! 451: break;
! 452: default:
! 453: /*
! 454: * to check for monster, we have to strip out
! 455: * standout bit
! 456: */
! 457: if (isupper(toascii(ch)))
! 458: {
! 459: if (on(player, SEEMONST))
! 460: {
! 461: standout();
! 462: addch(ch);
! 463: standend();
! 464: break;
! 465: }
! 466: pp = INDEX(y,x);
! 467: addch(pp->p_ch == DOOR ? DOOR : floor);
! 468: }
! 469: }
! 470: }
! 471: door_open(rp);
! 472: }
CVSweb