OSDN Git Service

add missing "#ifdef X11LARGETILE"
[jnethack/source.git] / src / mkroom.c
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 /*-Copyright (c) Robert Patrick Rankin, 2011. */
4 /* NetHack may be freely redistributed.  See license for details. */
5
6 /*
7  * Entry points:
8  *      mkroom() -- make and stock a room of a given type
9  *      nexttodoor() -- return TRUE if adjacent to a door
10  *      has_dnstairs() -- return TRUE if given room has a down staircase
11  *      has_upstairs() -- return TRUE if given room has an up staircase
12  *      courtmon() -- generate a court monster
13  *      save_rooms() -- save rooms into file fd
14  *      rest_rooms() -- restore rooms from file fd
15  *      cmap_to_type() -- convert S_xxx symbol to XXX topology code
16  */
17
18 #include "hack.h"
19
20 STATIC_DCL boolean FDECL(isbig, (struct mkroom *));
21 STATIC_DCL struct mkroom *FDECL(pick_room, (BOOLEAN_P));
22 STATIC_DCL void NDECL(mkshop), FDECL(mkzoo, (int)), NDECL(mkswamp);
23 STATIC_DCL void NDECL(mktemple);
24 STATIC_DCL coord *FDECL(shrine_pos, (int));
25 STATIC_DCL struct permonst *NDECL(morguemon);
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
30 #define sq(x) ((x) * (x))
31
32 extern const struct shclass shtypes[]; /* defined in shknam.c */
33
34 STATIC_OVL boolean
35 isbig(sroom)
36 register struct mkroom *sroom;
37 {
38     register int area = (sroom->hx - sroom->lx + 1)
39                         * (sroom->hy - sroom->ly + 1);
40
41     return (boolean) (area > 20);
42 }
43
44 /* make and stock a room of a given type */
45 void
46 mkroom(roomtype)
47 int roomtype;
48 {
49     if (roomtype >= SHOPBASE)
50         mkshop(); /* someday, we should be able to specify shop type */
51     else
52         switch (roomtype) {
53         case COURT:
54             mkzoo(COURT);
55             break;
56         case ZOO:
57             mkzoo(ZOO);
58             break;
59         case BEEHIVE:
60             mkzoo(BEEHIVE);
61             break;
62         case MORGUE:
63             mkzoo(MORGUE);
64             break;
65         case BARRACKS:
66             mkzoo(BARRACKS);
67             break;
68         case SWAMP:
69             mkswamp();
70             break;
71         case TEMPLE:
72             mktemple();
73             break;
74         case LEPREHALL:
75             mkzoo(LEPREHALL);
76             break;
77         case COCKNEST:
78             mkzoo(COCKNEST);
79             break;
80         case ANTHOLE:
81             mkzoo(ANTHOLE);
82             break;
83         default:
84             impossible("Tried to make a room of type %d.", roomtype);
85         }
86 }
87
88 STATIC_OVL void
89 mkshop()
90 {
91     register struct mkroom *sroom;
92     int i = -1;
93     char *ep = (char *) 0; /* (init == lint suppression) */
94
95     /* first determine shoptype */
96     if (wizard) {
97 #ifndef MAC
98         ep = nh_getenv("SHOPTYPE");
99         if (ep) {
100             if (*ep == 'z' || *ep == 'Z') {
101                 mkzoo(ZOO);
102                 return;
103             }
104             if (*ep == 'm' || *ep == 'M') {
105                 mkzoo(MORGUE);
106                 return;
107             }
108             if (*ep == 'b' || *ep == 'B') {
109                 mkzoo(BEEHIVE);
110                 return;
111             }
112             if (*ep == 't' || *ep == 'T' || *ep == '\\') {
113                 mkzoo(COURT);
114                 return;
115             }
116             if (*ep == 's' || *ep == 'S') {
117                 mkzoo(BARRACKS);
118                 return;
119             }
120             if (*ep == 'a' || *ep == 'A') {
121                 mkzoo(ANTHOLE);
122                 return;
123             }
124             if (*ep == 'c' || *ep == 'C') {
125                 mkzoo(COCKNEST);
126                 return;
127             }
128             if (*ep == 'l' || *ep == 'L') {
129                 mkzoo(LEPREHALL);
130                 return;
131             }
132             if (*ep == '_') {
133                 mktemple();
134                 return;
135             }
136             if (*ep == '}') {
137                 mkswamp();
138                 return;
139             }
140             for (i = 0; shtypes[i].name; i++)
141                 if (*ep == def_oc_syms[(int) shtypes[i].symb].sym)
142                     goto gottype;
143             if (*ep == 'g' || *ep == 'G')
144                 i = 0;
145             else if (*ep == 'v' || *ep == 'V')
146                 i = FODDERSHOP - SHOPBASE; /* veggy food */
147             else
148                 i = -1;
149         }
150 #endif
151     }
152 #ifndef MAC
153 gottype:
154 #endif
155     for (sroom = &rooms[0];; sroom++) {
156         if (sroom->hx < 0)
157             return;
158         if (sroom - rooms >= nroom) {
159             pline("rooms not closed by -1?");
160             return;
161         }
162         if (sroom->rtype != OROOM)
163             continue;
164         if (has_dnstairs(sroom) || has_upstairs(sroom))
165             continue;
166         if ((wizard && ep && sroom->doorct != 0) || sroom->doorct == 1)
167             break;
168     }
169     if (!sroom->rlit) {
170         int x, y;
171
172         for (x = sroom->lx - 1; x <= sroom->hx + 1; x++)
173             for (y = sroom->ly - 1; y <= sroom->hy + 1; y++)
174                 levl[x][y].lit = 1;
175         sroom->rlit = 1;
176     }
177
178     if (i < 0) { /* shoptype not yet determined */
179         register int j;
180
181         /* pick a shop type at random */
182         for (j = rnd(100), i = 0; (j -= shtypes[i].prob) > 0; i++)
183             continue;
184
185         /* big rooms cannot be wand or book shops,
186          * - so make them general stores
187          */
188         if (isbig(sroom) && (shtypes[i].symb == WAND_CLASS
189                              || shtypes[i].symb == SPBOOK_CLASS))
190             i = 0;
191     }
192     sroom->rtype = SHOPBASE + i;
193
194     /* set room bits before stocking the shop */
195 #ifdef SPECIALIZATION
196     topologize(sroom, FALSE); /* doesn't matter - this is a special room */
197 #else
198     topologize(sroom);
199 #endif
200
201     /* stock the room with a shopkeeper and artifacts */
202     stock_room(i, sroom);
203 }
204
205 /* pick an unused room, preferably with only one door */
206 STATIC_OVL struct mkroom *
207 pick_room(strict)
208 register boolean strict;
209 {
210     register struct mkroom *sroom;
211     register int i = nroom;
212
213     for (sroom = &rooms[rn2(nroom)]; i--; sroom++) {
214         if (sroom == &rooms[nroom])
215             sroom = &rooms[0];
216         if (sroom->hx < 0)
217             return (struct mkroom *) 0;
218         if (sroom->rtype != OROOM)
219             continue;
220         if (!strict) {
221             if (has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
222                 continue;
223         } else if (has_upstairs(sroom) || has_dnstairs(sroom))
224             continue;
225         if (sroom->doorct == 1 || !rn2(5) || wizard)
226             return sroom;
227     }
228     return (struct mkroom *) 0;
229 }
230
231 STATIC_OVL void
232 mkzoo(type)
233 int type;
234 {
235     register struct mkroom *sroom;
236
237     if ((sroom = pick_room(FALSE)) != 0) {
238         sroom->rtype = type;
239         fill_zoo(sroom);
240     }
241 }
242
243 void
244 mk_zoo_thronemon(x,y)
245 int x,y;
246 {
247     int i = rnd(level_difficulty());
248     int pm = (i > 9) ? PM_OGRE_KING
249         : (i > 5) ? PM_ELVENKING
250         : (i > 2) ? PM_DWARF_KING
251         : PM_GNOME_KING;
252     struct monst *mon = makemon(&mons[pm], x, y, NO_MM_FLAGS);
253
254     if (mon) {
255         mon->msleeping = 1;
256         mon->mpeaceful = 0;
257         set_malign(mon);
258         /* Give him a sceptre to pound in judgment */
259         (void) mongets(mon, MACE);
260     }
261 }
262
263 void
264 fill_zoo(sroom)
265 struct mkroom *sroom;
266 {
267     struct monst *mon;
268     register int sx, sy, i;
269     int sh, tx = 0, ty = 0, goldlim = 0, type = sroom->rtype;
270     int rmno = (int) ((sroom - rooms) + ROOMOFFSET);
271     coord mm;
272
273     sh = sroom->fdoor;
274     switch (type) {
275     case COURT:
276         if (level.flags.is_maze_lev) {
277             for (tx = sroom->lx; tx <= sroom->hx; tx++)
278                 for (ty = sroom->ly; ty <= sroom->hy; ty++)
279                     if (IS_THRONE(levl[tx][ty].typ))
280                         goto throne_placed;
281         }
282         i = 100;
283         do { /* don't place throne on top of stairs */
284             (void) somexy(sroom, &mm);
285             tx = mm.x;
286             ty = mm.y;
287         } while (occupied((xchar) tx, (xchar) ty) && --i > 0);
288     throne_placed:
289         mk_zoo_thronemon(tx, ty);
290         break;
291     case BEEHIVE:
292         tx = sroom->lx + (sroom->hx - sroom->lx + 1) / 2;
293         ty = sroom->ly + (sroom->hy - sroom->ly + 1) / 2;
294         if (sroom->irregular) {
295             /* center might not be valid, so put queen elsewhere */
296             if ((int) levl[tx][ty].roomno != rmno || levl[tx][ty].edge) {
297                 (void) somexy(sroom, &mm);
298                 tx = mm.x;
299                 ty = mm.y;
300             }
301         }
302         break;
303     case ZOO:
304     case LEPREHALL:
305         goldlim = 500 * level_difficulty();
306         break;
307     }
308
309     for (sx = sroom->lx; sx <= sroom->hx; sx++)
310         for (sy = sroom->ly; sy <= sroom->hy; sy++) {
311             if (sroom->irregular) {
312                 if ((int) levl[sx][sy].roomno != rmno || levl[sx][sy].edge
313                     || (sroom->doorct
314                         && distmin(sx, sy, doors[sh].x, doors[sh].y) <= 1))
315                     continue;
316             } else if (!SPACE_POS(levl[sx][sy].typ)
317                        || (sroom->doorct
318                            && ((sx == sroom->lx && doors[sh].x == sx - 1)
319                                || (sx == sroom->hx && doors[sh].x == sx + 1)
320                                || (sy == sroom->ly && doors[sh].y == sy - 1)
321                                || (sy == sroom->hy
322                                    && doors[sh].y == sy + 1))))
323                 continue;
324             /* don't place monster on explicitly placed throne */
325             if (type == COURT && IS_THRONE(levl[sx][sy].typ))
326                 continue;
327             mon = makemon((type == COURT)
328                            ? courtmon()
329                            : (type == BARRACKS)
330                               ? squadmon()
331                               : (type == MORGUE)
332                                  ? morguemon()
333                                  : (type == BEEHIVE)
334                                      ? (sx == tx && sy == ty
335                                          ? &mons[PM_QUEEN_BEE]
336                                          : &mons[PM_KILLER_BEE])
337                                      : (type == LEPREHALL)
338                                          ? &mons[PM_LEPRECHAUN]
339                                          : (type == COCKNEST)
340                                              ? &mons[PM_COCKATRICE]
341                                              : (type == ANTHOLE)
342                                                  ? antholemon()
343                                                  : (struct permonst *) 0,
344                           sx, sy, MM_ASLEEP);
345             if (mon) {
346                 mon->msleeping = 1;
347                 if (type == COURT && mon->mpeaceful) {
348                     mon->mpeaceful = 0;
349                     set_malign(mon);
350                 }
351             }
352             switch (type) {
353             case ZOO:
354             case LEPREHALL:
355                 if (sroom->doorct) {
356                     int distval = dist2(sx, sy, doors[sh].x, doors[sh].y);
357                     i = sq(distval);
358                 } else
359                     i = goldlim;
360                 if (i >= goldlim)
361                     i = 5 * level_difficulty();
362                 goldlim -= i;
363                 (void) mkgold((long) rn1(i, 10), sx, sy);
364                 break;
365             case MORGUE:
366                 if (!rn2(5))
367                     (void) mk_tt_object(CORPSE, sx, sy);
368                 if (!rn2(10)) /* lots of treasure buried with dead */
369                     (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy,
370                                      TRUE, FALSE);
371                 if (!rn2(5))
372                     make_grave(sx, sy, (char *) 0);
373                 break;
374             case BEEHIVE:
375                 if (!rn2(3))
376                     (void) mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy, TRUE,
377                                      FALSE);
378                 break;
379             case BARRACKS:
380                 if (!rn2(20)) /* the payroll and some loot */
381                     (void) mksobj_at((rn2(3)) ? LARGE_BOX : CHEST, sx, sy,
382                                      TRUE, FALSE);
383                 break;
384             case COCKNEST:
385                 if (!rn2(3)) {
386                     struct obj *sobj = mk_tt_object(STATUE, sx, sy);
387
388                     if (sobj) {
389                         for (i = rn2(5); i; i--)
390                             (void) add_to_container(
391                                 sobj, mkobj(RANDOM_CLASS, FALSE));
392                         sobj->owt = weight(sobj);
393                     }
394                 }
395                 break;
396             case ANTHOLE:
397                 if (!rn2(3))
398                     (void) mkobj_at(FOOD_CLASS, sx, sy, FALSE);
399                 break;
400             }
401         }
402     switch (type) {
403     case COURT: {
404         struct obj *chest, *gold;
405         levl[tx][ty].typ = THRONE;
406         (void) somexy(sroom, &mm);
407         gold = mksobj(GOLD_PIECE, TRUE, FALSE);
408         gold->quan = (long) rn1(50 * level_difficulty(), 10);
409         gold->owt = weight(gold);
410         /* the royal coffers */
411         chest = mksobj_at(CHEST, mm.x, mm.y, TRUE, FALSE);
412         add_to_container(chest, gold);
413         chest->owt = weight(chest);
414         chest->spe = 2; /* so it can be found later */
415         level.flags.has_court = 1;
416         break;
417     }
418     case BARRACKS:
419         level.flags.has_barracks = 1;
420         break;
421     case ZOO:
422         level.flags.has_zoo = 1;
423         break;
424     case MORGUE:
425         level.flags.has_morgue = 1;
426         break;
427     case SWAMP:
428         level.flags.has_swamp = 1;
429         break;
430     case BEEHIVE:
431         level.flags.has_beehive = 1;
432         break;
433     }
434 }
435
436 /* make a swarm of undead around mm */
437 void
438 mkundead(mm, revive_corpses, mm_flags)
439 coord *mm;
440 boolean revive_corpses;
441 int mm_flags;
442 {
443     int cnt = (level_difficulty() + 1) / 10 + rnd(5);
444     struct permonst *mdat;
445     struct obj *otmp;
446     coord cc;
447
448     while (cnt--) {
449         mdat = morguemon();
450         if (mdat && enexto(&cc, mm->x, mm->y, mdat)
451             && (!revive_corpses
452                 || !(otmp = sobj_at(CORPSE, cc.x, cc.y))
453                 || !revive(otmp, FALSE)))
454             (void) makemon(mdat, cc.x, cc.y, mm_flags);
455     }
456     level.flags.graveyard = TRUE; /* reduced chance for undead corpse */
457 }
458
459 STATIC_OVL struct permonst *
460 morguemon()
461 {
462     register int i = rn2(100), hd = rn2(level_difficulty());
463
464     if (hd > 10 && i < 10) {
465         if (Inhell || In_endgame(&u.uz)) {
466             return mkclass(S_DEMON, 0);
467         } else {
468             int ndemon_res = ndemon(A_NONE);
469             if (ndemon_res != NON_PM)
470                 return &mons[ndemon_res];
471             /* else do what? As is, it will drop to ghost/wraith/zombie */
472         }
473     }
474
475     if (hd > 8 && i > 85)
476         return mkclass(S_VAMPIRE, 0);
477
478     return ((i < 20) ? &mons[PM_GHOST]
479                      : (i < 40) ? &mons[PM_WRAITH]
480                                 : mkclass(S_ZOMBIE, 0));
481 }
482
483 struct permonst *
484 antholemon()
485 {
486     int mtyp, indx, trycnt = 0;
487
488     /* casts are for dealing with time_t */
489     indx = (int) ((long) ubirthday % 3L);
490     indx += level_difficulty();
491     /* Same monsters within a level, different ones between levels */
492     do {
493         switch ((indx + trycnt) % 3) {
494         case 0:
495             mtyp = PM_SOLDIER_ANT;
496             break;
497         case 1:
498             mtyp = PM_FIRE_ANT;
499             break;
500         default:
501             mtyp = PM_GIANT_ANT;
502             break;
503         }
504         /* try again if chosen type has been genocided or used up */
505     } while (++trycnt < 3 && (mvitals[mtyp].mvflags & G_GONE));
506
507     return ((mvitals[mtyp].mvflags & G_GONE) ? (struct permonst *) 0
508                                              : &mons[mtyp]);
509 }
510
511 STATIC_OVL void
512 mkswamp() /* Michiel Huisjes & Fred de Wilde */
513 {
514     register struct mkroom *sroom;
515     register int sx, sy, i, eelct = 0;
516
517     for (i = 0; i < 5; i++) { /* turn up to 5 rooms swampy */
518         sroom = &rooms[rn2(nroom)];
519         if (sroom->hx < 0 || sroom->rtype != OROOM || has_upstairs(sroom)
520             || has_dnstairs(sroom))
521             continue;
522
523         /* satisfied; make a swamp */
524         sroom->rtype = SWAMP;
525         for (sx = sroom->lx; sx <= sroom->hx; sx++)
526             for (sy = sroom->ly; sy <= sroom->hy; sy++)
527                 if (!OBJ_AT(sx, sy) && !MON_AT(sx, sy) && !t_at(sx, sy)
528                     && !nexttodoor(sx, sy)) {
529                     if ((sx + sy) % 2) {
530                         levl[sx][sy].typ = POOL;
531                         if (!eelct || !rn2(4)) {
532                             /* mkclass() won't do, as we might get kraken */
533                             (void) makemon(rn2(5)
534                                               ? &mons[PM_GIANT_EEL]
535                                               : rn2(2)
536                                                  ? &mons[PM_PIRANHA]
537                                                  : &mons[PM_ELECTRIC_EEL],
538                                            sx, sy, NO_MM_FLAGS);
539                             eelct++;
540                         }
541                     } else if (!rn2(4)) /* swamps tend to be moldy */
542                         (void) makemon(mkclass(S_FUNGUS, 0), sx, sy,
543                                        NO_MM_FLAGS);
544                 }
545         level.flags.has_swamp = 1;
546     }
547 }
548
549 STATIC_OVL coord *
550 shrine_pos(roomno)
551 int roomno;
552 {
553     static coord buf;
554     int delta;
555     struct mkroom *troom = &rooms[roomno - ROOMOFFSET];
556
557     /* if width and height are odd, placement will be the exact center;
558        if either or both are even, center point is a hypothetical spot
559        between map locations and placement will be adjacent to that */
560     delta = troom->hx - troom->lx;
561     buf.x = troom->lx + delta / 2;
562     if ((delta % 2) && rn2(2))
563         buf.x++;
564     delta = troom->hy - troom->ly;
565     buf.y = troom->ly + delta / 2;
566     if ((delta % 2) && rn2(2))
567         buf.y++;
568     return &buf;
569 }
570
571 STATIC_OVL void
572 mktemple()
573 {
574     register struct mkroom *sroom;
575     coord *shrine_spot;
576     register struct rm *lev;
577
578     if (!(sroom = pick_room(TRUE)))
579         return;
580
581     /* set up Priest and shrine */
582     sroom->rtype = TEMPLE;
583     /*
584      * In temples, shrines are blessed altars
585      * located in the center of the room
586      */
587     shrine_spot = shrine_pos((int) ((sroom - rooms) + ROOMOFFSET));
588     lev = &levl[shrine_spot->x][shrine_spot->y];
589     lev->typ = ALTAR;
590     lev->altarmask = induced_align(80);
591     priestini(&u.uz, sroom, shrine_spot->x, shrine_spot->y, FALSE);
592     lev->altarmask |= AM_SHRINE;
593     level.flags.has_temple = 1;
594 }
595
596 boolean
597 nexttodoor(sx, sy)
598 register int sx, sy;
599 {
600     register int dx, dy;
601     register struct rm *lev;
602
603     for (dx = -1; dx <= 1; dx++)
604         for (dy = -1; dy <= 1; dy++) {
605             if (!isok(sx + dx, sy + dy))
606                 continue;
607             lev = &levl[sx + dx][sy + dy];
608             if (IS_DOOR(lev->typ) || lev->typ == SDOOR)
609                 return TRUE;
610         }
611     return FALSE;
612 }
613
614 boolean
615 has_dnstairs(sroom)
616 register struct mkroom *sroom;
617 {
618     if (sroom == dnstairs_room)
619         return TRUE;
620     if (sstairs.sx && !sstairs.up)
621         return (boolean) (sroom == sstairs_room);
622     return FALSE;
623 }
624
625 boolean
626 has_upstairs(sroom)
627 register struct mkroom *sroom;
628 {
629     if (sroom == upstairs_room)
630         return TRUE;
631     if (sstairs.sx && sstairs.up)
632         return (boolean) (sroom == sstairs_room);
633     return FALSE;
634 }
635
636 int
637 somex(croom)
638 register struct mkroom *croom;
639 {
640     return rn1(croom->hx - croom->lx + 1, croom->lx);
641 }
642
643 int
644 somey(croom)
645 register struct mkroom *croom;
646 {
647     return rn1(croom->hy - croom->ly + 1, croom->ly);
648 }
649
650 boolean
651 inside_room(croom, x, y)
652 struct mkroom *croom;
653 xchar x, y;
654 {
655     return (boolean) (x >= croom->lx - 1 && x <= croom->hx + 1
656                       && y >= croom->ly - 1 && y <= croom->hy + 1);
657 }
658
659 boolean
660 somexy(croom, c)
661 struct mkroom *croom;
662 coord *c;
663 {
664     int try_cnt = 0;
665     int i;
666
667     if (croom->irregular) {
668         i = (int) ((croom - rooms) + ROOMOFFSET);
669
670         while (try_cnt++ < 100) {
671             c->x = somex(croom);
672             c->y = somey(croom);
673             if (!levl[c->x][c->y].edge && (int) levl[c->x][c->y].roomno == i)
674                 return TRUE;
675         }
676         /* try harder; exhaustively search until one is found */
677         for (c->x = croom->lx; c->x <= croom->hx; c->x++)
678             for (c->y = croom->ly; c->y <= croom->hy; c->y++)
679                 if (!levl[c->x][c->y].edge
680                     && (int) levl[c->x][c->y].roomno == i)
681                     return TRUE;
682         return FALSE;
683     }
684
685     if (!croom->nsubrooms) {
686         c->x = somex(croom);
687         c->y = somey(croom);
688         return TRUE;
689     }
690
691     /* Check that coords doesn't fall into a subroom or into a wall */
692
693     while (try_cnt++ < 100) {
694         c->x = somex(croom);
695         c->y = somey(croom);
696         if (IS_WALL(levl[c->x][c->y].typ))
697             continue;
698         for (i = 0; i < croom->nsubrooms; i++)
699             if (inside_room(croom->sbrooms[i], c->x, c->y))
700                 goto you_lose;
701         break;
702     you_lose:
703         ;
704     }
705     if (try_cnt >= 100)
706         return FALSE;
707     return TRUE;
708 }
709
710 /*
711  * Search for a special room given its type (zoo, court, etc...)
712  *      Special values :
713  *              - ANY_SHOP
714  *              - ANY_TYPE
715  */
716 struct mkroom *
717 search_special(type)
718 schar type;
719 {
720     register struct mkroom *croom;
721
722     for (croom = &rooms[0]; croom->hx >= 0; croom++)
723         if ((type == ANY_TYPE && croom->rtype != OROOM)
724             || (type == ANY_SHOP && croom->rtype >= SHOPBASE)
725             || croom->rtype == type)
726             return croom;
727     for (croom = &subrooms[0]; croom->hx >= 0; croom++)
728         if ((type == ANY_TYPE && croom->rtype != OROOM)
729             || (type == ANY_SHOP && croom->rtype >= SHOPBASE)
730             || croom->rtype == type)
731             return croom;
732     return (struct mkroom *) 0;
733 }
734
735 struct permonst *
736 courtmon()
737 {
738     int i = rn2(60) + rn2(3 * level_difficulty());
739
740     if (i > 100)
741         return mkclass(S_DRAGON, 0);
742     else if (i > 95)
743         return mkclass(S_GIANT, 0);
744     else if (i > 85)
745         return mkclass(S_TROLL, 0);
746     else if (i > 75)
747         return mkclass(S_CENTAUR, 0);
748     else if (i > 60)
749         return mkclass(S_ORC, 0);
750     else if (i > 45)
751         return &mons[PM_BUGBEAR];
752     else if (i > 30)
753         return &mons[PM_HOBGOBLIN];
754     else if (i > 15)
755         return mkclass(S_GNOME, 0);
756     else
757         return mkclass(S_KOBOLD, 0);
758 }
759
760 #define NSTYPES (PM_CAPTAIN - PM_SOLDIER + 1)
761
762 static struct {
763     unsigned pm;
764     unsigned prob;
765 } squadprob[NSTYPES] = { { PM_SOLDIER, 80 },
766                          { PM_SERGEANT, 15 },
767                          { PM_LIEUTENANT, 4 },
768                          { PM_CAPTAIN, 1 } };
769
770 /* return soldier types. */
771 STATIC_OVL struct permonst *
772 squadmon()
773 {
774     int sel_prob, i, cpro, mndx;
775
776     sel_prob = rnd(80 + level_difficulty());
777
778     cpro = 0;
779     for (i = 0; i < NSTYPES; i++) {
780         cpro += squadprob[i].prob;
781         if (cpro > sel_prob) {
782             mndx = squadprob[i].pm;
783             goto gotone;
784         }
785     }
786     mndx = squadprob[rn2(NSTYPES)].pm;
787 gotone:
788     if (!(mvitals[mndx].mvflags & G_GONE))
789         return &mons[mndx];
790     else
791         return (struct permonst *) 0;
792 }
793
794 /*
795  * save_room : A recursive function that saves a room and its subrooms
796  * (if any).
797  */
798 STATIC_OVL void
799 save_room(fd, r)
800 int fd;
801 struct mkroom *r;
802 {
803     short i;
804
805     /*
806      * Well, I really should write only useful information instead
807      * of writing the whole structure. That is I should not write
808      * the subrooms pointers, but who cares ?
809      */
810     bwrite(fd, (genericptr_t) r, sizeof (struct mkroom));
811     for (i = 0; i < r->nsubrooms; i++)
812         save_room(fd, r->sbrooms[i]);
813 }
814
815 /*
816  * save_rooms : Save all the rooms on disk!
817  */
818 void
819 save_rooms(fd)
820 int fd;
821 {
822     short i;
823
824     /* First, write the number of rooms */
825     bwrite(fd, (genericptr_t) &nroom, sizeof(nroom));
826     for (i = 0; i < nroom; i++)
827         save_room(fd, &rooms[i]);
828 }
829
830 STATIC_OVL void
831 rest_room(fd, r)
832 int fd;
833 struct mkroom *r;
834 {
835     short i;
836
837     mread(fd, (genericptr_t) r, sizeof(struct mkroom));
838     for (i = 0; i < r->nsubrooms; i++) {
839         r->sbrooms[i] = &subrooms[nsubroom];
840         rest_room(fd, &subrooms[nsubroom]);
841         subrooms[nsubroom++].resident = (struct monst *) 0;
842     }
843 }
844
845 /*
846  * rest_rooms : That's for restoring rooms. Read the rooms structure from
847  * the disk.
848  */
849 void
850 rest_rooms(fd)
851 int fd;
852 {
853     short i;
854
855     mread(fd, (genericptr_t) &nroom, sizeof(nroom));
856     nsubroom = 0;
857     for (i = 0; i < nroom; i++) {
858         rest_room(fd, &rooms[i]);
859         rooms[i].resident = (struct monst *) 0;
860     }
861     rooms[nroom].hx = -1; /* restore ending flags */
862     subrooms[nsubroom].hx = -1;
863 }
864
865 /* convert a display symbol for terrain into topology type;
866    used for remembered terrain when mimics pose as furniture */
867 int
868 cmap_to_type(sym)
869 int sym;
870 {
871     int typ = STONE; /* catchall */
872
873     switch (sym) {
874     case S_stone:
875         typ = STONE;
876         break;
877     case S_vwall:
878         typ = VWALL;
879         break;
880     case S_hwall:
881         typ = HWALL;
882         break;
883     case S_tlcorn:
884         typ = TLCORNER;
885         break;
886     case S_trcorn:
887         typ = TRCORNER;
888         break;
889     case S_blcorn:
890         typ = BLCORNER;
891         break;
892     case S_brcorn:
893         typ = BRCORNER;
894         break;
895     case S_crwall:
896         typ = CROSSWALL;
897         break;
898     case S_tuwall:
899         typ = TUWALL;
900         break;
901     case S_tdwall:
902         typ = TDWALL;
903         break;
904     case S_tlwall:
905         typ = TLWALL;
906         break;
907     case S_trwall:
908         typ = TRWALL;
909         break;
910     case S_ndoor:  /* no door (empty doorway) */
911     case S_vodoor: /* open door in vertical wall */
912     case S_hodoor: /* open door in horizontal wall */
913     case S_vcdoor: /* closed door in vertical wall */
914     case S_hcdoor:
915         typ = DOOR;
916         break;
917     case S_bars:
918         typ = IRONBARS;
919         break;
920     case S_tree:
921         typ = TREE;
922         break;
923     case S_room:
924         typ = ROOM;
925         break;
926     case S_corr:
927     case S_litcorr:
928         typ = CORR;
929         break;
930     case S_upstair:
931     case S_dnstair:
932         typ = STAIRS;
933         break;
934     case S_upladder:
935     case S_dnladder:
936         typ = LADDER;
937         break;
938     case S_altar:
939         typ = ALTAR;
940         break;
941     case S_grave:
942         typ = GRAVE;
943         break;
944     case S_throne:
945         typ = THRONE;
946         break;
947     case S_sink:
948         typ = SINK;
949         break;
950     case S_fountain:
951         typ = FOUNTAIN;
952         break;
953     case S_pool:
954         typ = POOL;
955         break;
956     case S_ice:
957         typ = ICE;
958         break;
959     case S_lava:
960         typ = LAVAPOOL;
961         break;
962     case S_vodbridge: /* open drawbridge spanning north/south */
963     case S_hodbridge:
964         typ = DRAWBRIDGE_DOWN;
965         break;        /* east/west */
966     case S_vcdbridge: /* closed drawbridge in vertical wall */
967     case S_hcdbridge:
968         typ = DBWALL;
969         break;
970     case S_air:
971         typ = AIR;
972         break;
973     case S_cloud:
974         typ = CLOUD;
975         break;
976     case S_water:
977         typ = WATER;
978         break;
979     default:
980         break; /* not a cmap symbol? */
981     }
982     return typ;
983 }
984
985 /*mkroom.c*/