Source:Hack 1.0/hack.c

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

Note: for the latest version, see Source code

1.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */ 2.     3.    #include "hack.h"  4.    #include   5. 6.    7.    extern char news0; 8.   extern char *nomovemsg; 9.   extern char *exclam; 10.  extern struct obj *addinv; 11.  extern boolean hmon; 12.   13.    14.    15.   /* called on movement: 16.  	1. when throwing ball+chain far away 17.  	2. when teleporting 18.  	3. when walking out of a lit room 19.   */  20.   unsee { 21.  	register x,y; 22.  	register struct rm *lev; 23.   24.   /*  25.   	if(u.udispl){ 26.  		u.udispl = 0; 27.  		newsym(u.udisx, u.udisy); 28.  	}  29.   */  30.   #ifndef QUEST 31.  	if(seehx){ 32.  		seehx = 0; 33.  	} else 34.  #endif QUEST 35.  	for(x = u.ux-1; x < u.ux+2; x++) 36.  	  for(y = u.uy-1; y < u.uy+2; y++) { 37.  		lev = &levl[x][y]; 38.  		if(!lev->lit && lev->scrsym == '.') { 39.  			lev->scrsym =' '; 40.  			lev->new = 1; 41.  			on_scr(x,y); 42.  		}  43.   	}  44.   }  45.    46.   /* called: 47.  	in hack.eat.c: seeoff(0) - blind after eating rotten food 48.  	in hack.mon.c: seeoff(0) - blinded by a yellow light 49.  	in hack.mon.c: seeoff(1) - swallowed 50.  	in hack.do.c:  seeoff(0) - blind after drinking potion 51.  	in hack.do.c:  seeoff(1) - go up or down the stairs 52.  	in hack.trap.c:seeoff(1) - fall through trapdoor 53.   */  54.   seeoff(mode)	/* 1 to redo @, 0 to leave them */ 55.  {	/* 1 means misc movement, 0 means blindness */ 56.  	register x,y; 57.  	register struct rm *lev; 58.   59.   	if(u.udispl && mode){ 60.  		u.udispl = 0; 61.  		levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy); 62.  	}  63.   #ifndef QUEST 64.  	if(seehx) { 65.  		seehx = 0; 66.  	} else 67.  #endif QUEST 68.  	if(!mode) { 69.  		for(x = u.ux-1; x < u.ux+2; x++) 70.  			for(y = u.uy-1; y < u.uy+2; y++) { 71.  				lev = &levl[x][y]; 72.  				if(!lev->lit && lev->scrsym == '.') 73.  					lev->seen = 0; 74.  			}  75.   	}  76.   }  77.    78.   /* 'rogue'-like direction commands */ 79.  char sdir[] = "hykulnjb"; 80.  schar xdir[8] = { -1,-1,0,1,1,1,0,-1 }; 81.  schar ydir[8] = { 0,-1,-1,-1,0,1,1,1 }; 82.   83.   movecm(cmd) 84.  register char *cmd; 85.  {  86.   register char *dp; 87.  		if(!(dp = index(sdir, *cmd))) return(0); 88.  		u.dx = xdir[dp-sdir]; 89.  		u.dy = ydir[dp-sdir]; 90.  		return(1); 91.  }  92.    93.   #ifdef QUEST 94.  finddir{ 95.  register int i, ui = u.di; 96.  	for(i = 0; i <= 8; i++){ 97.  		if(flags.run & 1) ui++; else ui += 7; 98.  		ui %= 8; 99.  		if(i == 8){ 100. 			pline("Not near a wall."); 101. 			flags.move = multi = 0; 102. 			return(0); 103. 		}  104.  		if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui])) 105. 			break; 106. 	}  107.  	for(i = 0; i <= 8; i++){ 108. 		if(flags.run & 1) ui += 7; else ui++; 109. 		ui %= 8; 110. 		if(i == 8){ 111. 			pline("Not near a room."); 112. 			flags.move = multi = 0; 113. 			return(0); 114. 		}  115.  		if(isroom(u.ux+xdir[ui], u.uy+ydir[ui])) 116. 			break; 117. 	}  118.  	u.di = ui; 119. 	u.dx = xdir[ui]; 120. 	u.dy = ydir[ui]; 121. }  122.   123.  isroom(x,y)  register x,y; { 124. 	return(isok(x,y) && (levl[x][y].typ == ROOM || 125. 				(levl[x][y].typ >= LDOOR && flags.run >= 6))); 126. }  127.  #endif QUEST 128.  129.  isok(x,y) register x,y; { 130. 	return(x >= 0 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1); 131. }  132.   133.  domove 134. {  135.  	xchar oldx,oldy; 136. 	register struct monst *mtmp; 137. 	register struct rm *tmpr,*ust; 138. 	struct gen *trap; 139. 	register struct obj *otmp; 140.  141.  	wipe_engr_at(u.ux, u.uy, rnd(5)); 142. 	if(inv_weight > 0){ 143. 		pline("You collapse under your load."); 144. 		nomul(0); 145. 		return; 146. 	}  147.  	if(Confusion) { 148. 		do { 149. 			u.dx = rn1(3,-1); 150. 			u.dy = rn1(3,-1); 151. 			tmpr = &levl[u.ux+u.dx][u.uy+u.dy]; 152. 		} while((!u.dx && !u.dy) ||  153.   !isok(u.ux+u.dx, u.uy+u.dy) || tmpr->typ < DOOR); 154. 	} else tmpr = &levl[u.ux+u.dx][u.uy+u.dy]; 155. 	if(!isok(u.ux+u.dx, u.uy+u.dy)){ 156. 		nomul(0); 157. 		return; 158. 	}  159.   160.  	ust = &levl[u.ux][u.uy]; 161. 	oldx = u.ux; 162. 	oldy = u.uy; 163. 	if(!u.uswallow) 164. 	    if(trap = g_at(u.ux+u.dx,u.uy+u.dy,ftrap)) { 165. 		if(trap->gflag & SEEN) nomul(0); 166. 	}  167.  	if(u.ustuck && !u.uswallow && (u.ux+u.dx != u.ustuck->mx || 168. 		u.uy+u.dy != u.ustuck->my)) { 169. 		if(dist(u.ustuck->mx, u.ustuck->my) > 2){ 170. 			/* perhaps it fled (or was teleported or ... ) */ 171. 			u.ustuck = 0; 172. 		} else { 173. 			if(Blind) pline("You cannot escape from it!"); 174. 			else pline("You cannot escape from %s!.",  175.  				monnam(u.ustuck)); 176. 			nomul(0); 177. 			return; 178. 		}  179.  	}  180.  	if((mtmp = m_at(u.ux+u.dx,u.uy+u.dy)) || u.uswallow) { 181. 	/* attack monster */ 182. 		schar tmp; 183. 		boolean malive = TRUE; 184. 		register struct permonst *mdat; 185.  186.  		nomul(0); 187. 		gethungry; 188. 		if(multi < 0) return;	/* we just fainted */ 189. 		if(u.uswallow) mtmp = u.ustuck; 190. 		mdat = mtmp->data; 191. 		if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep &&  192.  		   !mtmp->mconf && mtmp->mcansee && !rn2(7) &&  193.  		   (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */ 194. 			mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy)) 195. 			goto nomon; 196. 		if(mtmp->mimic){ 197. 			if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp; 198. 			switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){ 199. 			case '+': 200. 				pline("The door actually was a Mimic."); 201. 				break; 202. 			case '$': 203. 				pline("The chest was a Mimic!"); 204. 				break; 205. 			default: 206. 				pline("Wait! That's a Mimic!"); 207. 			}  208.  			wakeup(mtmp);	/* clears mtmp->mimic */ 209. 			return; 210. 		}  211.  		wakeup(mtmp);	/* clears mtmp->mimic */ 212. 		if(mtmp->mhide && mtmp->mundetected){ 213. 			register struct obj *obj; 214. 			mtmp->mundetected = 0; 215. 			if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind) 216. 				pline("Wait! There's a %s hiding under %s!",  217.  					mdat->mname, doname(obj)); 218. 			return; 219. 		}  220.  		tmp = u.uluck + u.ulevel + mdat->ac + abon; 221. 		if(uwep) { 222. 			if(uwep->olet == WEAPON_SYM) 223. 				tmp += uwep->spe; 224. 			if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1; 225. 			else if(uwep->otyp == DAGGER) tmp += 2; 226. 			else if(uwep->otyp == CRYSKNIFE) tmp += 3; 227. 			else if(uwep->otyp == SPEAR &&  228.  				index("XDne", mdat->mlet)) tmp += 2; 229. 		}  230.  		if(mtmp->msleep) { 231. 			mtmp->msleep = 0; 232. 			tmp += 2; 233. 		}  234.  		if(mtmp->mfroz) { 235. 			tmp += 4; 236. 			if(!rn2(10)) mtmp->mfroz = 0; 237. 		}  238.  		if(mtmp->mflee) tmp += 2; 239. 		if(u.utrap) tmp -= 3; 240. 		if(tmp <= rnd(20) && !u.uswallow){ 241. 			if(Blind) pline("You miss it."); 242. 			else pline("You miss %s.",monnam(mtmp)); 243. 		} else { 244. 			/* we hit the monster; be careful: it might die! */ 245.   246.  			if((malive = hmon(mtmp,uwep,0)) == TRUE) { 247. 				/* monster still alive */ 248. 				if(!rn2(25) && mtmp->mhp < mtmp->orig_hp/2) { 249. 					mtmp->mflee = 1; 250. 					if(u.ustuck == mtmp && !u.uswallow) 251. 						u.ustuck = 0; 252. 				}  253.  #ifndef NOWORM 254. 				if(mtmp->wormno) 255. 					cutworm(mtmp, u.ux+u.dx, u.uy+u.dy,  256.  						uwep ? uwep->otyp : 0); 257. #endif NOWORM 258. 			}  259.  			if(mdat->mlet == 'a') { 260. 				if(rn2(2)) { 261. 				pline("You are splashed by the blob's acid!"); 262. 					losehp_m(rnd(6), mtmp); 263. 				}  264.  				if(!rn2(6)) corrode_weapon; 265. 				else if(!rn2(60)) corrode_armor; 266. 			}  267.  		}  268.  		if(malive && !Blind && mdat->mlet == 'E' && rn2(3)) { 269. 		    if(mtmp->mcansee) { 270. 		      pline("You are frozen by the floating eye's gaze!"); 271. 		      nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200); 272. 		    } else { 273. 		      pline("The blinded floating eye cannot defend itself."); 274. 		      if(!rn2(500)) u.uluck--; 275. 		    }  276.  		}  277.   return; 278. 	}  279.  nomon: 280. 	/* not attacking an animal, so we try to move */ 281. 	if(u.utrap) { 282. 		if(u.utraptype == TT_PIT) { 283. 			pline("You are still in a pit."); 284. 			u.utrap--; 285. 		} else { 286. 			pline("You are caught in a beartrap."); 287. 			if((u.dx && u.dy) || !rn2(5)) u.utrap--; 288. 		}  289.   return; 290. 	}  291.  	if((tmpr->typ < DOOR) ||  292.  	   (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))){ 293. 		flags.move = 0; 294. 		nomul(0); 295. 		return; 296. 	}  297.  	while(otmp = sobj_at(ENORMOUS_ROCK, u.ux+u.dx, u.uy+u.dy)) { 298. 		register xchar rx = u.ux+2*u.dx, ry = u.uy+2*u.dy; 299. 		register struct gen *gtmp; 300. 		nomul(0); 301. 		if(isok(rx,ry) && (levl[rx][ry].typ > DOOR || 302. 		    (levl[rx][ry].typ == DOOR && (!u.dx || !u.dy)))) { 303. 			if(m_at(rx,ry)) { 304. 			    pline("You hear a monster behind the rock."); 305. 			    pline("Perhaps that's why you cannot move it."); 306. 			    return; 307. 			}  308.  			if(gtmp = g_at(rx,ry,ftrap)) 309. #include	"def.trap.h"  310. switch(gtmp->gflag & ~SEEN) { 311. 			    case PIT: 312. 				pline("You push the rock into a pit!"); 313. 				deltrap(gtmp); 314. 				delobj(otmp); 315. 				pline("It completely fills the pit!"); 316. 				continue; 317. 			    case TELEP_TRAP: 318. 				pline("You push the rock and suddenly it disappears!"); 319. 				delobj(otmp); 320. 				continue; 321. 			    }  322.  			otmp->ox = rx; 323. 			otmp->oy = ry; 324. 			/* pobj(otmp); */ 325. 			if(cansee(rx,ry)) atl(rx,ry,otmp->olet); 326. 			if(Invis) newsym(u.ux+u.dx, u.uy+u.dy); 327.  328.  			{ static int lastmovetime; 329. 			/* note: this var contains garbage initially and 330. 			   after a restore */ 331. 			if(moves > lastmovetime+2 || moves < lastmovetime) 332. 			pline("With great effort you move the enormous rock."); 333. 			lastmovetime = moves; 334. 			}  335.  		} else { 336. 		    pline("You try to move the enormous rock, but in vain."); 337. 		    return; 338. 		}  339.  	    }  340.  	if(u.dx && u.dy && levl[u.ux][u.uy+u.dy].typ < DOOR &&  341.  		levl[u.ux+u.dx][u.uy].typ < DOOR &&  342.  		invent && inv_weight+40 > 0) { 343. 		pline("You are carrying too much to get through."); 344. 		nomul(0); 345. 		return; 346. 	}  347.  	if(Punished &&  348.  	   DIST(u.ux+u.dx, u.uy+u.dy, uchain->ox, uchain->oy) > 2){ 349. 		if(carried(uball)) { 350. 			movobj(uchain, u.ux, u.uy); 351. 			goto nodrag; 352. 		}  353.   354.  		if(DIST(u.ux+u.dx, u.uy+u.dy, uball->ox, uball->oy) < 3){ 355. 			/* leave ball, move chain under/over ball */ 356. 			movobj(uchain, uball->ox, uball->oy); 357. 			goto nodrag; 358. 		}  359.   360.  		if(inv_weight + (int) uball->owt/2 > 0) { 361. 			pline("You cannot %sdrag the heavy iron ball.",  362.  			invent ? "carry all that and also " : ""); 363. 			nomul(0); 364. 			return; 365. 		}  366.   367.  		movobj(uball, uchain->ox, uchain->oy); 368. 		unpobj(uball);		/* BAH %% */ 369. 		uchain->ox = u.ux; 370. 		uchain->oy = u.uy; 371. 		nomul(-2); 372. 		nomovemsg = ""; 373. 	nodrag:	; 374. 	}  375.  	u.ux += u.dx; 376. 	u.uy += u.dy; 377. 	if(flags.run) { 378. 		if(tmpr->typ == DOOR ||  379.  		(xupstair == u.ux && yupstair == u.uy) ||  380.  		(xdnstair == u.ux && ydnstair == u.uy)) 381. 			nomul(0); 382. 	}  383.  /*  384.  	if(u.udispl) { 385. 		u.udispl = 0; 386. 		newsym(oldx,oldy); 387. 	}  388.  */  389.  	if(!Blind) { 390. #ifdef QUEST 391. 		setsee; 392. #else 393. 		if(ust->lit) { 394. 			if(tmpr->lit) { 395. 				if(tmpr->typ == DOOR) prl1(u.ux+u.dx,u.uy+u.dy); 396. 				else if(ust->typ == DOOR) nose1(oldx-u.dx,oldy-u.dy); 397. 			} else { 398. 				unsee; 399. 				prl1(u.ux+u.dx,u.uy+u.dy); 400. 			}  401.  		} else { 402. 			if(tmpr->lit) setsee; 403. 			else { 404. 				prl1(u.ux+u.dx,u.uy+u.dy); 405. 				if(tmpr->typ == DOOR) { 406. 					if(u.dy) { 407. 						prl(u.ux-1,u.uy); 408. 						prl(u.ux+1,u.uy); 409. 					} else { 410. 						prl(u.ux,u.uy-1); 411. 						prl(u.ux,u.uy+1); 412. 					}  413.  				}  414.  			}  415.   nose1(oldx-u.dx,oldy-u.dy); 416. 		}  417.   #endif QUEST 418. 	} else { 419.  pru; 420. 	}  421.  	if(!flags.nopick) pickup; 422. 	if(trap) dotrap(trap);		/* fall into pit, arrow trap, etc. */ 423. 	(void) inshop; 424. 	if(!Blind) read_engr_at(u.ux,u.uy); 425. }  426.   427.  movobj(obj, ox, oy) 428. register struct obj *obj; 429. register int ox, oy; 430. {  431.  	/* Some dirty programming to get display right */ 432. 	freeobj(obj); 433. 	unpobj(obj); 434. 	obj->nobj = fobj; 435. 	fobj = obj; 436. 	obj->ox = ox; 437. 	obj->oy = oy; 438. }  439.   440.  pickup{ 441. register struct gen *gold; 442. register struct obj *obj, *obj2; 443. register int wt; 444. 	if(Levitation) return; 445. 	while(gold = g_at(u.ux,u.uy,fgold)) { 446. 		pline("%u gold piece%s.", gold->gflag, plur(gold->gflag)); 447. 		u.ugold += gold->gflag; 448. 		flags.botl = 1; 449. 		freegold(gold); 450. 		if(flags.run) nomul(0); 451. 		if(Invis) newsym(u.ux,u.uy); 452. 	}  453.  	for(obj = fobj; obj; obj = obj2) { 454. 	    obj2 = obj->nobj;	/* perhaps obj will be picked up */ 455. 	    if(obj->ox == u.ux && obj->oy == u.uy) { 456. 		if(flags.run) nomul(0); 457.  458.  #define	DEAD_c	CORPSE+('c'-'a'+'Z'-'@'+1) 459. 		if(obj->otyp == DEAD_COCKATRICE && !uarmg){ 460. 		    pline("Touching the dead cockatrice is a fatal mistake."); 461. 		    pline("You turn to stone."); 462. 		    killer = "cockatrice cadaver"; 463. 		    done("died"); 464. 		}  465.   466.  		if(obj->otyp == SCR_SCARE_MONSTER){ 467. 		  if(!obj->spe) obj->spe = 1; 468. 		  else { 469. 		    /* Note: perhaps the 1st pickup failed: you cannot 470. 			carry anymore, and so we never dropped it - 471. 			let's assume that treading on it twice also 472. 			destroys the scroll */ 473. 		    pline("The scroll turns to dust as you pick it up."); 474. 		    delobj(obj); 475. 		    continue; 476. 		  }  477.  		}  478.   479.  		/* do not pick up uchain */ 480. 		if(Punished && obj == uchain) 481. 			continue; 482.  483.  		wt = inv_weight + obj->owt; 484. 		if(wt > 0) { 485. 			if(obj->quan > 1) { 486. 				/* see how many we can lift */ 487. 				extern struct obj *splitobj; 488. 				int savequan = obj->quan; 489. 				int iw = inv_weight; 490. 				int qq; 491. 				for(qq = 1; qq < savequan; qq++){ 492. 					obj->quan = qq; 493. 					if(iw + weight(obj) > 0) 494. 						break; 495. 				}  496.  				obj->quan = savequan; 497. 				qq--; 498. 				/* we can carry qq of them */ 499. 				if(!qq) goto too_heavy; 500. 			pline("You can only carry %s of the %s lying here.",  501.  					(qq == 1) ? "one" : "some",  502.  					doname(obj)); 503. 				(void) splitobj(obj, qq); 504. 				/* note: obj2 is set already, so we'll never 505. 				 * encounter the other half; if it should be  506. * otherwise then write 507. 				 *	obj2 = splitobj(obj,qq); 508. 				 */  509.  				goto lift_some; 510. 			}  511.  		too_heavy: 512. 			pline("There %s %s here, but %s.",  513.  				(obj->quan == 1) ? "is" : "are",  514.  				doname(obj),  515.  				!invent ? "it is too heavy for you to lift"  516.  					: "you cannot carry anymore"); 517. 			break; 518. 		}  519.  	lift_some: 520. 		if(inv_cnt >= 52) { 521. 		    pline("Your knapsack cannot accomodate anymore items."); 522. 		    break; 523. 		}  524.  		if(wt > -5) pline("You have a little trouble lifting"); 525. 		freeobj(obj); 526. 		if(Invis) newsym(u.ux,u.uy); 527. 		addtobill(obj);       /* sets obj->unpaid if necessary */ 528. 		{ int pickquan = obj->quan; 529. 		  int mergquan; 530. 		if(!Blind) obj->dknown = 1;	/* this is done by prinv, 531. 				 but addinv needs it already for merging */ 532. 		obj = addinv(obj);    /* might merge it with other objects */ 533. 		  mergquan = obj->quan; 534. 		  obj->quan = pickquan;	/* to fool prinv */ 535. 		prinv(obj); 536. 		  obj->quan = mergquan; 537. 		}  538.    }  539.  	}  540.  }  541.   542.  /* stop running if we see something interesting */ 543. /* turn around a corner if that is the only way we can proceed */ 544. /* do not turn left or right twice */ 545. lookaround{ 546. register x,y,i,x0,y0,m0,i0 = 9; 547. register int corrct = 0, noturn = 0; 548. register struct monst *mtmp; 549. #ifdef lint 550. 	/* suppress "used before set" message */ 551. 	x0 = y0 = 0; 552. #endif lint 553. 	if(Blind || flags.run == 0) return; 554. 	if(flags.run == 1 && levl[u.ux][u.uy].typ >= ROOM) return; 555. #ifdef QUEST 556. 	if(u.ux0 == u.ux+u.dx && u.uy0 == u.uy+u.dy) goto stop; 557. #endif QUEST 558. 	for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){ 559. 		if(x == u.ux && y == u.uy) continue; 560. 		if(!levl[x][y].typ) continue; 561. 		if((mtmp = m_at(x,y)) && !mtmp->mimic &&  562.  		    (!mtmp->minvis || See_invisible)){ 563. 			if(!mtmp->mtame || (x == u.ux+u.dx && y == u.uy+u.dy)) 564. 				goto stop; 565. 		} else mtmp = 0; /* invisible M cannot influence us */ 566. 		if(x == u.ux-u.dx && y == u.uy-u.dy) continue; 567. 		switch(levl[x][y].scrsym){ 568. 		case '|': 569. 		case '-': 570. 		case '.': 571. 		case ' ': 572. 			break; 573. 		case '+': 574. 			if(x != u.ux && y != u.uy) break; 575. 			if(flags.run != 1) goto stop; 576. 			/* fall into next case */ 577. 		case CORR_SYM: 578. 		corr: 579. 			if(flags.run == 1 || flags.run == 3) { 580. 				i = DIST(x,y,u.ux+u.dx,u.uy+u.dy); 581. 				if(i > 2) break; 582. 				if(corrct == 1 && DIST(x,y,x0,y0) != 1) 583. 					noturn = 1; 584. 				if(i < i0) { 585. 					i0 = i;  586. x0 = x; 587. y0 = y; 588. m0 = mtmp ? 1 : 0; 589.  				}  590.  			}  591.  			corrct++; 592. 			break; 593. 		case '^': 594. 			if(flags.run == 1) goto corr;	/* if you must */ 595. 			if(x == u.ux+u.dx && y == u.uy+u.dx) goto stop; 596. 			break; 597. 		default:	/* e.g. objects or trap or stairs */ 598. 			if(flags.run == 1) goto corr; 599. 			if(mtmp) break;		/* d */ 600. 		stop: 601. 			nomul(0); 602. 			return; 603. 		}  604.  	}  605.  #ifdef QUEST 606. 	if(corrct > 0 && (flags.run == 4 || flags.run == 5)) goto stop; 607. #endif QUEST 608. 	if(corrct > 1 && flags.run == 2) goto stop; 609. 	if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&  610.  		(corrct == 1 || (corrct == 2 && i0 == 1))) { 611. 		/* make sure that we do not turn too far */ 612. 		if(i0 == 2) { 613. 		    if(u.dx == y0-u.uy && u.dy == u.ux-x0) 614. 			i = 2;		/* straight turn right */ 615. 		    else 616. 			i = -2;		/* straight turn left */ 617. 		} else if(u.dx && u.dy) { 618. 		    if((u.dx == u.dy && y0 == u.uy) ||  619.  			(u.dx != u.dy && y0 != u.uy)) 620. 			i = -1;		/* half turn left */ 621. 		    else 622. 			i = 1;		/* half turn right */ 623. 		} else { 624. 		    if((x0-u.ux == y0-u.uy && !u.dy) ||  625.  			(x0-u.ux != y0-u.uy && u.dy)) 626. 			i = 1;		/* half turn right */ 627. 		    else 628. 			i = -1;		/* half turn left */ 629. 		}  630.  		i += u.last_str_turn; 631. 		if(i <= 2 && i >= -2) { 632. 			u.last_str_turn = i;  633. u.dx = x0-u.ux, u.dy = y0-u.uy; 634. 		}  635.  	}  636.  }  637.   638.  #ifdef QUEST 639. cansee(x,y) xchar x,y; { 640. register int dx,dy,adx,ady,sdx,sdy,dmax,d; 641. 	if(Blind) return(0); 642. 	if(!isok(x,y)) return(0); 643. 	d = dist(x,y); 644. 	if(d < 3) return(1); 645. 	if(d > u.uhorizon*u.uhorizon) return(0); 646. 	if(!levl[x][y].lit) 647. 		return(0); 648. 	dx = x - u.ux;	adx = abs(dx);	sdx = sgn(dx); 649. 	dy = y - u.uy;  ady = abs(dy);	sdy = sgn(dy); 650. 	if(dx == 0 || dy == 0 || adx == ady){ 651. 		dmax = (dx == 0) ? ady : adx; 652. 		for(d = 1; d <= dmax; d++) 653. 			if(!rroom(sdx*d,sdy*d)) 654. 				return(0); 655. 		return(1); 656. 	} else if(ady > adx){ 657. 		for(d = 1; d <= ady; d++){ 658. 			if(!rroom(sdx*( (d*adx)/ady ), sdy*d) ||  659.  			   !rroom(sdx*( (d*adx-1)/ady+1 ), sdy*d)) 660. 				return(0); 661. 		}  662.   return(1); 663. 	} else { 664. 		for(d = 1; d <= adx; d++){ 665. 			if(!rroom(sdx*d, sdy*( (d*ady)/adx )) ||  666.  			   !rroom(sdx*d, sdy*( (d*ady-1)/adx+1 ))) 667. 				return(0); 668. 		}  669.   return(1); 670. 	}  671.  }  672.   673.  rroom(x,y) register int x,y; { 674. 	return(levl[u.ux+x][u.uy+y].typ >= ROOM); 675. }  676.   677.  #else 678.  679.  cansee(x,y) xchar x,y; { 680. 	if(Blind || u.uswallow) return(0); 681. 	if(dist(x,y) < 3) return(1); 682. 	if(levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&  683.  		y <= seehy) return(1); 684. 	return(0); 685. }  686.  #endif QUEST 687.  688.  sgn(a) register int a; { 689. 	return((a> 0) ? 1 : (a == 0) ? 0 : -1); 690. }  691.   692.  pow(num) /* returns 2 to the num */ 693. register unsigned num; 694. {  695.  	return(1 << num); 696. }  697.   698.  #ifdef QUEST 699. setsee 700. {  701.  	register x,y; 702.  703.  	if(Blind) { 704. 		pru; 705. 		return; 706. 	}  707.  	for(y = u.uy-u.uhorizon; y <= u.uy+u.uhorizon; y++) 708. 		for(x = u.ux-u.uhorizon; x <= u.ux+u.uhorizon; x++) { 709. 			if(cansee(x,y)) 710. 				prl(x,y); 711. 	}  712.  }  713.   714.  #else 715.  716.  setsee 717. {  718.  	register x,y; 719.  720.  	if(Blind) { 721. 		pru; 722. 		return; 723. 	}  724.  	if(!levl[u.ux][u.uy].lit) { 725. 		seelx = u.ux-1; 726. 		seehx = u.ux+1; 727. 		seely = u.uy-1; 728. 		seehy = u.uy+1; 729. 	} else { 730. 		for(seelx = u.ux; levl[seelx-1][u.uy].lit; seelx--); 731. 		for(seehx = u.ux; levl[seehx+1][u.uy].lit; seehx++); 732. 		for(seely = u.uy; levl[u.ux][seely-1].lit; seely--); 733. 		for(seehy = u.uy; levl[u.ux][seehy+1].lit; seehy++); 734. 	}  735.  	for(y = seely; y <= seehy; y++) 736. 		for(x = seelx; x <= seehx; x++) { 737. 			prl(x,y); 738. 	}  739.  	if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */ 740. 	else { 741. 	    if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1); 742. 	    if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1); 743. 	    if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y); 744. 	    if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y); 745. 	}  746.  }  747.  #endif QUEST 748.  749.  nomul(nval) 750. register nval; 751. {  752.  	if(multi < 0) return; 753. 	multi = nval; 754. 	flags.mv = flags.run = 0; 755. }  756.   757.  abon 758. {  759.  	if(u.ustr == 3) return(-3); 760. 	else if(u.ustr < 6) return(-2); 761. 	else if(u.ustr < 8) return(-1); 762. 	else if(u.ustr < 17) return(0); 763. 	else if(u.ustr < 69) return(1);	/* up to 18/50 */ 764. 	else if(u.ustr < 118) return(2); 765. 	else return(3); 766. }  767.   768.  dbon 769. {  770.  	if(u.ustr < 6) return(-1); 771. 	else if(u.ustr < 16) return(0); 772. 	else if(u.ustr < 18) return(1); 773. 	else if(u.ustr == 18) return(2);	/* up to 18 */ 774. 	else if(u.ustr < 94) return(3);	/* up to 18/75 */ 775. 	else if(u.ustr < 109) return(4);	/* up to 18/90 */ 776. 	else if(u.ustr < 118) return(5);	/* up to 18/99 */ 777. 	else return(6); 778. }  779.   780.  losestr(num) 781. register num; 782. {  783.  	u.ustr -= num; 784. 	while(u.ustr < 3) { 785. 		u.ustr++; 786. 		u.uhp -= 6; 787. 		u.uhpmax -= 6; 788. 	}  789.   flags.botl = 1; 790. }  791.   792.  losehp(n,knam) 793. register n;  794. register char *knam; 795. {  796.  	u.uhp -= n;  797. if(u.uhp > u.uhpmax) 798. 		u.uhpmax = u.uhp;	/* perhaps n was negative */ 799. 	flags.botl = 1; 800. 	if(u.uhp < 1) 801. 		killer = knam;	/* the thing that killed you */ 802. }  803.   804.  losehp_m(n,mtmp) 805. register n;  806. register struct monst *mtmp; 807. {  808.  	u.uhp -= n;  809. flags.botl = 1; 810. 	if(u.uhp < 1) done_in_by(mtmp); 811. }  812.   813.  losexp	/* hit by V or W */ 814. {  815.  	register num; 816.  817.  	if(u.ulevel > 1) pline("Goodbye level %d.",u.ulevel--); 818. 	else u.uhp = -1; 819. 	num = rnd(10); 820. 	u.uhp -= num; 821. 	u.uhpmax -= num; 822. 	u.uexp = 10*pow(u.ulevel-1); 823. 	flags.botl = 1; 824. }  825.   826.  inv_weight{ 827. register struct obj *otmp = invent; 828. register int wt = 0; 829. register int carrcap = 5*(((u.ustr > 18) ? 20 : u.ustr) + u.ulevel); 830. 	if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP; 831. 	if(Wounded_legs & LEFT_SIDE) carrcap -= 10; 832. 	if(Wounded_legs & RIGHT_SIDE) carrcap -= 10; 833. 	while(otmp){ 834. 		wt += otmp->owt; 835. 		otmp = otmp->nobj; 836. 	}  837.   return(wt - carrcap); 838. }  839.   840.  inv_cnt{ 841. register struct obj *otmp = invent; 842. register int ct = 0; 843. 	while(otmp){ 844. 		ct++; 845. 		otmp = otmp->nobj; 846. 	}  847.   return(ct); 848. }