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