1/* SCCS Id: @(#)mkroom.c 3.4 2001/09/06 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5/* 6 * Entry points: 7 * mkroom() -- make and stock a room of a given type 8 * nexttodoor() -- return TRUE if adjacent to a door 9 * has_dnstairs() -- return TRUE if given room has a down staircase 10 * has_upstairs() -- return TRUE if given room has an up staircase 11 * courtmon() -- generate a court monster 12 * save_rooms() -- save rooms into file fd 13 * rest_rooms() -- restore rooms from file fd 14 */ 15 16#include "hack.h" 17 18#ifdef OVLB 19STATIC_DCL boolean FDECL(isbig, (struct mkroom *)); 20STATIC_DCL struct mkroom * FDECL(pick_room,(BOOLEAN_P)); 21STATIC_DCL void NDECL(mkshop), FDECL(mkzoo,(int)), NDECL(mkswamp); 22STATIC_DCL void NDECL(mktemple); 23STATIC_DCL coord * FDECL(shrine_pos, (int)); 24STATIC_DCL struct permonst * NDECL(morguemon); 25STATIC_DCL struct permonst * NDECL(antholemon); 26STATIC_DCL struct permonst * NDECL(squadmon); 27STATIC_DCL void FDECL(save_room, (int,struct mkroom *)); 28STATIC_DCL void FDECL(rest_room, (int,struct mkroom *)); 29#endif /* OVLB */ 30 31#define sq(x) ((x)*(x)) 32 33extern const struct shclass shtypes[]; /* defined in shknam.c */ 34 35#ifdef OVLB 36 37STATIC_OVL boolean 38isbig(sroom) 39register struct mkroom *sroom; 40{ 41 register int area = (sroom->hx - sroom->lx + 1) 42 * (sroom->hy - sroom->ly + 1); 43 return((boolean)( area > 20 )); 44} 45 46void 47mkroom(roomtype) 48/* make and stock a room of a given type */ 49int roomtype; 50{ 51 if (roomtype >= SHOPBASE) 52 mkshop(); /* someday, we should be able to specify shop type */ 53 else switch(roomtype) { 54 case COURT: mkzoo(COURT); break; 55 case ZOO: mkzoo(ZOO); break; 56 case BEEHIVE: mkzoo(BEEHIVE); break; 57 case MORGUE: mkzoo(MORGUE); break; 58 case BARRACKS: mkzoo(BARRACKS); break; 59 case SWAMP: mkswamp(); break; 60 case TEMPLE: mktemple(); break; 61 case LEPREHALL: mkzoo(LEPREHALL); break; 62 case COCKNEST: mkzoo(COCKNEST); break; 63 case ANTHOLE: mkzoo(ANTHOLE); break; 64 default: impossible("Tried to make a room of type %d.", roomtype); 65 } 66} 67 68STATIC_OVL void 69mkshop() 70{ 71 register struct mkroom *sroom; 72 int i = -1; 73#ifdef WIZARD 74 char *ep = (char *)0; /* (init == lint suppression) */ 75 76 /* first determine shoptype */ 77 if(wizard){ 78#ifndef MAC 79 ep = nh_getenv("SHOPTYPE"); 80 if(ep){ 81 if(*ep == 'z' || *ep == 'Z'){ 82 mkzoo(ZOO); 83 return; 84 } 85 if(*ep == 'm' || *ep == 'M'){ 86 mkzoo(MORGUE); 87 return; 88 } 89 if(*ep == 'b' || *ep == 'B'){ 90 mkzoo(BEEHIVE); 91 return; 92 } 93 if(*ep == 't' || *ep == 'T' || *ep == '\\'){ 94 mkzoo(COURT); 95 return; 96 } 97 if(*ep == 's' || *ep == 'S'){ 98 mkzoo(BARRACKS); 99 return; 100 } 101 if(*ep == 'a' || *ep == 'A'){ 102 mkzoo(ANTHOLE); 103 return; 104 } 105 if(*ep == 'c' || *ep == 'C'){ 106 mkzoo(COCKNEST); 107 return; 108 } 109 if(*ep == 'l' || *ep == 'L'){ 110 mkzoo(LEPREHALL); 111 return; 112 } 113 if(*ep == '_'){ 114 mktemple(); 115 return; 116 } 117 if(*ep == '}'){ 118 mkswamp(); 119 return; 120 } 121 for(i=0; shtypes[i].name; i++) 122 if(*ep == def_oc_syms[(int)shtypes[i].symb]) 123 goto gottype; 124 if(*ep == 'g' || *ep == 'G') 125 i = 0; 126 else 127 i = -1; 128 } 129#endif 130 } 131#ifndef MAC 132gottype: 133#endif 134#endif 135 for(sroom = &rooms[0]; ; sroom++){ 136 if(sroom->hx < 0) return; 137 if(sroom - rooms >= nroom) { 138 pline("rooms not closed by -1?"); 139 return; 140 } 141 if(sroom->rtype != OROOM) continue; 142 if(has_dnstairs(sroom) || has_upstairs(sroom)) 143 continue; 144 if( 145#ifdef WIZARD 146 (wizard && ep && sroom->doorct != 0) || 147#endif 148 sroom->doorct == 1) break; 149 } 150 if (!sroom->rlit) { 151 int x, y; 152 153 for(x = sroom->lx - 1; x <= sroom->hx + 1; x++) 154 for(y = sroom->ly - 1; y <= sroom->hy + 1; y++) 155 levl[x][y].lit = 1; 156 sroom->rlit = 1; 157 } 158 159 if(i < 0) { /* shoptype not yet determined */ 160 register int j; 161 162 /* pick a shop type at random */ 163 for (j = rnd(100), i = 0; (j -= shtypes[i].prob) > 0; i++) 164 continue; 165 166 /* big rooms cannot be wand or book shops, 167 * - so make them general stores 168 */ 169 if(isbig(sroom) && (shtypes[i].symb == WAND_CLASS 170 || shtypes[i].symb == SPBOOK_CLASS)) i = 0; 171 } 172 sroom->rtype = SHOPBASE + i; 173 174 /* set room bits before stocking the shop */ 175#ifdef SPECIALIZATION 176 topologize(sroom, FALSE); /* doesn't matter - this is a special room */ 177#else 178 topologize(sroom); 179#endif 180 181 /* stock the room with a shopkeeper and artifacts */ 182 stock_room(i, sroom); 183} 184 185STATIC_OVL struct mkroom * 186pick_room(strict) 187register boolean strict; 188/* pick an unused room, preferably with only one door */ 189{ 190 register struct mkroom *sroom; 191 register int i = nroom; 192 193 for(sroom = &rooms[rn2(nroom)]; i--; sroom++) { 194 if(sroom == &rooms[nroom]) 195 sroom = &rooms[0]; 196 if(sroom->hx < 0) 197 return (struct mkroom *)0; 198 if(sroom->rtype != OROOM) continue; 199 if(!strict) { 200 if(has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3))) 201 continue; 202 } else if(has_upstairs(sroom) || has_dnstairs(sroom)) 203 continue; 204 if(sroom->doorct == 1 || !rn2(5) 205#ifdef WIZARD 206 || wizard 207#endif 208 ) 209 return sroom; 210 } 211 return (struct mkroom *)0; 212} 213 214STATIC_OVL void 215mkzoo(type) 216int type; 217{ 218 register struct mkroom *sroom; 219 220 if ((sroom = pick_room(FALSE)) != 0) { 221 sroom->rtype = type; 222 fill_zoo(sroom); 223 } 224} 225 226void 227fill_zoo(sroom) 228struct mkroom *sroom; 229{ 230 struct monst *mon; 231 register int sx,sy,i; 232 int sh, tx, ty, goldlim, type = sroom->rtype; 233 int rmno = (sroom - rooms) + ROOMOFFSET; 234 coord mm; 235 236#ifdef GCC_WARN 237 tx = ty = goldlim = 0; 238#endif 239 240 sh = sroom->fdoor; 241 switch(type) { 242 case COURT: 243 if(level.flags.is_maze_lev) { 244 for(tx = sroom->lx; tx <= sroom->hx; tx++) 245 for(ty = sroom->ly; ty <= sroom->hy; ty++) 246 if(IS_THRONE(levl[tx][ty].typ)) 247 goto throne_placed; 248 } 249 i = 100; 250 do { /* don't place throne on top of stairs */ 251 (void) somexy(sroom, &mm); 252 tx = mm.x; ty = mm.y; 253 } while (occupied((xchar)tx, (xchar)ty) && --i > 0); 254 throne_placed: 255 /* TODO: try to ensure the enthroned monster is an M2_PRINCE */ 256 break; 257 case BEEHIVE: 258 tx = sroom->lx + (sroom->hx - sroom->lx + 1)/2; 259 ty = sroom->ly + (sroom->hy - sroom->ly + 1)/2; 260 if(sroom->irregular) { 261 /* center might not be valid, so put queen elsewhere */ 262 if ((int) levl[tx][ty].roomno != rmno || 263 levl[tx][ty].edge) { 264 (void) somexy(sroom, &mm); 265 tx = mm.x; ty = mm.y; 266 } 267 } 268 break; 269 case ZOO: 270 case LEPREHALL: 271 goldlim = 500 * level_difficulty(); 272 break; 273 } 274 for(sx = sroom->lx; sx <= sroom->hx; sx++) 275 for(sy = sroom->ly; sy <= sroom->hy; sy++) { 276 if(sroom->irregular) { 277 if ((int) levl[sx][sy].roomno != rmno || 278 levl[sx][sy].edge || 279 (sroom->doorct && 280 distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1)) 281 continue; 282 } else if(!SPACE_POS(levl[sx][sy].typ) || 283 (sroom->doorct && 284 ((sx == sroom->lx && doors[sh].x == sx-1) || 285 (sx == sroom->hx && doors[sh].x == sx+1) || 286 (sy == sroom->ly && doors[sh].y == sy-1) || 287 (sy == sroom->hy && doors[sh].y == sy+1)))) 288 continue; 289 /* don't place monster on explicitly placed throne */ 290 if(type == COURT && IS_THRONE(levl[sx][sy].typ)) 291 continue; 292 mon = makemon( 293 (type == COURT) ? courtmon() : 294 (type == BARRACKS) ? squadmon() : 295 (type == MORGUE) ? morguemon() : 296 (type == BEEHIVE) ? 297 (sx == tx && sy == ty ? &mons[PM_QUEEN_BEE] : 298 &mons[PM_KILLER_BEE]) : 299 (type == LEPREHALL) ? &mons[PM_LEPRECHAUN] : 300 (type == COCKNEST) ? &mons[PM_COCKATRICE] : 301 (type == ANTHOLE) ? antholemon() : 302 (struct permonst *) 0, 303 sx, sy, NO_MM_FLAGS); 304 if(mon) { 305 mon->msleeping = 1; 306 if (type==COURT && mon->mpeaceful) { 307 mon->mpeaceful = 0; 308 set_malign(mon); 309 } 310 } 311 switch(type) { 312 case ZOO: 313 case LEPREHALL: 314 if(sroom->doorct) 315 { 316 int distval = dist2(sx,sy,doors[sh].x,doors[sh].y); 317 i = sq(distval); 318 } 319 else 320 i = goldlim; 321 if(i >= goldlim) i = 5*level_difficulty(); 322 goldlim -= i; 323 (void) mkgold((long) rn1(i, 10), sx, sy); 324 break; 325 case MORGUE: 326 if(!rn2(5)) 327 (void) mk_tt_object(CORPSE, sx, sy); 328 if(!rn2(10)) /* lots of treasure buried with dead */ 329 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, 330 sx, sy, TRUE, FALSE); 331 if (!rn2(5)) 332 make_grave(sx, sy, (char *)0); 333 break; 334 case BEEHIVE: 335 if(!rn2(3)) 336 (void) mksobj_at(LUMP_OF_ROYAL_JELLY, 337 sx, sy, TRUE, FALSE); 338 break; 339 case BARRACKS: 340 if(!rn2(20)) /* the payroll and some loot */ 341 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, 342 sx, sy, TRUE, FALSE); 343 break; 344 case COCKNEST: 345 if(!rn2(3)) { 346 struct obj *sobj = mk_tt_object(STATUE, sx, sy); 347 348 if (sobj) { 349 for (i = rn2(5); i; i--) 350 (void) add_to_container(sobj, 351 mkobj(RANDOM_CLASS, FALSE)); 352 sobj->owt = weight(sobj); 353 } 354 } 355 break; 356 case ANTHOLE: 357 if(!rn2(3)) 358 (void) mkobj_at(FOOD_CLASS, sx, sy, FALSE); 359 break; 360 } 361 } 362 switch (type) { 363 case COURT: 364 { 365 struct obj *chest; 366 levl[tx][ty].typ = THRONE; 367 (void) somexy(sroom, &mm); 368 (void) mkgold((long) rn1(50 * level_difficulty(),10), mm.x, mm.y); 369 /* the royal coffers */ 370 chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE); 371 chest->spe = 2; /* so it can be found later */ 372 level.flags.has_court = 1; 373 break; 374 } 375 case BARRACKS: 376 level.flags.has_barracks = 1; 377 break; 378 case ZOO: 379 level.flags.has_zoo = 1; 380 break; 381 case MORGUE: 382 level.flags.has_morgue = 1; 383 break; 384 case SWAMP: 385 level.flags.has_swamp = 1; 386 break; 387 case BEEHIVE: 388 level.flags.has_beehive = 1; 389 break; 390 } 391} 392 393/* make a swarm of undead around mm */ 394void 395mkundead(mm, revive_corpses, mm_flags) 396coord *mm; 397boolean revive_corpses; 398int mm_flags; 399{ 400 int cnt = (level_difficulty() + 1)/10 + rnd(5); 401 struct permonst *mdat; 402 struct obj *otmp; 403 coord cc; 404 405 while (cnt--) { 406 mdat = morguemon(); 407 if (enexto(&cc, mm->x, mm->y, mdat) && 408 (!revive_corpses || 409 !(otmp = sobj_at(CORPSE, cc.x, cc.y)) || 410 !revive(otmp))) 411 (void) makemon(mdat, cc.x, cc.y, mm_flags); 412 } 413 level.flags.graveyard = TRUE; /* reduced chance for undead corpse */ 414} 415 416STATIC_OVL struct permonst * 417morguemon() 418{ 419 register int i = rn2(100), hd = rn2(level_difficulty()); 420 421 if(hd > 10 && i < 10) 422 return((Inhell || In_endgame(&u.uz)) ? mkclass(S_DEMON,0) : 423 &mons[ndemon(A_NONE)]); 424 if(hd > 8 && i > 85) 425 return(mkclass(S_VAMPIRE,0)); 426 427 return((i < 20) ? &mons[PM_GHOST] 428 : (i < 40) ? &mons[PM_WRAITH] : mkclass(S_ZOMBIE,0)); 429} 430 431STATIC_OVL struct permonst * 432antholemon() 433{ 434 int mtyp; 435 436 /* Same monsters within a level, different ones between levels */ 437 switch ((level_difficulty() + ((long)u.ubirthday)) % 3) { 438 default: mtyp = PM_GIANT_ANT; break; 439 case 0: mtyp = PM_SOLDIER_ANT; break; 440 case 1: mtyp = PM_FIRE_ANT; break; 441 } 442 return ((mvitals[mtyp].mvflags & G_GONE) ? 443 (struct permonst *)0 : &mons[mtyp]); 444} 445 446STATIC_OVL void 447mkswamp() /* Michiel Huisjes & Fred de Wilde */ 448{ 449 register struct mkroom *sroom; 450 register int sx,sy,i,eelct = 0; 451 452 for(i=0; i<5; i++) { /* turn up to 5 rooms swampy */ 453 sroom = &rooms[rn2(nroom)]; 454 if(sroom->hx < 0 || sroom->rtype != OROOM || 455 has_upstairs(sroom) || has_dnstairs(sroom)) 456 continue; 457 458 /* satisfied; make a swamp */ 459 sroom->rtype = SWAMP; 460 for(sx = sroom->lx; sx <= sroom->hx; sx++) 461 for(sy = sroom->ly; sy <= sroom->hy; sy++) 462 if(!OBJ_AT(sx, sy) && 463 !MON_AT(sx, sy) && !t_at(sx,sy) && !nexttodoor(sx,sy)) { 464 if((sx+sy)%2) { 465 levl[sx][sy].typ = POOL; 466 if(!eelct || !rn2(4)) { 467 /* mkclass() won't do, as we might get kraken */ 468 (void) makemon(rn2(5) ? &mons[PM_GIANT_EEL] 469 : rn2(2) ? &mons[PM_PIRANHA] 470 : &mons[PM_ELECTRIC_EEL], 471 sx, sy, NO_MM_FLAGS); 472 eelct++; 473 } 474 } else 475 if(!rn2(4)) /* swamps tend to be moldy */ 476 (void) makemon(mkclass(S_FUNGUS,0), 477 sx, sy, NO_MM_FLAGS); 478 } 479 level.flags.has_swamp = 1; 480 } 481} 482 483STATIC_OVL coord * 484shrine_pos(roomno) 485int roomno; 486{ 487 static coord buf; 488 struct mkroom *troom = &rooms[roomno - ROOMOFFSET]; 489 490 buf.x = troom->lx + ((troom->hx - troom->lx) / 2); 491 buf.y = troom->ly + ((troom->hy - troom->ly) / 2); 492 return(&buf); 493} 494 495STATIC_OVL void 496mktemple() 497{ 498 register struct mkroom *sroom; 499 coord *shrine_spot; 500 register struct rm *lev; 501 502 if(!(sroom = pick_room(TRUE))) return; 503 504 /* set up Priest and shrine */ 505 sroom->rtype = TEMPLE; 506 /* 507 * In temples, shrines are blessed altars 508 * located in the center of the room 509 */ 510 shrine_spot = shrine_pos((sroom - rooms) + ROOMOFFSET); 511 lev = &levl[shrine_spot->x][shrine_spot->y]; 512 lev->typ = ALTAR; 513 lev->altarmask = induced_align(80); 514 priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE); 515 lev->altarmask |= AM_SHRINE; 516 level.flags.has_temple = 1; 517} 518 519boolean 520nexttodoor(sx,sy) 521register int sx, sy; 522{ 523 register int dx, dy; 524 register struct rm *lev; 525 for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++) { 526 if(!isok(sx+dx, sy+dy)) continue; 527 if(IS_DOOR((lev = &levl[sx+dx][sy+dy])->typ) || 528 lev->typ == SDOOR) 529 return(TRUE); 530 } 531 return(FALSE); 532} 533 534boolean 535has_dnstairs(sroom) 536register struct mkroom *sroom; 537{ 538 if (sroom == dnstairs_room) 539 return TRUE; 540 if (sstairs.sx && !sstairs.up) 541 return((boolean)(sroom == sstairs_room)); 542 return FALSE; 543} 544 545boolean 546has_upstairs(sroom) 547register struct mkroom *sroom; 548{ 549 if (sroom == upstairs_room) 550 return TRUE; 551 if (sstairs.sx && sstairs.up) 552 return((boolean)(sroom == sstairs_room)); 553 return FALSE; 554} 555 556#endif /* OVLB */ 557#ifdef OVL0 558 559int 560somex(croom) 561register struct mkroom *croom; 562{ 563 return rn2(croom->hx-croom->lx+1) + croom->lx; 564} 565 566int 567somey(croom) 568register struct mkroom *croom; 569{ 570 return rn2(croom->hy-croom->ly+1) + croom->ly; 571} 572 573boolean 574inside_room(croom, x, y) 575struct mkroom *croom; 576xchar x, y; 577{ 578 return((boolean)(x >= croom->lx-1 && x <= croom->hx+1 && 579 y >= croom->ly-1 && y <= croom->hy+1)); 580} 581 582boolean 583somexy(croom, c) 584struct mkroom *croom; 585coord *c; 586{ 587 int try_cnt = 0; 588 int i; 589 590 if (croom->irregular) { 591 i = (croom - rooms) + ROOMOFFSET; 592 593 while(try_cnt++ < 100) { 594 c->x = somex(croom); 595 c->y = somey(croom); 596 if (!levl[c->x][c->y].edge && 597 (int) levl[c->x][c->y].roomno == i) 598 return TRUE; 599 } 600 /* try harder; exhaustively search until one is found */ 601 for(c->x = croom->lx; c->x <= croom->hx; c->x++) 602 for(c->y = croom->ly; c->y <= croom->hy; c->y++) 603 if (!levl[c->x][c->y].edge && 604 (int) levl[c->x][c->y].roomno == i) 605 return TRUE; 606 return FALSE; 607 } 608 609 if (!croom->nsubrooms) { 610 c->x = somex(croom); 611 c->y = somey(croom); 612 return TRUE; 613 } 614 615 /* Check that coords doesn't fall into a subroom or into a wall */ 616 617 while(try_cnt++ < 100) { 618 c->x = somex(croom); 619 c->y = somey(croom); 620 if (IS_WALL(levl[c->x][c->y].typ)) 621 continue; 622 for(i=0 ; i<croom->nsubrooms;i++) 623 if(inside_room(croom->sbrooms[i], c->x, c->y)) 624 goto you_lose; 625 break; 626you_lose: ; 627 } 628 if (try_cnt >= 100) 629 return FALSE; 630 return TRUE; 631} 632 633/* 634 * Search for a special room given its type (zoo, court, etc...) 635 * Special values : 636 * - ANY_SHOP 637 * - ANY_TYPE 638 */ 639 640struct mkroom * 641search_special(type) 642schar type; 643{ 644 register struct mkroom *croom; 645 646 for(croom = &rooms[0]; croom->hx >= 0; croom++) 647 if((type == ANY_TYPE && croom->rtype != OROOM) || 648 (type == ANY_SHOP && croom->rtype >= SHOPBASE) || 649 croom->rtype == type) 650 return croom; 651 for(croom = &subrooms[0]; croom->hx >= 0; croom++) 652 if((type == ANY_TYPE && croom->rtype != OROOM) || 653 (type == ANY_SHOP && croom->rtype >= SHOPBASE) || 654 croom->rtype == type) 655 return croom; 656 return (struct mkroom *) 0; 657} 658 659#endif /* OVL0 */ 660#ifdef OVLB 661 662struct permonst * 663courtmon() 664{ 665 int i = rn2(60) + rn2(3*level_difficulty()); 666 if (i > 100) return(mkclass(S_DRAGON,0)); 667 else if (i > 95) return(mkclass(S_GIANT,0)); 668 else if (i > 85) return(mkclass(S_TROLL,0)); 669 else if (i > 75) return(mkclass(S_CENTAUR,0)); 670 else if (i > 60) return(mkclass(S_ORC,0)); 671 else if (i > 45) return(&mons[PM_BUGBEAR]); 672 else if (i > 30) return(&mons[PM_HOBGOBLIN]); 673 else if (i > 15) return(mkclass(S_GNOME,0)); 674 else return(mkclass(S_KOBOLD,0)); 675} 676 677#define NSTYPES (PM_CAPTAIN - PM_SOLDIER + 1) 678 679static struct { 680 unsigned pm; 681 unsigned prob; 682} squadprob[NSTYPES] = { 683 {PM_SOLDIER, 80}, {PM_SERGEANT, 15}, {PM_LIEUTENANT, 4}, {PM_CAPTAIN, 1} 684}; 685 686STATIC_OVL struct permonst * 687squadmon() /* return soldier types. */ 688{ 689 int sel_prob, i, cpro, mndx; 690 691 sel_prob = rnd(80+level_difficulty()); 692 693 cpro = 0; 694 for (i = 0; i < NSTYPES; i++) { 695 cpro += squadprob[i].prob; 696 if (cpro > sel_prob) { 697 mndx = squadprob[i].pm; 698 goto gotone; 699 } 700 } 701 mndx = squadprob[rn2(NSTYPES)].pm; 702gotone: 703 if (!(mvitals[mndx].mvflags & G_GONE)) return(&mons[mndx]); 704 else return((struct permonst *) 0); 705} 706 707/* 708 * save_room : A recursive function that saves a room and its subrooms 709 * (if any). 710 */ 711 712STATIC_OVL void 713save_room(fd, r) 714int fd; 715struct mkroom *r; 716{ 717 short i; 718 /* 719 * Well, I really should write only useful information instead 720 * of writing the whole structure. That is I should not write 721 * the subrooms pointers, but who cares ? 722 */ 723 bwrite(fd, (genericptr_t) r, sizeof(struct mkroom)); 724 for(i=0; i<r->nsubrooms; i++) 725 save_room(fd, r->sbrooms[i]); 726} 727 728/* 729 * save_rooms : Save all the rooms on disk! 730 */ 731 732void 733save_rooms(fd) 734int fd; 735{ 736 short i; 737 738 /* First, write the number of rooms */ 739 bwrite(fd, (genericptr_t) &nroom, sizeof(nroom)); 740 for(i=0; i<nroom; i++) 741 save_room(fd, &rooms[i]); 742} 743 744STATIC_OVL void 745rest_room(fd, r) 746int fd; 747struct mkroom *r; 748{ 749 short i; 750 751 mread(fd, (genericptr_t) r, sizeof(struct mkroom)); 752 for(i=0; i<r->nsubrooms; i++) { 753 r->sbrooms[i] = &subrooms[nsubroom]; 754 rest_room(fd, &subrooms[nsubroom]); 755 subrooms[nsubroom++].resident = (struct monst *)0; 756 } 757} 758 759/* 760 * rest_rooms : That's for restoring rooms. Read the rooms structure from 761 * the disk. 762 */ 763 764void 765rest_rooms(fd) 766int fd; 767{ 768 short i; 769 770 mread(fd, (genericptr_t) &nroom, sizeof(nroom)); 771 nsubroom = 0; 772 for(i = 0; i<nroom; i++) { 773 rest_room(fd, &rooms[i]); 774 rooms[i].resident = (struct monst *)0; 775 } 776 rooms[nroom].hx = -1; /* restore ending flags */ 777 subrooms[nsubroom].hx = -1; 778} 779#endif /* OVLB */ 780 781/*mkroom.c*/ 782