Source:NetHack 3.1.0/mkroom.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to mkroom.c from the source code of NetHack 3.1.0. To link to a particular line, write [[NetHack 3.1.0/mkroom.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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