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