Source:NetHack 2.3e/invent.c

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

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

1.   /*	SCCS Id: @(#)invent.c	2.3	88/01/21 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.     4.    #include	  5.    #include	"hack.h"  6.    extern struct obj *splitobj; 7.   extern struct obj zeroobj; 8.   extern void savech; 9.   extern char morc; 10.  extern char quitchars[]; 11.  static char *xprname; 12.   13.   #ifndef NOWORM 14.  #include	"wseg.h"  15. extern struct wseg *wsegs[32]; 16.  #endif 17.   18.   #define	NOINVSYM	'#' 19.   20.   int lastinvnr = 51;	/* 0 ... 51 */ 21.    22.   static 23.  assigninvlet(otmp) 24.  register struct obj *otmp; 25.  {  26.   	boolean inuse[52]; 27.  	register int i;  28. register struct obj *obj; 29.   30.   	for(i = 0; i < 52; i++) inuse[i] = FALSE; 31.  	for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) { 32.  		i = obj->invlet; 33.  		if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else 34.  		if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE; 35.  		if(i == otmp->invlet) otmp->invlet = 0; 36.  	}  37.   	if((i = otmp->invlet) &&  38.   	    (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z'))) 39.  		return; 40.  	for(i = lastinvnr+1; i != lastinvnr; i++) { 41.  		if(i == 52) { i = -1; continue; } 42.  		if(!inuse[i]) break; 43.  	}  44.   	otmp->invlet = (inuse[i] ? NOINVSYM :  45.   			(i < 26) ? ('a'+i) : ('A'+i-26)); 46.  	lastinvnr = i;  47. } 48.    49.   struct obj * 50.  addinv(obj) 51.  register struct obj *obj; 52.  {  53.   	register struct obj *otmp; 54.   55.   	/* merge or attach to end of chain */ 56.  	if(!invent) { 57.  		invent = obj; 58.  		otmp = 0; 59.  	} else 60.  	for(otmp = invent; /* otmp */; otmp = otmp->nobj) { 61.  		if(merged(otmp, obj, 0)) 62.  			return(otmp); 63.  		if(!otmp->nobj) { 64.  			otmp->nobj = obj; 65.  			break; 66.  		}  67.   	}  68.   	obj->nobj = 0; 69.   70.   	if(flags.invlet_constant) { 71.  		assigninvlet(obj); 72.  		/*  73.   		 * The ordering of the chain is nowhere significant 74.  		 * so in case you prefer some other order than the 75.  		 * historical one, change the code below. 76.  		 */  77.   		if(otmp) {	/* find proper place in chain */ 78.  			otmp->nobj = 0; 79.  			if((invent->invlet ^ 040) > (obj->invlet ^ 040)) { 80.  				obj->nobj = invent; 81.  				invent = obj; 82.  			} else 83.  			for(otmp = invent; ; otmp = otmp->nobj) { 84.  			    if(!otmp->nobj ||  85.   				(otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){ 86.  				obj->nobj = otmp->nobj; 87.  				otmp->nobj = obj; 88.  				break; 89.  			    }  90.   			}  91.   		}  92.   	}  93.    94.   	return(obj); 95.  }  96.    97.   useup(obj) 98.  register struct obj *obj; 99.  {  100.  	if(obj->quan > 1){ 101. 		obj->quan--; 102. 		obj->owt = weight(obj); 103. 	} else { 104. 		setnotworn(obj); 105. 		freeinv(obj); 106. 		obfree(obj, (struct obj *) 0); 107. 	}  108.  }  109.   110.  freeinv(obj) 111. register struct obj *obj; 112. {  113.  	register struct obj *otmp; 114.  115.  	if(obj == invent) 116. 		invent = invent->nobj; 117. 	else { 118. 		for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj) 119. 			if(!otmp->nobj) panic("freeinv"); 120. 		otmp->nobj = obj->nobj; 121. 	}  122.  }  123.   124.  /* destroy object in fobj chain (if unpaid, it remains on the bill) */ 125. delobj(obj) register struct obj *obj; { 126. 	freeobj(obj); 127. 	unpobj(obj); 128. 	obfree(obj, (struct obj *) 0); 129. }  130.   131.  /* unlink obj from chain starting with fobj */ 132. freeobj(obj) register struct obj *obj; { 133. 	register struct obj *otmp; 134.  135.  	if(obj == fobj) fobj = fobj->nobj; 136. 	else { 137. 		for(otmp = fobj; otmp->nobj != obj; otmp = otmp->nobj) 138. 			if(!otmp) panic("error in freeobj"); 139. 		otmp->nobj = obj->nobj; 140. 	}  141.  }  142.   143.  /* Note: freegold throws away its argument! */ 144.  freegold(gold) register struct gold *gold; { 145. 	register struct gold *gtmp; 146.  147.  	if(gold == fgold) fgold = gold->ngold; 148. 	else { 149. 		for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold) 150. 			if(!gtmp) panic("error in freegold"); 151. 		gtmp->ngold = gold->ngold; 152. 	}  153.  	free((char *) gold); 154. }  155.   156.  deltrap(trap) 157. register struct trap *trap; 158. {  159.  	register struct trap *ttmp; 160.  161.  	if(trap == ftrap) 162. 		ftrap = ftrap->ntrap; 163. 	else { 164. 		for(ttmp = ftrap; ttmp->ntrap != trap; ttmp = ttmp->ntrap) ; 165. 		ttmp->ntrap = trap->ntrap; 166. 	}  167.  	free((char *) trap); 168. }  169.   170.  struct wseg *m_atseg; 171.  172.  struct monst * 173. m_at(x,y) 174. register x,y; 175. {  176.  	register struct monst *mtmp; 177. #ifndef NOWORM 178. 	register struct wseg *wtmp; 179. #endif 180.  181.  	m_atseg = 0; 182. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon){ 183. 		if(mtmp->mx == x && mtmp->my == y)  184. return(mtmp); 185. #ifndef NOWORM 186. 		if(mtmp->wormno){ 187. 		    for(wtmp = wsegs[mtmp->wormno]; wtmp; wtmp = wtmp->nseg) 188. 		    if(wtmp->wx == x && wtmp->wy == y){ 189. 			m_atseg = wtmp; 190. 			return(mtmp); 191. 		    }  192.  		}  193.  #endif 194. 	}  195.  	return(0); 196. }  197.   198.  struct obj * 199. o_at(x,y) 200. register x,y; 201. {  202.  	register struct obj *otmp; 203.  204.  	for(otmp = fobj; otmp; otmp = otmp->nobj) 205. 		if(otmp->ox == x && otmp->oy == y) return(otmp); 206. 	return(0); 207. }  208.   209.  struct obj * 210. sobj_at(n,x,y) 211. register n,x,y; 212. {  213.  	register struct obj *otmp; 214.  215.  	for(otmp = fobj; otmp; otmp = otmp->nobj) 216. 		if(otmp->ox == x && otmp->oy == y && otmp->otyp == n)  217. return(otmp); 218. 	return(0); 219. }  220.   221.  carried(obj) register struct obj *obj; { 222. register struct obj *otmp; 223. 	for(otmp = invent; otmp; otmp = otmp->nobj) 224. 		if(otmp == obj) return(1); 225. 	return(0); 226. }  227.   228.  struct obj * 229. carrying(type) 230. register int type; 231. {  232.  	register struct obj *otmp; 233.  234.  	for(otmp = invent; otmp; otmp = otmp->nobj) 235. 		if(otmp->otyp == type) 236. 			return(otmp); 237. 	return((struct obj *) 0); 238. }  239.   240.  struct obj * 241. o_on(id, objchn) unsigned int id; register struct obj *objchn; { 242. 	while(objchn) { 243. 		if(objchn->o_id == id) return(objchn); 244. 		objchn = objchn->nobj; 245. 	}  246.  	return((struct obj *) 0); 247. }  248.   249.  struct trap * 250. t_at(x,y) 251. register x,y; 252. {  253.  	register struct trap *trap = ftrap; 254. 	while(trap) { 255. 		if(trap->tx == x && trap->ty == y) return(trap); 256. 		trap = trap->ntrap; 257. 	}  258.  	return(0); 259. }  260.   261.  struct gold * 262. g_at(x,y) 263. register x,y; 264. {  265.  	register struct gold *gold = fgold; 266. 	while(gold) { 267. 		if(gold->gx == x && gold->gy == y) return(gold); 268. 		gold = gold->ngold; 269. 	}  270.  	return(0); 271. }  272.   273.  /* make dummy object structure containing gold - for temporary use only */ 274. struct obj * 275. mkgoldobj(q) 276. register long q;  277. { 278.  	register struct obj *otmp; 279.  280.  	otmp = newobj(0); 281. 	/* should set o_id etc. but otmp will be freed soon */ 282. 	otmp->olet = GOLD_SYM; 283. 	u.ugold -= q;  284. OGOLD(otmp) = q; 285. flags.botl = 1; 286. 	return(otmp); 287. }  288.   289.  /*  290.   * getobj returns: 291.  *	struct obj *xxx:	object to do something with. 292.  *	(struct obj *) 0	error return: no object. 293.  *	&zeroobj		explicitly no object (as in w-). 294.  */  295.  struct obj * 296. getobj(let,word) 297. register char *let,*word; 298. {  299.  	register struct obj *otmp; 300. 	register char ilet,ilet1,ilet2; 301. 	char buf[BUFSZ]; 302. 	char lets[BUFSZ]; 303. 	register int foo = 0, foo2; 304. 	register char *bp = buf; 305. 	xchar allowcnt = 0;	/* 0, 1 or 2 */ 306. 	boolean allowgold = FALSE; 307. 	boolean allowall = FALSE; 308. 	boolean allownone = FALSE; 309. 	xchar foox = 0; 310. 	long cnt; 311.  312.  	if(*let == '0') let++, allowcnt = 1; 313. 	if(*let == GOLD_SYM) let++, allowgold = TRUE; 314. 	if(*let == '#') let++, allowall = TRUE; 315. 	if(*let == '-') let++, allownone = TRUE; 316. 	if(allownone) *bp++ = '-'; 317. 	if(allowgold) *bp++ = GOLD_SYM; 318. 	if(bp > buf && bp[-1] == '-') *bp++ = ' '; 319.  320.  	ilet = 'a'; 321. 	for(otmp = invent; otmp; otmp = otmp->nobj){ 322. 	    if(!*let || index(let, otmp->olet)) { 323. 		bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet; 324.  325.  		/* ugly check: remove inappropriate things */ 326. 		if((!strcmp(word, "take off") && 327. 		    !(otmp->owornmask & (W_ARMOR - W_ARM2)))  328.  		|| (!strcmp(word, "wear") && 329. 		    (otmp->owornmask & (W_ARMOR | W_RING)))  330.  		|| (!strcmp(word, "wield") && 331. 		    (otmp->owornmask & W_WEP))  332.  #ifdef MARKER  333.  		|| (!strcmp(word, "write with") && 334. 		    (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))  335.  #endif  336.  		    ) { 337. 			foo--; 338. 			foox++; 339. 		}  340.  	    }  341.  	    if(ilet == 'z') ilet = 'A'; else ilet++; 342. 	}  343.  	bp[foo] = 0; 344. 	if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0; 345. 	(void) strcpy(lets, bp);	/* necessary since we destroy buf */ 346. 	if(foo > 5) {			/* compactify string */ 347. 		foo = foo2 = 1; 348. 		ilet2 = bp[0]; 349. 		ilet1 = bp[1]; 350. 		while(ilet = bp[++foo2] = bp[++foo]){ 351. 			if(ilet == ilet1+1){ 352. 				if(ilet1 == ilet2+1) 353. 					bp[foo2 - 1] = ilet1 = '-'; 354. 				else if(ilet2 == '-') { 355. 					bp[--foo2] = ++ilet1; 356. 					continue; 357. 				}  358.  			}  359.  			ilet2 = ilet1; 360. 			ilet1 = ilet; 361. 		}  362.  	}  363.  	if(!foo && !allowall && !allowgold && !allownone) { 364. 		pline("You don't have anything %sto %s.",  365.  			foox ? "else " : "", word); 366. 		return(0); 367. 	}  368.  	for { 369. 		if(!buf[0]) { 370. #ifdef REDO 371. 		    if(!in_doagain) 372. #endif 373. 			pline("What do you want to %s [*]? ", word); 374. 		} else { 375. #ifdef REDO 376. 		    if(!in_doagain) 377. #endif 378. 			pline("What do you want to %s [%s or ?*]? ",  379.  				word, buf); 380. 		}  381.  		cnt = 0; 382. 		ilet = readchar; 383. 		while(digit(ilet) && allowcnt) { 384. #ifdef REDO 385. 			if (ilet != '?' && ilet != '*')	savech(ilet); 386. #endif 387. 			cnt = 10*cnt + (ilet - '0'); 388. 			allowcnt = 2;	/* signal presence of cnt */ 389. 			ilet = readchar; 390. 		}  391.  		if(digit(ilet)) { 392. 			pline("No count allowed with this command."); 393. 			continue; 394. 		}  395.  		if(index(quitchars,ilet)) { 396. 			pline("Never mind."); 397. 			return((struct obj *)0); 398. 		}  399.  		if(ilet == '-') { 400. 			return(allownone ? &zeroobj : (struct obj *) 0); 401. 		}  402.  		if(ilet == GOLD_SYM) { 403. 			if(!allowgold){ 404. 				pline("You cannot %s gold.", word); 405. 				continue; 406. 			}  407.  			if(!(allowcnt == 2 && cnt < u.ugold)) 408. 				cnt = u.ugold; 409. 			return(mkgoldobj(cnt)); 410. 		}  411.  		if(ilet == '?') { 412. 			doinv(lets); 413. 			if(!(ilet = morc)) continue; 414. 			/* he typed a letter (not a space) to more */ 415. 		} else if(ilet == '*') { 416. 			doinv((char *) 0); 417. 			if(!(ilet = morc)) continue; 418. 			/* ... */  419.  		}  420.  #ifdef REDO 421. 		if (ilet != '?' && ilet != '*')	savech(ilet); 422. #endif 423. 		if(flags.invlet_constant) { 424. 			for(otmp = invent; otmp; otmp = otmp->nobj) 425. 				if(otmp->invlet == ilet) break; 426. 		} else { 427. 			if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1; 428. 			ilet -= 'a'; 429. 			for(otmp = invent; otmp && ilet;  430.  					ilet--, otmp = otmp->nobj) ; 431. 		}  432.  		if(!otmp) { 433. 			pline("You don't have that object."); 434. 			continue; 435. 		}  436.  		if(cnt < 0 || otmp->quan < cnt) { 437. 			pline("You don't have that many! [You have %u]"  438.  		, otmp->quan); 439. 			continue; 440. 		}  441.  		break; 442. 	}  443.  	if(!allowall && let && !index(let,otmp->olet)) { 444. 		pline("That is a silly thing to %s.",word); 445. 		return(0); 446. 	}  447.  	if(allowcnt == 2) {	/* cnt given */ 448. 		if(cnt == 0) return(0); 449. 		if(cnt != otmp->quan) { 450. 			register struct obj *obj; 451. 			obj = splitobj(otmp, (int) cnt); 452. 			if(otmp == uwep) setuwep(obj); 453. 		}  454.  	}  455.  	return(otmp); 456. }  457.   458.  ckunpaid(otmp) register struct obj *otmp; { 459. 	return( otmp->unpaid ); 460. }  461.   462.  /* interactive version of getobj - used for Drop and Identify */ 463. /* return the number of times fn was called successfully */ 464. ggetobj(word, fn, max) 465. char *word; 466. int (*fn),  max; 467. {  468.  char buf[BUFSZ]; 469. register char *ip; 470. register char sym; 471. register int oletct = 0, iletct = 0; 472. register boolean allflag = FALSE; 473. char olets[20], ilets[20]; 474. int (*ckfn) = (int (*)) 0; 475. xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0;	/* BAH */ 476. 	if(!invent && !allowgold){ 477. 		pline("You have nothing to %s.", word); 478. 		return(0); 479. 	} else { 480. 		register struct obj *otmp = invent; 481. 		register int uflg = 0; 482.  483.  		if(allowgold) ilets[iletct++] = GOLD_SYM; 484. 		ilets[iletct] = 0; 485. 		while(otmp) { 486. 			if(!index(ilets, otmp->olet)){ 487. 				ilets[iletct++] = otmp->olet; 488. 				ilets[iletct] = 0; 489. 			}  490.  			if(otmp->unpaid) uflg = 1; 491. 			otmp = otmp->nobj; 492. 		}  493.  		ilets[iletct++] = ' '; 494. 		if(uflg) ilets[iletct++] = 'u'; 495. 		if(invent) ilets[iletct++] = 'a'; 496. 		ilets[iletct] = 0; 497. 	}  498.  	pline("What kinds of thing do you want to %s? [%s] ",  499.  		word, ilets); 500. 	getlin(buf); 501. 	if(buf[0] == '\033') { 502. 		clrlin; 503. 		return(0); 504. 	}  505.  	ip = buf; 506. 	olets[0] = 0; 507. 	while(sym = *ip++){ 508. 		if(sym == ' ') continue; 509. 		if(sym == GOLD_SYM) { 510. 			if(allowgold == 1) 511. 				(*fn)(mkgoldobj(u.ugold)); 512. 			else if(!u.ugold) 513. 				pline("You have no gold."); 514. 			allowgold = 2; 515. 		} else 516. 		if(sym == 'a' || sym == 'A') allflag = TRUE; else 517. 		if(sym == 'u' || sym == 'U') ckfn = ckunpaid; else 518. #ifdef SPELLS 519. 		if(index("!%?[=*/+\"0", sym)){  520.  #else  521.  		if(index("!%?[=*/\"0", sym)){ 522. #endif 523. 			if(!index(olets, sym)){ 524. 				olets[oletct++] = sym; 525. 				olets[oletct] = 0; 526. 			}  527.  		}  528.  		else pline("You don't have any %c's.", sym); 529. 	}  530.  	if(allowgold == 2 && !oletct) 531. 		return(1);	/* he dropped gold (or at least tried to) */ 532. 	else 533. 		return(askchain(invent, olets, allflag, fn, ckfn, max)); 534. }  535.   536.  /*  537.   * Walk through the chain starting at objchn and ask for all objects 538.  * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL) 539.  * whether the action in question (i.e., fn) has to be performed. 540.  * If allflag then no questions are asked. Max gives the max nr of 541. * objects to be treated. Return the number of objects treated. 542.  */  543.  askchain(objchn, olets, allflag, fn, ckfn, max) 544. struct obj *objchn; 545. register char *olets; 546. int allflag; 547. int (*fn), (*ckfn); 548. int max; 549. {  550.  register struct obj *otmp, *otmp2; 551. register char sym, ilet; 552. register int cnt = 0; 553. #ifdef SORTING 554. 	/* changes so the askchain is interrogated in the order specified. 555. 	 * For example, if a person specifies =/ then first all rings will be  556. * asked about followed by all wands -dgk 557. 	 */  558.  nextclass: 559. #endif 560. 	ilet = 'a'-1; 561. 	for(otmp = objchn; otmp; otmp = otmp2){ 562. 		if(ilet == 'z') ilet = 'A'; else ilet++; 563. 		otmp2 = otmp->nobj; 564. #ifdef SORTING 565. 		if (olets && *olets && otmp->olet != *olets) continue; 566. #else 567. 		if(olets && *olets && !index(olets, otmp->olet)) continue; 568. #endif 569. 		if(ckfn && !(*ckfn)(otmp)) continue; 570. 		if(!allflag) { 571. 			pline(xprname(otmp, ilet)); 572. 			addtopl(" [nyaq]? "); 573. 			sym = readchar; 574. 		}  575.  		else	sym = 'y'; 576.  577.  		switch(sym){ 578. 		case 'a': 579. 			allflag = 1; 580. 		case 'y': 581. 			cnt += (*fn)(otmp); 582. 			if(--max == 0) goto ret; 583. 		case 'n': 584. 		default: 585. 			break; 586. 		case 'q': 587. 			goto ret; 588. 		}  589.  	}  590.  #ifdef SORTING 591. 	if (olets && *olets && *++olets) 592. 		goto nextclass; 593. #endif 594. 	pline(cnt ? "That was all." : "No applicable objects."); 595. ret: 596. 	return(cnt); 597. }  598.   599.  obj_to_let(obj)	/* should of course only be called for things in invent */ 600. register struct obj *obj; 601. {  602.  	register struct obj *otmp; 603. 	register char ilet; 604.  605.  	if(flags.invlet_constant) 606. 		return(obj->invlet); 607. 	ilet = 'a'; 608. 	for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj) 609. 		if(++ilet > 'z') ilet = 'A'; 610. 	return(otmp ? ilet : NOINVSYM); 611. }  612.   613.  prinv(obj) 614. register struct obj *obj; 615. {  616.  	pline(xprname(obj, obj_to_let(obj))); 617. }  618.   619.  static char * 620. xprname(obj,let) 621. register struct obj *obj; 622. register char let; 623. {  624.  	static char li[BUFSZ]; 625.  626.  	(void) sprintf(li, "%c - %s.",  627.  		flags.invlet_constant ? obj->invlet : let,  628.  		doname(obj)); 629. 	return(li); 630. }  631.   632.  ddoinv 633. {  634.  	doinv((char *) 0); 635. 	return(0); 636. }  637.   638.  #ifdef SORTING 639. # ifdef SPELLS 640. char inv_order[] = "\")[%?+/=!(*0_`";	/* to be safe, include _ and ` */  641.  # else  642.  char inv_order[] = "\")[%?/=!(*0_`"; 643. # endif 644. extern char *let_to_name; 645. #endif 646.  647.  /* called with 0 or "": all objects in inventory */ 648. /* otherwise: all objects with (serial) letter in lets */ 649. doinv(lets) 650. register char *lets; 651. {  652.  	register struct obj *otmp; 653. 	register char ilet; 654. 	int ct = 0; 655. 	char any[BUFSZ]; 656. #ifdef SORTING 657. 	char *invlet = inv_order; 658. 	int classcount = 0; 659. #endif /* SORTING /**/ 660.  661.  	morc = 0;		/* just to be sure */ 662.  663.  	if(!invent){ 664. 		pline("Not carrying anything."); 665. 		return; 666. 	}  667.   668.  	cornline(0, (char *) 0); 669. #ifdef SORTING 670. nextclass: 671. 	classcount = 0; 672. 	ilet = 'a'; 673. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 674. 		if(flags.invlet_constant) ilet = otmp->invlet; 675. 		if(!lets || !*lets || index(lets, ilet)) { 676. 			if (!flags.sortpack || otmp->olet == *invlet) { 677. 				if (flags.sortpack && !classcount) { 678. 					cornline(1, let_to_name(*invlet)); 679. 					classcount++; 680. 				}  681.  				cornline(1, xprname(otmp, ilet)); 682. 				any[ct++] = ilet; 683. 			}  684.  		}  685.  		if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 686. 	}  687.  	if (flags.sortpack && *++invlet) goto nextclass; 688. #else 689. 	ilet = 'a'; 690. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 691. 	    if(flags.invlet_constant) ilet = otmp->invlet; 692. 	    if(!lets || !*lets || index(lets, ilet)) { 693. 		    cornline(1, xprname(otmp, ilet)); 694. 		    any[ct++] = ilet; 695. 	    }  696.  	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 697. 	}  698.  #endif /* SORTING /**/ 699. 	any[ct] = 0; 700. 	cornline(2, any); 701. }  702.   703.  dotypeinv 				/* free after Robert Viduya */ 704. /* Changed to one type only, so he doesnt have to type cr */ 705. {  706.      char c, ilet; 707.     char stuff[BUFSZ]; 708.     register int stct; 709.     register struct obj *otmp; 710.     boolean billx = inshop && doinvbill(0); 711.     boolean unpd = FALSE; 712.  713.  	if (!invent && !u.ugold && !billx) { 714. 	    pline ("You aren't carrying anything."); 715. 	    return(0); 716. 	}  717.   718.  	stct = 0; 719. 	if(u.ugold) stuff[stct++] = GOLD_SYM; 720. 	stuff[stct] = 0; 721. 	for(otmp = invent; otmp; otmp = otmp->nobj) { 722. 	    if (!index (stuff, otmp->olet)) { 723. 		stuff[stct++] = otmp->olet; 724. 		stuff[stct] = 0; 725. 	    }  726.  	    if(otmp->unpaid) 727. 		unpd = TRUE; 728. 	}  729.  	if(unpd) stuff[stct++] = 'u'; 730. 	if(billx) stuff[stct++] = 'x'; 731. 	stuff[stct] = 0; 732.  733.  	if(stct > 1) { 734. #ifdef REDO 735. 	  if (!in_doagain) 736. #endif 737. 	    pline ("What type of object [%s] do you want an inventory of? ",  738.  		stuff); 739. 	    c = readchar; 740. #ifdef REDO 741. 	    savech(c); 742. #endif 743. 	    if(index(quitchars,c)) { 744. 	    	    clrlin; 745. 	    	    return(0); 746. 	    }  747.  	} else 748. 	    c = stuff[0]; 749.  750.  	if(c == GOLD_SYM) 751. 	    return(doprgold); 752.  753.  	if(c == 'x' || c == 'X') { 754. 	    if(billx) 755. 		(void) doinvbill(1); 756. 	    else 757. 		pline("No used-up objects on the shopping bill."); 758. 	    return(0); 759. 	}  760.   761.  	if((c == 'u' || c == 'U') && !unpd) { 762. 		pline("You are not carrying any unpaid objects."); 763. 		return(0); 764. 	}  765.   766.  	stct = 0; 767. 	ilet = 'a'; 768. 	for (otmp = invent; otmp; otmp = otmp -> nobj) { 769. 	    if(flags.invlet_constant) ilet = otmp->invlet; 770. 	    if (c == otmp -> olet || (c == 'u' && otmp -> unpaid)) 771. 		stuff[stct++] = ilet; 772. 	    if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A'; 773. 	}  774.  	stuff[stct] = '\0'; 775. 	if(stct == 0) 776. 		pline("You have no such objects."); 777. 	else 778. 		doinv (stuff); 779.  780.  	return(0); 781. }  782.   783.  /* look at what is here */ 784. dolook { 785.     register struct obj *otmp, *otmp0; 786.     register struct gold *gold; 787.     char *verb = Blind ? "feel" : "see"; 788.     int	ct = 0; 789.     int fd = 0; 790.  791.  #ifdef KAA 792.     read_engr_at(u.ux, u.uy); /* Eric Backus */ 793. #endif 794.     if(!u.uswallow) { 795. 	otmp0 = o_at(u.ux, u.uy); 796. 	gold = g_at(u.ux, u.uy); 797.     }  else  { 798. 	pline("You %s no objects here.", verb); 799. 	return(!!Blind); 800.     }  801.   802.      /* added by GAN 10/30/86 */ 803. #ifdef FOUNTAINS 804.     if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  { 805. 	fd++; 806. 	pline("There is a fountain here."); 807.     }  808.  #endif 809. #ifdef NEWCLASS 810.     if(IS_THRONE(levl[u.ux][u.uy].typ))  { 811. 	fd++; 812. 	pline("There is an opulent throne here."); 813.     }     814.  #endif 815. #ifdef SINKS 816.     if(IS_SINK(levl[u.ux][u.uy].typ))  { 817. 	fd++; 818. 	pline("There is a kitchen sink here."); 819.     }  820.  #endif 821.     if(u.ux == xupstair && u.uy == yupstair)  { 822. 	fd++; 823. 	pline("There is a stairway up here."); 824.     }  825.      if(u.ux == xdnstair && u.uy == ydnstair)  { 826. 	fd++; 827. 	pline("There is a stairway down here."); 828.     }  829.      if(Blind)  { 830. 	 pline("You try to feel what is lying here on the floor."); 831. 	 if(Levitation)  { 832. 		pline("But you can't reach it!"); 833. 		return(0); 834. 	 }  835.      }  836.    837.      if(!otmp0 && !gold) { 838. 	if(Blind || !fd) 839. 		pline("You %s no objects here.", verb); 840. 	return(!!Blind); 841.     }  842.   843.      cornline(0, "Things that are here:"); 844.     for(otmp = otmp0; otmp; otmp = otmp->nobj) { 845. 	if(otmp->ox == u.ux && otmp->oy == u.uy) { 846. 	    ct++; 847. 	    cornline(1, doname(otmp)); 848. 			  849.  	    if(Blind && otmp->otyp == DEAD_COCKATRICE && !uarmg) { 850. 		pline("Touching the dead cockatrice is a fatal mistake ..."); 851. 		pline("You die ..."); 852. 		killer = "dead cockatrice"; 853. 		done("died"); 854. 	    }  855.  	}  856.      }  857.   858.      if(gold) { 859. 	char gbuf[30]; 860.  861.  	(void) sprintf(gbuf, "%ld gold piece%s",  862.  		gold->amount, plur(gold->amount)); 863. 	if(!ct++) 864. 	    pline("You %s here %s.", verb, gbuf); 865. 	else 866. 	    cornline(1, gbuf); 867.     }  868.   869.      if(ct == 1 && !gold) { 870. 	pline("You %s here %s.", verb, doname(otmp0)); 871. 	cornline(3, (char *) 0); 872.     }  873.      if(ct > 1) 874. 	cornline(2, (char *) 0); 875.     return(!!Blind); 876. }  877.   878.  stackobj(obj) register struct obj *obj; { 879. register struct obj *otmp = fobj; 880. 	for(otmp = fobj; otmp; otmp = otmp->nobj) if(otmp != obj) 881. 	if(otmp->ox == obj->ox && otmp->oy == obj->oy &&  882.  		merged(obj,otmp,1)) 883. 			return; 884. }  885.   886.  /* merge obj with otmp and delete obj if types agree */ 887. merged(otmp,obj,lose) register struct obj *otmp, *obj; { 888. 	if(obj->otyp == otmp->otyp &&  889.  	  obj->unpaid == otmp->unpaid &&  890.  	  obj->spe == otmp->spe &&  891.  	  obj->dknown == otmp->dknown &&  892.  	  obj->cursed == otmp->cursed &&  893.  #ifdef SPELLS  894.  	  (index("%*?!+", obj->olet) || 895. #else 896. 	  (index("%*?!", obj->olet) ||  897.  #endif  898.  	    (obj->known == otmp->known && 899. 		(obj->olet == WEAPON_SYM && obj->otyp < BOOMERANG)))) {  900.  		otmp->quan += obj->quan;  901.  		otmp->owt += obj->owt;  902.  		if(lose) freeobj(obj);  903.  		obfree(obj,otmp);	/* free(obj), bill->otmp */  904.  		return(1);  905.  	} else	return(0);  906.  }  907.   908.  /*  909.   * Gold is no longer displayed; in fact, when you have a lot of money,  910.   * it may take a while before you have counted it all.  911.   * [Bug: d$ and pickup still tell you how much it was.]  912.   */  913.  extern int (*occupation);  914.  extern char *occtxt;  915.  static long goldcounted;  916.   917.  countgold{  918.  	if((goldcounted += 100*(u.ulevel + 1)) >= u.ugold) {  919.  		long eps = 0;  920.  		if(!rn2(2)) eps = rnd((int) (u.ugold/100 + 1));  921.  		pline("You probably have about %ld gold pieces.", 922. 			u.ugold + eps);  923.  		return(0);	/* done */  924.  	}  925.  	return(1);		/* continue */  926.  }  927.   928.  doprgold{  929.  	if(!u.ugold)  930.  		pline("You do not carry any gold.");  931.  	else if(u.ugold <= 500)  932.  		pline("You are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));  933.  	else {  934.  		pline("You sit down in order to count your gold pieces.");  935.  		goldcounted = 500;  936.  		occupation = countgold;  937.  		occtxt = "counting your gold";  938.  	}  939.  	return(1);  940.  }  941.   942.  /* --- end of gold counting section --- */  943.   944.  doprwep{  945.  	if(!uwep) pline("You are empty handed.");  946.  	else prinv(uwep);  947.  	return(0);  948.  }  949.   950.  doprarm{  951.  #ifdef SHIRT  952.  	if(!uarm && !uarmg && !uarms && !uarmh && !uarmu)  953.  #else  954.  	if(!uarm && !uarmg && !uarms && !uarmh)  955.  #endif 956. 		pline("You are not wearing any armor."); 957. 	else { 958. #ifdef SHIRT 959. 		char lets[7]; 960. #else 961. 		char lets[6]; 962. #endif 963. 		register int ct = 0; 964.  965.  #ifdef SHIRT 966. 		if(uarmu) lets[ct++] = obj_to_let(uarmu); 967. #endif 968. 		if(uarm) lets[ct++] = obj_to_let(uarm); 969. 		if(uarm2) lets[ct++] = obj_to_let(uarm2); 970. 		if(uarmh) lets[ct++] = obj_to_let(uarmh); 971. 		if(uarms) lets[ct++] = obj_to_let(uarms); 972. 		if(uarmg) lets[ct++] = obj_to_let(uarmg); 973. 		lets[ct] = 0; 974. 		doinv(lets); 975. 	}  976.  	return(0); 977. }  978.   979.  doprring{ 980. 	if(!uleft && !uright) 981. 		pline("You are not wearing any rings."); 982. 	else { 983. 		char lets[3]; 984. 		register int ct = 0; 985.  986.  		if(uleft) lets[ct++] = obj_to_let(uleft); 987. 		if(uright) lets[ct++] = obj_to_let(uright); 988. 		lets[ct] = 0; 989. 		doinv(lets); 990. 	}  991.  	return(0); 992. }  993.   994.  digit(c) char c; { 995. 	return(c >= '0' && c <= '9'); 996. }  997.   998.  /*  999.   * useupf(obj) 1000. * uses up an object that's on the floor 1001. */  1002. useupf(obj) 1003. register struct obj *obj; 1004. { 1005. 	if(obj->quan > 1)  { 1006. 		obj->quan--; 1007. 		obj->owt = weight(obj); 1008. 	} else delobj(obj); 1009. } 1010.  1011. #ifdef SORTING 1012. /* 1013.  * Convert from a symbol to a string for printing object classes 1014. *  1015.  * Names from objects.h  1016. * char obj_symbols[] = { 1017. *	ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM, 1018. *	BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, 1019. *	WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 }; 1020. */  1021. #define Sprintf (void) sprintf 1022. 1023. extern char obj_symbols[]; 1024. static char *names[] = {"Illegal objects", "Amulets", "Comestibles", "Weapons", 1025. 			"Tools", "Iron balls", "Chains", "Rocks", "Armor", 1026. 			"Potions", "Scrolls", "Wands", 1027. #ifdef SPELLS 1028. 			"Spellbooks", 1029. #endif 1030. 			"Rings", "Gems"}; 1031. char * 1032. let_to_name(let) 1033. char let; 1034. { 1035. 	char *pos = index(obj_symbols, let); 1036. 	extern char *HI, *HE; 1037. 	/* arbitrary buffer size by Tom May (tom@uw-warp) */ 1038. 	static char *buf = NULL; 1039. 1040. 	if (buf == NULL) 1041. 	   buf = (char *) alloc ((unsigned)(strlen(HI)+strlen(HE)+15+1)); 1042. 1043. 	if (pos == NULL) pos = obj_symbols; 1044. 	if (HI && HE) 1045. 	   Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE); 1046. 	else 1047. 	   Sprintf(buf, "%s", names[pos - obj_symbols]); 1048. 	return (buf); 1049. } 1050. #endif /* SORTING /**/ 1051. 1052. reassign 1053. { 1054. 	register int i;  1055. register struct obj *obj; 1056. 1057. 	for(obj = invent, i = 0; obj; obj = obj->nobj, i++) 1058. 		obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26); 1059. 	lastinvnr = i; 1060. }