Source:Hack 1.0/hack.zap.c

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

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= 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. }