xref: /dragonfly/games/hack/hack.mkshop.c (revision b9a6fe08)
1 /*	$NetBSD: hack.mkshop.c,v 1.11 2011/08/07 06:03:45 dholland Exp $	*/
2 
3 /*
4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5  * Amsterdam
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are
10  * met:
11  *
12  * - Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * - Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  *
19  * - Neither the name of the Stichting Centrum voor Wiskunde en
20  * Informatica, nor the names of its contributors may be used to endorse or
21  * promote products derived from this software without specific prior
22  * written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 /*
38  * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39  * All rights reserved.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. The name of the author may not be used to endorse or promote products
50  *    derived from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  */
63 
64 #include <stdlib.h>
65 #ifndef QUEST
66 #include "hack.h"
67 #include "extern.h"
68 #include "def.mkroom.h"
69 #include "def.eshk.h"
70 
71 #define	ESHK	((struct eshk *)(&(shk->mextra[0])))
72 
73 /* their probabilities */
74 static const schar shprobs[] = {3, 3, 5, 5, 10, 10, 14, 50};
75 
76 static const struct permonst *morguemon(void);
77 static int nexttodoor(int, int);
78 static int has_dnstairs(struct mkroom *);
79 static int has_upstairs(struct mkroom *);
80 static int isbig(struct mkroom *);
81 static int dist2(int, int, int, int);
82 static int sq(int);
83 
84 void
85 mkshop(void)
86 {
87 	struct mkroom  *sroom;
88 	int             sh, sx, sy, i = -1;
89 	char            let;
90 	int             roomno;
91 	struct monst   *shk;
92 #ifdef WIZARD
93 	/* first determine shoptype */
94 	if (wizard) {
95 		char           *ep = getenv("SHOPTYPE");
96 		if (ep) {
97 			if (*ep == 'z' || *ep == 'Z') {
98 				mkzoo(ZOO);
99 				return;
100 			}
101 			if (*ep == 'm' || *ep == 'M') {
102 				mkzoo(MORGUE);
103 				return;
104 			}
105 			if (*ep == 'b' || *ep == 'B') {
106 				mkzoo(BEEHIVE);
107 				return;
108 			}
109 			if (*ep == 's' || *ep == 'S') {
110 				mkswamp();
111 				return;
112 			}
113 			for (i = 0; shtypes[i]; i++)
114 				if (*ep == shtypes[i])
115 					break;
116 			goto gottype;
117 		}
118 	}
119 gottype:
120 #endif	/* WIZARD */
121 	for (sroom = &rooms[0], roomno = 0;; sroom++, roomno++) {
122 		if (sroom->hx < 0)
123 			return;
124 		if (sroom - rooms >= nroom) {
125 			pline("rooms not closed by -1?");
126 			return;
127 		}
128 		if (sroom->rtype)
129 			continue;
130 		if (!sroom->rlit || has_dnstairs(sroom) || has_upstairs(sroom))
131 			continue;
132 		if (
133 #ifdef WIZARD
134 		    (wizard && getenv("SHOPTYPE") && sroom->doorct != 0) ||
135 #endif	/* WIZARD */
136 		    sroom->doorct == 1)
137 			break;
138 	}
139 
140 	if (i < 0) {		/* shoptype not yet determined */
141 		int             j;
142 
143 		for (j = rn2(100), i = 0; (j -= shprobs[i]) >= 0; i++)
144 			if (!shtypes[i])
145 				break;	/* superfluous */
146 		if (isbig(sroom) && i + SHOPBASE == WANDSHOP)
147 			i = GENERAL - SHOPBASE;
148 	}
149 	sroom->rtype = i + SHOPBASE;
150 	let = shtypes[i];
151 	sh = sroom->fdoor;
152 	sx = doors[sh].x;
153 	sy = doors[sh].y;
154 	if (sx == sroom->lx - 1)
155 		sx++;
156 	else if (sx == sroom->hx + 1)
157 		sx--;
158 	else if (sy == sroom->ly - 1)
159 		sy++;
160 	else if (sy == sroom->hy + 1)
161 		sy--;
162 	else {
163 #ifdef WIZARD
164 		/* This is said to happen sometimes, but I've never seen it. */
165 		if (wizard) {
166 			int             j = sroom->doorct;
167 
168 			pline("Where is shopdoor?");
169 			pline("Room at (%d,%d),(%d,%d).", sroom->lx, sroom->ly,
170 			      sroom->hx, sroom->hy);
171 			pline("doormax=%d doorct=%d fdoor=%d",
172 			      doorindex, sroom->doorct, sh);
173 			while (j--) {
174 				pline("door [%d,%d]", doors[sh].x, doors[sh].y);
175 				sh++;
176 			}
177 			more();
178 		}
179 #endif	/* WIZARD */
180 		return;
181 	}
182 	if (!(shk = makemon(PM_SHK, sx, sy)))
183 		return;
184 	shk->isshk = shk->mpeaceful = 1;
185 	shk->msleep = 0;
186 	shk->mtrapseen = ~0U;	/* we know all the traps already */
187 	ESHK->shoproom = roomno;
188 	ESHK->shoplevel = dlevel;
189 	ESHK->shd = doors[sh];
190 	ESHK->shk.x = sx;
191 	ESHK->shk.y = sy;
192 	ESHK->robbed = 0;
193 	ESHK->visitct = 0;
194 	ESHK->following = 0;
195 	shk->mgold = 1000 + 30 * rnd(100);	/* initial capital */
196 	ESHK->billct = 0;
197 	findname(ESHK->shknam, let);
198 	for (sx = sroom->lx; sx <= sroom->hx; sx++)
199 		for (sy = sroom->ly; sy <= sroom->hy; sy++) {
200 			struct monst   *mtmp;
201 			if ((sx == sroom->lx && doors[sh].x == sx - 1) ||
202 			    (sx == sroom->hx && doors[sh].x == sx + 1) ||
203 			    (sy == sroom->ly && doors[sh].y == sy - 1) ||
204 			    (sy == sroom->hy && doors[sh].y == sy + 1))
205 				continue;
206 			if (rn2(100) < dlevel && !m_at(sx, sy) &&
207 			    (mtmp = makemon(PM_MIMIC, sx, sy))) {
208 				mtmp->mimic = 1;
209 				mtmp->mappearance =
210 					(let && rn2(10) < dlevel) ? let : ']';
211 				continue;
212 			}
213 			(void) mkobj_at(let, sx, sy);
214 		}
215 }
216 
217 void
218 mkzoo(int type)
219 {
220 	struct mkroom  *sroom;
221 	struct monst   *mon;
222 	int             sh, sx, sy, i;
223 	int             goldlim = 500 * dlevel;
224 	int             moct = 0;
225 
226 	i = nroom;
227 	for (sroom = &rooms[rn2(nroom)];; sroom++) {
228 		if (sroom == &rooms[nroom])
229 			sroom = &rooms[0];
230 		if (!i-- || sroom->hx < 0)
231 			return;
232 		if (sroom->rtype)
233 			continue;
234 		if (type == MORGUE && sroom->rlit)
235 			continue;
236 		if (has_upstairs(sroom) || (has_dnstairs(sroom) && rn2(3)))
237 			continue;
238 		if (sroom->doorct == 1 || !rn2(5))
239 			break;
240 	}
241 	sroom->rtype = type;
242 	sh = sroom->fdoor;
243 	for (sx = sroom->lx; sx <= sroom->hx; sx++)
244 		for (sy = sroom->ly; sy <= sroom->hy; sy++) {
245 			if ((sx == sroom->lx && doors[sh].x == sx - 1) ||
246 			    (sx == sroom->hx && doors[sh].x == sx + 1) ||
247 			    (sy == sroom->ly && doors[sh].y == sy - 1) ||
248 			    (sy == sroom->hy && doors[sh].y == sy + 1))
249 				continue;
250 			mon = makemon(
251 				      (type == MORGUE) ? morguemon() :
252 				      (type == BEEHIVE) ? PM_KILLER_BEE : (struct permonst *) 0,
253 				      sx, sy);
254 			if (mon)
255 				mon->msleep = 1;
256 			switch (type) {
257 			case ZOO:
258 				i = sq(dist2(sx, sy, doors[sh].x, doors[sh].y));
259 				if (i >= goldlim)
260 					i = 5 * dlevel;
261 				goldlim -= i;
262 				mkgold((long) (10 + rn2(i)), sx, sy);
263 				break;
264 			case MORGUE:
265 				/*
266 				 * Usually there is one dead body in the
267 				 * morgue
268 				 */
269 				if (!moct && rn2(3)) {
270 					mksobj_at(CORPSE, sx, sy);
271 					moct++;
272 				}
273 				break;
274 			case BEEHIVE:
275 				if (!rn2(3))
276 					mksobj_at(LUMP_OF_ROYAL_JELLY, sx, sy);
277 				break;
278 			}
279 		}
280 }
281 
282 static const struct permonst *
283 morguemon(void)
284 {
285 	int             i = rn2(100), hd = rn2(dlevel);
286 
287 	if (hd > 10 && i < 10)
288 		return (PM_DEMON);
289 	if (hd > 8 && i > 85)
290 		return (PM_VAMPIRE);
291 	return ((i < 40) ? PM_GHOST : (i < 60) ? PM_WRAITH : PM_ZOMBIE);
292 }
293 
294 void
295 mkswamp(void)
296 {				/* Michiel Huisjes & Fred de Wilde */
297 	struct mkroom  *sroom;
298 	int             sx, sy, i, eelct = 0;
299 
300 	for (i = 0; i < 5; i++) {	/* 5 tries */
301 		sroom = &rooms[rn2(nroom)];
302 		if (sroom->hx < 0 || sroom->rtype ||
303 		    has_upstairs(sroom) || has_dnstairs(sroom))
304 			continue;
305 
306 		/* satisfied; make a swamp */
307 		sroom->rtype = SWAMP;
308 		for (sx = sroom->lx; sx <= sroom->hx; sx++)
309 			for (sy = sroom->ly; sy <= sroom->hy; sy++)
310 				if ((sx + sy) % 2 && !o_at(sx, sy) && !t_at(sx, sy)
311 				  && !m_at(sx, sy) && !nexttodoor(sx, sy)) {
312 					levl[sx][sy].typ = POOL;
313 					levl[sx][sy].scrsym = POOL_SYM;
314 					if (!eelct || !rn2(4)) {
315 						(void) makemon(PM_EEL, sx, sy);
316 						eelct++;
317 					}
318 				}
319 	}
320 }
321 
322 static int
323 nexttodoor(int sx, int sy)
324 {
325 	int		dx, dy;
326 	struct rm      *lev;
327 	for (dx = -1; dx <= 1; dx++)
328 		for (dy = -1; dy <= 1; dy++)
329 			if ((lev = &levl[sx + dx][sy + dy])->typ == DOOR ||
330 			    lev->typ == SDOOR || lev->typ == LDOOR)
331 				return (1);
332 	return (0);
333 }
334 
335 static int
336 has_dnstairs(struct mkroom *sroom)
337 {
338 	return (sroom->lx <= xdnstair && xdnstair <= sroom->hx &&
339 		sroom->ly <= ydnstair && ydnstair <= sroom->hy);
340 }
341 
342 static int
343 has_upstairs(struct mkroom *sroom)
344 {
345 	return (sroom->lx <= xupstair && xupstair <= sroom->hx &&
346 		sroom->ly <= yupstair && yupstair <= sroom->hy);
347 }
348 
349 static int
350 isbig(struct mkroom *sroom)
351 {
352 	int             area = (sroom->hx - sroom->lx) * (sroom->hy - sroom->ly);
353 	return (area > 20);
354 }
355 
356 static int
357 dist2(int x0, int y0, int x1, int y1)
358 {
359 	return ((x0 - x1) * (x0 - x1) + (y0 - y1) * (y0 - y1));
360 }
361 
362 static int
363 sq(int a)
364 {
365 	return (a * a);
366 }
367 #endif	/* QUEST */
368