Source:NetHack 3.0.0/pri.c

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

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

1.   /*	SCCS Id: @(#)pri.c	3.0	89/06/16 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    /* block some unused #defines to avoid overloading some cpp's */ 6.   #define MONATTK_H 7.   #include "hack.h"  8.    #include   /* for isalpha */ 9.    10.   static void hilite P((uchar, uchar)); 11.  static void cornbot P((int)); 12.  static boolean ismnst P((char)); 13.  #if !defined(DECRAINBOW) && !defined(UNIX) 14.  #  define g_putch  (void) putchar 15.  #endif 16.   17.   #ifndef g_putch 18.  static boolean GFlag = FALSE; /* graphic flag */ 19.  #endif 20.   21.   /* 100 suffices for bot; must be larger than COLNO */ 22.  #define MAXCO 100 23.  static char oldbot1[MAXCO], newbot1[MAXCO]; 24.  static char oldbot2[MAXCO], newbot2[MAXCO]; 25.  static const char *dispst = "*0#@#0#*0#@#0#*0#@#0#*0#@#0#*0#@#0#*"; 26.  static int mrank_sz = 0;  /* loaded by max_rank_sz (called in u_init) */ 27.   28.   void 29.  swallowed(first) 30.  register int first; 31.  {  32.   	if(first) cls; 33.  	else { 34.  		curs(u.ustuck->mdx-1, u.ustuck->mdy+1); 35.  		(void) fputs("   ", stdout); 36.  		curx = u.ustuck->mdx+2; 37.  		curs(u.ustuck->mdx-1, u.ustuck->mdy+2); 38.  		(void) fputs("   ", stdout); 39.  		curx = u.ustuck->mdx+2; 40.  		curs(u.ustuck->mdx-1, u.ustuck->mdy+3); 41.  		(void) fputs("   ", stdout); 42.  		curx = u.ustuck->mdx+2; 43.  	}  44.   	curs(u.ux-1, u.uy+1); 45.  	(void) fputs("/-\\", stdout); 46.  	curx = u.ux+2; 47.  	curs(u.ux-1, u.uy+2); 48.  	(void) putchar('|'); 49.  	hilite(u.usym, AT_MON); 50.  	(void) putchar('|'); 51.  	curx = u.ux+2; 52.  	curs(u.ux-1, u.uy+3); 53.  	(void) fputs("\\-/", stdout); 54.  	curx = u.ux+2; 55.  	u.udispl = 1; 56.  	u.udisx = u.ux; 57.  	u.udisy = u.uy; 58.  }  59.    60.   void 61.  setclipped 62.  {  63.   	error("NetHack needs a screen of size at least %d by %d.\n",  64.   		ROWNO+3, COLNO); 65.  }  66.    67.   /*  68.    *  Allow for a different implementation than this...  69. */ 70.    71.   #ifndef g_putch 72.   73.   static void 74.  g_putch(ch) 75.  uchar ch; 76.  {  77.   	if (ch & 0x80) { 78.  		if (!GFlag) { 79.  			graph_on; 80.  			GFlag = TRUE; 81.  		}  82.   		(void) putchar(ch ^ 0x80); /* Strip 8th bit */ 83.  	} else { 84.  		if (GFlag) { 85.  			graph_off; 86.  			GFlag = FALSE; 87.  		}  88.   		(void) putchar(ch); 89.  	}  90.   }  91.    92.   #endif 93.   94.   static boolean 95.  showmon(mon) 96.  register struct monst *mon; 97.  {  98.   	register boolean show = (Blind && Telepat) || canseemon(mon); 99.   100.  	if (!show && (HTelepat & WORN_HELMET)) 101. 		show = (dist(mon->mx, mon->my) <= (BOLT_LIM * BOLT_LIM)); 102. 	return(show); 103. }  104.   105.  void 106. at(x,y,ch,typ) 107. register xchar x,y; 108. uchar ch,typ; 109. {  110.  #ifndef LINT 111. 	/* if xchar is unsigned, lint will complain about  if(x < 0)  */ 112. 	if(x < 0 || x > COLNO-1 || y < 0 || y > ROWNO-1) { 113. 		impossible("At gets 0%o at %d %d.", ch, x, y); 114. 		return; 115. 	}  116.  #endif 117. 	if(!ch) { 118. 		impossible("At gets null at %d %d.", x, y); 119. 		return; 120. 	}  121.   122.  	if (typ == AT_APP  123.  #ifndef MSDOS  124.  	    && flags.standout  125.  #endif  126.  	   ) 127. 		/* don't hilite if this isn't a monster or object. 128. 		 *  129.  		 * not complete; a scroll dropped by some monster 130. 		 * on an unseen doorway which is later magic mapped 131. 		 * will still hilite the doorway symbol. -3. 132.  		 */  133.  		if (!vism_at(x,y) &&  134.  		    (!levl[x][y].omask && !levl[x][y].gmask || is_pool(x,y))) 135. 		    typ = AT_MAP; 136.  137.  	y += 2; 138. 	curs(x,y); 139.  140.  	hilite(ch,typ); 141. 	curx++; 142. }  143.   144.  void 145. prme{ 146. 	if(!Invisible  147.  #ifdef POLYSELF  148.  			&& !u.uundetected  149.  #endif  150.  					) at(u.ux,u.uy,u.usym,AT_U); 151. }  152.   153.  void 154. shieldeff(x, y)		/* produce a magical shield effect at x,y */ 155. 	register xchar x, y;  156. { 157.  	register char *ch; 158. 	register struct monst *mtmp = 0; 159.  160.  	if((x != u.ux) || (y != u.uy)) { 161. 	    if(!(mtmp = m_at(x, y))) { 162.  163.  		impossible("shield effect at %d,%d", x, y); 164. 		return; 165. 	    }  166.  	    if(!showmon(mtmp)) return; 167. 	}  168.   169.  	for(ch = dispst; *ch; ch++)  { 170. 		at(x, y, (uchar) *ch, AT_ZAP); 171. 		(void) fflush(stdout); 172. 		delay_output; 173. 		delay_output; 174. 	}  175.   176.  	nomul(0); 177. 	if(!mtmp) { 178. 		if(Invisible) { 179. 			prl(x, y); 180. 			at(x, y, levl[x][y].scrsym, AT_APP); 181. 		} else prme; 182. 	} else { 183. 		mtmp->mdispl = 0;	/* make sure it gets redrawn */ 184. 		prl(x, y); 185. 		if(mtmp->minvis) 186. 			at(x, y, levl[x][y].scrsym, AT_APP); 187. 		else	at(x, y, (uchar) mtmp->data->mlet, AT_MON); 188. 	}  189.   190.  	return; 191. }  192.   193.  int 194. doredraw 195. {  196.  	docrt; 197. 	return 0; 198. }  199.   200.  void 201. docrt 202. {  203.  	register int x,y; 204. 	register struct rm *room; 205. 	register struct monst *mtmp; 206.  207.  	if(u.uswallow) { 208. 		swallowed(1); 209. 		return; 210. 	}  211.  	cls; 212.  213.  /* Some ridiculous code to get display of @ and monsters (almost) right */ 214. 	if(!Invisible  215.  #ifdef POLYSELF  216.  			|| u.uundetected  217.  #endif  218.  					) { 219. 		levl[(u.udisx = u.ux)][(u.udisy = u.uy)].scrsym = u.usym; 220. 		levl[u.udisx][u.udisy].seen = 1; 221. 		u.udispl = 1; 222. 	} else	u.udispl = 0; 223.  224.  	seemons;	/* reset old positions */ 225. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 226. 		mtmp->mdispl = 0; 227. 	seemons;	/* force new positions to be shown */ 228.  229.  #if defined(DGK) && !defined(MSDOSCOLOR) 230. 	/* Otherwise, line buffer the output to do the redraw in  231. * about 2/3 of the time. 232. 	 */  233.  		for(y = 0; y < ROWNO; y++) { 234. 			char buf[COLNO+1]; 235. 			int start, end; 236. #ifdef TOS 237. 			setmem(buf, COLNO, ' '); 238. #else 239. 			memset(buf, ' ', COLNO); 240. #endif /* TOS */ 241. 			for(x = 0, start = -1, end = -1; x < COLNO; x++) 242. 				if((room = &levl[x][y])->new) { 243. 					room->new = 0; 244. 					buf[x] = room->scrsym; 245. 					if (start < 0) 246. 						start = x;  247. end = x; 248. } else if(room->seen) { 249. 					buf[x] = room->scrsym; 250. 					if (start < 0) 251. 						start = x;  252. end = x; 253. } 254.  			if (end >= 0) { 255. 				buf[end + 1] = '\0'; 256. 				curs(start, y + 2); 257. 				(void) fputs(buf + start, stdout); 258. 				curx = end + 1; 259. 			}  260.  		}  261.  #else /* DGK && !MSDOSCOLOR */ 262. 	for(y = 0; y < ROWNO; y++) 263. 		for(x = 0; x < COLNO; x++) 264. 			if((room = &levl[x][y])->new) { 265. 				room->new = 0; 266. 				at(x,y,room->scrsym,AT_APP); 267. 			} else if(room->seen) 268. 				at(x,y,room->scrsym,AT_APP); 269. #endif /* DGK && !MSDOSCOLOR */ 270. #ifndef g_putch 271. 	if (GFlag) { 272. 		graph_off; 273. 		GFlag = FALSE; 274. 	}  275.  #endif 276. 	scrlx = COLNO; 277. 	scrly = ROWNO; 278. 	scrhx = scrhy = 0; 279. 	cornbot(0); 280. 	bot; 281. }  282.   283.  static void 284. cornbot(lth) 285. register int lth; 286. {  287.  	oldbot1[lth] = 0; 288. 	oldbot2[lth] = 0; 289. 	flags.botl = 1; 290. }  291.   292.  void 293. docorner(xmin, ymax) 294. register int xmin, ymax; 295. {  296.  	register int x, y;  297. register struct rm *room; 298. 	register struct monst *mtmp; 299.  300.  	if(u.uswallow) {	/* Can be done more efficiently */ 301. 		swallowed(1); 302. 		return; 303. 	}  304.   305.  	seemons;	/* reset old positions */ 306. 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) 307. 	    if(mtmp->mx >= xmin && mtmp->my < ymax) 308. 		mtmp->mdispl = 0; 309. 	seemons;	/* force new positions to be shown */ 310.  311.  	for(y = 0; y < ymax; y++) { 312. 		if(y > ROWNO+1 && CD) break; 313. 		curs(xmin,y+2); 314. 		cl_end; 315. 		if(y < ROWNO) { 316. 		    for(x = xmin; x < COLNO; x++) { 317. 			if((room = &levl[x][y])->new) { 318. 				room->new = 0; 319. 				at(x,y,room->scrsym,AT_APP); 320. 			} else 321. 				if(room->seen) 322. 					at(x,y,room->scrsym,AT_APP); 323. 		    }  324.  		}  325.  	}  326.  #ifndef g_putch 327. 	if (GFlag) { 328. 		graph_off; 329. 		GFlag = FALSE; 330. 	}  331.  #endif 332. 	/* Note:          y values: 0 to ymax-1 333. 	 * screen positions from y: 2 to ymax+1 334. 	 *            whole screen: 1 to ROWNO+3 335. 	 *                top line: 1 336. 	 *         dungeon display: 2 to ROWNO+1 337. 	 *       first bottom line: ROWNO+2 338. 	 *      second bottom line: ROWNO+3 339. 	 *         lines on screen: ROWNO+3 340. 	 */  341.  	if(ymax > ROWNO) { 342. 		cornbot(xmin-1); 343. 		if(ymax > ROWNO+2 && CD) {	/* clear portion of long */ 344. 			curs(1,ROWNO+4);	/* screen below status lines */ 345. 			cl_eos; 346. 		}  347.  	}  348.  }  349.   350.  void 351. seeglds 352. {  353.  	register struct gold *gold, *gold2; 354.  355.  	for(gold = fgold; gold; gold = gold2) { 356. 	    gold2 = gold->ngold; 357. 	    if(Hallucination && cansee(gold->gx,gold->gy)) 358. 		if(!(gold->gx == u.ux && gold->gy == u.uy) || Invisible) 359. 		    atl(gold->gx,gold->gy,rndobjsym); 360. 	}  361.  }  362.   363.  /* Trolls now regenerate thanks to KAA */ 364.  365.  void 366. seeobjs 367. {  368.  	register struct obj *obj, *obj2; 369.  370.  	for(obj = fobj; obj; obj = obj2) { 371. 	    obj2 = obj->nobj; 372.  373.  	    if(Hallucination && cansee(obj->ox,obj->oy)) 374. 		if(!(obj->ox == u.ux && obj->oy == u.uy) || Invisible) 375. 		    atl(obj->ox,obj->oy,rndobjsym); 376.  377.  	    if(obj->olet == FOOD_SYM && obj->otyp == CORPSE) { 378.  379.  		if(mons[obj->corpsenm].mlet == S_TROLL &&  380.  		    obj->age + 20 < moves) { 381. 			boolean visible = cansee(obj->ox,obj->oy); 382. 			struct monst *mtmp = revive(obj, FALSE); 383.  384.  			if (mtmp && visible) 385. 				pline("%s rises from the dead!", Monnam(mtmp)); 386. 		} else if (obj->age + 250 < moves) delobj(obj); 387. 	    }  388.  	}  389.   390.  	for(obj = invent; obj; obj = obj2) { 391. 	    obj2 = obj->nobj; 392. 	    if(obj->otyp == CORPSE) { 393. 		if(mons[obj->corpsenm].mlet == S_TROLL  394.  			    && obj->age + 20 < moves) { 395. 		    boolean wielded = (obj==uwep); 396. 		    struct monst *mtmp = revive(obj, TRUE); 397.  398.  		    if (mtmp && wielded) 399. 			pline("The %s %s writhes out of your grasp!",  400.  				mtmp->data->mname, xname(obj)); 401. 		    else if (mtmp) 402. 			You("feel squirming in your backpack!"); 403. 		} else if (obj->age + 250 < moves) useup(obj); 404. 	    }  405.  	}  406.  }  407.   408.  void 409. seemons 410. {  411.  	register struct monst *mtmp; 412.  413.  	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { 414. 	    if(mtmp->data->mlet == S_EEL) 415. 		mtmp->minvis = (u.ustuck != mtmp && is_pool(mtmp->mx,mtmp->my)); 416. 	    pmon(mtmp); 417. #ifdef WORM 418. 	    if(mtmp->wormno) wormsee(mtmp->wormno); 419. #endif 420. 	}  421.  }  422.   423.  void 424. pmon(mon) 425. register struct monst *mon; 426. {  427.  	register int show = showmon(mon); 428.  429.  	if(mon->mdispl) 430. 	    if(mon->mdx != mon->mx || mon->mdy != mon->my || !show) 431. 		unpmon(mon); 432.  433.  /* If you're hallucinating, the monster must be redrawn even if it has 434.  * already been printed. 435.  */  436.  	if(show && (!mon->mdispl || Hallucination)) { 437. 	    if (Hallucination) 438. 	    atl(mon->mx,mon->my,  439.  		(char) ((!mon->mimic || Protection_from_shape_changers) ? 440. 		rndmonsym : (mon->mappearance == DOOR_SYM) ? 441. 		DOOR_SYM : rndobjsym)); 442. 	    else 443.  444.  		atl(mon->mx,mon->my,  445.  		    (!mon->mappearance || 446. 		     Protection_from_shape_changers) ?  447.  		     mon->data->mlet : mon->mappearance); 448. 		mon->mdispl = 1; 449. 		mon->mdx = mon->mx; 450. 		mon->mdy = mon->my; 451. 	}  452.  #ifndef g_putch 453. 	if (GFlag) { 454. 		graph_off; 455. 		GFlag = FALSE; 456. 	}  457.  #endif 458. }  459.   460.  void 461. unpmon(mon) 462. register struct monst *mon; 463. {  464.  	if(mon->mdispl) { 465. 		newsym(mon->mdx, mon->mdy); 466. 		mon->mdispl = 0; 467. 	}  468.  }  469.   470.  void 471. nscr { 472. 	register int x, y;  473. register struct rm *room; 474.  475.  	if(u.uswallow || u.ux == FAR || flags.nscrinh) return; 476. 	pru; 477. 	for(y = scrly; y <= scrhy; y++) 478. 		for(x = scrlx; x <= scrhx; x++) 479. 			if((room = &levl[x][y])->new) { 480. 				room->new = 0; 481. 				at(x,y,room->scrsym,AT_APP); 482. 			}  483.  #ifndef g_putch 484. 	if (GFlag) { 485. 		graph_off; 486. 		GFlag = FALSE; 487. 	}  488.  #endif 489. 	scrhx = scrhy = 0; 490. 	scrlx = COLNO; 491. 	scrly = ROWNO; 492. }  493.   494.  /* Make sure that there are 18 entries in the rank arrays. */ 495.  /* 0 and even entries are male ranks, odd entries are female. */ 496.   497.  static const char *mage_ranks[] = { 498. 	"Evoker", 499. 	"Evoker", 500. 	"Conjurer", 501. 	"Conjurer", 502. 	"Thaumaturge", 503. 	"Thaumaturge", 504. 	"Magician", 505. 	"Magician", 506. 	"Enchanter", 507. 	"Enchanter", 508. 	"Sorcerer", 509. 	"Sorceress", 510. 	"Necromancer", 511. 	"Necromancer", 512. 	"Wizard", 513. 	"Wizard", 514. 	"Mage", 515. 	"Mage" 516. };  517.   518.  static const char *priest_ranks[] = { 519. 	"Aspirant", 520. 	"Aspirant", 521. 	"Acolyte", 522. 	"Acolyte", 523. 	"Adept", 524. 	"Adept", 525. 	"Priest", 526. 	"Priestess", 527. 	"Curate", 528. 	"Curate", 529. 	"Canon", 530. 	"Canoness", 531. 	"Lama", 532. 	"Lama", 533. 	"Patriarch", 534. 	"Matriarch", 535. 	"High Priest", 536. 	"High Priestess" 537. };  538.   539.  static const char *thief_ranks[] = { 540. 	"Footpad", 541. 	"Footpad", 542. 	"Cutpurse", 543. 	"Cutpurse", 544. 	"Rogue", 545. 	"Rogue", 546. 	"Pilferer", 547. 	"Pilferer", 548. 	"Robber", 549. 	"Robber", 550. 	"Burglar", 551. 	"Burglar", 552. 	"Filcher", 553. 	"Filcher", 554. 	"Magsman", 555. 	"Magswoman", 556. 	"Thief", 557. 	"Thief" 558. };  559.   560.  static const char *fighter_ranks[] = { 561. 	"Stripling", 562. 	"Stripling", 563. 	"Skirmisher", 564. 	"Skirmisher", 565. 	"Fighter", 566. 	"Fighter", 567. 	"Man-at-arms", 568. 	"Woman-at-arms", 569. 	"Warrior", 570. 	"Warrior", 571. 	"Swashbuckler", 572. 	"Swashbuckler", 573. 	"Hero", 574. 	"Heroine", 575. 	"Champion", 576. 	"Champion", 577. 	"Lord", 578. 	"Lady" 579. };  580.   581.  static const char *tourist_ranks[] = { 582. 	"Rambler", 583. 	"Rambler", 584. 	"Sightseer", 585. 	"Sightseer", 586. 	"Excursionist", 587. 	"Excursionist", 588. 	"Peregrinator", 589. 	"Peregrinator", 590. 	"Traveler", 591. 	"Traveler", 592. 	"Journeyer", 593. 	"Journeyer", 594. 	"Voyager", 595. 	"Voyager", 596. 	"Explorer", 597. 	"Explorer", 598. 	"Adventurer", 599. 	"Adventurer" 600. };  601.   602.  static const char *nomad_ranks[] = { 603. 	"Troglodyte", 604. 	"Troglodyte", 605. 	"Aborigine", 606. 	"Aborigine", 607. 	"Wanderer", 608. 	"Wanderer", 609. 	"Vagrant", 610. 	"Vagrant", 611. 	"Wayfarer", 612. 	"Wayfarer", 613. 	"Roamer", 614. 	"Roamer", 615. 	"Nomad", 616. 	"Nomad", 617. 	"Rover", 618. 	"Rover", 619. 	"Pioneer", 620. 	"Pioneer" 621. };  622.   623.  static const char *knight_ranks[] = { 624. 	"Gallant", 625. 	"Gallant", 626. 	"Esquire", 627. 	"Esquire", 628. 	"Bachelor", 629. 	"Bachelor", 630. 	"Sergeant", 631. 	"Sergeant", 632. 	"Knight", 633. 	"Knight", 634. 	"Banneret", 635. 	"Banneret", 636. 	"Chevalier", 637. 	"Chevalier", 638. 	"Seignieur", 639. 	"Seignieur", 640. 	"Paladin", 641. 	"Paladin" 642. };  643.   644.  static const char *archeo_ranks[] = { 645. 	"Digger", 646. 	"Digger", 647. 	"Field Worker", 648. 	"Field Worker", 649. 	"Investigator", 650. 	"Investigator", 651. 	"Exhumer", 652. 	"Exhumer", 653. 	"Excavator", 654. 	"Excavator", 655. 	"Spelunker", 656. 	"Spelunker", 657. 	"Speleologist", 658. 	"Speleologist", 659. 	"Collector", 660. 	"Collector", 661. 	"Curator", 662. 	"Curator" 663. };  664.   665.  static const char *healer_ranks[] = { 666. 	"Pre-Med", 667. 	"Pre-Med", 668. 	"Med Student", 669. 	"Med Student", 670. 	"Medic", 671. 	"Medic", 672. 	"Intern", 673. 	"Intern", 674. 	"Doctor", 675. 	"Doctor", 676. 	"Physician", 677. 	"Physician", 678. 	"Specialist", 679. 	"Specialist", 680. 	"Surgeon", 681. 	"Surgeon", 682. 	"Chief Surgeon", 683. 	"Chief Surgeon" 684. };  685.   686.  static const char *barbarian_ranks[] = { 687. 	"Plunderer", 688. 	"Plunderess", 689. 	"Pillager", 690. 	"Pillager", 691. 	"Bandit", 692. 	"Bandit", 693. 	"Brigand", 694. 	"Brigand", 695. 	"Raider", 696. 	"Raider", 697. 	"Reaver", 698. 	"Reaver", 699. 	"Slayer", 700. 	"Slayer", 701. 	"Chieftain", 702. 	"Chieftainess", 703. 	"Conqueror", 704. 	"Conqueress" 705. };  706.   707.  static const char *ninja_ranks[] = { 708. 	"Chigo", 709. 	"Chigo", 710. 	"Bushi", 711. 	"Bushi", 712. 	"Genin", 713. 	"Genin", 714. 	"Genin", 715. 	"Genin", 716. 	"Chunin", 717. 	"Chunin", 718. 	"Chunin", 719. 	"Chunin", 720. 	"Jonin", 721. 	"Jonin", 722. 	"Jonin", 723. 	"Jonin", 724. 	"Jonin", 725. 	"Jonin", 726. };  727.   728.  static const char *elf_ranks[] = { 729. 	"Edhel", 730. 	"Elleth", 731. 	"Edhel", 732. 	"Elleth", 	/* elf-maid */ 733. 	"Ohtar", 	/* warrior */ 734. 	"Ohtie", 735. 	"Kano", 	/* commander (Q.) ['a] */ 736. 	"Kanie", 	/* educated guess, until further research- SAC */ 737. 	"Arandur", 	/* king's servant, minister (Q.) - educated guess */ 738. 	"Aranduriel", 	/* educated guess */ 739. 	"Hir", 		/* lord (S.) */ 740. 	"Hiril", 	/* lady (S.) ['ir] */ 741. 	"Aredhel", 	/* noble elf (S.) */ 742. 	"Arwen", 	/* noble maiden (S.) */ 743. 	"Ernil", 	/* prince (S.) */ 744. 	"Elentariel", 	/* elf-maiden (Q.) */ 745. 	"Elentar", 	/* Star-king (Q.) */ 746. 	"Elentari", 	/* Star-queen (Q.) */ /* Elbereth (S.) */ 747. };  748.   749.  static const char ** 750. rank_array { 751. 	register const char **ranks; 752.  753.  	switch(pl_character[0]) { 754. 		case 'A':  ranks = archeo_ranks; break; 755. 		case 'B':  ranks = barbarian_ranks; break; 756. 		case 'C':  ranks = nomad_ranks; break; 757. 		case 'E':  ranks = elf_ranks; break; 758. 		case 'H':  ranks = healer_ranks; break; 759. 		case 'K':  ranks = knight_ranks; break; 760. 		case 'P':  ranks = priest_ranks; break; 761. 		case 'R':  ranks = thief_ranks; break; 762. 		case 'S':  ranks = ninja_ranks; break; 763. 		case 'T':  ranks = tourist_ranks; break; 764. 		case 'V':  ranks = fighter_ranks; break; 765. 		case 'W':  ranks = mage_ranks; break; 766. 		default:   ranks = 0; break; 767. 	}  768.  	return(ranks); 769. }  770.   771.  static char * 772. rank { 773. 	register int place; 774. 	register const char **ranks = rank_array; 775.  776.  	if(u.ulevel < 3) place = 0; 777. 	else if(u.ulevel <  6) place =  2; 778. 	else if(u.ulevel < 10) place =  4; 779. 	else if(u.ulevel < 14) place =  6; 780. 	else if(u.ulevel < 18) place =  8; 781. 	else if(u.ulevel < 22) place = 10; 782. 	else if(u.ulevel < 26) place = 12; 783. 	else if(u.ulevel < 30) place = 14; 784. 	else place = 16; 785. 	if(flags.female) place++; 786.  787.  	if (!!ranks) return(ranks[place]); 788. 	return(pl_character); 789. }  790.   791.  void 792. max_rank_sz { 793. 	register int i, maxr = 0; 794. 	register const char **ranks = rank_array; 795.  796.  	if (!!ranks) { 797. 		for(i = flags.female; i < 18; i += 2) 798. 			if(strlen(ranks[i]) > maxr) maxr = strlen(ranks[i]); 799. 		mrank_sz = maxr; 800. 	}  801.  	else mrank_sz = strlen(pl_character); 802. }  803.   804.  static void 805. fillbot(row,oldbot,newbot) 806. int row; 807. char *oldbot, *newbot; 808. {  809.  	register char *ob = oldbot, *nb = newbot; 810. 	register int i;  811. int fillcol; 812.  813.  	fillcol = min(CO, MAXCO-1); 814.  815.  	/* compress in case line too long */ 816. 	if(strlen(newbot) >= fillcol) { 817. 		register char *bp0 = newbot, *bp1 = newbot; 818.  819.  		do { 820. 			if(*bp0 != ' ' || bp0[1] != ' ' || bp0[2] != ' ') 821. 				*bp1++ = *bp0; 822. 		} while(*bp0++); 823. 	}  824.  	newbot[fillcol] = '\0'; 825.  826.  	for(i = 1; i < fillcol; i++) { 827. 		if(!*nb) { 828. 			if(*ob || flags.botlx) { 829. 				/* last char printed may be in middle of line */ 830. 				curs(strlen(newbot)+1,row); 831. 				cl_end; 832. 			}  833.  			break; 834. 		}  835.  		if(*ob != *nb) { 836. 			curs(i,row); 837. 			(void) putchar(*nb); 838. 			curx++; 839. 		}  840.  		if(*ob) ob++; 841. 		nb++; 842. 	}  843.  	Strcpy(oldbot, newbot); 844. }  845.   846.  static void 847. bot1 848. {  849.  	register int i,j; 850.  851.  	Strcpy(newbot1, plname); 852. 	if('a' <= newbot1[0] && newbot1[0] <= 'z') newbot1[0] += 'A'-'a'; 853. 	newbot1[10] = 0; 854. 	Sprintf(eos(newbot1)," the "); 855. #ifdef POLYSELF 856. 	if (u.mtimedone) { 857. 		char mbot[BUFSZ]; 858. 		int k = 0; 859.  860.  		Strcpy(mbot, mons[u.umonnum].mname); 861. 		while(mbot[k] != 0) { 862. 		    if ((k == 0 || (k > 0 && mbot[k-1] == ' ')) &&  863.  					'a' <= mbot[k] && mbot[k] <= 'z') 864. 			mbot[k] += 'A' - 'a'; 865. 		    k++; 866. 		}  867.  		Sprintf(eos(newbot1), mbot); 868. 	} else 869. 		Sprintf(eos(newbot1), rank); 870. #else 871. 	Sprintf(eos(newbot1), rank); 872. #endif 873. 	Sprintf(eos(newbot1),"  "); 874. 	i = mrank_sz + 15; 875. 	j = strlen(newbot1); 876. 	if((i - j) > 0) 877. 	      do { Sprintf(eos(newbot1)," "); /* pad with spaces */ 878. 		   i--; 879. 	      } while((i - j) > 0); 880. 	if(ACURR(A_STR)>18) { 881. 		if(ACURR(A_STR)>118) 882. 		    Sprintf(eos(newbot1),"St:%2d ",ACURR(A_STR)-100); 883. 		else if(ACURR(A_STR)<118) 884. 		    Sprintf(eos(newbot1), "St:18/%02d ",ACURR(A_STR)-18); 885. 		else 886. 		    Sprintf(eos(newbot1),"St:18/** "); 887. 	} else 888. 		Sprintf(eos(newbot1), "St:%-1d ",ACURR(A_STR)); 889. 	Sprintf(eos(newbot1),  890.  		"Dx:%-1d Co:%-1d In:%-1d Wi:%-1d Ch:%-1d",  891.  		ACURR(A_DEX), ACURR(A_CON), ACURR(A_INT), ACURR(A_WIS), ACURR(A_CHA)); 892. 	Sprintf(eos(newbot1), (u.ualigntyp == U_CHAOTIC) ? "  Chaotic" :  893.  			(u.ualigntyp == U_NEUTRAL) ? "  Neutral" : "  Lawful"); 894. #ifdef SCORE_ON_BOTL 895. 	Sprintf(eos(newbot1)," S:%lu"  896.  	    ,(u.ugold - u.ugold0 > 0 ? u.ugold - u.ugold0 : 0) 897.  	    + u.urexp + (50 * maxdlevel)  898.  	    + (maxdlevel > 20? 1000*((maxdlevel > 30) ? 10 : maxdlevel - 20) :0)); 899. #endif 900. 	fillbot(ROWNO+2, oldbot1, newbot1); 901. }  902.   903.  static void 904. bot2 905. {  906.  #ifdef ENDGAME 907. 	if(dlevel == ENDLEVEL) 908. 		Sprintf(newbot2, "EndLevel "); 909. 	else 910. #endif 911. #ifdef SPELLS 912. 		Sprintf(newbot2, "Dlvl:%-2d ", dlevel); 913. #else 914. 		Sprintf(newbot2, "Level:%-1d ", dlevel); 915. #endif 916. 	Sprintf(eos(newbot2),  917.  #ifdef SPELLS  918.  		"G:%-2ld HP:%d(%d) Pw:%d(%d) AC:%-2d",  919.  		u.ugold,  920.  # ifdef POLYSELF  921.  		u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax,  922.  		u.uen, u.uenmax, u.uac); 923. # else 924. 		u.uhp, u.uhpmax, u.uen, u.uenmax, u.uac);  925.  # endif  926.  #else  927.  		"Gold:%-1lu HP:%d(%d) AC:%-1d",  928.  		u.ugold,  929.  # ifdef POLYSELF  930.  		u.mtimedone ? u.mh : u.uhp, u.mtimedone ? u.mhmax : u.uhpmax,  931.  		u.uac); 932. # else 933. 		u.uhp, u.uhpmax, u.uac);  934.  # endif  935.  #endif  936.  #ifdef POLYSELF  937.  	if (u.mtimedone)  938.  		Sprintf(eos(newbot2), " HD:%d", mons[u.umonnum].mlevel);  939.  	else  940.  #endif  941.  #ifdef EXP_ON_BOTL  942.  	Sprintf(eos(newbot2), " Xp:%u/%-1ld", u.ulevel,u.uexp);  943.  #else  944.  	Sprintf(eos(newbot2), " Exp:%u", u.ulevel);  945.  #endif  946.  	if(flags.time)  947.  	    Sprintf(eos(newbot2), " T:%ld", moves);  948.  	if(strcmp(hu_stat[u.uhs], "        ")) {  949.  		Sprintf(eos(newbot2), " ");  950.  		Strcat(newbot2, hu_stat[u.uhs]);  951.  	}  952.  	if(Confusion)	   Sprintf(eos(newbot2), " Conf");  953.  	if(Sick)	   Sprintf(eos(newbot2), " Sick");  954.  	if(Blinded)	   Sprintf(eos(newbot2), " Blind");  955.  	if(Stunned)	   Sprintf(eos(newbot2), " Stun");  956.  	if(Hallucination)  Sprintf(eos(newbot2), " Hallu");  957.  	fillbot(ROWNO+3, oldbot2, newbot2); 958. }  959.   960.  void 961. bot { 962. register char *ob1 = oldbot1, *ob2 = oldbot2; 963. 	if(flags.botlx) *ob1 = *ob2 = 0; 964. 	bot1; 965. 	bot2; 966. 	flags.botl = flags.botlx = 0; 967. }  968.   969.   970.  void 971. mstatusline(mtmp) 972. register struct monst *mtmp; 973. {  974.  	pline("Status of %s (%s): ", mon_nam(mtmp),  975.  		(mtmp->data->maligntyp <= -1) ? "chaotic" :  976.  		mtmp->data->maligntyp ? "lawful" : "neutral"); 977. 	pline("Level %d  Gold %lu  HP %d(%d)",  978.  	    mtmp->m_lev, mtmp->mgold, mtmp->mhp, mtmp->mhpmax); 979. 	pline("AC %d%s%s", mtmp->data->ac,  980.  	    mtmp->mcan ? ", cancelled" : "" ,mtmp->mtame ? ", tame" : ""); 981. }  982.   983.  void 984. ustatusline 985. {  986.  	pline("Status of %s (%s%s):", plname,  987.  		(u.ualign > 3) ? "stridently " :  988.  		(u.ualign == 3) ? "" :  989.  		(u.ualign >= 1) ? "haltingly " :  990.  		(u.ualign == 0) ? "nominally " :  991.  				"insufficiently ",  992.  		(u.ualigntyp == U_CHAOTIC) ? "chaotic" :  993.  		u.ualigntyp ? "lawful" : "neutral"); 994. 	pline("Level %d  Gold %lu  HP %d(%d)  AC %d",  995.  # ifdef POLYSELF  996.  		u.mtimedone ? mons[u.umonnum].mlevel : u.ulevel,  997.  		u.ugold, u.mtimedone ? u.mh : u.uhp,  998.  		u.mtimedone ? u.mhmax : u.uhpmax, u.uac); 999. # else 1000. 		u.ulevel, u.ugold, u.uhp, u.uhpmax, u.uac); 1001. # endif  1002. }  1003.  1004. void  1005. cls  1006. {  1007. 	extern xchar tlx, tly;  1008.  1009. 	if(flags.toplin == 1)  1010. 		more;  1011. 	flags.toplin = 0;  1012.  1013. 	clear_screen;  1014.  1015. 	tlx = tly = 1;  1016.  1017. 	flags.botlx = 1;  1018. }  1019.  1020. char  1021. rndmonsym  1022. {  1023. 	return(mons[rn2(NUMMONS - 1)].mlet);  1024. }  1025.  1026. static const char objsyms[] = {  1027. 	WEAPON_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM, WAND_SYM,  1028. #ifdef SPELLS  1029. 	SPBOOK_SYM,  1030. #endif  1031. 	RING_SYM, AMULET_SYM, FOOD_SYM, TOOL_SYM, GEM_SYM, GOLD_SYM, ROCK_SYM };  1032.  1033. char  1034. rndobjsym  1035. {  1036. 	return objsyms[rn2(SIZE(objsyms))];  1037. }  1038.  1039. static const char *hcolors[] = {  1040. 			"ultraviolet", "infrared", "hot pink", "psychedelic",  1041. 			"bluish-orange", "reddish-green", "dark white", 1042. 			"light black", "loud", "salty", "sweet", "sour", 1043. 			"bitter", "luminescent", "striped", "polka-dotted", 1044. 			"square", "round", "triangular", "brilliant", 1045. 			"navy blue", "cerise", "chartreuse", "mauve", 1046. 			"lime green", "copper", "sea green", "spiral", 1047. 			"swirly", "blotchy", "fluorescent green", 1048. 			"burnt orange", "indigo", "amber", "tan", 1049. 			"sky blue-pink", "lemon yellow", "off-white", 1050. 			"paisley", "plaid", "argyle", "incandescent"}; 1051. 1052. const char * 1053. hcolor 1054. { 1055. 	return hcolors[rn2(SIZE(hcolors))]; 1056. } 1057.  1058. /*  Bug: if a level character is the same as an object/monster, it may be  1059. * hilited, because we use a kludge to figure out if a character is an  1060. * object/monster symbol. It's smarter than it was in 2.3, but you 1061. *  can still fool it (ex. if an object is in a doorway you have not seen,  1062.  *  and you look at a map, the '+' will be taken as a spellbook symbol). 1063. *  1064.  *  The problem is that whenever a portion of the map needs to be redrawn 1065. *  (by ^R, after an inventory dropover, after regurgitation...), the 1066. *  levl[][].scrsym field is used to redraw the map. A great duplication 1067. *  of code would be needed to trace back every scrsym to find out what color 1068. *  it should be. 1069. *  1070.  *  What is really needed is a levl[][].color field; the color be figured 1071. *  out at the same time as the screen symbol, and be restored with 1072. *  redraws. Unfortunately, as this requires much time and testing, 1073. *  it will have to wait for NetHack 3.1. -3. 1074.  */  1075.  1076. static void 1077. hilite(let,typ) 1078. uchar let, typ; 1079. { 1080.  1081. 	if (let == ' '  1082. #ifndef MSDOS  1083. 	    || !flags.standout  1084. #endif  1085. 	    ) { 1086. 		/* don't hilite spaces; it's pointless colorwise, 1087. 		  and also hilites secret corridors and dark areas. -3. */ 1088. 		g_putch(let); 1089. 		return; 1090. 	} 1091.  1092. 	if (!typ) { 1093. 		char *isobjct = index(obj_symbols, (char) let); 1094. 1095. 		if (let == GOLD_SYM) 1096. 			typ = AT_GLD; 1097. #ifdef MSDOSCOLOR 1098. 		else if (let == POOL_SYM) 1099. 			if (HI_BLUE == HI) typ = AT_MAP; 1100. 			else typ = AT_BLUE; 1101. #endif 1102. 		else if (isobjct != NULL || let == S_MIMIC_DEF) 1103. 			/* is an object */ 1104. 			typ = AT_OBJ; 1105. 		else if (ismnst((char) let)) 1106. 			/* is a monster */ 1107. 			typ = AT_MON; 1108. 	} 1109. #ifndef MSDOSCOLOR 1110. 	if (typ == AT_MON) revbeg; 1111. #else 1112. 	switch (typ) { 1113. 	   case AT_MON: 1114. 		xputs(let != S_MIMIC_DEF ? HI_MON : HI_OBJ); 1115. 		break; 1116. 	   case AT_OBJ: 1117. 		xputs(let == GOLD_SYM ? HI_GOLD : HI_OBJ); 1118. 		break; 1119. 	   case AT_MAP: 1120. 		if (!(typ = (let == POOL_SYM))) 1121. 		   break; 1122. 	   case AT_BLUE: 1123. 		xputs(HI_BLUE); 1124. 		break; 1125. 	   case AT_ZAP: 1126. 		xputs(HI_ZAP); 1127. 		break; 1128. 	   case AT_RED: 1129. 		xputs(HI_RED); 1130. 		break; 1131. 	   case AT_WHITE: 1132. 		xputs(HI_WHITE); 1133. 		break; 1134. 	} 1135. #endif 1136. 1137. 	g_putch(let); 1138. 1139. #ifdef MSDOSCOLOR 1140. 	if (typ) xputs(HE); 1141. #else 1142. 	if (typ == AT_MON) m_end; 1143. #endif 1144. } 1145.  1146. static boolean 1147. ismnst(let) 1148. char let; 1149. { 1150. 	register int ct; 1151. 	register struct permonst *ptr; 1152. 1153. 	if (let & 0x80) return 0; 1154. 	if (isalpha(let)) return 1; /* for speed */ 1155. 1156. 	for (ct = 0 ; ct < NUMMONS; ct++) { 1157. 		ptr = &mons[ct]; 1158. 		if(ptr->mlet == let) return 1; 1159. 	} 1160. #ifdef WORM 1161. 	if (let == S_WORM_TAIL) return 1; 1162. #endif 1163. 	return 0; 1164. }