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