option parsing buffer overflow vulnerability
[aNetHack.git] / src / mkroom.c
blobc7f6196e4a2fbfd4ffbb90c13a82113ac92d69a7
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;
384 levl[tx][ty].typ = THRONE;
385 (void) somexy(sroom, &mm);
386 (void) mkgold((long) rn1(50 * level_difficulty(), 10), mm.x, mm.y);
387 /* the royal coffers */
388 chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE);
389 chest->spe = 2; /* so it can be found later */
390 level.flags.has_court = 1;
391 break;
393 case BARRACKS:
394 level.flags.has_barracks = 1;
395 break;
396 case ZOO:
397 level.flags.has_zoo = 1;
398 break;
399 case MORGUE:
400 level.flags.has_morgue = 1;
401 break;
402 case SWAMP:
403 level.flags.has_swamp = 1;
404 break;
405 case BEEHIVE:
406 level.flags.has_beehive = 1;
407 break;
411 /* make a swarm of undead around mm */
412 void
413 mkundead(mm, revive_corpses, mm_flags)
414 coord *mm;
415 boolean revive_corpses;
416 int mm_flags;
418 int cnt = (level_difficulty() + 1) / 10 + rnd(5);
419 struct permonst *mdat;
420 struct obj *otmp;
421 coord cc;
423 while (cnt--) {
424 mdat = morguemon();
425 if (mdat && enexto(&cc, mm->x, mm->y, mdat)
426 && (!revive_corpses
427 || !(otmp = sobj_at(CORPSE, cc.x, cc.y))
428 || !revive(otmp, FALSE)))
429 (void) makemon(mdat, cc.x, cc.y, mm_flags);
431 level.flags.graveyard = TRUE; /* reduced chance for undead corpse */
434 STATIC_OVL struct permonst *
435 morguemon()
437 register int i = rn2(100), hd = rn2(level_difficulty());
439 if (hd > 10 && i < 10) {
440 if (Inhell || In_endgame(&u.uz)) {
441 return mkclass(S_DEMON, 0);
442 } else {
443 int ndemon_res = ndemon(A_NONE);
444 if (ndemon_res != NON_PM)
445 return &mons[ndemon_res];
446 /* else do what? As is, it will drop to ghost/wraith/zombie */
450 if (hd > 8 && i > 85)
451 return mkclass(S_VAMPIRE, 0);
453 return ((i < 20) ? &mons[PM_GHOST]
454 : (i < 40) ? &mons[PM_WRAITH]
455 : mkclass(S_ZOMBIE, 0));
458 struct permonst *
459 antholemon()
461 int mtyp, indx, trycnt = 0;
463 /* casts are for dealing with time_t */
464 indx = (int) ((long) ubirthday % 3L);
465 indx += level_difficulty();
466 /* Same monsters within a level, different ones between levels */
467 do {
468 switch ((indx + trycnt) % 3) {
469 case 0:
470 mtyp = PM_SOLDIER_ANT;
471 break;
472 case 1:
473 mtyp = PM_FIRE_ANT;
474 break;
475 default:
476 mtyp = PM_GIANT_ANT;
477 break;
479 /* try again if chosen type has been genocided or used up */
480 } while (++trycnt < 3 && (mvitals[mtyp].mvflags & G_GONE));
482 return ((mvitals[mtyp].mvflags & G_GONE) ? (struct permonst *) 0
483 : &mons[mtyp]);
486 STATIC_OVL void
487 mkswamp() /* Michiel Huisjes & Fred de Wilde */
489 register struct mkroom *sroom;
490 register int sx, sy, i, eelct = 0;
492 for (i = 0; i < 5; i++) { /* turn up to 5 rooms swampy */
493 sroom = &rooms[rn2(nroom)];
494 if (sroom->hx < 0 || sroom->rtype != OROOM || has_upstairs(sroom)
495 || has_dnstairs(sroom))
496 continue;
498 /* satisfied; make a swamp */
499 sroom->rtype = SWAMP;
500 for (sx = sroom->lx; sx <= sroom->hx; sx++)
501 for (sy = sroom->ly; sy <= sroom->hy; sy++)
502 if (!OBJ_AT(sx, sy) && !MON_AT(sx, sy) && !t_at(sx, sy)
503 && !nexttodoor(sx, sy)) {
504 if ((sx + sy) % 2) {
505 levl[sx][sy].typ = POOL;
506 if (!eelct || !rn2(4)) {
507 /* mkclass() won't do, as we might get kraken */
508 (void) makemon(rn2(5)
509 ? &mons[PM_GIANT_EEL]
510 : rn2(2)
511 ? &mons[PM_PIRANHA]
512 : &mons[PM_ELECTRIC_EEL],
513 sx, sy, NO_MM_FLAGS);
514 eelct++;
516 } else if (!rn2(4)) /* swamps tend to be moldy */
517 (void) makemon(mkclass(S_FUNGUS, 0), sx, sy,
518 NO_MM_FLAGS);
520 level.flags.has_swamp = 1;
524 STATIC_OVL coord *
525 shrine_pos(roomno)
526 int roomno;
528 static coord buf;
529 int delta;
530 struct mkroom *troom = &rooms[roomno - ROOMOFFSET];
532 /* if width and height are odd, placement will be the exact center;
533 if either or both are even, center point is a hypothetical spot
534 between map locations and placement will be adjacent to that */
535 delta = troom->hx - troom->lx;
536 buf.x = troom->lx + delta / 2;
537 if ((delta % 2) && rn2(2))
538 buf.x++;
539 delta = troom->hy - troom->ly;
540 buf.y = troom->ly + delta / 2;
541 if ((delta % 2) && rn2(2))
542 buf.y++;
543 return &buf;
546 STATIC_OVL void
547 mktemple()
549 register struct mkroom *sroom;
550 coord *shrine_spot;
551 register struct rm *lev;
553 if (!(sroom = pick_room(TRUE)))
554 return;
556 /* set up Priest and shrine */
557 sroom->rtype = TEMPLE;
559 * In temples, shrines are blessed altars
560 * located in the center of the room
562 shrine_spot = shrine_pos((int) ((sroom - rooms) + ROOMOFFSET));
563 lev = &levl[shrine_spot->x][shrine_spot->y];
564 lev->typ = ALTAR;
565 lev->altarmask = induced_align(80);
566 priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE);
567 lev->altarmask |= AM_SHRINE;
568 level.flags.has_temple = 1;
571 boolean
572 nexttodoor(sx, sy)
573 register int sx, sy;
575 register int dx, dy;
576 register struct rm *lev;
578 for (dx = -1; dx <= 1; dx++)
579 for (dy = -1; dy <= 1; dy++) {
580 if (!isok(sx + dx, sy + dy))
581 continue;
582 lev = &levl[sx + dx][sy + dy];
583 if (IS_DOOR(lev->typ) || lev->typ == SDOOR)
584 return TRUE;
586 return FALSE;
589 boolean
590 has_dnstairs(sroom)
591 register struct mkroom *sroom;
593 if (sroom == dnstairs_room)
594 return TRUE;
595 if (sstairs.sx && !sstairs.up)
596 return (boolean) (sroom == sstairs_room);
597 return FALSE;
600 boolean
601 has_upstairs(sroom)
602 register struct mkroom *sroom;
604 if (sroom == upstairs_room)
605 return TRUE;
606 if (sstairs.sx && sstairs.up)
607 return (boolean) (sroom == sstairs_room);
608 return FALSE;
612 somex(croom)
613 register struct mkroom *croom;
615 return rn1(croom->hx - croom->lx + 1, croom->lx);
619 somey(croom)
620 register struct mkroom *croom;
622 return rn1(croom->hy - croom->ly + 1, croom->ly);
625 boolean
626 inside_room(croom, x, y)
627 struct mkroom *croom;
628 xchar x, y;
630 return (boolean) (x >= croom->lx - 1 && x <= croom->hx + 1
631 && y >= croom->ly - 1 && y <= croom->hy + 1);
634 boolean
635 somexy(croom, c)
636 struct mkroom *croom;
637 coord *c;
639 int try_cnt = 0;
640 int i;
642 if (croom->irregular) {
643 i = (int) ((croom - rooms) + ROOMOFFSET);
645 while (try_cnt++ < 100) {
646 c->x = somex(croom);
647 c->y = somey(croom);
648 if (!levl[c->x][c->y].edge && (int) levl[c->x][c->y].roomno == i)
649 return TRUE;
651 /* try harder; exhaustively search until one is found */
652 for (c->x = croom->lx; c->x <= croom->hx; c->x++)
653 for (c->y = croom->ly; c->y <= croom->hy; c->y++)
654 if (!levl[c->x][c->y].edge
655 && (int) levl[c->x][c->y].roomno == i)
656 return TRUE;
657 return FALSE;
660 if (!croom->nsubrooms) {
661 c->x = somex(croom);
662 c->y = somey(croom);
663 return TRUE;
666 /* Check that coords doesn't fall into a subroom or into a wall */
668 while (try_cnt++ < 100) {
669 c->x = somex(croom);
670 c->y = somey(croom);
671 if (IS_WALL(levl[c->x][c->y].typ))
672 continue;
673 for (i = 0; i < croom->nsubrooms; i++)
674 if (inside_room(croom->sbrooms[i], c->x, c->y))
675 goto you_lose;
676 break;
677 you_lose:
680 if (try_cnt >= 100)
681 return FALSE;
682 return TRUE;
686 * Search for a special room given its type (zoo, court, etc...)
687 * Special values :
688 * - ANY_SHOP
689 * - ANY_TYPE
691 struct mkroom *
692 search_special(type)
693 schar type;
695 register struct mkroom *croom;
697 for (croom = &rooms[0]; croom->hx >= 0; croom++)
698 if ((type == ANY_TYPE && croom->rtype != OROOM)
699 || (type == ANY_SHOP && croom->rtype >= SHOPBASE)
700 || croom->rtype == type)
701 return croom;
702 for (croom = &subrooms[0]; croom->hx >= 0; croom++)
703 if ((type == ANY_TYPE && croom->rtype != OROOM)
704 || (type == ANY_SHOP && croom->rtype >= SHOPBASE)
705 || croom->rtype == type)
706 return croom;
707 return (struct mkroom *) 0;
710 struct permonst *
711 courtmon()
713 int i = rn2(60) + rn2(3 * level_difficulty());
715 if (i > 100)
716 return mkclass(S_DRAGON, 0);
717 else if (i > 95)
718 return mkclass(S_GIANT, 0);
719 else if (i > 85)
720 return mkclass(S_TROLL, 0);
721 else if (i > 75)
722 return mkclass(S_CENTAUR, 0);
723 else if (i > 60)
724 return mkclass(S_ORC, 0);
725 else if (i > 45)
726 return &mons[PM_BUGBEAR];
727 else if (i > 30)
728 return &mons[PM_HOBGOBLIN];
729 else if (i > 15)
730 return mkclass(S_GNOME, 0);
731 else
732 return mkclass(S_KOBOLD, 0);
735 #define NSTYPES (PM_CAPTAIN - PM_SOLDIER + 1)
737 static struct {
738 unsigned pm;
739 unsigned prob;
740 } squadprob[NSTYPES] = { { PM_SOLDIER, 80 },
741 { PM_SERGEANT, 15 },
742 { PM_LIEUTENANT, 4 },
743 { PM_CAPTAIN, 1 } };
745 /* return soldier types. */
746 STATIC_OVL struct permonst *
747 squadmon()
749 int sel_prob, i, cpro, mndx;
751 sel_prob = rnd(80 + level_difficulty());
753 cpro = 0;
754 for (i = 0; i < NSTYPES; i++) {
755 cpro += squadprob[i].prob;
756 if (cpro > sel_prob) {
757 mndx = squadprob[i].pm;
758 goto gotone;
761 mndx = squadprob[rn2(NSTYPES)].pm;
762 gotone:
763 if (!(mvitals[mndx].mvflags & G_GONE))
764 return &mons[mndx];
765 else
766 return (struct permonst *) 0;
770 * save_room : A recursive function that saves a room and its subrooms
771 * (if any).
773 STATIC_OVL void
774 save_room(fd, r)
775 int fd;
776 struct mkroom *r;
778 short i;
781 * Well, I really should write only useful information instead
782 * of writing the whole structure. That is I should not write
783 * the subrooms pointers, but who cares ?
785 bwrite(fd, (genericptr_t) r, sizeof (struct mkroom));
786 for (i = 0; i < r->nsubrooms; i++)
787 save_room(fd, r->sbrooms[i]);
791 * save_rooms : Save all the rooms on disk!
793 void
794 save_rooms(fd)
795 int fd;
797 short i;
799 /* First, write the number of rooms */
800 bwrite(fd, (genericptr_t) &nroom, sizeof(nroom));
801 for (i = 0; i < nroom; i++)
802 save_room(fd, &rooms[i]);
805 STATIC_OVL void
806 rest_room(fd, r)
807 int fd;
808 struct mkroom *r;
810 short i;
812 mread(fd, (genericptr_t) r, sizeof(struct mkroom));
813 for (i = 0; i < r->nsubrooms; i++) {
814 r->sbrooms[i] = &subrooms[nsubroom];
815 rest_room(fd, &subrooms[nsubroom]);
816 subrooms[nsubroom++].resident = (struct monst *) 0;
821 * rest_rooms : That's for restoring rooms. Read the rooms structure from
822 * the disk.
824 void
825 rest_rooms(fd)
826 int fd;
828 short i;
830 mread(fd, (genericptr_t) &nroom, sizeof(nroom));
831 nsubroom = 0;
832 for (i = 0; i < nroom; i++) {
833 rest_room(fd, &rooms[i]);
834 rooms[i].resident = (struct monst *) 0;
836 rooms[nroom].hx = -1; /* restore ending flags */
837 subrooms[nsubroom].hx = -1;
840 /* convert a display symbol for terrain into topology type;
841 used for remembered terrain when mimics pose as furniture */
843 cmap_to_type(sym)
844 int sym;
846 int typ = STONE; /* catchall */
848 switch (sym) {
849 case S_stone:
850 typ = STONE;
851 break;
852 case S_vwall:
853 typ = VWALL;
854 break;
855 case S_hwall:
856 typ = HWALL;
857 break;
858 case S_tlcorn:
859 typ = TLCORNER;
860 break;
861 case S_trcorn:
862 typ = TRCORNER;
863 break;
864 case S_blcorn:
865 typ = BLCORNER;
866 break;
867 case S_brcorn:
868 typ = BRCORNER;
869 break;
870 case S_crwall:
871 typ = CROSSWALL;
872 break;
873 case S_tuwall:
874 typ = TUWALL;
875 break;
876 case S_tdwall:
877 typ = TDWALL;
878 break;
879 case S_tlwall:
880 typ = TLWALL;
881 break;
882 case S_trwall:
883 typ = TRWALL;
884 break;
885 case S_ndoor: /* no door (empty doorway) */
886 case S_vodoor: /* open door in vertical wall */
887 case S_hodoor: /* open door in horizontal wall */
888 case S_vcdoor: /* closed door in vertical wall */
889 case S_hcdoor:
890 typ = DOOR;
891 break;
892 case S_bars:
893 typ = IRONBARS;
894 break;
895 case S_tree:
896 typ = TREE;
897 break;
898 case S_room:
899 typ = ROOM;
900 break;
901 case S_corr:
902 case S_litcorr:
903 typ = CORR;
904 break;
905 case S_upstair:
906 case S_dnstair:
907 typ = STAIRS;
908 break;
909 case S_upladder:
910 case S_dnladder:
911 typ = LADDER;
912 break;
913 case S_altar:
914 typ = ALTAR;
915 break;
916 case S_grave:
917 typ = GRAVE;
918 break;
919 case S_throne:
920 typ = THRONE;
921 break;
922 case S_sink:
923 typ = SINK;
924 break;
925 case S_fountain:
926 typ = FOUNTAIN;
927 break;
928 case S_pool:
929 typ = POOL;
930 break;
931 case S_ice:
932 typ = ICE;
933 break;
934 case S_lava:
935 typ = LAVAPOOL;
936 break;
937 case S_vodbridge: /* open drawbridge spanning north/south */
938 case S_hodbridge:
939 typ = DRAWBRIDGE_DOWN;
940 break; /* east/west */
941 case S_vcdbridge: /* closed drawbridge in vertical wall */
942 case S_hcdbridge:
943 typ = DBWALL;
944 break;
945 case S_air:
946 typ = AIR;
947 break;
948 case S_cloud:
949 typ = CLOUD;
950 break;
951 case S_water:
952 typ = WATER;
953 break;
954 default:
955 break; /* not a cmap symbol? */
957 return typ;
960 /*mkroom.c*/