xref: /netbsd-src/games/hack/hack.mkshop.c (revision d5b021c7edb8313eee3804ec3819b28abef1d1a0)
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