OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / src / mkroom.c
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
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
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
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
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 #ifndef MAC
132 gottype:
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
185 STATIC_OVL struct mkroom *
186 pick_room(strict)
187 register 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
214 STATIC_OVL void
215 mkzoo(type)
216 int 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
226 void
227 fill_zoo(sroom)
228 struct 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 */
394 void
395 mkundead(mm, revive_corpses, mm_flags)
396 coord *mm;
397 boolean revive_corpses;
398 int 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
416 STATIC_OVL struct permonst *
417 morguemon()
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
431 STATIC_OVL struct permonst *
432 antholemon()
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
446 STATIC_OVL void
447 mkswamp()       /* 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
483 STATIC_OVL coord *
484 shrine_pos(roomno)
485 int 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
495 STATIC_OVL void
496 mktemple()
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
519 boolean
520 nexttodoor(sx,sy)
521 register 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
534 boolean
535 has_dnstairs(sroom)
536 register 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
545 boolean
546 has_upstairs(sroom)
547 register 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
559 int
560 somex(croom)
561 register struct mkroom *croom;
562 {
563         return rn2(croom->hx-croom->lx+1) + croom->lx;
564 }
565
566 int
567 somey(croom)
568 register struct mkroom *croom;
569 {
570         return rn2(croom->hy-croom->ly+1) + croom->ly;
571 }
572
573 boolean
574 inside_room(croom, x, y)
575 struct mkroom *croom;
576 xchar 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
582 boolean
583 somexy(croom, c)
584 struct mkroom *croom;
585 coord *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;
626 you_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
640 struct mkroom *
641 search_special(type)
642 schar 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
662 struct permonst *
663 courtmon()
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
679 static 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
686 STATIC_OVL struct permonst *
687 squadmon()              /* 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;
702 gotone:
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
712 STATIC_OVL void
713 save_room(fd, r)
714 int     fd;
715 struct 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
732 void
733 save_rooms(fd)
734 int 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
744 STATIC_OVL void
745 rest_room(fd, r)
746 int fd;
747 struct 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
764 void
765 rest_rooms(fd)
766 int     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*/