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