Source:NetHack 3.2.0/cmd.c

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

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

1.   /*	SCCS Id: @(#)cmd.c	3.2	95/08/12	*/ 2.   /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include "hack.h"  6.    #include "func_tab.h"  7.    /* #define DEBUG	/* uncomment for debugging */ 8.    9.    /*  10.    * Some systems may have getchar return EOF for various reasons, and 11.   * we should not quit before seeing at least NR_OF_EOFS consecutive EOFs. 12.   */  13.   #if defined(SYSV) || defined(DGUX) || defined(HPUX) 14.  #define NR_OF_EOFS	20 15.  #endif 16.   17.   #ifdef DEBUG 18.  /*  19.    * only one "wiz_debug_cmd" routine should be available (in whatever  20.    * module you are trying to debug) or things are going to get rather 21.   * hard to link :-)  22.    */  23.   extern void NDECL(wiz_debug_cmd);  24.   #endif  25.    26.   #ifdef DUMB	/* stuff commented out in extern.h, but needed here */  27.   extern int NDECL(doapply); /**/  28.   extern int NDECL(dorub); /**/  29.   extern int NDECL(dojump); /**/  30.   extern int NDECL(doextlist); /**/  31.   extern int NDECL(dodrop); /**/  32.   extern int NDECL(doddrop); /**/  33.   extern int NDECL(dodown); /**/  34.   extern int NDECL(doup); /**/  35.   extern int NDECL(donull); /**/  36.   extern int NDECL(dowipe); /**/  37.   extern int NDECL(do_mname); /**/  38.   extern int NDECL(ddocall); /**/  39.   extern int NDECL(dotakeoff); /**/  40.   extern int NDECL(doremring); /**/  41.   extern int NDECL(dowear); /**/  42.   extern int NDECL(doputon); /**/  43.   extern int NDECL(doddoremarm); /**/  44.   extern int NDECL(dokick); /**/  45.   extern int NDECL(dothrow); /**/ 46.  extern int NDECL(doeat); /**/ 47.  extern int NDECL(done2); /**/ 48.  extern int NDECL(doengrave); /**/ 49.  extern int NDECL(dopickup); /**/ 50.  extern int NDECL(ddoinv); /**/ 51.  extern int NDECL(dotypeinv); /**/ 52.  extern int NDECL(dolook); /**/ 53.  extern int NDECL(doprgold); /**/ 54.  extern int NDECL(doprwep); /**/ 55.  extern int NDECL(doprarm); /**/ 56.  extern int NDECL(doprring); /**/ 57.  extern int NDECL(dopramulet); /**/ 58.  extern int NDECL(doprtool); /**/ 59.  extern int NDECL(dosuspend); /**/ 60.  extern int NDECL(doforce); /**/ 61.  extern int NDECL(doopen); /**/ 62.  extern int NDECL(doclose); /**/ 63.  extern int NDECL(dosh); /**/ 64.  extern int NDECL(dodiscovered); /**/ 65.  extern int NDECL(doset); /**/ 66.  extern int NDECL(dotogglepickup); /**/ 67.  extern int NDECL(dowhatis); /**/ 68.  extern int NDECL(doquickwhatis); /**/ 69.  extern int NDECL(dowhatdoes); /**/ 70.  extern int NDECL(dohelp); /**/ 71.  extern int NDECL(dohistory); /**/ 72.  extern int NDECL(doloot); /**/ 73.  extern int NDECL(dodrink); /**/ 74.  extern int NDECL(dodip); /**/ 75.  extern int NDECL(dosacrifice); /**/ 76.  extern int NDECL(dopray); /**/ 77.  extern int NDECL(doturn); /**/ 78.  extern int NDECL(doredraw); /**/ 79.  extern int NDECL(doread); /**/ 80.  extern int NDECL(dosave); /**/ 81.  extern int NDECL(dosearch); /**/ 82.  extern int NDECL(doidtrap); /**/ 83.  extern int NDECL(dopay); /**/ 84.  extern int NDECL(dosit); /**/ 85.  extern int NDECL(dotalk); /**/ 86.  extern int NDECL(docast); /**/ 87.  extern int NDECL(dovspell); /**/ 88.  extern int NDECL(dotele); /**/ 89.  extern int NDECL(dountrap); /**/ 90.  extern int NDECL(doversion); /**/ 91.  extern int NDECL(doextversion); /**/ 92.  extern int NDECL(dowield); /**/ 93.  extern int NDECL(dozap); /**/ 94.  extern int NDECL(doorganize); /**/ 95.  #endif /* DUMB */ 96.   97.   #ifdef OVL1 98.  static int NDECL((*timed_occ_fn)); 99.  #endif /* OVL1 */ 100.  101.  STATIC_PTR int NDECL(doprev_message); 102. STATIC_PTR int NDECL(timed_occupation); 103. STATIC_PTR int NDECL(doextcmd); 104. STATIC_PTR int NDECL(domonability); 105. # ifdef WIZARD 106. STATIC_PTR int NDECL(wiz_wish); 107. STATIC_PTR int NDECL(wiz_identify); 108. STATIC_PTR int NDECL(wiz_map); 109. STATIC_PTR int NDECL(wiz_genesis); 110. STATIC_PTR int NDECL(wiz_where); 111. STATIC_PTR int NDECL(wiz_detect); 112. STATIC_PTR int NDECL(wiz_level_tele); 113. STATIC_PTR int NDECL(wiz_show_seenv); 114. STATIC_PTR int NDECL(wiz_show_vision); 115. STATIC_PTR int NDECL(wiz_show_wmodes); 116. #ifdef __BORLANDC__ 117. extern void FDECL(show_borlandc_stats, (winid)); 118. #endif 119. static void FDECL(count_obj, (struct obj *, long *, long *, BOOLEAN_P, BOOLEAN_P)); 120. static void FDECL(obj_chain, (winid, const char *, struct obj *, long *, long *)); 121. static void FDECL(mon_invent_chain, (winid, const char *, struct monst *, long *, long *)); 122. static void FDECL(mon_chain, (winid, const char *, struct monst *, long *, long *)); 123. static void FDECL(contained, (winid, const char *, long *, long *)); 124. STATIC_PTR int NDECL(wiz_show_stats); 125. # endif 126. STATIC_PTR int NDECL(enter_explore_mode); 127. STATIC_PTR int NDECL(wiz_attributes); 128.  129.  #ifdef OVLB 130. static void FDECL(enlght_line, (const char *,const char *,const char *)); 131. #ifdef UNIX 132. static void NDECL(end_of_input); 133. #endif 134. #endif /* OVLB */ 135.  136.  STATIC_DCL char *NDECL(parse); 137.  138.  #ifdef OVL1 139.  140.  STATIC_PTR int 141. doprev_message 142. {  143.      return nh_doprev_message; 144. }  145.   146.  /* Count down by decrementing multi */ 147. STATIC_PTR int 148. timed_occupation { 149. 	(*timed_occ_fn); 150. 	if (multi > 0) 151. 		multi--; 152. 	return multi > 0; 153. }  154.   155.  /* If you have moved since initially setting some occupations, they 156.  * now shouldn't be able to restart. 157.  *  158.   * The basic rule is that if you are carrying it, you can continue 159.  * since it is with you. If you are acting on something at a distance, 160.  * your orientation to it must have changed when you moved. 161.  *  162.   * The exception to this is taking off items, since they can be taken 163.  * off in a number of ways in the intervening time, screwing up ordering. 164.  *  165.   *	Currently:	Take off all armor. 166.  *			Picking Locks / Forcing Chests. 167.  */  168.  void 169. reset_occupations { 170.  171.  	reset_remarm; 172. 	reset_pick; 173. }  174.   175.  /* If a time is given, use it to timeout this function, otherwise the 176.  * function times out by its own means. 177.  */  178.  void 179. set_occupation(fn, txt, xtime) 180. int NDECL((*fn)); 181. const char *txt; 182. int xtime; 183. {  184.  	if (xtime) { 185. 		occupation = timed_occupation; 186. 		timed_occ_fn = fn; 187. 	} else 188. 		occupation = fn; 189. 	occtxt = txt; 190. 	occtime = 0; 191. 	return; 192. }  193.   194.  #ifdef REDO 195.  196.  static char NDECL(popch); 197.  198.  /* Provide a means to redo the last command. The flag `in_doagain' is set 199.  * to true while redoing the command. This flag is tested in commands that 200.  * require additional input (like `throw' which requires a thing and a  201.   * direction), and the input prompt is not shown. Also, while in_doagain is 202. * TRUE, no keystrokes can be saved into the saveq. 203.  */  204.  #define BSIZE 20 205. static char pushq[BSIZE], saveq[BSIZE]; 206. static NEARDATA int phead, ptail, shead, stail; 207.  208.  static char 209. popch { 210. 	/* If occupied, return '\0', letting tgetch know a character should 211. 	 * be read from the keyboard. If the character read is not the 212. 	 * ABORT character (as checked in pcmain.c), that character will be  213. * pushed back on the pushq. 214. 	 */  215.  	if (occupation) return '\0'; 216. 	if (in_doagain) return(char)((shead != stail) ? saveq[stail++] : '\0'); 217. 	else		return(char)((phead != ptail) ? pushq[ptail++] : '\0'); 218. }  219.   220.  char 221. pgetchar {		/* curtesy of aeb@cwi.nl */ 222. 	register int ch; 223.  224.  	if(!(ch = popch)) 225. 		ch = nhgetch; 226. 	return((char)ch); 227. }  228.   229.  /* A ch == 0 resets the pushq */ 230. void 231. pushch(ch) 232. char ch; 233. {  234.  	if (!ch) 235. 		phead = ptail = 0; 236. 	if (phead < BSIZE) 237. 		pushq[phead++] = ch; 238. 	return; 239. }  240.   241.  /* A ch == 0 resets the saveq. Only save keystrokes when not 242.  * replaying a previous command. 243.  */  244.  void 245. savech(ch) 246. char ch; 247. {  248.  	if (!in_doagain) { 249. 		if (!ch) 250. 			phead = ptail = shead = stail = 0; 251. 		else if (shead < BSIZE) 252. 			saveq[shead++] = ch; 253. 	}  254.  	return; 255. }  256.  #endif /* REDO */ 257.  258.  #endif /* OVL1 */ 259. #ifdef OVLB 260.  261.  STATIC_PTR int 262. doextcmd	/* here after # - now read a full-word command */ 263. {  264.  	int idx, retval; 265.  266.  	/* keep repeating until we don't run help or quit */ 267. 	do { 268. 	    idx = get_ext_cmd; 269. 	    if (idx < 0) return 0;	/* quit */ 270.  271.  	    retval = (*extcmdlist[idx].ef_funct); 272. 	} while (extcmdlist[idx].ef_funct == doextlist); 273.  274.  	return retval; 275. }  276.   277.  int 278. doextlist	/* here after #? - now list all full-word commands */ 279. {  280.  	register const struct ext_func_tab *efp; 281. 	char	 buf[BUFSZ]; 282. 	winid datawin; 283.  284.  	datawin = create_nhwindow(NHW_TEXT); 285. 	putstr(datawin, 0, ""); 286. 	putstr(datawin, 0, "            Extended Commands List"); 287. 	putstr(datawin, 0, ""); 288. 	putstr(datawin, 0, "    Press '#', then type:"); 289. 	putstr(datawin, 0, ""); 290.  291.  	for(efp = extcmdlist; efp->ef_txt; efp++) { 292. 		Sprintf(buf, "    %-14s  - %s.", efp->ef_txt, efp->ef_desc); 293. 		putstr(datawin, 0, buf); 294. 	}  295.  	display_nhwindow(datawin, FALSE); 296. 	destroy_nhwindow(datawin); 297. 	return 0; 298. }  299.   300.  STATIC_PTR int 301. domonability 302. {  303.  	if (can_breathe(uasmon)) return dobreathe; 304. 	else if (attacktype(uasmon, AT_SPIT)) return dospit; 305. 	else if (u.usym == S_NYMPH) return doremove; 306. 	else if (u.usym == S_UMBER) return doconfuse; 307. 	else if (is_were(uasmon)) return dosummon; 308. 	else if (webmaker(uasmon)) return dospinweb; 309. 	else if (is_hider(uasmon)) return dohide; 310. 	else if(u.umonnum == PM_GREMLIN) { 311. 	    if(IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { 312. 		struct monst *mtmp; 313. 		if ((mtmp = cloneu) != 0) { 314. 			mtmp->mhpmax = (u.mhmax /= 2); 315. 			You("multiply."); 316. 			dryup(u.ux,u.uy); 317. 		}  318.  	    } else pline("There is no fountain here."); 319. 	}  320.  	else if (u.usym == S_UNICORN) { 321. 	    use_unicorn_horn((struct obj *)0); 322. 	    return 1; 323. 	} else if (u.umonnum == PM_MIND_FLAYER) return domindblast; 324. 	else if (uasmon->msound == MS_SHRIEK) { 325. 	    You("shriek."); 326. 	    if(u.uburied) 327. 		pline("Unfortunately sound does not carry well through rock."); 328. 	    else aggravate; 329. 	} else if (Upolyd) 330. 		pline("Any special ability you may have is purely reflexive."); 331. 	else You("don't have a special ability!"); 332. 	return 0; 333. }  334.   335.  STATIC_PTR int 336. enter_explore_mode 337. {  338.  	if(!discover && !wizard) { 339. 		pline("Beware!  From explore mode there will be no return to normal game."); 340. 		if (yn("Do you want to enter explore mode?") == 'y') { 341. 			clear_nhwindow(WIN_MESSAGE); 342. 			You("are now in non-scoring explore mode."); 343. 			discover = TRUE; 344. 		}  345.  		else { 346. 			clear_nhwindow(WIN_MESSAGE); 347. 			pline("Resuming normal game."); 348. 		}  349.  	}  350.  	return 0; 351. }  352.   353.  #ifdef WIZARD 354. STATIC_PTR int 355. wiz_wish	/* Unlimited wishes for debug mode by Paul Polderman */ 356. {  357.  	if (wizard) { 358. 	    boolean save_verbose = flags.verbose; 359.  360.  	    flags.verbose = FALSE; 361. 	    makewish; 362. 	    flags.verbose = save_verbose; 363. 	    (void) encumber_msg; 364. 	} else 365. 	    pline("Unavailable command '^W'."); 366. 	return 0; 367. }  368.   369.  STATIC_PTR int 370. wiz_identify 371. {  372.  	if (wizard)	identify_pack(0); 373. 	else		pline("Unavailable command '^I'."); 374. 	return 0; 375. }  376.   377.  STATIC_PTR int 378. wiz_map 379. {  380.  	if (wizard)	do_mapping; 381. 	else		pline("Unavailable command '^F'."); 382. 	return 0; 383. }  384.   385.  STATIC_PTR int 386. wiz_genesis 387. {  388.  	if (wizard)	(void) create_particular; 389. 	else		pline("Unavailable command '^G'."); 390. 	return 0; 391. }  392.   393.  STATIC_PTR int 394. wiz_where 395. {  396.  	if (wizard) print_dungeon; 397. 	else	    pline("Unavailable command '^O'."); 398. 	return 0; 399. }  400.   401.  STATIC_PTR int 402. wiz_detect 403. {  404.  	if(wizard)  (void) findit; 405. 	else	    pline("Unavailable command '^E'."); 406. 	return 0; 407. }  408.   409.  STATIC_PTR int 410. wiz_level_tele 411. {  412.  	if (wizard)	level_tele; 413. 	else		pline("Unavailable command '^V'."); 414. 	return 0; 415. }  416.   417.  STATIC_PTR int 418. wiz_show_seenv 419. {  420.  	winid win; 421. 	int x, y, v, startx, stopx, curx; 422. 	char row[COLNO+1]; 423.  424.  	win = create_nhwindow(NHW_TEXT); 425. 	/*  426.  	 * Each seenv description takes up 2 characters, so center 427. 	 * the seenv display around the hero. 428. 	 */  429.  	startx = max(1, u.ux-(COLNO/4)); 430. 	stopx = min(startx+(COLNO/2), COLNO); 431. 	/* can't have a line exactly 80 chars long */ 432. 	if (stopx - startx == COLNO/2) startx++; 433.  434.  	for (y = 0; y < ROWNO; y++) { 435. 	    for (x = startx, curx = 0; x < stopx; x++, curx += 2) { 436. 		if (x == u.ux && y == u.uy) { 437. 		    row[curx] = row[curx+1] = '@'; 438. 		} else { 439. 		    v = levl[x][y].seenv & 0xff; 440. 		    if (v == 0) 441. 			row[curx] = row[curx+1] = ' '; 442. 		    else 443. 			Sprintf(&row[curx], "%02x", v); 444. 		}  445.  	    }  446.  	    /* remove trailing spaces */ 447. 	    for (x = curx-1; x >= 0; x--) 448. 		if (row[x] != ' ') break; 449. 	    row[x+1] = '\0'; 450.  451.  	    putstr(win, 0, row); 452. 	}  453.  	display_nhwindow(win, TRUE); 454. 	destroy_nhwindow(win); 455. 	return 0; 456. }  457.   458.  STATIC_PTR int 459. wiz_show_vision 460. {  461.  	winid win; 462. 	int x, y, v;  463. char row[COLNO+1]; 464.  465.  	win = create_nhwindow(NHW_TEXT); 466. 	Sprintf(row, "Flags: 0x%x could see, 0x%x in sight, 0x%x temp lit",  467.  		COULD_SEE, IN_SIGHT, TEMP_LIT); 468. 	putstr(win, 0, row); 469. 	putstr(win, 0, ""); 470. 	for (y = 0; y < ROWNO; y++) { 471. 	    for (x = 1; x < COLNO; x++) { 472. 		if (x == u.ux && y == u.uy) 473. 		    row[x] = '@'; 474. 		else { 475. 		    v = viz_array[y][x]; /* data access should be hidden */ 476. 		    if (v == 0) 477. 			row[x] = ' '; 478. 		    else 479. 			row[x] = '0' + viz_array[y][x]; 480. 		}  481.  	    }  482.  	    /* remove trailing spaces */ 483. 	    for (x = COLNO-1; x >= 1; x--) 484. 		if (row[x] != ' ') break; 485. 	    row[x+1] = '\0'; 486.  487.  	    putstr(win, 0, &row[1]); 488. 	}  489.  	display_nhwindow(win, TRUE); 490. 	destroy_nhwindow(win); 491. 	return 0; 492. }  493.   494.  STATIC_PTR int 495. wiz_show_wmodes 496. {  497.  	winid win; 498. 	int x,y; 499. 	char row[COLNO+1]; 500. 	struct rm *lev; 501.  502.  	win = create_nhwindow(NHW_TEXT); 503. 	for (y = 0; y < ROWNO; y++) { 504. 	    for (x = 0; x < COLNO; x++) { 505. 		lev = &levl[x][y]; 506. 		if (x == u.ux && y == u.uy) 507. 		    row[x] = '@'; 508. 		if (IS_WALL(lev->typ) || lev->typ == SDOOR) 509. 		    row[x] = '0' + (lev->wall_info & WM_MASK); 510. 		else if (lev->typ == CORR) 511. 		    row[x] = '#'; 512. 		else if (IS_ROOM(lev->typ) || IS_DOOR(lev->typ)) 513. 		    row[x] = '.'; 514. 		else 515. 		    row[x] = 'x'; 516. 	    }  517.  	    row[COLNO] = '\0'; 518. 	    putstr(win, 0, row); 519. 	}  520.  	display_nhwindow(win, TRUE); 521. 	destroy_nhwindow(win); 522. 	return 0; 523. }  524.   525.  #endif /* WIZARD */ 526.  527.  /* -enlightenment- */ 528. static winid en_win; 529. static const char 530. 	*You_ = "You ", 531. 	*are  = "are ",  *were  = "were ", 532. 	*have = "have ", *had   = "had ", 533. 	*can  = "can ",  *could = "could "; 534.  535.  #define enl_msg(prefix,present,past,suffix) \ 536. 			enlght_line(prefix, final ? past : present, suffix) 537. #define you_are(attr)	enl_msg(You_,are,were,attr) 538. #define you_have(attr)	enl_msg(You_,have,had,attr) 539. #define you_can(attr)	enl_msg(You_,can,could,attr) 540.  541.  static void 542. enlght_line(start, middle, end) 543. const char *start, *middle, *end; 544. {  545.  	char buf[BUFSZ]; 546.  547.  	Sprintf(buf, "%s%s%s.", start, middle, end); 548. 	putstr(en_win, 0, buf); 549. }  550.   551.  void 552. enlightenment(final) 553. int final;	/* 0 => still in progress; 1 => over, survived; 2 => dead */ 554. {  555.  	int ltmp; 556. 	char buf[BUFSZ]; 557.  558.  	en_win = create_nhwindow(NHW_MENU); 559. 	putstr(en_win, 0, final ? "Final Attributes:" : "Current Attributes:"); 560. 	putstr(en_win, 0, ""); 561.  562.  #ifdef ELBERETH 563. 	if (u.uevent.uhand_of_elbereth) { 564. 	    static const char *hofe_titles[3] = { 565. 				"the Hand of Elbereth", 566. 				"the Envoy of Balance", 567. 				"the Glory of Arioch" 568. 	    };  569.  	    you_are(hofe_titles[u.uevent.uhand_of_elbereth - 1]); 570. 	}  571.  #endif 572.  573.  	/* note: piousness 20 matches MIN_QUEST_ALIGN (quest.h) */ 574. 	if (u.ualign.record >= 20)	you_are("piously aligned"); 575. 	else if (u.ualign.record > 13)	you_are("devoutly aligned"); 576. 	else if (u.ualign.record > 8)	you_are("fervently aligned"); 577. 	else if (u.ualign.record > 3)	you_are("stridently aligned"); 578. 	else if (u.ualign.record == 3)	you_are("aligned"); 579. 	else if (u.ualign.record > 0)	you_are("haltingly aligned"); 580. 	else if (u.ualign.record == 0)	you_are("nominally aligned"); 581. 	else if (u.ualign.record >= -3)	you_have("strayed"); 582. 	else if (u.ualign.record >= -8)	you_have("sinned"); 583. 	else you_have("transgressed"); 584. #ifdef WIZARD 585. 	if (wizard) { 586. 		Sprintf(buf, " %d", u.ualign.record); 587. 		enl_msg("Your alignment ", "is", "was", buf); 588. 	}  589.  #endif 590.  591.  	if (Telepat) you_are("telepathic"); 592. 	if (Searching) you_have("automatic searching"); 593. 	if (Teleportation) you_can("teleport"); 594. 	if (Teleport_control) you_have("teleport control"); 595. 	if (See_invisible) enl_msg(You_, "see", "saw", " invisible"); 596. 	if (Invisible) you_are("invisible"); 597. 	else if (Invis) you_are("invisible to others"); 598. 	/* ordinarily "visible" is redundant; this is a special case for 599. 	   the situation when invisibility would be an expected attribute */ 600. 	else if ((HInvis & I_BLOCKED) != 0L &&  601.  		 ((HInvis & ~I_BLOCKED) != 0L || pm_invisible(uasmon))) 602. 	    you_are("visible"); 603. 	if (Fast) you_are((Fast & ~INTRINSIC) ? "very fast" : "fast"); 604. 	if (Stealth) you_are("stealthy"); 605. 	if (Regeneration) enl_msg("You regenerate", "", "d", ""); 606. 	if (Hunger) enl_msg("You hunger", "", "ed", " rapidly"); 607. 	if (Conflict) enl_msg("You cause", "", "d", " conflict"); 608. 	if (Aggravate_monster) enl_msg("You aggravate", "", "d", " monsters"); 609. 	if (Poison_resistance) you_are("poison resistant"); 610. 	if (Fire_resistance) you_are("fire resistant"); 611. 	if (Cold_resistance) you_are("cold resistant"); 612. 	if (Shock_resistance) you_are("shock resistant"); 613. 	if (Sleep_resistance) you_are("sleep resistant"); 614. 	if (Disint_resistance) you_are("disintegration-resistant"); 615. 	if (Protection_from_shape_changers) 616. 		you_are("protected from shape changers"); 617. 	if (Polymorph) you_are("polymorphing"); 618. 	if (Polymorph_control) you_have("polymorph control"); 619. 	if (HHalluc_resistance) 620. 		enl_msg("You resist", "", "ed", " hallucinations"); 621. 	if (final) { 622. 		if (Hallucination) you_are("hallucinating"); 623. 		if (Stunned) you_are("stunned"); 624. 		if (Confusion) you_are("confused"); 625. 		if (Sick) { 626. 			if (u.usick_type & SICK_VOMITABLE) 627. 				you_are("sick from food poisoning"); 628. 			if (u.usick_type & SICK_NONVOMITABLE) 629. 				you_are("sick from illness"); 630. 		}  631.  		if (Blinded) you_are("blinded"); 632. 	}  633.  	if (Wounded_legs) { 634. 		Sprintf(buf, "wounded %s", makeplural(body_part(LEG))); 635. 		you_have(buf); 636. 	}  637.  	if (Glib) { 638. 		Sprintf(buf, "slippery %s", makeplural(body_part(FINGER))); 639. 		you_have(buf); 640. 	}  641.  	if (Strangled) you_are((u.uburied) ? "buried" : "being strangled"); 642. 	if (Stoned) you_are("turning to stone"); 643. 	if (Lifesaved) 644. 		enl_msg("Your life ", "will be", "would have been", " saved"); 645. 	if (Adornment) you_are("adorned"); 646. 	if (Warning) you_are("warned"); 647. 	if (Protection) you_are("protected"); 648. 	if (Reflecting) you_have("reflection"); 649. 	if ((HLevitation & (I_SPECIAL|W_ARTI)) != 0L &&  650.  	    (HLevitation & ~(I_SPECIAL|W_ARTI|TIMEOUT)) == 0L &&  651.  	    !is_floater(uasmon)) you_are("levitating, at will"); 652. 	else if (Levitation) you_are("levitating");	/* without control */ 653. 	else if (is_flyer(uasmon)) you_can("fly"); 654. 	if (Fumbling) enl_msg("You fumble", "", "d", ""); 655. 	if (Jumping) you_can("jump"); 656. 	if (Wwalking) you_can("walk on water"); 657. 	if (passes_walls(uasmon)) you_can("walk through walls"); 658. 	if (Breathless) you_can("survive without air"); 659. 	else if (Amphibious) you_can("breathe water"); 660. 	if (Antimagic) you_are("magic-protected"); 661. 	if (Displaced) you_are("displaced"); 662. 	if (Clairvoyant) you_are("clairvoyant"); 663. 	if (u.ulycn >= LOW_PM) { 664. 		Strcpy(buf, an(mons[u.ulycn].mname)); 665. 		you_are(buf); 666. 	}  667.  	if (Luck) { 668. 	    ltmp = abs((int)Luck); 669. 	    Sprintf(buf, "%s%slucky",  670.  		    ltmp >= 10 ? "extremely " : ltmp >= 5 ? "very " : "",  671.  		    Luck < 0 ? "un" : ""); 672. #ifdef WIZARD 673. 	    if (wizard) Sprintf(eos(buf), " (%d)", Luck); 674. #endif 675. 	    you_are(buf); 676. 	}  677.  #ifdef WIZARD 678. 	 else if (wizard) enl_msg("Your luck ", "is", "was", " zero"); 679. #endif 680. 	if (u.moreluck > 0) you_have("extra luck"); 681. 	else if (u.moreluck < 0) you_have("reduced luck"); 682. 	if (carrying(LUCKSTONE)) { 683. 	    ltmp = stone_luck(FALSE); 684. 	    if (ltmp <= 0) 685. 		enl_msg("Bad luck ", "does", "did", " not time out for you"); 686. 	    if (ltmp >= 0) 687. 		enl_msg("Good luck ", "does", "did", " not time out for you"); 688. 	}  689.   690.  	if (u.ugangr) { 691. 	    Sprintf(buf, " %sangry with you",  692.  		    u.ugangr > 6 ? "extremely " : u.ugangr > 3 ? "very " : ""); 693. #ifdef WIZARD 694. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.ugangr); 695. #endif 696. 	    enl_msg(u_gname, " is", " was", buf); 697. 	} else 698. 	    /*  699.  	     * We need to suppress this when the game is over, because death 700. 	     * can change the value calculated by can_pray, potentially 701. 	     * resulting in a false claim that you could have prayed safely. 702. 	     */  703.  	  if (!final) { 704. #if 0 705. 	    /* "can [not] safely pray" vs "could [not] have safely prayed" */ 706. 	    Sprintf(buf, "%s%ssafely pray%s", can_pray(FALSE) ? "" : "not ",  707.  		    final ? "have " : "", final ? "ed" : ""); 708. #else 709. 	    Sprintf(buf, "%ssafely pray", can_pray(FALSE) ? "" : "not "); 710. #endif 711. #ifdef WIZARD 712. 	    if (wizard) Sprintf(eos(buf), " (%d)", u.ublesscnt); 713. #endif 714. 	    you_can(buf); 715. 	}  716.   717.      {  718.  	const char *p; 719.  720.  	buf[0] = '\0'; 721. 	if (final < 2) {    /* still in progress, or quit/escaped/ascended */ 722. 	    p = "survived after being killed "; 723. 	    switch (u.umortality) { 724. 	    case 0:  p = !final ? (char *)0 : "survived"; break; 725. 	    case 1:  Strcpy(buf, "once");  break; 726. 	    case 2:  Strcpy(buf, "twice");  break; 727. 	    case 3:  Strcpy(buf, "thrice");  break; 728. 	    default: Sprintf(buf, "%d times", u.umortality); 729. 		     break; 730. 	    }  731.  	} else {		/* game ended in character's death */ 732. 	    p = "are dead"; 733. 	    switch (u.umortality) { 734. 	    case 0:  impossible("dead without dying?"); 735. 	    case 1:  break;			/* just "are dead" */ 736. 	    default: Sprintf(buf, " (%d%s time!)", u.umortality,  737.  			     ordin(u.umortality)); 738. 		     break; 739. 	    }  740.  	}  741.  	if (p) enl_msg(You_, "have been killed ", p, buf); 742.     }  743.   744.  	display_nhwindow(en_win, TRUE); 745. 	destroy_nhwindow(en_win); 746. 	return; 747. }  748.   749.  STATIC_PTR int 750. wiz_attributes 751. {  752.  	if (wizard || discover) 753. 		enlightenment(0); 754. 	else 755. 		pline("Unavailable command '^X'."); 756. 	return 0; 757. }  758.   759.  #endif /* OVLB */ 760. #ifdef OVL1 761.  762.  #ifndef M  763. # ifndef NHSTDC 764. #  define M(c)		(0x80 | (c)) 765. # else 766. #  define M(c)		((c) - 128) 767. # endif /* NHSTDC */ 768. #endif 769. #ifndef C  770. #define C(c)		(0x1f & (c)) 771. #endif 772.  773.  static const struct func_tab cmdlist[] = { 774. 	{C('d'), FALSE, dokick}, /* "D" is for door!...? Msg is in dokick.c */ 775. #ifdef WIZARD 776. 	{C('e'), TRUE, wiz_detect}, 777. 	{C('f'), TRUE, wiz_map}, 778. 	{C('g'), TRUE, wiz_genesis}, 779. 	{C('i'), TRUE, wiz_identify}, 780. #endif 781. 	{C('l'), TRUE, doredraw}, /* if number_pad is set */ 782. #ifdef WIZARD 783. 	{C('o'), TRUE, wiz_where}, 784. #endif 785. 	{C('p'), TRUE, doprev_message}, 786. 	{C('r'), TRUE, doredraw}, 787. 	{C('t'), TRUE, dotele}, 788. #ifdef WIZARD 789. 	{C('v'), TRUE, wiz_level_tele}, 790. 	{C('w'), TRUE, wiz_wish}, 791. #endif 792. 	{C('x'), TRUE, wiz_attributes}, 793. #ifdef SUSPEND 794. 	{C('z'), TRUE, dosuspend}, 795. #endif 796. 	{'a', FALSE, doapply}, 797. 	{'A', FALSE, doddoremarm}, 798. 	{M('a'), TRUE, doorganize}, 799. /*	'b', 'B' : go sw */ 800. 	{'c', FALSE, doclose}, 801. 	{'C', TRUE, do_mname}, 802. 	{M('c'), TRUE, dotalk}, 803. 	{'d', FALSE, dodrop}, 804. 	{'D', FALSE, doddrop}, 805. 	{M('d'), FALSE, dodip}, 806. 	{'e', FALSE, doeat}, 807. 	{'E', FALSE, doengrave}, 808. #ifdef WEAPON_SKILLS 809. 	{M('e'), TRUE, select_weapon_skill}, 810. #endif /* WEAPON_SKILLS */ 811. /* Soon to be  812. {'f', FALSE, dofight, "fighting"}, 813. 	{'F', FALSE, doFight, "fighting"}, 814.  */  815.  	{M('f'), FALSE, doforce}, 816. /*	'g', 'G' : multiple go */ 817. /*	'h', 'H' : go west */ 818. 	{'h', TRUE, dohelp}, /* if number_pad is set */ 819. 	{'i', TRUE, ddoinv}, 820. 	{'I', TRUE, dotypeinv},		/* Robert Viduya */ 821. 	{M('i'), TRUE, doinvoke}, 822. /*	'j', 'J', 'k', 'K', 'l', 'L', 'm', 'M', 'n', 'N' : move commands */ 823. 	{'j', FALSE, dojump}, /* if number_pad is on */ 824. 	{M('j'), FALSE, dojump}, 825. 	{'k', FALSE, dokick}, /* if number_pad is on */ 826. 	{'l', FALSE, doloot}, /* if number_pad is on */ 827. 	{M('l'), FALSE, doloot}, 828. /*	'n' prefixes a count if number_pad is on */ 829. 	{M('m'), TRUE, domonability}, 830. 	{'N', TRUE, ddocall}, /* if number_pad is on */ 831. 	{M('n'), TRUE, ddocall}, 832. 	{M('N'), TRUE, ddocall}, 833. 	{'o', FALSE, doopen}, 834. 	{'O', TRUE, doset}, 835. 	{M('o'), FALSE, dosacrifice}, 836. 	{'p', FALSE, dopay}, 837. 	{'P', FALSE, doputon}, 838. 	{M('p'), TRUE, dopray}, 839. 	{'q', FALSE, dodrink}, 840. 	{'Q', TRUE, done2}, 841. #ifdef WEAPON_SKILLS 842. 	{M('q'), TRUE, check_weapon_skills}, 843. #endif /* WEAPON_SKILLS */ 844. 	{'r', FALSE, doread}, 845. 	{'R', FALSE, doremring}, 846. 	{M('r'), FALSE, dorub}, 847. 	{'s', TRUE, dosearch, "searching"}, 848. 	{'S', TRUE, dosave}, 849. 	{M('s'), FALSE, dosit}, 850. 	{'t', FALSE, dothrow}, 851. 	{'T', FALSE, dotakeoff}, 852. 	{M('t'), TRUE, doturn}, 853. /*	'u', 'U' : go ne */ 854. 	{'u', FALSE, dountrap}, /* if number_pad is on */ 855. 	{M('u'), FALSE, dountrap}, 856. 	{'v', TRUE, doversion}, 857. 	{'V', TRUE, dohistory}, 858. 	{M('v'), TRUE, doextversion}, 859. 	{'w', FALSE, dowield}, 860. 	{'W', FALSE, dowear}, 861. 	{M('w'), FALSE, dowipe}, 862. 	{'x', TRUE, dovspell},			/* Mike Stephenson */ 863. 	{'X', TRUE, enter_explore_mode}, 864. /*	'y', 'Y' : go nw */ 865. 	{'z', FALSE, dozap}, 866. 	{'Z', TRUE, docast}, 867. 	{'<', FALSE, doup}, 868. 	{'>', FALSE, dodown}, 869. 	{'/', TRUE, dowhatis}, 870. 	{'&', TRUE, dowhatdoes}, 871. 	{'?', TRUE, dohelp}, 872. 	{M('?'), TRUE, doextlist}, 873. #ifdef SHELL 874. 	{'!', TRUE, dosh}, 875. #endif 876. 	{'.', TRUE, donull, "waiting"}, 877. 	{' ', TRUE, donull, "waiting"}, 878. 	{',', FALSE, dopickup}, 879. 	{':', TRUE, dolook}, 880. 	{';', TRUE, doquickwhatis}, 881. 	{'^', TRUE, doidtrap}, 882. 	{'\\', TRUE, dodiscovered},		/* Robert Viduya */ 883. 	{'@', TRUE, dotogglepickup}, 884. 	{WEAPON_SYM,  TRUE, doprwep}, 885. 	{ARMOR_SYM,  TRUE, doprarm}, 886. 	{RING_SYM,  TRUE, doprring}, 887. 	{AMULET_SYM, TRUE, dopramulet}, 888. 	{TOOL_SYM, TRUE, doprtool}, 889. 	{GOLD_SYM, TRUE, doprgold}, 890. 	{SPBOOK_SYM, TRUE, dovspell},			/* Mike Stephenson */ 891. 	{'#', TRUE, doextcmd}, 892. 	{0,0,0,0}  893.  };  894.   895.  struct ext_func_tab extcmdlist[] = { 896. 	{"adjust", "adjust inventory letters", doorganize, TRUE}, 897. 	{"chat", "talk to someone", dotalk, TRUE},	/* converse? */ 898.  	{"dip", "dip an object into something", dodip, FALSE}, 899. #ifdef WEAPON_SKILLS 900. 	{"enhance", "advance a weapon skill", select_weapon_skill, TRUE}, 901. #endif /* WEAPON_SKILLS */ 902. 	{"force", "force a lock", doforce, FALSE}, 903. 	{"invoke", "invoke an object's powers", doinvoke, TRUE}, 904. 	{"jump", "jump to a location", dojump, FALSE}, 905. 	{"loot", "loot a box on the floor", doloot, FALSE}, 906. 	{"monster", "use a monster's special ability", domonability, TRUE}, 907. 	{"name", "name an item or type of object", ddocall, TRUE}, 908. 	{"offer", "offer a sacrifice to the gods", dosacrifice, FALSE}, 909. 	{"pray", "pray to the gods for help", dopray, TRUE}, 910. #ifdef WEAPON_SKILLS 911. 	{"qualifications", "check your weapon skills", check_weapon_skills, TRUE}, 912. #endif /* WEAPON_SKILLS */ 913. 	{"rub", "rub a lamp", dorub, FALSE}, 914. 	{"sit", "sit down", dosit, FALSE}, 915. 	{"turn", "turn undead", doturn, TRUE}, 916. 	{"untrap", "untrap something", dountrap, FALSE}, 917. 	{"version", "list compile time options for this version of NetHack", 918. 		doextversion, TRUE}, 919. 	{"wipe", "wipe off your face", dowipe, FALSE}, 920. 	{"?", "get this list of extended commands", doextlist, TRUE}, 921. #if defined(WIZARD) 922. 	/*  923.  	 * There must be a blank entry here for every entry in the table 924. 	 * below. 925. 	 */  926.  	{(char *)0, (char *)0, donull, TRUE}, 927. 	{(char *)0, (char *)0, donull, TRUE}, 928. 	{(char *)0, (char *)0, donull, TRUE}, 929. 	{(char *)0, (char *)0, donull, TRUE}, 930. 	{(char *)0, (char *)0, donull, TRUE}, 931. #ifdef DEBUG 932. 	{(char *)0, (char *)0, donull, TRUE}, 933. #endif 934. 	{(char *)0, (char *)0, donull, TRUE}, 935. #endif 936. 	{(char *)0, (char *)0, donull, TRUE} 937. };  938.   939.  #if defined(WIZARD) 940. static const struct ext_func_tab debug_extcmdlist[] = { 941. 	{"light sources", "show mobile light sources", wiz_light_sources, TRUE}, 942. 	{"seenv", "show seen vectors", wiz_show_seenv, TRUE}, 943. 	{"stats", "show memory statistics", wiz_show_stats, TRUE}, 944. 	{"timeout", "look at timeout queue", wiz_timeout_queue, TRUE}, 945. 	{"vision", "show vision array", wiz_show_vision, TRUE}, 946. #ifdef DEBUG 947. 	{"wizdebug", "wizard debug command", wiz_debug_cmd, TRUE}, 948. #endif 949. 	{"wmode", "show wall modes", wiz_show_wmodes, TRUE}, 950. 	{(char *)0, (char *)0, donull, TRUE} 951. };  952.   953.  /*  954.   * Insert debug commands into the extended command list. This function 955.  * assumes that the last entry will be the help entry. 956.  *  957.   * You must add entries in ext_func_tab every time you add one to the 958.  * debug_extcmdlist. 959.  */  960.  void 961. add_debug_extended_commands 962. {  963.  	int i, j, k, n;  964. 965. 	/* count the # of help entries */ 966. 	for (n = 0; extcmdlist[n].ef_txt[0] != '?'; n++) 967. 	    ;  968.   969.  	for (i = 0; debug_extcmdlist[i].ef_txt; i++) { 970. 	    for (j = 0; j < n; j++) 971. 		if (strcmp(debug_extcmdlist[i].ef_txt, extcmdlist[j].ef_txt) < 0) break; 972.  973.  	    /* insert i'th debug entry into extcmdlist[j], pushing down  */ 974. 	    for (k = n; k >= j; --k) 975. 		extcmdlist[k+1] = extcmdlist[k]; 976. 	    extcmdlist[j] = debug_extcmdlist[i]; 977. 	    n++;	/* now an extra entry */ 978. 	}  979.  }  980.   981.   982.  static const char *template = "%-18s %4ld  %6ld"; 983. static const char *count_str = "                   count  bytes"; 984. static const char *separator = "-- -  --"; 985.  986.  static void 987. count_obj(chain, total_count, total_size, top, recurse) 988. 	struct obj *chain; 989. 	long *total_count; 990. 	long *total_size; 991. 	boolean top; 992. 	boolean recurse; 993. {  994.  	long count, size; 995. 	struct obj *obj; 996.  997.  	for (count = size = 0, obj = chain; obj; obj = obj->nobj) { 998. 	    if (top) { 999. 		count++; 1000. 		size += sizeof(struct obj) + obj->onamelth; 1001. 	   }  1002. 	    if (recurse && obj->cobj) 1003. 		count_obj(obj->cobj, total_count, total_size, TRUE, TRUE); 1004. 	} 1005. 	*total_count += count; 1006. 	*total_size += size; 1007. } 1008.  1009. static void 1010. obj_chain(win, src, chain, total_count, total_size) 1011. 	winid win; 1012. 	const char *src; 1013. 	struct obj *chain; 1014. 	long *total_count; 1015. 	long *total_size; 1016. { 1017. 	char buf[BUFSZ]; 1018. 	long count = 0, size = 0; 1019. 1020. 	count_obj(chain, &count, &size, TRUE, FALSE); 1021. 	*total_count += count; 1022. 	*total_size += size; 1023. 	Sprintf(buf, template, src, count, size); 1024. 	putstr(win, 0, buf); 1025. } 1026.  1027. static void 1028. mon_invent_chain(win, src, chain, total_count, total_size) 1029. 	winid win; 1030. 	const char *src; 1031. 	struct monst *chain; 1032. 	long *total_count; 1033. 	long *total_size; 1034. { 1035. 	char buf[BUFSZ]; 1036. 	long count = 0, size = 0; 1037. 	struct monst *mon; 1038. 1039. 	for (mon = chain; mon; mon = mon->nmon) 1040. 	   count_obj(mon->minvent, &count, &size, TRUE, FALSE); 1041. 	*total_count += count; 1042. 	*total_size += size; 1043. 	Sprintf(buf, template, src, count, size); 1044. 	putstr(win, 0, buf); 1045. } 1046.  1047. static void 1048. contained(win, src, total_count, total_size) 1049. 	winid win; 1050. 	const char *src; 1051. 	long *total_count; 1052. 	long *total_size; 1053. { 1054. 	char buf[BUFSZ]; 1055. 	long count = 0, size = 0; 1056. 	struct monst *mon; 1057. 1058. 	count_obj(invent, &count, &size, FALSE, TRUE); 1059. 	count_obj(fobj, &count, &size, FALSE, TRUE); 1060. 	count_obj(level.buriedobjlist, &count, &size, FALSE, TRUE); 1061. 	count_obj(migrating_objs, &count, &size, FALSE, TRUE); 1062. 	for (mon = fmon; mon; mon = mon->nmon) 1063. 	   count_obj(mon->minvent, &count, &size, FALSE, TRUE); 1064. 	for (mon = migrating_mons; mon; mon = mon->nmon) 1065. 	   count_obj(mon->minvent, &count, &size, FALSE, TRUE); 1066. 1067. 	*total_count += count; *total_size += size; 1068. 1069. 	Sprintf(buf, template, src, count, size); 1070. 	putstr(win, 0, buf); 1071. } 1072.  1073. static void 1074. mon_chain(win, src, chain, total_count, total_size) 1075. 	winid win; 1076. 	const char *src; 1077. 	struct monst *chain; 1078. 	long *total_count; 1079. 	long *total_size; 1080. { 1081. 	char buf[BUFSZ]; 1082. 	long count, size; 1083. 	struct monst *mon; 1084. 1085. 	for (count = size = 0, mon = chain; mon; mon = mon->nmon) { 1086. 	   count++; 1087. 	   size += sizeof(struct monst) + mon->mxlth + mon->mnamelth; 1088. 	} 1089. 	*total_count += count; 1090. 	*total_size += size; 1091. 	Sprintf(buf, template, src, count, size); 1092. 	putstr(win, 0, buf); 1093. } 1094.  1095. /*  1096.  * Display memory usage of all monsters and objects on the level. 1097. */  1098. static int 1099. wiz_show_stats 1100. { 1101. 	char buf[BUFSZ]; 1102. 	winid win; 1103. 	long total_obj_size = 0, total_obj_count = 0; 1104. 	long total_mon_size = 0, total_mon_count = 0; 1105. 1106. 	win = create_nhwindow(NHW_TEXT); 1107. 	putstr(win, 0, "Current memory statistics:"); 1108. 	putstr(win, 0, ""); 1109. 	Sprintf(buf, "Objects, size %d", (int) sizeof(struct obj)); 1110. 	putstr(win, 0, buf); 1111. 	putstr(win, 0, ""); 1112. 	putstr(win, 0, count_str); 1113. 1114. 	obj_chain(win, "invent", invent, &total_obj_count, &total_obj_size); 1115. 	obj_chain(win, "fobj", fobj, &total_obj_count, &total_obj_size); 1116. 	obj_chain(win, "buried", level.buriedobjlist, 1117. 				&total_obj_count, &total_obj_size); 1118. 	obj_chain(win, "migrating obj", migrating_objs, 1119. 				&total_obj_count, &total_obj_size); 1120. 	mon_invent_chain(win, "minvent", fmon, 1121. 				&total_obj_count,&total_obj_size); 1122. 	mon_invent_chain(win, "migrating minvent", migrating_mons, 1123. 				&total_obj_count, &total_obj_size); 1124. 1125. 	contained(win, "contained",  1126. 				&total_obj_count, &total_obj_size); 1127. 1128. 	putstr(win, 0, separator); 1129. 	Sprintf(buf, template, "Total", total_obj_count, total_obj_size); 1130. 	putstr(win, 0, buf); 1131. 1132. 	putstr(win, 0, ""); 1133. 	putstr(win, 0, ""); 1134. 	Sprintf(buf, "Monsters, size %d", (int) sizeof(struct monst)); 1135. 	putstr(win, 0, buf); 1136. 	putstr(win, 0, ""); 1137. 1138. 	mon_chain(win, "fmon", fmon,  1139. 				&total_mon_count, &total_mon_size); 1140. 	mon_chain(win, "migrating", migrating_mons, 1141. 				&total_mon_count, &total_mon_size); 1142. 1143. 	putstr(win, 0, separator); 1144. 	Sprintf(buf, template, "Total", total_mon_count, total_mon_size); 1145. 	putstr(win, 0, buf); 1146. 1147. #ifdef __BORLANDC__ 1148. 	show_borlandc_stats(win); 1149. #endif 1150. 1151. 	display_nhwindow(win, FALSE); 1152. 	destroy_nhwindow(win); 1153. 	return 0; 1154. } 1155.  1156. void 1157. sanity_check 1158. { 1159. 	obj_sanity_check; 1160. 	timer_sanity_check; 1161. } 1162.  1163. #endif /* WIZARD */ 1164. 1165. #define unctrl(c)	((c) <= C('z') ? (0x60 | (c)) : (c)) 1166. #define unmeta(c)	(0x7f & (c)) 1167. 1168.  1169. void 1170. rhack(cmd) 1171. register char *cmd; 1172. { 1173. 	boolean do_walk, do_rush, prefix_seen, bad_command, 1174. 		firsttime = (cmd == 0); 1175. 1176. 	if (firsttime) { 1177. 		flags.nopick = 0; 1178. 		cmd = parse; 1179. 	} 1180. 	if (*cmd == '\033') { 1181. 		flags.move = FALSE; 1182. 		return; 1183. 	} 1184. #ifdef REDO 1185. 	if (*cmd == DOAGAIN && !in_doagain && saveq[0]) { 1186. 		in_doagain = TRUE; 1187. 		stail = 0; 1188. 		rhack((char *)0);	/* read and execute command */ 1189. 		in_doagain = FALSE; 1190. 		return; 1191. 	} 1192. 	/* Special case of *cmd == ' ' handled better below */ 1193. 	if(!*cmd || *cmd == (char)0377) { 1194. #else 1195. 	if(!*cmd || *cmd == (char)0377 || 1196. 	   (!flags.rest_on_space && *cmd == ' ')) { 1197. #endif 1198. 		nhbell; 1199. 		flags.move = FALSE; 1200. 		return;		/* probably we just had an interrupt */ 1201. 	} 1202.  1203. 	/* handle most movement commands */ 1204. 	do_walk = do_rush = prefix_seen = FALSE; 1205. 	switch (*cmd) { 1206. 	 case 'g': if (movecmd(cmd[1])) { 1207. 			flags.run = 2; 1208. 			do_rush = TRUE; 1209. 		   } else 1210. 			prefix_seen = TRUE; 1211. 		   break; 1212. 	 case '5': if (!flags.num_pad) break;	/* else FALLTHRU */ 1213. 	 case 'G': if (movecmd(lowc(cmd[1]))) { 1214. 			flags.run = 3; 1215. 			do_rush = TRUE; 1216. 		   } else 1217. 			prefix_seen = TRUE; 1218. 		   break; 1219. 	 case '-': if (!flags.num_pad) break;	/* else FALLTHRU */ 1220. 	 case 'm': if (movecmd(cmd[1]) || u.dz) { 1221. 			flags.run = 0; 1222. 			flags.nopick = 1; 1223. 			if (!u.dz) do_walk = TRUE; 1224. 			else cmd[0] = cmd[1];	/* "m<" or "m>" */ 1225. 		   } else 1226. 			prefix_seen = TRUE; 1227. 		   break; 1228. 	 case 'M': if (movecmd(lowc(cmd[1]))) { 1229. 			flags.run = 1; 1230. 			flags.nopick = 1; 1231. 			do_rush = TRUE; 1232. 		   } else 1233. 			prefix_seen = TRUE; 1234. 		   break; 1235. 	 case '0': if (!flags.num_pad) break; 1236. 		   (void)ddoinv; /* a convenience borrowed from the PC */ 1237. 		   flags.move = FALSE; 1238. 		   multi = 0; 1239. 		   return; 1240. 	 default:  if (movecmd(*cmd)) {	/* ordinary movement */ 1241. 			do_walk = TRUE; 1242. 		   } else if (movecmd(flags.num_pad ? 1243. 				      unmeta(*cmd) : lowc(*cmd))) { 1244. 			flags.run = 1; 1245. 			do_rush = TRUE; 1246. 		   } else if (movecmd(unctrl(*cmd))) { 1247. 			flags.run = 3; 1248. 			do_rush = TRUE; 1249. 		   }  1250. 		    break; 1251. 	} 1252. 	if (do_walk) { 1253. 	   if (multi) flags.mv = TRUE; 1254. 	   domove; 1255. 	   return; 1256. 	} else if (do_rush) { 1257. 	   if (firsttime) { 1258. 		if (!multi) multi = max(COLNO,ROWNO); 1259. 		u.last_str_turn = 0; 1260. 	   }  1261. 	    flags.mv = TRUE; 1262. 	   domove; 1263. 	   return; 1264. 	} else if (prefix_seen && cmd[1] == '\033') {	/* */ 1265. 	   /* don't report "unknown command" for change of heart... */ 1266. 	    bad_command = FALSE; 1267. 	} else if (*cmd == ' ' && !flags.rest_on_space) { 1268. 	   bad_command = TRUE;		/* skip cmdlist[] loop */ 1269. 1270. 	/* handle all other commands */ 1271. 	} else { 1272. 	   register const struct func_tab *tlist; 1273. 	   int res, NDECL((*func)); 1274. 1275. 	    for (tlist = cmdlist; tlist->f_char; tlist++) { 1276. 		if ((*cmd & 0xff) != (tlist->f_char & 0xff)) continue; 1277. 1278. 		if (u.uburied && !tlist->can_if_buried) { 1279. 		   You_cant("do that while you are buried!"); 1280. 		   res = 0; 1281. 		} else { 1282. 		   /* we discard 'const' because some compilers seem to have 1283. 		      trouble with the pointer passed to set_occupation */ 1284. 		   func = ((struct func_tab *)tlist)->f_funct; 1285. 		   if (tlist->f_text && !occupation && multi) 1286. 			set_occupation(func, tlist->f_text, multi); 1287. 		   res = (*func);		/* perform the command */ 1288. 		} 1289. 		if (!res) { 1290. 		   flags.move = FALSE; 1291. 		   multi = 0; 1292. 		} 1293. 		return; 1294. 	   }  1295. 	    /* if we reach here, cmd wasn't found in cmdlist[] */ 1296. 	   bad_command = TRUE; 1297. 	} 1298.  1299. 	if (bad_command) { 1300. 	   char expcmd[10]; 1301. 	   register char *cp = expcmd; 1302. 1303. 	    while (*cmd && (int)(cp - expcmd) < (int)(sizeof expcmd - 3)) { 1304. 		if (*cmd >= 040 && *cmd < 0177) { 1305. 		   *cp++ = *cmd++; 1306. 		} else if (*cmd & 0200) { 1307. 		   *cp++ = 'M'; 1308. 		   *cp++ = '-'; 1309. 		   *cp++ = *cmd++ &= ~0200; 1310. 		} else { 1311. 		   *cp++ = '^'; 1312. 		   *cp++ = *cmd++ ^ 0100; 1313. 		} 1314. 	    }  1315. 	    *cp = '\0'; 1316. 	   Norep("Unknown command '%s'.", expcmd); 1317. 	} 1318. 	/* didn't move */ 1319. 	flags.move = FALSE; 1320. 	multi = 0; 1321. 	return; 1322. } 1323.  1324. int 1325. xytod(x, y)	/* convert an x,y pair into a direction code */ 1326. schar x, y; 1327. { 1328. 	register int dd; 1329. 1330. 	for(dd = 0; dd < 8; dd++) 1331. 	   if(x == xdir[dd] && y == ydir[dd]) return dd; 1332. 1333. 	return -1; 1334. } 1335.  1336. void 1337. dtoxy(cc,dd)	/* convert a direction code into an x,y pair */ 1338. coord *cc; 1339. register int dd; 1340. { 1341. 	cc->x = xdir[dd]; 1342. 	cc->y = ydir[dd]; 1343. 	return; 1344. } 1345.  1346. int 1347. movecmd(sym)	/* also sets u.dz, but returns false for <> */ 1348. char sym; 1349. { 1350. 	register const char *dp; 1351. 	register const char *sdp; 1352. 	if(flags.num_pad) sdp = ndir; else sdp = sdir;	/* DICE workaround */ 1353. 1354. 	u.dz = 0; 1355. 	if(!(dp = index(sdp, sym))) return 0; 1356. 	u.dx = xdir[dp-sdp]; 1357. 	u.dy = ydir[dp-sdp]; 1358. 	u.dz = zdir[dp-sdp]; 1359. 	if (u.dx && u.dy && u.umonnum == PM_GRID_BUG) { 1360. 		u.dx = u.dy = 0; 1361. 		return 0; 1362. 	} 1363. 	return !u.dz; 1364. } 1365.  1366. int 1367. getdir(s) 1368. const char *s; 1369. { 1370. 	char dirsym; 1371. 1372. #ifdef REDO 1373. 	if(in_doagain) 1374. 	   dirsym = readchar; 1375. 	else 1376. #endif 1377. 	   dirsym = yn_function (s ? s : "In what direction?",  1378. 					(char *)0, '\0'); 1379. #ifdef REDO 1380. 	savech(dirsym); 1381. #endif 1382. 	if(dirsym == '.' || dirsym == 's') 1383. 		u.dx = u.dy = u.dz = 0; 1384. 	else if(!movecmd(dirsym) && !u.dz) { 1385. 		if(!index(quitchars, dirsym)) 1386. 			pline("What a strange direction!"); 1387. 		return 0; 1388. 	} 1389. 	if(!u.dz && (Stunned || (Confusion && !rn2(5)))) confdir; 1390. 	return 1; 1391. } 1392.  1393. #endif /* OVL1 */ 1394. #ifdef OVLB 1395. 1396. void 1397. confdir 1398. { 1399. 	register int x = (u.umonnum == PM_GRID_BUG) ? 2*rn2(4) : rn2(8); 1400. 	u.dx = xdir[x]; 1401. 	u.dy = ydir[x]; 1402. 	return; 1403. } 1404.  1405. #endif /* OVLB */ 1406. #ifdef OVL0 1407. 1408. int 1409. isok(x,y) 1410. register int x, y; 1411. { 1412. 	/* x corresponds to curx, so x==1 is the first column. Ach. %% */ 1413. 	return x >= 1 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1; 1414. } 1415.  1416. static NEARDATA int last_multi; 1417. 1418. /*  1419.  * convert a MAP window position into a movecmd 1420. */  1421. int 1422. click_to_cmd(x, y, mod) 1423.    int x, y, mod; 1424. { 1425.     x -= u.ux; 1426.    y -= u.uy; 1427.    /* convert without using floating point, allowing sloppy clicking */ 1428.    if(x > 2*abs(y)) 1429. 	x = 1, y = 0; 1430.    else if(y > 2*abs(x)) 1431. 	x = 0, y = 1; 1432.    else if(x < -2*abs(y)) 1433. 	x = -1, y = 0; 1434.    else if(y < -2*abs(x)) 1435. 	x = 0, y = -1; 1436.    else 1437. 	x = sgn(x), y = sgn(y); 1438. 1439.     if(x == 0 && y == 0)	/* map click on player to "rest" command */ 1440. 	return '.'; 1441. 1442.     x = xytod(x, y); 1443.    if(mod == CLICK_1) { 1444. 	return (flags.num_pad ? ndir[x] : sdir[x]); 1445.    } else { 1446. 	return (flags.num_pad ? M(ndir[x]) : 1447. 		(sdir[x] - 'a' + 'A')); /* run command */ 1448.    }  1449. }  1450.  1451. STATIC_OVL char * 1452. parse 1453. { 1454. #ifdef LINT	/* static char in_line[COLNO]; */ 1455. 	char in_line[COLNO]; 1456. #else 1457. 	static char in_line[COLNO]; 1458. #endif 1459. 	register int foo; 1460. 	boolean prezero = FALSE; 1461. 1462. 	multi = 0; 1463. 	flags.move = 1; 1464. 	flush_screen(1); /* Flush screen buffer. Put the cursor on the hero. */ 1465.  1466. 	if (!flags.num_pad || (foo = readchar) == 'n') 1467. 	   for  { 1468. 		foo = readchar; 1469. 		if (foo >= '0' && foo <= '9') { 1470. 		   multi = 10 * multi + foo - '0'; 1471. 		   if (multi < 0 || multi >= LARGEST_INT) multi = LARGEST_INT; 1472. 		   if (multi > 9) { 1473. 			clear_nhwindow(WIN_MESSAGE); 1474. 			Sprintf(in_line, "Count: %d", multi); 1475. 			pline(in_line); 1476. 			mark_synch; 1477. 		   }  1478. 		    last_multi = multi; 1479. 		   if (!multi && foo == '0') prezero = TRUE; 1480. 		} else break;	/* not a digit */ 1481. 	   }  1482.  1483. 	if (foo == '\033') {   /* esc cancels count (TH) */ 1484. 	   clear_nhwindow(WIN_MESSAGE); 1485. 	   multi = last_multi = 0; 1486. # ifdef REDO 1487. 	} else if (foo == DOAGAIN || in_doagain) { 1488. 	   multi = last_multi; 1489. 	} else { 1490. 	   last_multi = multi; 1491. 	   savech(0);	/* reset input queue */ 1492. 	   savech((char)foo); 1493. # endif 1494. 	} 1495.  1496. 	if (multi) { 1497. 	   multi--; 1498. 	   save_cm = in_line; 1499. 	} else { 1500. 	   save_cm = (char *)0; 1501. 	} 1502. 	in_line[0] = foo; 1503. 	in_line[1] = '\0'; 1504. 	if (foo == 'g' || foo == 'G' || (flags.num_pad && foo == '5') || 1505. 	    foo == 'm' || foo == 'M') { 1506. 	   foo = readchar; 1507. #ifdef REDO 1508. 	   savech((char)foo); 1509. #endif 1510. 	   in_line[1] = foo; 1511. 	   in_line[2] = 0; 1512. 	} 1513. 	clear_nhwindow(WIN_MESSAGE); 1514. 	if (prezero) in_line[0] = '\033'; 1515. 	return(in_line); 1516. } 1517.  1518. #endif /* OVL0 */ 1519. #ifdef OVLB 1520. 1521. #ifdef UNIX 1522. static 1523. void 1524. end_of_input 1525. { 1526. 	exit_nhwindows("End of input?"); 1527. #ifndef NOSAVEONHANGUP 1528. 	if (!program_state.done_hup++) 1529. 	   (void) dosave0; 1530. #endif 1531. 	clearlocks; 1532. 	terminate(EXIT_SUCCESS); 1533. } 1534. #endif 1535. 1536. #endif /* OVLB */ 1537. #ifdef OVL0 1538. 1539. char 1540. readchar 1541. { 1542. 	register int sym; 1543. 	int x, y, mod; 1544. 1545. #ifdef REDO 1546. 	sym = in_doagain ? Getchar : nh_poskey(&x, &y, &mod); 1547. #else 1548. 	sym = Getchar; 1549. #endif 1550. 1551. #ifdef UNIX 1552. # ifdef NR_OF_EOFS 1553. 	if (sym == EOF) { 1554. 	   register int cnt = NR_OF_EOFS; 1555. 	 /*  1556. 	   * Some SYSV systems seem to return EOFs for various reasons 1557. 	  * (?like when one hits break or for interrupted systemcalls?), 1558. 	  * and we must see several before we quit. 1559. 	  */  1560. 	    do { 1561. 		clearerr(stdin);	/* omit if clearerr is undefined */ 1562. 		sym = Getchar; 1563. 	   } while (--cnt && sym == EOF); 1564. 	} 1565. # endif /* NR_OF_EOFS */ 1566. 	if (sym == EOF) 1567. 	   end_of_input; 1568. #endif /* UNIX */ 1569. 1570. 	if(sym == 0) /* click event */ 1571. 	   sym = click_to_cmd(x, y, mod); 1572. 	return((char) sym); 1573. } 1574. #endif /* OVL0 */ 1575. 1576. /*cmd.c*/