dumplog message history groundwork
[aNetHack.git] / src / mkroom.c
blobc76531b52d403f6cc9983bd4d28bad4cbfe882f4
1 /* NetHack 3.6 mkroom.c $NHDT-Date: 1446887530 2015/11/07 09:12:10 $ $NHDT-Branch: master $:$NHDT-Revision: 1.24 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
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 * cmap_to_type() -- convert S_xxx symbol to XXX topology code
17 #include "hack.h"
19 STATIC_DCL boolean FDECL(isbig, (struct mkroom *));
20 STATIC_DCL struct mkroom *FDECL(pick_room, (BOOLEAN_P));
21 STATIC_DCL void NDECL(mkshop), FDECL(mkzoo, (int)), NDECL(mkswamp);
22 STATIC_DCL void NDECL(mktemple);
23 STATIC_DCL coord *FDECL(shrine_pos, (int));
24 STATIC_DCL struct permonst *NDECL(morguemon);
25 STATIC_DCL struct permonst *NDECL(squadmon);
26 STATIC_DCL void FDECL(save_room, (int, struct mkroom *));
27 STATIC_DCL void FDECL(rest_room, (int, struct mkroom *));
29 #define sq(x) ((x) * (x))
31 extern const struct shclass shtypes[]; /* defined in shknam.c */
33 STATIC_OVL boolean
34 isbig(sroom)
35 register struct mkroom *sroom;
37 register int area = (sroom->hx - sroom->lx + 1)
38 * (sroom->hy - sroom->ly + 1);
40 return (boolean) (area > 20);
43 /* make and stock a room of a given type */
44 void
45 mkroom(roomtype)
46 int roomtype;
48 if (roomtype >= SHOPBASE)
49 mkshop(); /* someday, we should be able to specify shop type */
50 else
51 switch (roomtype) {
52 case COURT:
53 mkzoo(COURT);
54 break;
55 case ZOO:
56 mkzoo(ZOO);
57 break;
58 case BEEHIVE:
59 mkzoo(BEEHIVE);
60 break;
61 case MORGUE:
62 mkzoo(MORGUE);
63 break;
64 case BARRACKS:
65 mkzoo(BARRACKS);
66 break;
67 case SWAMP:
68 mkswamp();
69 break;
70 case TEMPLE:
71 mktemple();
72 break;
73 case LEPREHALL:
74 mkzoo(LEPREHALL);
75 break;
76 case COCKNEST:
77 mkzoo(COCKNEST);
78 break;
79 case ANTHOLE:
80 mkzoo(ANTHOLE);
81 break;
82 default:
83 impossible("Tried to make a room of type %d.", roomtype);
87 STATIC_OVL void
88 mkshop()
90 register struct mkroom *sroom;
91 int i = -1;
92 char *ep = (char *) 0; /* (init == lint suppression) */
94 /* first determine shoptype */
95 if (wizard) {
96 #ifndef MAC
97 ep = nh_getenv("SHOPTYPE");
98 if (ep) {
99 if (*ep == 'z' || *ep == 'Z') {
100 mkzoo(ZOO);
101 return;
103 if (*ep == 'm' || *ep == 'M') {
104 mkzoo(MORGUE);
105 return;
107 if (*ep == 'b' || *ep == 'B') {
108 mkzoo(BEEHIVE);
109 return;
111 if (*ep == 't' || *ep == 'T' || *ep == '\\') {
112 mkzoo(COURT);
113 return;
115 if (*ep == 's' || *ep == 'S') {
116 mkzoo(BARRACKS);
117 return;
119 if (*ep == 'a' || *ep == 'A') {
120 mkzoo(ANTHOLE);
121 return;
123 if (*ep == 'c' || *ep == 'C') {
124 mkzoo(COCKNEST);
125 return;
127 if (*ep == 'l' || *ep == 'L') {
128 mkzoo(LEPREHALL);
129 return;
131 if (*ep == '_') {
132 mktemple();
133 return;
135 if (*ep == '}') {
136 mkswamp();
137 return;
139 for (i = 0; shtypes[i].name; i++)
140 if (*ep == def_oc_syms[(int) shtypes[i].symb].sym)
141 goto gottype;
142 if (*ep == 'g' || *ep == 'G')
143 i = 0;
144 else if (*ep == 'v' || *ep == 'V')
145 i = FODDERSHOP - SHOPBASE; /* veggy food */
146 else
147 i = -1;
149 #endif
151 #ifndef MAC
152 gottype:
153 #endif
154 for (sroom = &rooms[0];; sroom++) {
155 if (sroom->hx < 0)
156 return;
157 if (sroom - rooms >= nroom) {
158 pline("rooms not closed by -1?");
159 return;
161 if (sroom->rtype != OROOM)
162 continue;
163 if (has_dnstairs(sroom) || has_upstairs(sroom))
164 continue;
165 if ((wizard && ep && sroom->doorct != 0) || sroom->doorct == 1)
166 break;
168 if (!sroom->rlit) {
169 int x, y;
171 for (x = sroom->lx - 1; x <= sroom->hx + 1; x++)
172 for (y = sroom->ly - 1; y <= sroom->hy + 1; y++)
173 levl[x][y].lit = 1;
174 sroom->rlit = 1;
177 if (i < 0) { /* shoptype not yet determined */
178 register int j;
180 /* pick a shop type at random */
181 for (j = rnd(100), i = 0; (j -= shtypes[i].prob) > 0; i++)
182 continue;
184 /* big rooms cannot be wand or book shops,
185 * - so make them general stores
187 if (isbig(sroom) && (shtypes[i].symb == WAND_CLASS
188 || shtypes[i].symb == SPBOOK_CLASS))
189 i = 0;
191 sroom->rtype = SHOPBASE + i;
193 /* set room bits before stocking the shop */
194 #ifdef SPECIALIZATION
195 topologize(sroom, FALSE); /* doesn't matter - this is a special room */
196 #else
197 topologize(sroom);
198 #endif
200 /* stock the room with a shopkeeper and artifacts */
201 stock_room(i, sroom);
204 /* pick an unused room, preferably with only one door */
205 STATIC_OVL struct mkroom *
206 pick_room(strict)
207 register boolean strict;
209 register struct mkroom *sroom;
210 register int i = nroom;
212 for (sroom = &rooms[rn2(nroom)]; i--; sroom++) {
213 if (sroom == &rooms[nroom])
214 sroom = &rooms[0];
215 if (sroom->hx < 0)
216 return (struct mkroom *) 0;
217 if (sroom->rtype != OROOM)
218 continue;
219 if (!strict) {
220 if (has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
221 continue;
222 } else if (has_upstairs(sroom) || has_dnstairs(sroom))
223 continue;
224 if (sroom->doorct == 1 || !rn2(5) || wizard)
225 return sroom;
227 return (struct mkroom *) 0;
230 STATIC_OVL void
231 mkzoo(type)
232 int type;
234 register struct mkroom *sroom;
236 if ((sroom = pick_room(FALSE)) != 0) {
237 sroom->rtype = type;
238 fill_zoo(sroom);
242 void
243 fill_zoo(sroom)
244 struct mkroom *sroom;
246 struct monst *mon;
247 register int sx, sy, i;
248 int sh, tx = 0, ty = 0, goldlim = 0, type = sroom->rtype;
249 int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
250 coord mm;
252 sh = sroom->fdoor;
253 switch (type) {
254 case COURT:
255 if (level.flags.is_maze_lev) {
256 for (tx = sroom->lx; tx <= sroom->hx; tx++)
257 for (ty = sroom->ly; ty <= sroom->hy; ty++)
258 if (IS_THRONE(levl[tx][ty].typ))
259 goto throne_placed;
261 i = 100;
262 do { /* don't place throne on top of stairs */
263 (void) somexy(sroom, &mm);
264 tx = mm.x;
265 ty = mm.y;
266 } while (occupied((xchar) tx, (xchar) ty) && --i > 0);
267 throne_placed:
268 /* TODO: try to ensure the enthroned monster is an M2_PRINCE */
269 break;
270 case BEEHIVE:
271 tx = sroom->lx + (sroom->hx - sroom->lx + 1) / 2;
272 ty = sroom->ly + (sroom->hy - sroom->ly + 1) / 2;
273 if (sroom->irregular) {
274 /* center might not be valid, so put queen elsewhere */
275 if ((int) levl[tx][ty].roomno != rmno || levl[tx][ty].edge) {
276 (void) somexy(sroom, &mm);
277 tx = mm.x;
278 ty = mm.y;
281 break;
282 case ZOO:
283 case LEPREHALL:
284 goldlim = 500 * level_difficulty();
285 break;
288 for (sx = sroom->lx; sx <= sroom->hx; sx++)
289 for (sy = sroom->ly; sy <= sroom->hy; sy++) {
290 if (sroom->irregular) {
291 if ((int) levl[sx][sy].roomno != rmno || levl[sx][sy].edge
292 || (sroom->doorct
293 && distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1))
294 continue;
295 } else if (!SPACE_POS(levl[sx][sy].typ)
296 || (sroom->doorct
297 && ((sx == sroom->lx && doors[sh].x == sx - 1)
298 || (sx == sroom->hx && doors[sh].x == sx + 1)
299 || (sy == sroom->ly && doors[sh].y == sy - 1)
300 || (sy == sroom->hy
301 && doors[sh].y == sy + 1))))
302 continue;
303 /* don't place monster on explicitly placed throne */
304 if (type == COURT && IS_THRONE(levl[sx][sy].typ))
305 continue;
306 mon = makemon((type == COURT)
307 ? courtmon()
308 : (type == BARRACKS)
309 ? squadmon()
310 : (type == MORGUE)
311 ? morguemon()
312 : (type == BEEHIVE)
313 ? (sx == tx && sy == ty
314 ? &mons[PM_QUEEN_BEE]
315 : &mons[PM_KILLER_BEE])
316 : (type == LEPREHALL)
317 ? &mons[PM_LEPRECHAUN]
318 : (type == COCKNEST)
319 ? &mons[PM_COCKATRICE]
320 : (type == ANTHOLE)
321 ? antholemon()
322 : (struct permonst *) 0,
323 sx, sy, NO_MM_FLAGS);
324 if (mon) {
325 mon->msleeping = 1;
326 if (type == COURT && mon->mpeaceful) {
327 mon->mpeaceful = 0;
328 set_malign(mon);
331 switch (type) {
332 case ZOO:
333 case LEPREHALL:
334 if (sroom->doorct) {
335 int distval = dist2(sx, sy, doors[sh].x, doors[sh].y);
336 i = sq(distval);
337 } else
338 i = goldlim;
339 if (i >= goldlim)
340 i = 5 * level_difficulty();
341 goldlim -= i;
342 (void) mkgold((long) rn1(i, 10), sx, sy);
343 break;
344 case MORGUE:
345 if (!rn2(5))
346 (void) mk_tt_object(CORPSE, sx, sy);
347 if (!rn2(10)) /* lots of treasure buried with dead */
348 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy,
349 TRUE, FALSE);
350 if (!rn2(5))
351 make_grave(sx, sy, (char *) 0);
352 break;
353 case BEEHIVE:
354 if (!rn2(3))
355 (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, TRUE,
356 FALSE);
357 break;
358 case BARRACKS:
359 if (!rn2(20)) /* the payroll and some loot */
360 (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy,
361 TRUE, FALSE);
362 break;
363 case COCKNEST:
364 if (!rn2(3)) {
365 struct obj *sobj = mk_tt_object(STATUE, sx, sy);
367 if (sobj) {
368 for (i = rn2(5); i; i--)
369 (void) add_to_container(
370 sobj, mkobj(RANDOM_CLASS, FALSE));
371 sobj->owt = weight(sobj);
374 break;
375 case ANTHOLE:
376 if (!rn2(3))
377 (void) mkobj_at(FOOD_CLASS, sx, sy, FALSE);
378 break;
381 switch (type) {
382 case COURT: {
383 struct obj *chest, *gold;
384 levl[tx][ty].typ = THRONE;
385 (void) somexy(sroom, &mm);
386 gold = mksobj(GOLD_PIECE, TRUE, FALSE);
387 gold->quan = (long) rn1(50 * level_difficulty(), 10);
388 gold->owt = weight(gold);
389 /* the royal coffers */
390 chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE);
391 add_to_container(chest, gold);
392 chest->owt = weight(chest);
393 chest->spe = 2; /* so it can be found later */
394 level.flags.has_court = 1;
395 break;
397 case BARRACKS:
398 level.flags.has_barracks = 1;
399 break;
400 case ZOO:
401 level.flags.has_zoo = 1;
402 break;
403 case MORGUE:
404 level.flags.has_morgue = 1;
405 break;
406 case SWAMP:
407 level.flags.has_swamp = 1;
408 break;
409 case BEEHIVE:
410 level.flags.has_beehive = 1;
411 break;
415 /* make a swarm of undead around mm */
416 void
417 mkundead(mm, revive_corpses, mm_flags)
418 coord *mm;
419 boolean revive_corpses;
420 int mm_flags;
422 int cnt = (level_difficulty() + 1) / 10 + rnd(5);
423 struct permonst *mdat;
424 struct obj *otmp;
425 coord cc;
427 while (cnt--) {
428 mdat = morguemon();
429 if (mdat && enexto(&cc, mm->x, mm->y, mdat)
430 && (!revive_corpses
431 || !(otmp = sobj_at(CORPSE, cc.x, cc.y))
432 || !revive(otmp, FALSE)))
433 (void) makemon(mdat, cc.x, cc.y, mm_flags);
435 level.flags.graveyard = TRUE; /* reduced chance for undead corpse */
438 STATIC_OVL struct permonst *
439 morguemon()
441 register int i = rn2(100), hd = rn2(level_difficulty());
443 if (hd > 10 && i < 10) {
444 if (Inhell || In_endgame(&u.uz)) {
445 return mkclass(S_DEMON, 0);
446 } else {
447 int ndemon_res = ndemon(A_NONE);
448 if (ndemon_res != NON_PM)
449 return &mons[ndemon_res];
450 /* else do what? As is, it will drop to ghost/wraith/zombie */
454 if (hd > 8 && i > 85)
455 return mkclass(S_VAMPIRE, 0);
457 return ((i < 20) ? &mons[PM_GHOST]
458 : (i < 40) ? &mons[PM_WRAITH]
459 : mkclass(S_ZOMBIE, 0));
462 struct permonst *
463 antholemon()
465 int mtyp, indx, trycnt = 0;
467 /* casts are for dealing with time_t */
468 indx = (int) ((long) ubirthday % 3L);
469 indx += level_difficulty();
470 /* Same monsters within a level, different ones between levels */
471 do {
472 switch ((indx + trycnt) % 3) {
473 case 0:
474 mtyp = PM_SOLDIER_ANT;
475 break;
476 case 1:
477 mtyp = PM_FIRE_ANT;
478 break;
479 default:
480 mtyp = PM_GIANT_ANT;
481 break;
483 /* try again if chosen type has been genocided or used up */
484 } while (++trycnt < 3 && (mvitals[mtyp].mvflags & G_GONE));
486 return ((mvitals[mtyp].mvflags & G_GONE) ? (struct permonst *) 0
487 : &mons[mtyp]);
490 STATIC_OVL void
491 mkswamp() /* Michiel Huisjes & Fred de Wilde */
493 register struct mkroom *sroom;
494 register int sx, sy, i, eelct = 0;
496 for (i = 0; i < 5; i++) { /* turn up to 5 rooms swampy */
497 sroom = &rooms[rn2(nroom)];
498 if (sroom->hx < 0 || sroom->rtype != OROOM || has_upstairs(sroom)
499 || has_dnstairs(sroom))
500 continue;
502 /* satisfied; make a swamp */
503 sroom->rtype = SWAMP;
504 for (sx = sroom->lx; sx <= sroom->hx; sx++)
505 for (sy = sroom->ly; sy <= sroom->hy; sy++)
506 if (!OBJ_AT(sx, sy) && !MON_AT(sx, sy) && !t_at(sx, sy)
507 && !nexttodoor(sx, sy)) {
508 if ((sx + sy) % 2) {
509 levl[sx][sy].typ = POOL;
510 if (!eelct || !rn2(4)) {
511 /* mkclass() won't do, as we might get kraken */
512 (void) makemon(rn2(5)
513 ? &mons[PM_GIANT_EEL]
514 : rn2(2)
515 ? &mons[PM_PIRANHA]
516 : &mons[PM_ELECTRIC_EEL],
517 sx, sy, NO_MM_FLAGS);
518 eelct++;
520 } else if (!rn2(4)) /* swamps tend to be moldy */
521 (void) makemon(mkclass(S_FUNGUS, 0), sx, sy,
522 NO_MM_FLAGS);
524 level.flags.has_swamp = 1;
528 STATIC_OVL coord *
529 shrine_pos(roomno)
530 int roomno;
532 static coord buf;
533 int delta;
534 struct mkroom *troom = &rooms[roomno - ROOMOFFSET];
536 /* if width and height are odd, placement will be the exact center;
537 if either or both are even, center point is a hypothetical spot
538 between map locations and placement will be adjacent to that */
539 delta = troom->hx - troom->lx;
540 buf.x = troom->lx + delta / 2;
541 if ((delta % 2) && rn2(2))
542 buf.x++;
543 delta = troom->hy - troom->ly;
544 buf.y = troom->ly + delta / 2;
545 if ((delta % 2) && rn2(2))
546 buf.y++;
547 return &buf;
550 STATIC_OVL void
551 mktemple()
553 register struct mkroom *sroom;
554 coord *shrine_spot;
555 register struct rm *lev;
557 if (!(sroom = pick_room(TRUE)))
558 return;
560 /* set up Priest and shrine */
561 sroom->rtype = TEMPLE;
563 * In temples, shrines are blessed altars
564 * located in the center of the room
566 shrine_spot = shrine_pos((int) ((sroom - rooms) + ROOMOFFSET));
567 lev = &levl[shrine_spot->x][shrine_spot->y];
568 lev->typ = ALTAR;
569 lev->altarmask = induced_align(80);
570 priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE);
571 lev->altarmask |= AM_SHRINE;
572 level.flags.has_temple = 1;
575 boolean
576 nexttodoor(sx, sy)
577 register int sx, sy;
579 register int dx, dy;
580 register struct rm *lev;
582 for (dx = -1; dx <= 1; dx++)
583 for (dy = -1; dy <= 1; dy++) {
584 if (!isok(sx + dx, sy + dy))
585 continue;
586 lev = &levl[sx + dx][sy + dy];
587 if (IS_DOOR(lev->typ) || lev->typ == SDOOR)
588 return TRUE;
590 return FALSE;
593 boolean
594 has_dnstairs(sroom)
595 register struct mkroom *sroom;
597 if (sroom == dnstairs_room)
598 return TRUE;
599 if (sstairs.sx && !sstairs.up)
600 return (boolean) (sroom == sstairs_room);
601 return FALSE;
604 boolean
605 has_upstairs(sroom)
606 register struct mkroom *sroom;
608 if (sroom == upstairs_room)
609 return TRUE;
610 if (sstairs.sx && sstairs.up)
611 return (boolean) (sroom == sstairs_room);
612 return FALSE;
616 somex(croom)
617 register struct mkroom *croom;
619 return rn1(croom->hx - croom->lx + 1, croom->lx);
623 somey(croom)
624 register struct mkroom *croom;
626 return rn1(croom->hy - croom->ly + 1, croom->ly);
629 boolean
630 inside_room(croom, x, y)
631 struct mkroom *croom;
632 xchar x, y;
634 return (boolean) (x >= croom->lx - 1 && x <= croom->hx + 1
635 && y >= croom->ly - 1 && y <= croom->hy + 1);
638 boolean
639 somexy(croom, c)
640 struct mkroom *croom;
641 coord *c;
643 int try_cnt = 0;
644 int i;
646 if (croom->irregular) {
647 i = (int) ((croom - rooms) + ROOMOFFSET);
649 while (try_cnt++ < 100) {
650 c->x = somex(croom);
651 c->y = somey(croom);
652 if (!levl[c->x][c->y].edge && (int) levl[c->x][c->y].roomno == i)
653 return TRUE;
655 /* try harder; exhaustively search until one is found */
656 for (c->x = croom->lx; c->x <= croom->hx; c->x++)
657 for (c->y = croom->ly; c->y <= croom->hy; c->y++)
658 if (!levl[c->x][c->y].edge
659 && (int) levl[c->x][c->y].roomno == i)
660 return TRUE;
661 return FALSE;
664 if (!croom->nsubrooms) {
665 c->x = somex(croom);
666 c->y = somey(croom);
667 return TRUE;
670 /* Check that coords doesn't fall into a subroom or into a wall */
672 while (try_cnt++ < 100) {
673 c->x = somex(croom);
674 c->y = somey(croom);
675 if (IS_WALL(levl[c->x][c->y].typ))
676 continue;
677 for (i = 0; i < croom->nsubrooms; i++)
678 if (inside_room(croom->sbrooms[i], c->x, c->y))
679 goto you_lose;
680 break;
681 you_lose:
684 if (try_cnt >= 100)
685 return FALSE;
686 return TRUE;
690 * Search for a special room given its type (zoo, court, etc...)
691 * Special values :
692 * - ANY_SHOP
693 * - ANY_TYPE
695 struct mkroom *
696 search_special(type)
697 schar type;
699 register struct mkroom *croom;
701 for (croom = &rooms[0]; croom->hx >= 0; croom++)
702 if ((type == ANY_TYPE && croom->rtype != OROOM)
703 || (type == ANY_SHOP && croom->rtype >= SHOPBASE)
704 || croom->rtype == type)
705 return croom;
706 for (croom = &subrooms[0]; croom->hx >= 0; croom++)
707 if ((type == ANY_TYPE && croom->rtype != OROOM)
708 || (type == ANY_SHOP && croom->rtype >= SHOPBASE)
709 || croom->rtype == type)
710 return croom;
711 return (struct mkroom *) 0;
714 struct permonst *
715 courtmon()
717 int i = rn2(60) + rn2(3 * level_difficulty());
719 if (i > 100)
720 return mkclass(S_DRAGON, 0);
721 else if (i > 95)
722 return mkclass(S_GIANT, 0);
723 else if (i > 85)
724 return mkclass(S_TROLL, 0);
725 else if (i > 75)
726 return mkclass(S_CENTAUR, 0);
727 else if (i > 60)
728 return mkclass(S_ORC, 0);
729 else if (i > 45)
730 return &mons[PM_BUGBEAR];
731 else if (i > 30)
732 return &mons[PM_HOBGOBLIN];
733 else if (i > 15)
734 return mkclass(S_GNOME, 0);
735 else
736 return mkclass(S_KOBOLD, 0);
739 #define NSTYPES (PM_CAPTAIN - PM_SOLDIER + 1)
741 static struct {
742 unsigned pm;
743 unsigned prob;
744 } squadprob[NSTYPES] = { { PM_SOLDIER, 80 },
745 { PM_SERGEANT, 15 },
746 { PM_LIEUTENANT, 4 },
747 { PM_CAPTAIN, 1 } };
749 /* return soldier types. */
750 STATIC_OVL struct permonst *
751 squadmon()
753 int sel_prob, i, cpro, mndx;
755 sel_prob = rnd(80 + level_difficulty());
757 cpro = 0;
758 for (i = 0; i < NSTYPES; i++) {
759 cpro += squadprob[i].prob;
760 if (cpro > sel_prob) {
761 mndx = squadprob[i].pm;
762 goto gotone;
765 mndx = squadprob[rn2(NSTYPES)].pm;
766 gotone:
767 if (!(mvitals[mndx].mvflags & G_GONE))
768 return &mons[mndx];
769 else
770 return (struct permonst *) 0;
774 * save_room : A recursive function that saves a room and its subrooms
775 * (if any).
777 STATIC_OVL void
778 save_room(fd, r)
779 int fd;
780 struct mkroom *r;
782 short i;
785 * Well, I really should write only useful information instead
786 * of writing the whole structure. That is I should not write
787 * the subrooms pointers, but who cares ?
789 bwrite(fd, (genericptr_t) r, sizeof (struct mkroom));
790 for (i = 0; i < r->nsubrooms; i++)
791 save_room(fd, r->sbrooms[i]);
795 * save_rooms : Save all the rooms on disk!
797 void
798 save_rooms(fd)
799 int fd;
801 short i;
803 /* First, write the number of rooms */
804 bwrite(fd, (genericptr_t) &nroom, sizeof(nroom));
805 for (i = 0; i < nroom; i++)
806 save_room(fd, &rooms[i]);
809 STATIC_OVL void
810 rest_room(fd, r)
811 int fd;
812 struct mkroom *r;
814 short i;
816 mread(fd, (genericptr_t) r, sizeof(struct mkroom));
817 for (i = 0; i < r->nsubrooms; i++) {
818 r->sbrooms[i] = &subrooms[nsubroom];
819 rest_room(fd, &subrooms[nsubroom]);
820 subrooms[nsubroom++].resident = (struct monst *) 0;
825 * rest_rooms : That's for restoring rooms. Read the rooms structure from
826 * the disk.
828 void
829 rest_rooms(fd)
830 int fd;
832 short i;
834 mread(fd, (genericptr_t) &nroom, sizeof(nroom));
835 nsubroom = 0;
836 for (i = 0; i < nroom; i++) {
837 rest_room(fd, &rooms[i]);
838 rooms[i].resident = (struct monst *) 0;
840 rooms[nroom].hx = -1; /* restore ending flags */
841 subrooms[nsubroom].hx = -1;
844 /* convert a display symbol for terrain into topology type;
845 used for remembered terrain when mimics pose as furniture */
847 cmap_to_type(sym)
848 int sym;
850 int typ = STONE; /* catchall */
852 switch (sym) {
853 case S_stone:
854 typ = STONE;
855 break;
856 case S_vwall:
857 typ = VWALL;
858 break;
859 case S_hwall:
860 typ = HWALL;
861 break;
862 case S_tlcorn:
863 typ = TLCORNER;
864 break;
865 case S_trcorn:
866 typ = TRCORNER;
867 break;
868 case S_blcorn:
869 typ = BLCORNER;
870 break;
871 case S_brcorn:
872 typ = BRCORNER;
873 break;
874 case S_crwall:
875 typ = CROSSWALL;
876 break;
877 case S_tuwall:
878 typ = TUWALL;
879 break;
880 case S_tdwall:
881 typ = TDWALL;
882 break;
883 case S_tlwall:
884 typ = TLWALL;
885 break;
886 case S_trwall:
887 typ = TRWALL;
888 break;
889 case S_ndoor: /* no door (empty doorway) */
890 case S_vodoor: /* open door in vertical wall */
891 case S_hodoor: /* open door in horizontal wall */
892 case S_vcdoor: /* closed door in vertical wall */
893 case S_hcdoor:
894 typ = DOOR;
895 break;
896 case S_bars:
897 typ = IRONBARS;
898 break;
899 case S_tree:
900 typ = TREE;
901 break;
902 case S_room:
903 typ = ROOM;
904 break;
905 case S_corr:
906 case S_litcorr:
907 typ = CORR;
908 break;
909 case S_upstair:
910 case S_dnstair:
911 typ = STAIRS;
912 break;
913 case S_upladder:
914 case S_dnladder:
915 typ = LADDER;
916 break;
917 case S_altar:
918 typ = ALTAR;
919 break;
920 case S_grave:
921 typ = GRAVE;
922 break;
923 case S_throne:
924 typ = THRONE;
925 break;
926 case S_sink:
927 typ = SINK;
928 break;
929 case S_fountain:
930 typ = FOUNTAIN;
931 break;
932 case S_pool:
933 typ = POOL;
934 break;
935 case S_ice:
936 typ = ICE;
937 break;
938 case S_lava:
939 typ = LAVAPOOL;
940 break;
941 case S_vodbridge: /* open drawbridge spanning north/south */
942 case S_hodbridge:
943 typ = DRAWBRIDGE_DOWN;
944 break; /* east/west */
945 case S_vcdbridge: /* closed drawbridge in vertical wall */
946 case S_hcdbridge:
947 typ = DBWALL;
948 break;
949 case S_air:
950 typ = AIR;
951 break;
952 case S_cloud:
953 typ = CLOUD;
954 break;
955 case S_water:
956 typ = WATER;
957 break;
958 default:
959 break; /* not a cmap symbol? */
961 return typ;
964 /*mkroom.c*/