Wikihack
Advertisement

Below is the full text to hack.zap.c from the source code of Hack 1.0. To link to a particular line, write [[Hack 1.0/hack.zap.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

Screenshots and source code from Hack are used under the CWI license.
1.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
2.    
3.    #include "hack.h"
4.    
5.    extern struct monst *makemon();
6.    struct monst *bhit();
7.    char *exclam();
8.    
9.    char *fl[]= {
10.   	"magic missile",
11.   	"bolt of fire",
12.   	"sleep ray",
13.   	"bolt of cold",
14.   	"death ray"
15.   };
16.   
17.   dozap()
18.   {
19.   	register struct obj *obj;
20.   	register struct monst *mtmp;
21.   	xchar zx,zy;
22.   	register num;
23.   
24.   	obj = getobj("/", "zap");
25.   	if(!obj) return(0);
26.   	if(obj->spe < 0 || (obj->spe == 0 && rn2(121))) {
27.   		pline("Nothing Happens");
28.   		return(1);
29.   	}
30.   	if(obj->spe == 0)
31.   		pline("You wrest one more spell from the worn-out wand.");
32.   	if(!(objects[obj->otyp].bits & NODIR) && !getdir())
33.   		return(1); /* make him pay for knowing !NODIR */
34.   	obj->spe--;
35.   	if(objects[obj->otyp].bits & IMMEDIATE) {
36.   		if((u.uswallow && (mtmp = u.ustuck)) ||
37.   		   (mtmp = bhit(u.dx,u.dy,rn1(8,6),0))) {
38.   			wakeup(mtmp);
39.   			switch(obj->otyp) {
40.   			case WAN_STRIKING:
41.   				if(rnd(20) < 10+mtmp->data->ac) {
42.   					register int tmp = d(2,12);
43.   					hit("wand", mtmp, exclam(tmp));
44.   					mtmp->mhp -= tmp;
45.   					if(mtmp->mhp < 1) killed(mtmp);
46.   				} else miss("wand", mtmp);
47.   				break;
48.   			case WAN_SLOW_MONSTER:
49.   				mtmp->mspeed = MSLOW;
50.   				break;
51.   			case WAN_SPEED_MONSTER:
52.   				mtmp->mspeed = MFAST;
53.   				break;
54.   			case WAN_UNDEAD_TURNING:
55.   				if(index("WVZ&",mtmp->data->mlet)) {
56.   					mtmp->mhp -= rnd(8);
57.   					if(mtmp->mhp<1) killed(mtmp);
58.   					else mtmp->mflee = 1;
59.   				}
60.   				break;
61.   			case WAN_POLYMORPH:
62.   				if( newcham(mtmp,&mons[rn2(CMNUM)]) )
63.   					objects[obj->otyp].oc_name_known = 1;
64.   				break;
65.   			case WAN_CANCELLATION:
66.   				mtmp->mcan = 1;
67.   				break;
68.   			case WAN_TELEPORT_MONSTER:
69.   				rloc(mtmp);
70.   				break;
71.   			case WAN_MAKE_INVISIBLE:
72.   				mtmp->minvis = 1;
73.   				break;
74.   #ifdef WAN_PROBING
75.   			case WAN_PROBING:
76.   				mstatusline(mtmp);
77.   				break;
78.   #endif WAN_PROBING
79.   			default:
80.   				pline("What an interesting wand (%d)",
81.   					obj->otyp);
82.   				impossible();
83.   			}
84.   		}
85.   	} else {
86.   	switch(obj->otyp){
87.   		case WAN_LIGHT:
88.   			litroom(TRUE);
89.   			break;
90.   		case WAN_SECRET_DOOR_DETECTION:
91.   			if(!findit()) return(1);
92.   			break;
93.   		case WAN_CREATE_MONSTER:
94.   			{ register int cnt = 1;
95.   			if(!rn2(23)) cnt += rn2(7) + 1;
96.   			while(cnt--)
97.   			    (void) makemon((struct permonst *) 0, u.ux, u.uy);
98.   			}
99.   			break;
100.  		case WAN_WISHING:
101.  			{ char buf[BUFSZ];
102.  			  register struct obj *otmp;
103.  			  extern struct obj *readobjnam(), *addinv();
104.  		      if(u.uluck + rn2(5) < 0) {
105.  			pline("Unfortunately, nothing happens.");
106.  			break;
107.  		      }
108.  		      pline("You may wish for an object. What do you want? ");
109.  		      getlin(buf);
110.  		      otmp = readobjnam(buf);
111.  		      otmp = addinv(otmp);
112.  		      prinv(otmp);
113.  		      break;
114.  			}
115.  		case WAN_DIGGING:
116.  			{ register struct rm *room;
117.  			  register int digdepth;
118.  			if(u.uswallow) {
119.  				pline("You pierce %s's stomach wall!",
120.  					monnam(u.ustuck));
121.  				u.uswallow = 0;
122.  				mnexto(u.ustuck);
123.  				u.ustuck->mhp = 1;	/* almost dead */
124.  				u.ustuck = 0;
125.  				setsee();
126.  				docrt();
127.  				break;
128.  			}
129.  			zx = u.ux+u.dx;
130.  			zy = u.uy+u.dy;
131.  			if(!isok(zx,zy)) break;
132.  			digdepth = 4 + rn2(10);
133.  			if(levl[zx][zy].typ == CORR) num = CORR;
134.  			else num = ROOM;
135.  			Tmp_at(-1, '*');	/* open call */
136.  			while(digdepth--) {
137.  				if(zx == 0 || zx == COLNO-1 ||
138.  					 zy == 0 || zy == ROWNO-1)
139.  					break;
140.  				room = &levl[zx][zy];
141.  				Tmp_at(zx,zy);
142.  				if(!xdnstair){
143.  					if(zx < 3 || zx > COLNO-3 ||
144.  					    zy < 3 || zy > ROWNO-3)
145.  						break;
146.  					if(room->typ == HWALL ||
147.  					    room->typ == VWALL){
148.  						room->typ = ROOM;
149.  						break;
150.  					}
151.  				} else if(num == ROOM || num == 10){
152.  					if(room->typ != ROOM && room->typ) {
153.  						if(room->typ != CORR)
154.  							room->typ = DOOR;
155.  						if(num == 10) break;
156.  						num = 10;
157.  					} else if(!room->typ)
158.  						room->typ = CORR;
159.  				} else {
160.  					if(room->typ != CORR && room->typ) {
161.  						room->typ = DOOR;
162.  						break;
163.  					} else room->typ = CORR;
164.  				}
165.  				mnewsym(zx,zy);
166.  				zx += u.dx;
167.  				zy += u.dy;
168.  			}
169.  			mnewsym(zx,zy);	/* not always necessary */
170.  			Tmp_at(-1,-1);	/* closing call */
171.  			break;
172.  			}
173.  		default:
174.  			buzz((int) obj->otyp - WAN_MAGIC_MISSILE,
175.  				u.ux, u.uy, u.dx, u.dy);
176.  			break;
177.  		}
178.  		if(!objects[obj->otyp].oc_name_known) {
179.  			u.urexp += 10;
180.  			objects[obj->otyp].oc_name_known = 1;
181.  		}
182.  	}
183.   return(1);
184.  }
185.  
186.  char *
187.  exclam(force)
188.  register int force;
189.  {
190.  	/* force == 0 occurs e.g. with sleep ray */
191.  	/* note that large force is usual with wands so that !! would
192.  		require information about hand/weapon/wand */
193.  	return( (force < 0) ? "?" : (force <= 4) ? "." : "!" );
194.  }
195.  
196.  hit(str,mtmp,force)
197.  register char *str;
198.  register struct monst *mtmp;
199.  register char *force;		/* usually either "." or "!" */
200.  {
201.  	if(!cansee(mtmp->mx,mtmp->my)) pline("The %s hits it.", str);
202.  	else pline("The %s hits %s%s", str, monnam(mtmp), force);
203.  }
204.  
205.  miss(str,mtmp)
206.  register char *str;
207.  register struct monst *mtmp;
208.  {
209.  	if(!cansee(mtmp->mx,mtmp->my)) pline("The %s misses it.",str);
210.  	else pline("The %s misses %s.",str,monnam(mtmp));
211.  }
212.  
213.  /* sets bhitpos to the final position of the weapon thrown */
214.  /* coord bhitpos; */
215.  
216.  /* check !u.uswallow before calling bhit() */
217.  struct monst *
218.  bhit(ddx,ddy,range,sym)
219.  register ddx,ddy,range;
220.  char sym;
221.  {
222.  	register struct monst *mtmp;
223.  
224.  	bhitpos.x = u.ux;
225.  	bhitpos.y = u.uy;
226.  
227.  	if(sym) tmp_at(-1, sym);	/* open call */
228.  	while(range--) {
229.  		bhitpos.x += ddx;
230.  		bhitpos.y += ddy;
231.  		if(mtmp = m_at(bhitpos.x,bhitpos.y)){
232.  			if(sym) tmp_at(-1, -1);	/* close call */
233.  			return(mtmp);
234.  		}
235.  		if(levl[bhitpos.x][bhitpos.y].typ<CORR) {
236.  			bhitpos.x -= ddx;
237.  			bhitpos.y -= ddy;
238.  			break;
239.  		}
240.   if(sym) tmp_at(bhitpos.x, bhitpos.y);
241.  	}
242.  	if(sym) tmp_at(-1, 0);	/* leave last symbol */
243.  	return(0);
244.  }
245.  
246.  struct monst *
247.  boomhit(dx,dy) {
248.  	register int i, ct;
249.  	register struct monst *mtmp;
250.  	char sym = ')';
251.  	extern schar xdir[], ydir[];
252.  
253.  	bhitpos.x = u.ux;
254.  	bhitpos.y = u.uy;
255.  
256.  	for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break;
257.  	tmp_at(-1, sym);	/* open call */
258.  	for(ct=0; ct<10; ct++) {
259.  		if(i == 8) i = 0;
260.  		sym = ')' + '(' - sym;
261.  		tmp_at(-2, sym);	/* change let call */
262.  		dx = xdir[i];
263.  		dy = ydir[i];
264.  		bhitpos.x += dx;
265.  		bhitpos.y += dy;
266.  		if(mtmp = m_at(bhitpos.x, bhitpos.y)){
267.  			tmp_at(-1,-1);
268.  			return(mtmp);
269.  		}
270.  		if(levl[bhitpos.x][bhitpos.y].typ<CORR) {
271.  			bhitpos.x -= dx;
272.  			bhitpos.y -= dy;
273.  			break;
274.  		}
275.  		if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
276.  			if(rn2(20) >= 10+u.ulevel){	/* we hit ourselves */
277.  				(void) thitu(10, rnd(10), "boomerang");
278.  				break;
279.  			} else {	/* we catch it */
280.  				tmp_at(-1,-1);
281.  				pline("Skillfully, you catch the boomerang.");
282.  				return((struct monst *) -1);
283.  			}
284.  		}
285.  		tmp_at(bhitpos.x, bhitpos.y);
286.  		if(ct % 5 != 0) i++;
287.  	}
288.  	tmp_at(-1, -1);	/* do not leave last symbol */
289.  	return(0);
290.  }
291.  
292.  char
293.  dirlet(dx,dy) register dx,dy; {
294.  	return
295.  		(dx == dy) ? '\\' : (dx && dy) ? '/' : dx ? '-' : '|';
296.  }
297.  
298.  /* type < 0: monster spitting fire at you */
299.  buzz(type,sx,sy,dx,dy)
300.  register int type;
301.  register xchar sx,sy;
302.  register int dx,dy;
303.  {
304.  	register char *fltxt = (type < 0) ? "blaze of fire" : fl[type];
305.  	struct rm *lev;
306.  	xchar range;
307.  	struct monst *mon;
308.  
309.  	if(u.uswallow) {
310.  		register int tmp;
311.  
312.  		if(type < 0) return;
313.  		tmp = zhit(u.ustuck, type);
314.  		pline("The %s rips into %s%s",
315.  			fltxt, monnam(u.ustuck), exclam(tmp));
316.  		return;
317.  	}
318.  	if(type < 0) pru();
319.  	range = rn1(7,7);
320.  	Tmp_at(-1, dirlet(dx,dy));	/* open call */
321.  	while(range-- > 0) {
322.  		sx += dx;
323.  		sy += dy;
324.  		if((lev = &levl[sx][sy])->typ) Tmp_at(sx,sy);
325.  		else {
326.  			int bounce = 0;
327.  			if(cansee(sx-dx,sy-dy)) pline("The %s bounces!",fltxt);
328.  			if(levl[sx][sy-dy].typ > DOOR) bounce = 1;
329.  			if(levl[sx-dx][sy].typ > DOOR) {
330.  				if(!bounce || rn2(2)) bounce = 2;
331.  			}
332.  			switch(bounce){
333.  			case 0:
334.  				dx = -dx;
335.  				dy = -dy;
336.  				continue;
337.  			case 1:
338.  				dy = -dy;
339.  				sx -= dx;
340.  				break;
341.  			case 2:
342.  				dx = -dx;
343.  				sy -= dy;
344.  				break;
345.  			}
346.  			Tmp_at(-2,dirlet(dx,dy));
347.  			continue;
348.  		}
349.  		if((mon = m_at(sx,sy)) &&
350.  		   (type >= 0 || mon->data->mlet != 'D')) {
351.  			wakeup(mon);
352.  			if(rnd(20) < 18 + mon->data->ac) {
353.  				register int tmp = zhit(mon,type);
354.  				if(mon->mhp < 1) {
355.  					if(type < 0) {
356.  					    if(cansee(mon->mx,mon->my))
357.  					      pline("%s is killed by the %s!",
358.  						Monnam(mon), fltxt);
359.  					    mondied(mon);
360.  					} else
361.  					    killed(mon);
362.  				} else
363.  					hit(fltxt, mon, exclam(tmp));
364.  				range -= 2;
365.  			} else
366.   miss(fltxt,mon);
367.  		} else if(sx == u.ux && sy == u.uy) {
368.  			if(rnd(20) < 18+u.uac) {
369.  				register int dam = 0;
370.  				range -= 2;
371.  				pline("The %s hits you!",fltxt);
372.  				switch(type) {
373.  				case 0:
374.  					dam = d(2,6);
375.  					break;
376.  				case -1:	/* dragon fire */
377.  				case 1:
378.  					if(Fire_resistance)
379.  						pline("You don't feel hot!");
380.  					else dam = d(6,6);
381.  					break;
382.  				case 2:
383.  					nomul(-rnd(25)); /* sleep ray */
384.  					break;
385.  				case 3:
386.  					if(Cold_resistance)
387.  						pline("You don't feel cold!");
388.  					else dam = d(6,6);
389.  					break;
390.  				case 4:
391.  					u.uhp = -1;
392.  				}
393.   losehp(dam,fltxt);
394.  			} else pline("The %s whizzes by you!",fltxt);
395.  		}
396.  		if(lev->typ <= DOOR) {
397.  			int bounce = 0, rmn;
398.  			if(cansee(sx,sy)) pline("The %s bounces!",fltxt);
399.  			range--;
400.  			if(!dx || !dy || !rn2(20)){
401.  				dx = -dx;
402.  				dy = -dy;
403.  			} else {
404.  			  if((rmn = levl[sx][sy-dy].typ) > DOOR &&
405.  			    (
406.  			     rmn >= ROOM ||
407.  				levl[sx+dx][sy-dy].typ > DOOR)){
408.  				bounce = 1;
409.  			  }
410.  			  if((rmn = levl[sx-dx][sy].typ) > DOOR &&
411.  			    (
412.  			     rmn >= ROOM ||
413.  				levl[sx-dx][sy+dy].typ > DOOR)){
414.  				if(!bounce || rn2(2)){
415.  					bounce = 2;
416.  				}
417.  			  }
418.  			  switch(bounce){
419.  			  case 0:
420.  				dy = -dy;
421.  				dx = -dx;
422.  				break;
423.  			  case 1:
424.  				dy = -dy;
425.  				break;
426.  			  case 2:
427.  				dx = -dx;
428.  				break;
429.  			  }
430.  			  Tmp_at(-2, dirlet(dx,dy));
431.  			}
432.  		}
433.  	}
434.   Tmp_at(-1,-1);
435.  }
436.  
437.  zhit(mon,type)			/* returns damage to mon */
438.  register struct monst *mon;
439.  register type;
440.  {
441.  	register int tmp = 0;
442.  
443.  	switch(type) {
444.  	case 0:			/* magic missile */
445.  		tmp = d(2,6);
446.  		break;
447.  	case -1:		/* Dragon blazing fire */
448.  	case 1:			/* fire */
449.  		if(index("Dg", mon->data->mlet)) break;
450.  		tmp = d(6,6);
451.  		if(mon->data->mlet == 'Y') tmp += 7;
452.  		break;
453.  	case 2:			/* sleep*/
454.  		mon->mfroz = 1;
455.  		break;
456.  	case 3:			/* cold */
457.  		if(index("YFgf", mon->data->mlet)) break;
458.  		tmp = d(6,6);
459.  		if(mon->data->mlet == 'D') tmp += 7;
460.  		break;
461.  	case 4:			/* death*/
462.  		if(index("WVZ",mon->data->mlet)) break;
463.  		tmp = mon->mhp+1;
464.  		break;
465.  	}
466.  	mon->mhp -= tmp;
467.  	return(tmp);
468.  }
Advertisement