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