1*d5b021c7Sdholland /* $NetBSD: hack.mkshop.c,v 1.11 2011/08/07 06:03:45 dholland Exp $ */
23ea4a95cSchristos
302ded532Smycroft /*
41c7f94e5Sjsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
51c7f94e5Sjsm * Amsterdam
61c7f94e5Sjsm * All rights reserved.
71c7f94e5Sjsm *
81c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
91c7f94e5Sjsm * modification, are permitted provided that the following conditions are
101c7f94e5Sjsm * met:
111c7f94e5Sjsm *
121c7f94e5Sjsm * - Redistributions of source code must retain the above copyright notice,
131c7f94e5Sjsm * this list of conditions and the following disclaimer.
141c7f94e5Sjsm *
151c7f94e5Sjsm * - Redistributions in binary form must reproduce the above copyright
161c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
171c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
181c7f94e5Sjsm *
191c7f94e5Sjsm * - Neither the name of the Stichting Centrum voor Wiskunde en
201c7f94e5Sjsm * Informatica, nor the names of its contributors may be used to endorse or
211c7f94e5Sjsm * promote products derived from this software without specific prior
221c7f94e5Sjsm * written permission.
231c7f94e5Sjsm *
241c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
251c7f94e5Sjsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
261c7f94e5Sjsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
271c7f94e5Sjsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
281c7f94e5Sjsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
291c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
301c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
311c7f94e5Sjsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
321c7f94e5Sjsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
331c7f94e5Sjsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
341c7f94e5Sjsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
351c7f94e5Sjsm */
361c7f94e5Sjsm
371c7f94e5Sjsm /*
381c7f94e5Sjsm * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
391c7f94e5Sjsm * All rights reserved.
401c7f94e5Sjsm *
411c7f94e5Sjsm * Redistribution and use in source and binary forms, with or without
421c7f94e5Sjsm * modification, are permitted provided that the following conditions
431c7f94e5Sjsm * are met:
441c7f94e5Sjsm * 1. Redistributions of source code must retain the above copyright
451c7f94e5Sjsm * notice, this list of conditions and the following disclaimer.
461c7f94e5Sjsm * 2. Redistributions in binary form must reproduce the above copyright
471c7f94e5Sjsm * notice, this list of conditions and the following disclaimer in the
481c7f94e5Sjsm * documentation and/or other materials provided with the distribution.
491c7f94e5Sjsm * 3. The name of the author may not be used to endorse or promote products
501c7f94e5Sjsm * derived from this software without specific prior written permission.
511c7f94e5Sjsm *
521c7f94e5Sjsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
531c7f94e5Sjsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
541c7f94e5Sjsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
551c7f94e5Sjsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
561c7f94e5Sjsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
571c7f94e5Sjsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
581c7f94e5Sjsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
591c7f94e5Sjsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
601c7f94e5Sjsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
611c7f94e5Sjsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6202ded532Smycroft */
6302ded532Smycroft
643ea4a95cSchristos #include <sys/cdefs.h>
6502ded532Smycroft #ifndef lint
66*d5b021c7Sdholland __RCSID("$NetBSD: hack.mkshop.c,v 1.11 2011/08/07 06:03:45 dholland Exp $");
6702ded532Smycroft #endif /* not lint */
6861f28255Scgd
69f7f4b85cSmycroft #include <stdlib.h>
7061f28255Scgd #ifndef QUEST
7161f28255Scgd #include "hack.h"
723ea4a95cSchristos #include "extern.h"
7361f28255Scgd #include "def.mkroom.h"
7461f28255Scgd #include "def.eshk.h"
759b92b189Sdholland
7661f28255Scgd #define ESHK ((struct eshk *)(&(shk->mextra[0])))
779b92b189Sdholland
789b92b189Sdholland /* their probabilities */
799b92b189Sdholland static const schar shprobs[] = {3, 3, 5, 5, 10, 10, 14, 50};
809b92b189Sdholland
819b92b189Sdholland static const struct permonst *morguemon(void);
829b92b189Sdholland static int nexttodoor(int, int);
839b92b189Sdholland static int has_dnstairs(struct mkroom *);
849b92b189Sdholland static int has_upstairs(struct mkroom *);
859b92b189Sdholland static int isbig(struct mkroom *);
869b92b189Sdholland static int dist2(int, int, int, int);
879b92b189Sdholland static int sq(int);
8861f28255Scgd
893ea4a95cSchristos void
mkshop(void)901fa8a9a6Sdholland mkshop(void)
913ea4a95cSchristos {
923ea4a95cSchristos struct mkroom *sroom;
933ea4a95cSchristos int sh, sx, sy, i = -1;
943ea4a95cSchristos char let;
9561f28255Scgd int roomno;
963ea4a95cSchristos struct monst *shk;
9761f28255Scgd #ifdef WIZARD
9861f28255Scgd /* first determine shoptype */
9961f28255Scgd if (wizard) {
1003ea4a95cSchristos char *ep = getenv("SHOPTYPE");
10161f28255Scgd if (ep) {
10261f28255Scgd if (*ep == 'z' || *ep == 'Z') {
10361f28255Scgd mkzoo(ZOO);
10461f28255Scgd return;
10561f28255Scgd }
10661f28255Scgd if (*ep == 'm' || *ep == 'M') {
10761f28255Scgd mkzoo(MORGUE);
10861f28255Scgd return;
10961f28255Scgd }
11061f28255Scgd if (*ep == 'b' || *ep == 'B') {
11161f28255Scgd mkzoo(BEEHIVE);
11261f28255Scgd return;
11361f28255Scgd }
11461f28255Scgd if (*ep == 's' || *ep == 'S') {
11561f28255Scgd mkswamp();
11661f28255Scgd return;
11761f28255Scgd }
11861f28255Scgd for (i = 0; shtypes[i]; i++)
1193ea4a95cSchristos if (*ep == shtypes[i])
1203ea4a95cSchristos break;
12161f28255Scgd goto gottype;
12261f28255Scgd }
12361f28255Scgd }
12461f28255Scgd gottype:
1253ea4a95cSchristos #endif /* WIZARD */
12661f28255Scgd for (sroom = &rooms[0], roomno = 0;; sroom++, roomno++) {
1273ea4a95cSchristos if (sroom->hx < 0)
1283ea4a95cSchristos return;
12961f28255Scgd if (sroom - rooms >= nroom) {
13061f28255Scgd pline("rooms not closed by -1?");
13161f28255Scgd return;
13261f28255Scgd }
1333ea4a95cSchristos if (sroom->rtype)
1343ea4a95cSchristos continue;
13561f28255Scgd if (!sroom->rlit || has_dnstairs(sroom) || has_upstairs(sroom))
13661f28255Scgd continue;
13761f28255Scgd if (
13861f28255Scgd #ifdef WIZARD
13961f28255Scgd (wizard && getenv("SHOPTYPE") && sroom->doorct != 0) ||
1403ea4a95cSchristos #endif /* WIZARD */
14188c6198cSchuck sroom->doorct == 1)
1423ea4a95cSchristos break;
14361f28255Scgd }
14461f28255Scgd
14561f28255Scgd if (i < 0) { /* shoptype not yet determined */
1463ea4a95cSchristos int j;
14761f28255Scgd
14861f28255Scgd for (j = rn2(100), i = 0; (j -= shprobs[i]) >= 0; i++)
1493ea4a95cSchristos if (!shtypes[i])
1503ea4a95cSchristos break; /* superfluous */
15161f28255Scgd if (isbig(sroom) && i + SHOPBASE == WANDSHOP)
15261f28255Scgd i = GENERAL - SHOPBASE;
15361f28255Scgd }
15461f28255Scgd sroom->rtype = i + SHOPBASE;
15561f28255Scgd let = shtypes[i];
15661f28255Scgd sh = sroom->fdoor;
15761f28255Scgd sx = doors[sh].x;
15861f28255Scgd sy = doors[sh].y;
1593ea4a95cSchristos if (sx == sroom->lx - 1)
1603ea4a95cSchristos sx++;
1613ea4a95cSchristos else if (sx == sroom->hx + 1)
1623ea4a95cSchristos sx--;
1633ea4a95cSchristos else if (sy == sroom->ly - 1)
1643ea4a95cSchristos sy++;
1653ea4a95cSchristos else if (sy == sroom->hy + 1)
1663ea4a95cSchristos sy--;
1673ea4a95cSchristos else {
16861f28255Scgd #ifdef WIZARD
16961f28255Scgd /* This is said to happen sometimes, but I've never seen it. */
17061f28255Scgd if (wizard) {
1713ea4a95cSchristos int j = sroom->doorct;
17261f28255Scgd
17361f28255Scgd pline("Where is shopdoor?");
17461f28255Scgd pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly,
17561f28255Scgd sroom->hx, sroom->hy);
17661f28255Scgd pline("doormax=%d doorct=%d fdoor=%d",
17761f28255Scgd doorindex, sroom->doorct, sh);
17861f28255Scgd while (j--) {
17961f28255Scgd pline("door [%d,%d]", doors[sh].x, doors[sh].y);
18061f28255Scgd sh++;
18161f28255Scgd }
18261f28255Scgd more();
18361f28255Scgd }
1843ea4a95cSchristos #endif /* WIZARD */
18561f28255Scgd return;
18661f28255Scgd }
1873ea4a95cSchristos if (!(shk = makemon(PM_SHK, sx, sy)))
1883ea4a95cSchristos return;
18961f28255Scgd shk->isshk = shk->mpeaceful = 1;
19061f28255Scgd shk->msleep = 0;
191*d5b021c7Sdholland shk->mtrapseen = ~0U; /* we know all the traps already */
19261f28255Scgd ESHK->shoproom = roomno;
19361f28255Scgd ESHK->shoplevel = dlevel;
19461f28255Scgd ESHK->shd = doors[sh];
19561f28255Scgd ESHK->shk.x = sx;
19661f28255Scgd ESHK->shk.y = sy;
19761f28255Scgd ESHK->robbed = 0;
19861f28255Scgd ESHK->visitct = 0;
19961f28255Scgd ESHK->following = 0;
20061f28255Scgd shk->mgold = 1000 + 30 * rnd(100); /* initial capital */
20161f28255Scgd ESHK->billct = 0;
20261f28255Scgd findname(ESHK->shknam, let);
20361f28255Scgd for (sx = sroom->lx; sx <= sroom->hx; sx++)
20461f28255Scgd for (sy = sroom->ly; sy <= sroom->hy; sy++) {
2053ea4a95cSchristos struct monst *mtmp;
20661f28255Scgd if ((sx == sroom->lx && doors[sh].x == sx - 1) ||
20761f28255Scgd (sx == sroom->hx && doors[sh].x == sx + 1) ||
20861f28255Scgd (sy == sroom->ly && doors[sh].y == sy - 1) ||
2093ea4a95cSchristos (sy == sroom->hy && doors[sh].y == sy + 1))
2103ea4a95cSchristos continue;
21161f28255Scgd if (rn2(100) < dlevel && !m_at(sx, sy) &&
21261f28255Scgd (mtmp = makemon(PM_MIMIC, sx, sy))) {
21361f28255Scgd mtmp->mimic = 1;
21461f28255Scgd mtmp->mappearance =
21561f28255Scgd (let && rn2(10) < dlevel) ? let : ']';
21661f28255Scgd continue;
21761f28255Scgd }
21861f28255Scgd (void) mkobj_at(let, sx, sy);
21961f28255Scgd }
22061f28255Scgd }
22161f28255Scgd
2223ea4a95cSchristos void
mkzoo(int type)2231fa8a9a6Sdholland mkzoo(int type)
22461f28255Scgd {
2253ea4a95cSchristos struct mkroom *sroom;
2263ea4a95cSchristos struct monst *mon;
2273ea4a95cSchristos int sh, sx, sy, i;
22861f28255Scgd int goldlim = 500 * dlevel;
22961f28255Scgd int moct = 0;
23061f28255Scgd
23161f28255Scgd i = nroom;
23261f28255Scgd for (sroom = &rooms[rn2(nroom)];; sroom++) {
23361f28255Scgd if (sroom == &rooms[nroom])
23461f28255Scgd sroom = &rooms[0];
23561f28255Scgd if (!i-- || sroom->hx < 0)
23661f28255Scgd return;
23761f28255Scgd if (sroom->rtype)
23861f28255Scgd continue;
23961f28255Scgd if (type == MORGUE && sroom->rlit)
24061f28255Scgd continue;
24161f28255Scgd if (has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
24261f28255Scgd continue;
24361f28255Scgd if (sroom->doorct == 1 || !rn2(5))
24461f28255Scgd break;
24561f28255Scgd }
24661f28255Scgd sroom->rtype = type;
24761f28255Scgd sh = sroom->fdoor;
24861f28255Scgd for (sx = sroom->lx; sx <= sroom->hx; sx++)
24961f28255Scgd for (sy = sroom->ly; sy <= sroom->hy; sy++) {
25061f28255Scgd if ((sx == sroom->lx && doors[sh].x == sx - 1) ||
25161f28255Scgd (sx == sroom->hx && doors[sh].x == sx + 1) ||
25261f28255Scgd (sy == sroom->ly && doors[sh].y == sy - 1) ||
2533ea4a95cSchristos (sy == sroom->hy && doors[sh].y == sy + 1))
2543ea4a95cSchristos continue;
25561f28255Scgd mon = makemon(
25661f28255Scgd (type == MORGUE) ? morguemon() :
25761f28255Scgd (type == BEEHIVE) ? PM_KILLER_BEE : (struct permonst *) 0,
25861f28255Scgd sx, sy);
2593ea4a95cSchristos if (mon)
2603ea4a95cSchristos mon->msleep = 1;
26161f28255Scgd switch (type) {
26261f28255Scgd case ZOO:
26361f28255Scgd i = sq(dist2(sx, sy, doors[sh].x, doors[sh].y));
2643ea4a95cSchristos if (i >= goldlim)
2653ea4a95cSchristos i = 5 * dlevel;
26661f28255Scgd goldlim -= i;
26761f28255Scgd mkgold((long) (10 + rn2(i)), sx, sy);
26861f28255Scgd break;
26961f28255Scgd case MORGUE:
2703ea4a95cSchristos /*
2713ea4a95cSchristos * Usually there is one dead body in the
2723ea4a95cSchristos * morgue
2733ea4a95cSchristos */
27461f28255Scgd if (!moct && rn2(3)) {
27561f28255Scgd mksobj_at(CORPSE, sx, sy);
27661f28255Scgd moct++;
27761f28255Scgd }
27861f28255Scgd break;
27961f28255Scgd case BEEHIVE:
2803ea4a95cSchristos if (!rn2(3))
2813ea4a95cSchristos mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy);
28261f28255Scgd break;
28361f28255Scgd }
28461f28255Scgd }
28561f28255Scgd }
28661f28255Scgd
2879b92b189Sdholland static const struct permonst *
morguemon(void)2881fa8a9a6Sdholland morguemon(void)
28961f28255Scgd {
2903ea4a95cSchristos int i = rn2(100), hd = rn2(dlevel);
29161f28255Scgd
2923ea4a95cSchristos if (hd > 10 && i < 10)
2933ea4a95cSchristos return (PM_DEMON);
2943ea4a95cSchristos if (hd > 8 && i > 85)
2953ea4a95cSchristos return (PM_VAMPIRE);
29661f28255Scgd return ((i < 40) ? PM_GHOST : (i < 60) ? PM_WRAITH : PM_ZOMBIE);
29761f28255Scgd }
29861f28255Scgd
2993ea4a95cSchristos void
mkswamp(void)3001fa8a9a6Sdholland mkswamp(void)
3013ea4a95cSchristos { /* Michiel Huisjes & Fred de Wilde */
3023ea4a95cSchristos struct mkroom *sroom;
3033ea4a95cSchristos int sx, sy, i, eelct = 0;
30461f28255Scgd
30561f28255Scgd for (i = 0; i < 5; i++) { /* 5 tries */
30661f28255Scgd sroom = &rooms[rn2(nroom)];
30761f28255Scgd if (sroom->hx < 0 || sroom->rtype ||
30861f28255Scgd has_upstairs(sroom) || has_dnstairs(sroom))
30961f28255Scgd continue;
31061f28255Scgd
31161f28255Scgd /* satisfied; make a swamp */
31261f28255Scgd sroom->rtype = SWAMP;
31361f28255Scgd for (sx = sroom->lx; sx <= sroom->hx; sx++)
31461f28255Scgd for (sy = sroom->ly; sy <= sroom->hy; sy++)
31561f28255Scgd if ((sx + sy) % 2 && !o_at(sx, sy) && !t_at(sx, sy)
31661f28255Scgd && !m_at(sx, sy) && !nexttodoor(sx, sy)) {
31761f28255Scgd levl[sx][sy].typ = POOL;
31861f28255Scgd levl[sx][sy].scrsym = POOL_SYM;
31961f28255Scgd if (!eelct || !rn2(4)) {
32061f28255Scgd (void) makemon(PM_EEL, sx, sy);
32161f28255Scgd eelct++;
32261f28255Scgd }
32361f28255Scgd }
32461f28255Scgd }
32561f28255Scgd }
32661f28255Scgd
3279b92b189Sdholland static int
nexttodoor(int sx,int sy)3281fa8a9a6Sdholland nexttodoor(int sx, int sy)
32961f28255Scgd {
3303ea4a95cSchristos int dx, dy;
3313ea4a95cSchristos struct rm *lev;
3323ea4a95cSchristos for (dx = -1; dx <= 1; dx++)
3333ea4a95cSchristos for (dy = -1; dy <= 1; dy++)
33461f28255Scgd if ((lev = &levl[sx + dx][sy + dy])->typ == DOOR ||
33561f28255Scgd lev->typ == SDOOR || lev->typ == LDOOR)
33661f28255Scgd return (1);
33761f28255Scgd return (0);
33861f28255Scgd }
33961f28255Scgd
3409b92b189Sdholland static int
has_dnstairs(struct mkroom * sroom)3411fa8a9a6Sdholland has_dnstairs(struct mkroom *sroom)
34261f28255Scgd {
34361f28255Scgd return (sroom->lx <= xdnstair && xdnstair <= sroom->hx &&
34461f28255Scgd sroom->ly <= ydnstair && ydnstair <= sroom->hy);
34561f28255Scgd }
34661f28255Scgd
3479b92b189Sdholland static int
has_upstairs(struct mkroom * sroom)3481fa8a9a6Sdholland has_upstairs(struct mkroom *sroom)
34961f28255Scgd {
35061f28255Scgd return (sroom->lx <= xupstair && xupstair <= sroom->hx &&
35161f28255Scgd sroom->ly <= yupstair && yupstair <= sroom->hy);
35261f28255Scgd }
35361f28255Scgd
3549b92b189Sdholland static int
isbig(struct mkroom * sroom)3551fa8a9a6Sdholland isbig(struct mkroom *sroom)
35661f28255Scgd {
3573ea4a95cSchristos int area = (sroom->hx - sroom->lx) * (sroom->hy - sroom->ly);
35861f28255Scgd return (area > 20);
35961f28255Scgd }
36061f28255Scgd
3619b92b189Sdholland static int
dist2(int x0,int y0,int x1,int y1)3621fa8a9a6Sdholland dist2(int x0, int y0, int x1, int y1)
3633ea4a95cSchristos {
36461f28255Scgd return ((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
36561f28255Scgd }
36661f28255Scgd
3679b92b189Sdholland static int
sq(int a)3681fa8a9a6Sdholland sq(int a)
3693ea4a95cSchristos {
37061f28255Scgd return (a * a);
37161f28255Scgd }
3723ea4a95cSchristos #endif /* QUEST */
373