Source:NetHack 2.3e/do.c

Below is the full text to do.c from the source code of NetHack 2.3e. To link to a particular line, write [[NetHack 2.3e/do.c#line123 ]], for example.

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

1.   /*	SCCS Id: @(#)do.c	2.3	88/02/11 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    /* Contains code for 'd', 'D' (drop), '>', '<' (up, down) and 't' (throw) */ 5.    6.    #include "hack.h"  7. 8.   extern struct obj *splitobj, *addinv; 9.   extern boolean hmon; 10.  extern boolean level_exists[]; 11.  extern struct monst youmonst; 12.  extern char *Doname; 13.  extern char *nomovemsg; 14.  int	identify; 15.  #ifdef KAA 16.  extern char *xname; 17.  #endif 18.   19.   dodrop { 20.  	if(u.ugold)	return(drop(getobj("0$#", "drop"))); 21.  	else		return(drop(getobj("0#", "drop"))); 22.  }  23.    24.   static 25.  drop(obj) register struct obj *obj; { 26.  	if(!obj) return(0); 27.  	if(obj->olet == GOLD_SYM) {		/* pseudo object */ 28.  		register long amount = OGOLD(obj); 29.   30.   		if(amount == 0) 31.  			pline("You didn't drop any gold pieces."); 32.  /* Fix bug with dropping huge amounts of gold read as negative    KAA */ 33.  		else if(amount < 0) { 34.  			u.ugold += amount; 35.  	pline("The LRS would be very interested to know you have that much."); 36.  		} else { 37.  			/* uswallow test added by GAN 01/29/87 */ 38.  			pline("You dropped %ld gold piece%s.",  39.   				 amount, plur(amount)); 40.  			if(u.uswallow) 41.  				(u.ustuck)->mgold += amount; 42.  			else { 43.  				mkgold(amount, u.ux, u.uy); 44.  				if(Invisible) newsym(u.ux, u.uy); 45.  			}  46.   		}  47.   		free((char *) obj); 48.  		return(1); 49.  	}  50.   	if(obj->owornmask & (W_ARMOR | W_RING | W_TOOL)){ 51.  		pline("You cannot drop something you are wearing."); 52.  		return(0); 53.  	}  54.   	if(obj == uwep) { 55.  		if(uwep->cursed) { 56.  			pline("Your weapon is welded to your hand!"); 57.  			return(0); 58.  		}  59.   		setuwep((struct obj *) 0); 60.  	}  61.   #ifdef WALKIES 62.          if (obj->otyp == LEASH) { 63.              register struct monst *mtmp = fmon; 64.              while (mtmp && !mtmp->mleashed) mtmp = mtmp->nmon; 65.              if (mtmp) { 66.                  pline ("Your leash is tied around your hand."); 67.                  return (0); 68.              }  69.           }  70.   #endif 71.  #ifdef SINKS 72.  	if((obj->olet == RING_SYM) && IS_SINK(levl[u.ux][u.uy].typ)) 73.  	    if (u.uswallow) { 74.  		freeinv(obj); 75.  		mpickobj(u.ustuck,obj); 76.  		return(1); 77.  	    }  78.   	    else { 79.  		dosinkring(obj); 80.  		return(1); 81.  	    }  82.   #endif 83.  	pline("You dropped %s.", doname(obj)); 84.  	dropx(obj); 85.  	return(1); 86.  }  87.    88.   /* Called in several places - should not produce texts */ 89.  dropx(obj) 90.  register struct obj *obj; 91.  {  92.   	freeinv(obj); 93.  	dropy(obj); 94.  }  95.    96.   dropy(obj) 97.  register struct obj *obj; 98.  {  99.   	if(obj->otyp == CRYSKNIFE) 100. 		obj->otyp = WORM_TOOTH; 101. 	/* uswallow check done by GAN 01/29/87 */ 102. 	if(u.uswallow) 103. 		mpickobj(u.ustuck,obj); 104. 	else  { 105. 		obj->ox = u.ux; 106. 		obj->oy = u.uy; 107. 		/* Blind check added by GAN 02/18/87 */ 108. 		if(Blind)  { 109. #ifdef KAA 110. 			if(obj->olet != ')')  111.  #endif  112.  			    obj->dknown = index("/=!?*",obj->olet) ? 0 : 1;  113.  			obj->known = 0;  114.  		}  115.  		obj->nobj = fobj;  116.  		fobj = obj;  117.  		if(Invisible) newsym(u.ux,u.uy);  118.  		subfrombill(obj);  119.  		stackobj(obj);  120.  	}  121.  }  122.   123.  /* drop several things */  124.  doddrop {  125.  	return(ggetobj("drop", drop, 0));  126.  }  127.   128.  dodown  129.  {  130.  	if(u.ux != xdnstair || u.uy != ydnstair) {  131.  		pline("You can't go down here.");  132.  		return(0);  133.  	}  134.  	if(u.ustuck) {  135.  		pline("You are being held, and cannot go down.");  136.  		return(1);  137.  	}  138.  	if(Levitation) {  139.  		pline("Your floating high above the stairs.");  140.  		return(0);  141.  	}  142.   143.  	goto_level(dlevel+1, TRUE);  144.  	return(1);  145.  }  146.   147.  doup  148.  {  149.  	if(u.ux != xupstair || u.uy != yupstair) { 150. 		pline("You can't go up here."); 151. 		return(0); 152. 	}  153.  	if(u.ustuck) { 154. 		pline("You are being held, and cannot go up."); 155. 		return(1); 156. 	}  157.  	if(!Levitation && inv_weight + 5 > 0) { 158. 		pline("Your load is too heavy to climb the stairs."); 159. 		return(1); 160. 	}  161.   162.  	goto_level(dlevel-1, TRUE); 163. 	return(1); 164. }  165.   166.  goto_level(newlevel, at_stairs) 167. register int newlevel; 168. register boolean at_stairs; 169. {  170.  	register fd; 171. 	register boolean up = (newlevel < dlevel); 172.  173.  	if(newlevel <= 0) done("escaped");    /* in fact < 0 is impossible */ 174. 	if(newlevel > MAXLEVEL) newlevel = MAXLEVEL;	/* strange ... */ 175.  	if(newlevel == dlevel) return;	      /* this can happen */ 176.  177.  	glo(dlevel); 178. #ifdef DGK 179. 	/* Use O_TRUNC to force the file to be shortened if it already 180. 	 * exists and is currently longer. 181. 	 */  182.  	fd = open(lock, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, FMASK); 183. #else 184. 	fd = creat(lock, FMASK); 185. #endif 186. 	if(fd < 0) { 187. 		/*  188.  		 * This is not quite impossible: e.g., we may have 189. 		 * exceeded our quota. If that is the case then we 190. * cannot leave this level, and cannot save either. 191. 		 * Another possibility is that the directory was not 192. 		 * writable. 193. 		 */  194.  #ifdef DGK 195. 		pline("Cannot create level file '%s'.", lock); 196. #else 197. 		pline("A mysterious force prevents you from going %s.",  198.  			up ? "up" : "down"); 199. #endif 200. 		return; 201. 	}  202.   203.  #ifdef DGK 204. 	if (!savelev(fd, dlevel, COUNT)) { 205. 		(void) close(fd); 206. 		(void) unlink(lock); 207. 		pline("HACK is out of disk space for making levels!"); 208. 		pline("You can save, quit, or continue playing."); 209. 		return; 210. 	}  211.  #endif 212. 	if(Punished) unplacebc; 213. 	u.utrap = 0;				/* needed in level_tele */ 214. 	u.ustuck = 0;				/* idem */ 215. 	keepdogs; 216. 	seeoff(1); 217. 	if(u.uswallow)				/* idem */ 218. 		u.uswldtim = u.uswallow = 0; 219. 	flags.nscrinh = 1; 220. 	u.ux = FAR;				/* hack */ 221. 	(void) inshop;			/* probably was a trapdoor */ 222.  223.  #ifdef DGK 224. 	savelev(fd,dlevel, WRITE); 225. #else 226. 	savelev(fd,dlevel); 227. #endif 228. 	(void) close(fd); 229.  230.  	dlevel = newlevel; 231. 	if(maxdlevel < dlevel) 232. 		maxdlevel = dlevel; 233. 	glo(dlevel); 234. #ifdef MSDOS 235. 	/* If the level has no where yet, it hasn't been made 236. 	 */  237.  	if(!fileinfo[dlevel].where) 238. #else 239. 	if(!level_exists[dlevel]) 240. #endif 241. 		mklev; 242. 	else { 243. 		extern int hackpid; 244. #ifdef DGK 245. 		/* If not currently accessible, swap it in. 246. 		 */  247.  		if (fileinfo[dlevel].where != ACTIVE) 248. 			swapin_file(dlevel); 249.  250.  		if((fd = open(lock, O_RDONLY | O_BINARY)) < 0) { 251. #else 252. 		if((fd = open(lock,0)) < 0) { 253. #endif 254. 			pline("Cannot open %s .", lock); 255. 			pline("Probably someone removed it."); 256. 			done("tricked"); 257. 		}  258.  		getlev(fd, hackpid, dlevel); 259. 		(void) close(fd); 260. 	}  261.   262.  	if(at_stairs) { 263. 	    if(up) { 264. 		u.ux = xdnstair; 265. 		u.uy = ydnstair; 266. 		if(!u.ux) {		/* entering a maze from below? */ 267.  		    u.ux = xupstair;	/* this will confuse the player! */ 268.  		    u.uy = yupstair; 269. 		}  270.  /* Remove bug which crashes with levitation/punishment  KAA */ 271. 		if(Punished) { 272. 		    if(!Levitation) 273. 			pline("With great effort you climb the stairs."); 274. 		    placebc(1); 275. 		}  276.  	    } else { 277. 		u.ux = xupstair; 278. 		u.uy = yupstair; 279. 		if(inv_weight + 5 > 0 || Punished){ 280. 			pline("You fall down the stairs.");	/* %% */ 281. 			losehp(rnd(3), "fall"); 282. 			if(Punished) { 283. 			    if(uwep != uball && rn2(3)){ 284. 				pline("... and are hit by the iron ball."); 285. 				losehp(rnd(20), "iron ball"); 286. 			    }  287.  			    placebc(1); 288. 			}  289.  			selftouch("Falling, you"); 290. 		}  291.  	    }  292.  	    { register struct monst *mtmp = m_at(u.ux, u.uy); 293. 	      if(mtmp) 294. 		mnexto(mtmp); 295. 	    }  296.  	} else {	/* trapdoor or level_tele */ 297. 	    do { 298. 		u.ux = rnd(COLNO-1); 299. 		u.uy = rn2(ROWNO); 300. 	    } while(levl[u.ux][u.uy].typ != ROOM ||  301.  			m_at(u.ux,u.uy)); 302. 	    if(Punished){ 303. 		if(uwep != uball && !up /* %% */ && rn2(5)){ 304. 			pline("The iron ball falls on your head."); 305. 			losehp(rnd(25), "iron ball"); 306. 		}  307.  		placebc(1); 308. 	    }  309.  	    selftouch("Falling, you"); 310. 	}  311.  	(void) inshop; 312. 	initrack; 313.  314.  	losedogs; 315. 	{ register struct monst *mtmp; 316. 	  if(mtmp = m_at(u.ux, u.uy)) mnexto(mtmp);	/* riv05!a3 */ 317. 	}  318.  	flags.nscrinh = 0; 319. 	setsee; 320. 	seeobjs;	/* make old cadavers disappear - riv05!a3 */ 321. 	docrt; 322. 	pickup(1); 323. 	read_engr_at(u.ux,u.uy); 324. }  325.   326.  donull { 327. 	return(1);	/* Do nothing, but let other things happen */ 328. }  329.   330.  #if defined(KAA) && defined(KOPS) 331. wipeoff 332. {  333.  	if(u.ucreamed < 4)	u.ucreamed = 0; 334. 	else			u.ucreamed -= 4; 335. 	if(u.ucreamed > 0)  { 336. 		Blinded -= 4; 337. 		if(Blind <= 1) { 338. 			pline("You've got the glop off."); 339. 			u.ucreamed = 0; 340. 			Blinded = 1; 341. 			return(0); 342. 		}  343.  		return(1);		/* still busy */ 344. 	}  345.  	pline("Your face feels clean now."); 346. 	u.ucreamed = 0; 347. 	return(0); 348. }  349.  	  350.  dowipe 351. {  352.  	if(u.ucreamed)  { 353. #ifdef DGKMOD 354. 		set_occupation(wipeoff, "wiping off your face", 0); 355. #else 356. 		occupation = wipeoff; 357. 		occtxt = "wiping off your face"; 358. #endif 359. 		return(1); 360. 	}  361.  	pline("Your face is already clean."); 362. 	return(1); 363. }  364.  #endif 365.  366.  /* split obj so that it gets size num */ 367. /* remainder is put in the object structure delivered by this call */ 368. struct obj * 369. splitobj(obj, num) register struct obj *obj; register int num; { 370. register struct obj *otmp; 371. 	otmp = newobj(0); 372. 	*otmp = *obj;		/* copies whole structure */ 373. 	otmp->o_id = flags.ident++; 374. 	otmp->onamelth = 0; 375. 	obj->quan = num; 376. 	obj->owt = weight(obj); 377. 	otmp->quan -= num; 378. 	otmp->owt = weight(otmp);	/* -= obj->owt ? */ 379.  	obj->nobj = otmp; 380. 	if(obj->unpaid) splitbill(obj,otmp); 381. 	return(otmp); 382. }  383.   384.  more_experienced(exp,rexp) 385. register int exp, rexp; 386. {  387.  	extern char pl_character[]; 388.  389.  	u.uexp += exp; 390. 	u.urexp += 4*exp + rexp; 391. 	if(exp) flags.botl = 1; 392. 	if(u.urexp >= ((pl_character[0] == 'W') ? 1000 : 2000)) 393.  		flags.beginner = 0; 394. }  395.   396.  set_wounded_legs(side, timex) 397. register long side; 398. register int timex; 399. {  400.  	if(!Wounded_legs || (Wounded_legs & TIMEOUT)) 401. 		Wounded_legs |= side + timex; 402. 	else 403. 		Wounded_legs |= side; 404. }  405.   406.  heal_legs 407. {  408.  	if(Wounded_legs) { 409. 		if((Wounded_legs & BOTH_SIDES) == BOTH_SIDES) 410. 			pline("Your legs feel somewhat better."); 411. 		else 412. 			pline("Your leg feels somewhat better."); 413. 		Wounded_legs = 0; 414. 	}  415.  }  416.   417.  #ifdef SINKS 418. trycall(obj) 419. register struct obj *obj; 420. {  421.  	if(!objects[obj->otyp].oc_name_known &&  422.  	   !objects[obj->otyp].oc_uname) 423. 	   docall(obj); 424. }  425.   426.  dosinkring(obj)  /* obj is a ring being dropped over a kitchen sink */ 427. register struct obj *obj; 428. {  429.  register struct obj *otmp,*otmp2; 430. register short eaten; 431. 	pline("You drop %s down the drain.", doname(obj)); 432. 	switch(obj->otyp) { 433. 	    case RIN_ADORNMENT:  { 434. 		pline("The faucets flash brightly for a moment."); 435. 		trycall(obj); 436. 		break; 437. 		}  438.  	    case RIN_REGENERATION:  { 439. 		pline("The sink looks as good as new."); 440. 		trycall(obj); 441. 		break; 442. 		}  443.  	    case RIN_SEARCHING: 444. 		break; 445. 	    case RIN_SEE_INVISIBLE: 446. 		break; 447. 	    case RIN_STEALTH:  { 448. 		pline("The sink seems to blend into the floor for a moment."); 449. 		trycall(obj); 450. 		break; 451. 		}  452.  	    case RIN_LEVITATION:  { 453. 		pline("The sink quivers upward for a moment."); 454. 		trycall(obj); 455. 		break; 456. 		}  457.  	    case RIN_POISON_RESISTANCE: 458. 		break; 459. 	    case RIN_AGGRAVATE_MONSTER: 460. 		break; 461. 	    case RIN_HUNGER:  { 462. 		eaten = 0; 463. 		for(otmp=fobj; otmp; otmp=otmp2) { 464. 		    otmp2 = otmp->nobj; 465. 		    if(otmp->ox == u.ux && otmp->oy == u.uy) 466. 			if(!Punished ||  467.  			    (otmp->otyp != HEAVY_IRON_BALL && otmp->otyp != IRON_CHAIN)) { 468. 			    eaten++; 469. 			    pline("Suddenly, %s vanishes from the sink!",doname(otmp)); 470. 			    delobj(otmp); 471. 			}  472.  		}  473.  		if(eaten) 474. 		    trycall(obj); 475. 		break; 476. 		}  477.  	    case RIN_FIRE_RESISTANCE:  { 478. 		pline("The hot water faucet flashes brightly for a moment."); 479. 		trycall(obj); 480. 		break; 481. 		}  482.  	    case RIN_COLD_RESISTANCE:  { 483. 		pline("The cold water faucet flashes brightly for a moment."); 484. 		trycall(obj); 485. 		break; 486. 		}  487.  	    case RIN_PROTECTION_FROM_SHAPE_CHAN:  { 488. 		pline("The sink momentarily looks nothing like a fountain."); 489. 		trycall(obj); 490. 		break; 491. 		}  492.  	    case RIN_CONFLICT: 493. 		break; 494. 	    case RIN_GAIN_STRENGTH: 495. 		break; 496. 	    case RIN_INCREASE_DAMAGE: 497. 		break; 498. 	    case RIN_PROTECTION: 499. 		break; 500. 	    case RIN_WARNING:  { 501. 		pline("The sink glows white for a moment."); 502. 		trycall(obj); 503. 		break; 504. 		}  505.  	    case RIN_TELEPORTATION:	/* fall through */ 506. 	    case RIN_TELEPORT_CONTROL:  { 507. 		pline("The sink momentarily vanishes."); 508. 		trycall(obj); 509. 		break; 510. 		}  511.  	    case RIN_POLYMORPH:		/* fall through */ 512. 	    case RIN_POLYMORPH_CONTROL:  { 513. 		pline("The sink momentarily looks like a fountain."); 514. 		trycall(obj); 515. 		break; 516. 		}  517.  	}  518.  	if (!rn2(20)) { 519. 		pline("The sink backs up, leaving %s.", doname(obj)); 520. 		dropx(obj); 521. 	}  522.  	else 523. 		useup(obj); 524. }  525.  #endif