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