]> git.cameronkatri.com Git - bsdgames-darwin.git/blob - hack/hack.trap.c
don't use char values for functions that can return -1; chars are not always
[bsdgames-darwin.git] / hack / hack.trap.c
1 /* $NetBSD: hack.trap.c,v 1.8 2009/06/07 18:30:39 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 <sys/cdefs.h>
65 #ifndef lint
66 __RCSID("$NetBSD: hack.trap.c,v 1.8 2009/06/07 18:30:39 dholland Exp $");
67 #endif /* not lint */
68
69 #include <stdlib.h>
70 #include "hack.h"
71 #include "extern.h"
72 #include "def.mkroom.h"
73
74 const char vowels[] = "aeiou";
75
76 const char *const traps[] = {
77 " bear trap",
78 "n arrow trap",
79 " dart trap",
80 " trapdoor",
81 " teleportation trap",
82 " pit",
83 " sleeping gas trap",
84 " piercer",
85 " mimic"
86 };
87
88 struct trap *
89 maketrap(int x, int y, int typ)
90 {
91 struct trap *ttmp;
92
93 ttmp = newtrap();
94 ttmp->ttyp = typ;
95 ttmp->tseen = 0;
96 ttmp->once = 0;
97 ttmp->tx = x;
98 ttmp->ty = y;
99 ttmp->ntrap = ftrap;
100 ftrap = ttmp;
101 return (ttmp);
102 }
103
104 void
105 dotrap(struct trap *trap)
106 {
107 int ttype = trap->ttyp;
108
109 nomul(0);
110 if (trap->tseen && !rn2(5) && ttype != PIT)
111 pline("You escape a%s.", traps[ttype]);
112 else {
113 trap->tseen = 1;
114 switch (ttype) {
115 case SLP_GAS_TRAP:
116 pline("A cloud of gas puts you to sleep!");
117 nomul(-rnd(25));
118 break;
119 case BEAR_TRAP:
120 if (Levitation) {
121 pline("You float over a bear trap.");
122 break;
123 }
124 u.utrap = 4 + rn2(4);
125 u.utraptype = TT_BEARTRAP;
126 pline("A bear trap closes on your foot!");
127 break;
128 case PIERC:
129 deltrap(trap);
130 if (makemon(PM_PIERCER, u.ux, u.uy)) {
131 pline("A piercer suddenly drops from the ceiling!");
132 if (uarmh)
133 pline("Its blow glances off your helmet.");
134 else
135 (void) thitu(3, d(4, 6), "falling piercer");
136 }
137 break;
138 case ARROW_TRAP:
139 pline("An arrow shoots out at you!");
140 if (!thitu(8, rnd(6), "arrow")) {
141 mksobj_at(ARROW, u.ux, u.uy);
142 fobj->quan = 1;
143 }
144 break;
145 case TRAPDOOR:
146 if (!xdnstair) {
147 pline("A trap door in the ceiling opens and a rock falls on your head!");
148 if (uarmh)
149 pline("Fortunately, you are wearing a helmet!");
150 losehp(uarmh ? 2 : d(2, 10), "falling rock");
151 mksobj_at(ROCK, u.ux, u.uy);
152 fobj->quan = 1;
153 stackobj(fobj);
154 if (Invisible)
155 newsym(u.ux, u.uy);
156 } else {
157 int newlevel = dlevel + 1;
158 while (!rn2(4) && newlevel < 29)
159 newlevel++;
160 pline("A trap door opens up under you!");
161 if (Levitation || u.ustuck) {
162 pline("For some reason you don't fall in.");
163 break;
164 }
165 goto_level(newlevel, FALSE);
166 }
167 break;
168 case DART_TRAP:
169 pline("A little dart shoots out at you!");
170 if (thitu(7, rnd(3), "little dart")) {
171 if (!rn2(6))
172 poisoned("dart", "poison dart");
173 } else {
174 mksobj_at(DART, u.ux, u.uy);
175 fobj->quan = 1;
176 }
177 break;
178 case TELEP_TRAP:
179 if (trap->once) {
180 deltrap(trap);
181 newsym(u.ux, u.uy);
182 vtele();
183 } else {
184 newsym(u.ux, u.uy);
185 tele();
186 }
187 break;
188 case PIT:
189 if (Levitation) {
190 pline("A pit opens up under you!");
191 pline("You don't fall in!");
192 break;
193 }
194 pline("You fall into a pit!");
195 u.utrap = rn1(6, 2);
196 u.utraptype = TT_PIT;
197 losehp(rnd(6), "fall into a pit");
198 selftouch("Falling, you");
199 break;
200 default:
201 impossible("You hit a trap of type %u", trap->ttyp);
202 }
203 }
204 }
205
206 int
207 mintrap(struct monst *mtmp)
208 {
209 struct trap *trap = t_at(mtmp->mx, mtmp->my);
210 int wasintrap = mtmp->mtrapped;
211
212 if (!trap) {
213 mtmp->mtrapped = 0; /* perhaps teleported? */
214 } else if (wasintrap) {
215 if (!rn2(40))
216 mtmp->mtrapped = 0;
217 } else {
218 int tt = trap->ttyp;
219 int in_sight = cansee(mtmp->mx, mtmp->my);
220
221 if (mtmp->mtrapseen & (1 << tt)) {
222 /* he has been in such a trap - perhaps he escapes */
223 if (rn2(4))
224 return (0);
225 }
226 mtmp->mtrapseen |= (1 << tt);
227 switch (tt) {
228 case BEAR_TRAP:
229 if (strchr(mlarge, mtmp->data->mlet)) {
230 if (in_sight)
231 pline("%s is caught in a bear trap!",
232 Monnam(mtmp));
233 else if (mtmp->data->mlet == 'o')
234 pline("You hear the roaring of an angry bear!");
235 mtmp->mtrapped = 1;
236 }
237 break;
238 case PIT:
239 /* there should be a mtmp/data -> floating */
240 if (!strchr("EywBfk'& ", mtmp->data->mlet)) { /* ab */
241 mtmp->mtrapped = 1;
242 if (in_sight)
243 pline("%s falls in a pit!", Monnam(mtmp));
244 }
245 break;
246 case SLP_GAS_TRAP:
247 if (!mtmp->msleep && !mtmp->mfroz) {
248 mtmp->msleep = 1;
249 if (in_sight)
250 pline("%s suddenly falls asleep!",
251 Monnam(mtmp));
252 }
253 break;
254 case TELEP_TRAP:
255 rloc(mtmp);
256 if (in_sight && !cansee(mtmp->mx, mtmp->my))
257 pline("%s suddenly disappears!",
258 Monnam(mtmp));
259 break;
260 case ARROW_TRAP:
261 if (in_sight) {
262 pline("%s is hit by an arrow!",
263 Monnam(mtmp));
264 }
265 mtmp->mhp -= 3;
266 break;
267 case DART_TRAP:
268 if (in_sight) {
269 pline("%s is hit by a dart!",
270 Monnam(mtmp));
271 }
272 mtmp->mhp -= 2;
273 /* not mondied here !! */
274 break;
275 case TRAPDOOR:
276 if (!xdnstair) {
277 mtmp->mhp -= 10;
278 if (in_sight)
279 pline("A trap door in the ceiling opens and a rock hits %s!", monnam(mtmp));
280 break;
281 }
282 if (mtmp->data->mlet != 'w') {
283 fall_down(mtmp);
284 if (in_sight)
285 pline("Suddenly, %s disappears out of sight.", monnam(mtmp));
286 return (2); /* no longer on this level */
287 }
288 break;
289 case PIERC:
290 break;
291 default:
292 impossible("Some monster encountered a strange trap.");
293 }
294 }
295 return (mtmp->mtrapped);
296 }
297
298 void
299 selftouch(const char *arg)
300 {
301 if (uwep && uwep->otyp == DEAD_COCKATRICE) {
302 pline("%s touch the dead cockatrice.", arg);
303 pline("You turn to stone.");
304 killer = objects[uwep->otyp].oc_name;
305 done("died");
306 }
307 }
308
309 void
310 float_up(void)
311 {
312 if (u.utrap) {
313 if (u.utraptype == TT_PIT) {
314 u.utrap = 0;
315 pline("You float up, out of the pit!");
316 } else {
317 pline("You float up, only your leg is still stuck.");
318 }
319 } else
320 pline("You start to float in the air!");
321 }
322
323 void
324 float_down(void)
325 {
326 struct trap *trap;
327 pline("You float gently to the ground.");
328 if ((trap = t_at(u.ux, u.uy)) != NULL)
329 switch (trap->ttyp) {
330 case PIERC:
331 break;
332 case TRAPDOOR:
333 if (!xdnstair || u.ustuck)
334 break;
335 /* fall into next case */
336 default:
337 dotrap(trap);
338 }
339 pickup(1);
340 }
341
342 void
343 vtele(void)
344 {
345 struct mkroom *croom;
346 for (croom = &rooms[0]; croom->hx >= 0; croom++)
347 if (croom->rtype == VAULT) {
348 int x, y;
349
350 x = rn2(2) ? croom->lx : croom->hx;
351 y = rn2(2) ? croom->ly : croom->hy;
352 if (teleok(x, y)) {
353 teleds(x, y);
354 return;
355 }
356 }
357 tele();
358 }
359
360 void
361 tele(void)
362 {
363 coord cc;
364 int nux, nuy;
365
366 if (Teleport_control) {
367 pline("To what position do you want to be teleported?");
368 cc = getpos(1, "the desired position"); /* 1: force valid */
369 /*
370 * possible extensions: introduce a small error if magic
371 * power is low; allow transfer to solid rock
372 */
373 if (teleok(cc.x, cc.y)) {
374 teleds(cc.x, cc.y);
375 return;
376 }
377 pline("Sorry ...");
378 }
379 do {
380 nux = rnd(COLNO - 1);
381 nuy = rn2(ROWNO);
382 } while (!teleok(nux, nuy));
383 teleds(nux, nuy);
384 }
385
386 void
387 teleds(int nux, int nuy)
388 {
389 if (Punished)
390 unplacebc();
391 unsee();
392 u.utrap = 0;
393 u.ustuck = 0;
394 u.ux = nux;
395 u.uy = nuy;
396 setsee();
397 if (Punished)
398 placebc(1);
399 if (u.uswallow) {
400 u.uswldtim = u.uswallow = 0;
401 docrt();
402 }
403 nomul(0);
404 if (levl[nux][nuy].typ == POOL && !Levitation)
405 drown();
406 (void) inshop();
407 pickup(1);
408 if (!Blind)
409 read_engr_at(u.ux, u.uy);
410 }
411
412 int
413 teleok(int x, int y)
414 { /* might throw him into a POOL */
415 return (isok(x, y) && !IS_ROCK(levl[x][y].typ) && !m_at(x, y) &&
416 !sobj_at(ENORMOUS_ROCK, x, y) && !t_at(x, y)
417 );
418 /* Note: gold is permitted (because of vaults) */
419 }
420
421 int
422 dotele(void)
423 {
424 if (
425 #ifdef WIZARD
426 !wizard &&
427 #endif /* WIZARD */
428 (!Teleportation || u.ulevel < 6 ||
429 (pl_character[0] != 'W' && u.ulevel < 10))) {
430 pline("You are not able to teleport at will.");
431 return (0);
432 }
433 if (u.uhunger <= 100 || u.ustr < 6) {
434 pline("You miss the strength for a teleport spell.");
435 return (1);
436 }
437 tele();
438 morehungry(100);
439 return (1);
440 }
441
442 void
443 placebc(int attach)
444 {
445 if (!uchain || !uball) {
446 impossible("Where are your chain and ball??");
447 return;
448 }
449 uball->ox = uchain->ox = u.ux;
450 uball->oy = uchain->oy = u.uy;
451 if (attach) {
452 uchain->nobj = fobj;
453 fobj = uchain;
454 if (!carried(uball)) {
455 uball->nobj = fobj;
456 fobj = uball;
457 }
458 }
459 }
460
461 void
462 unplacebc(void)
463 {
464 if (!carried(uball)) {
465 freeobj(uball);
466 unpobj(uball);
467 }
468 freeobj(uchain);
469 unpobj(uchain);
470 }
471
472 void
473 level_tele(void)
474 {
475 int newlevel;
476 if (Teleport_control) {
477 char buf[BUFSZ];
478
479 do {
480 pline("To what level do you want to teleport? [type a number] ");
481 getlin(buf);
482 } while (!digit(buf[0]) && (buf[0] != '-' || !digit(buf[1])));
483 newlevel = atoi(buf);
484 } else {
485 newlevel = 5 + rn2(20); /* 5 - 24 */
486 if (dlevel == newlevel) {
487 if (!xdnstair)
488 newlevel--;
489 else
490 newlevel++;
491 }
492 }
493 if (newlevel >= 30) {
494 if (newlevel > MAXLEVEL)
495 newlevel = MAXLEVEL;
496 pline("You arrive at the center of the earth ...");
497 pline("Unfortunately it is here that hell is located.");
498 if (Fire_resistance) {
499 pline("But the fire doesn't seem to harm you.");
500 } else {
501 pline("You burn to a crisp.");
502 dlevel = maxdlevel = newlevel;
503 killer = "visit to the hell";
504 done("burned");
505 }
506 }
507 if (newlevel < 0) {
508 newlevel = 0;
509 pline("You are now high above the clouds ...");
510 if (Levitation) {
511 pline("You float gently down to earth.");
512 done("escaped");
513 }
514 pline("Unfortunately, you don't know how to fly.");
515 pline("You fall down a few thousand feet and break your neck.");
516 dlevel = 0;
517 killer = "fall";
518 done("died");
519 }
520 goto_level(newlevel, FALSE); /* calls done("escaped") if
521 * newlevel==0 */
522 }
523
524 void
525 drown(void)
526 {
527 pline("You fall into a pool!");
528 pline("You can't swim!");
529 if (rn2(3) < u.uluck + 2) {
530 /* most scrolls become unreadable */
531 struct obj *obj;
532
533 for (obj = invent; obj; obj = obj->nobj)
534 if (obj->olet == SCROLL_SYM && rn2(12) > u.uluck)
535 obj->otyp = SCR_BLANK_PAPER;
536 /* we should perhaps merge these scrolls ? */
537
538 pline("You attempt a teleport spell."); /* utcsri!carroll */
539 (void) dotele();
540 if (levl[u.ux][u.uy].typ != POOL)
541 return;
542 }
543 pline("You drown ...");
544 killer = "pool of water";
545 done("drowned");
546 }