Source:SLASH'EM 0.0.7E7F2/tech.c

Below is the full text to tech.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/tech.c#line123 ]], for example.

The latest source code for vanilla NetHack is at Source code.

1.   /*      SCCS Id: @(#)tech.c    3.2     98/Oct/30        */ 2.   /*      Original Code by Warren Cheung (Basis: spell.c, attrib.c) */ 3.   /*      Copyright (c) M. Stephenson 1988                          */ 4.   /* NetHack may be freely redistributed. See license for details. */ 5.     6.    /* All of the techs from cmd.c are ported here */ 7.    8.    #include "hack.h"  9. 10.  /* #define DEBUG */		/* turn on for diagnostics */ 11.   12.   static boolean FDECL(gettech, (int *)); 13.  static boolean FDECL(dotechmenu, (int, int *)); 14.  static void NDECL(doblitzlist); 15.  static int FDECL(get_tech_no,(int)); 16.  static int FDECL(techeffects, (int)); 17.  static void FDECL(hurtmon, (struct monst *,int)); 18.  static int FDECL(mon_to_zombie, (int)); 19.  STATIC_PTR int NDECL(tinker); 20.  STATIC_PTR int NDECL(draw_energy); 21.  static const struct innate_tech * NDECL(role_tech); 22.  static const struct innate_tech * NDECL(race_tech); 23.  static int NDECL(doblitz); 24.  static int NDECL(blitz_chi_strike); 25.  static int NDECL(blitz_e_fist); 26.  static int NDECL(blitz_pummel); 27.  static int NDECL(blitz_g_slam); 28.  static int NDECL(blitz_dash); 29.  static int NDECL(blitz_power_surge); 30.  static int NDECL(blitz_spirit_bomb); 31.   32.   static NEARDATA schar delay;            /* moves left for tinker/energy draw */ 33.  static NEARDATA const char revivables[] = { ALLOW_FLOOROBJ, FOOD_CLASS, 0 }; 34.   35.   /*  36.    * Do try to keep the names <= 25 chars long, or else the 37.   * menu will look bad :B  WAC 38.   */  39.     40.   STATIC_OVL NEARDATA const char *tech_names[] = { 41.  	"no technique", 42.  	"berserk", 43.  	"kiii", 44.  	"research", 45.  	"surgery", 46.  	"reinforce memory", 47.  	"missile flurry", 48.  	"weapon practice", 49.  	"eviscerate", 50.  	"healing hands", 51.  	"calm steed", 52.  	"turn undead", 53.  	"vanish", 54.  	"cutthroat", 55.  	"blessing", 56.  	"elemental fist", 57.  	"primal roar", 58.  	"liquid leap", 59.  	"critical strike", 60.  	"sigil of control", 61.  	"sigil of tempest", 62.  	"sigil of discharge", 63.  	"raise zombies", 64.  	"revivification", 65.  	"ward against flame", 66.  	"ward against ice", 67.  	"ward against lightning", 68.  	"tinker", 69.  	"rage eruption", 70.  	"blink", 71.  	"chi strike", 72.  	"draw energy", 73.  	"chi healing", 74.  	"disarm", 75.  	"dazzle", 76.  	"chained blitz", 77.  	"pummel", 78.  	"ground slam", 79.  	"air dash", 80.  	"power surge", 81.  	"spirit bomb", 82.  	"draw blood", 83.  	""  84.   };  85.    86.   static const struct innate_tech 87.  	/* Roles */ 88.  	arc_tech[] = { {   1, T_RESEARCH, 1}, 89.  		       {   0, 0, 0} },  90.   	bar_tech[] = { {   1, T_BERSERK, 1}, 91.  		       {   0, 0, 0} },  92.   	cav_tech[] = { {   1, T_PRIMAL_ROAR, 1}, 93.  		       {   0, 0, 0} },  94.   	fla_tech[] = { {   1, T_REINFORCE, 1}, 95.  		       {   3, T_POWER_SURGE, 1}, 96.  		       {   5, T_DRAW_ENERGY, 1}, 97.  		       {  10, T_SIGIL_TEMPEST, 1}, 98.  		       {  20, T_SIGIL_DISCHARGE, 1}, 99.  		       {   0, 0, 0} },  100.  	hea_tech[] = { {   1, T_SURGERY, 1}, 101. 		       {  20, T_REVIVE, 1}, 102. 		       {   0, 0, 0} },  103.  	ice_tech[] = { {   1, T_REINFORCE, 1}, 104. 		       {   5, T_DRAW_ENERGY, 1}, 105. 		       {  10, T_SIGIL_TEMPEST, 1}, 106. 		       {  12, T_POWER_SURGE, 1}, 107. 		       {  20, T_SIGIL_DISCHARGE, 1}, 108. 		       {   0, 0, 0} },  109.  	kni_tech[] = { {   1, T_TURN_UNDEAD, 1}, 110. 		       {   1, T_HEAL_HANDS, 1}, 111. 		       {   0, 0, 0} },  112.  	mon_tech[] = { {   1, T_PUMMEL, 1}, 113. 		       {   1, T_DASH, 1}, 114. 		       {   1, T_BLITZ, 1}, 115. 		       {   2, T_CHI_STRIKE, 1}, 116. 	  	       {   4, T_CHI_HEALING, 1}, 117. 	  	       {   6, T_E_FIST, 1}, 118. 		       {   8, T_DRAW_ENERGY, 1}, 119. 		       {  10, T_G_SLAM, 1}, 120. 		       {  11, T_WARD_FIRE, 1}, 121. 		       {  13, T_WARD_COLD, 1}, 122. 		       {  15, T_WARD_ELEC, 1}, 123. 		       {  17, T_SPIRIT_BOMB, 1}, 124. 		       {  20, T_POWER_SURGE, 1}, 125. 		       {   0, 0, 0} },  126.  	nec_tech[] = { {   1, T_REINFORCE, 1}, 127. 		       {   1, T_RAISE_ZOMBIES, 1}, 128. 		       {  10, T_POWER_SURGE, 1}, 129. 		       {  15, T_SIGIL_TEMPEST, 1}, 130. 		       {   0, 0, 0} },  131.  	pri_tech[] = { {   1, T_TURN_UNDEAD, 1}, 132. 		       {   1, T_BLESSING, 1}, 133. 		       {   0, 0, 0} },  134.  	ran_tech[] = { {   1, T_FLURRY, 1}, 135. 		       {   0, 0, 0} },  136.  	rog_tech[] = { {   1, T_CRIT_STRIKE, 1}, 137. 		       {  15, T_CUTTHROAT, 1}, 138. 		       {   0, 0, 0} },  139.  	sam_tech[] = { {   1, T_KIII, 1}, 140. 		       {   0, 0, 0} },  141.  	tou_tech[] = { /* Put Tech here */ 142. 		       {   0, 0, 0} },  143.  	und_tech[] = { {   1, T_TURN_UNDEAD, 1}, 144. 		       {   1, T_PRACTICE, 1}, 145. 		       {   0, 0, 0} },  146.  	val_tech[] = { {   1, T_PRACTICE, 1}, 147. 		       {   0, 0, 0} },  148.  #ifdef YEOMAN 149. 	yeo_tech[] = { 150. #ifdef STEED 151. 		       {   1, T_CALM_STEED, 1}, 152. #endif 153. 		       {   0, 0, 0} },  154.  #endif 155. 	wiz_tech[] = { {   1, T_REINFORCE, 1}, 156. 		       {   3, T_DRAW_ENERGY, 1}, 157. 		       {   5, T_POWER_SURGE, 1}, 158. 		       {   7, T_SIGIL_CONTROL, 1}, 159. 		       {  14, T_SIGIL_TEMPEST, 1}, 160. 		       {  20, T_SIGIL_DISCHARGE, 1}, 161. 		       {   0, 0, 0} },		        162.  	/* Races */ 163. 	dop_tech[] = { {   1, T_LIQUID_LEAP, 1}, 164. 		       {   0, 0, 0} },  165.  	dwa_tech[] = { {   1, T_RAGE, 1}, 166. 		       {   0, 0, 0} },  167.  	elf_tech[] = { /* Put Tech here */ 168. 		       {   0, 0, 0} },  169.  	gno_tech[] = { {   1, T_VANISH, 1}, 170. 		       {   7, T_TINKER, 1}, 171. 		       {   0, 0, 0} },  172.  	hob_tech[] = { {   1, T_BLINK, 1}, 173. 		       {   0, 0, 0} },  174.  	lyc_tech[] = { {   1, T_EVISCERATE, 1}, 175. 		       {  10, T_BERSERK, 1}, 176. 		       {   0, 0, 0} },  177.  	vam_tech[] = { {   1, T_DAZZLE, 1}, 178. 		       {   1, T_DRAW_BLOOD, 1}, 179. 		       {   0, 0, 0} };  180.  	/* Orc */ 181.  182.  /* Local Macros 183.  * these give you direct access to the player's list of techs. 184.  * Are you sure you don't want to use tech_inuse,  which is the 185.  * extern function for checking whether a fcn is inuse 186.  */  187.   188.  #define techt_inuse(tech)       tech_list[tech].t_inuse 189. #define techtout(tech)        tech_list[tech].t_tout 190. #define techlev(tech)         (u.ulevel - tech_list[tech].t_lev) 191. #define techid(tech)          tech_list[tech].t_id 192. #define techname(tech)        (tech_names[techid(tech)]) 193. #define techlet(tech)  \ 194.         ((char)((tech < 26) ? ('a' + tech) : ('A' + tech - 26))) 195.  196.  /* A simple pseudorandom number generator 197.  *  198.   * This should generate fairly random numbers that will be  199. * mod LP_HPMOD from 2 to 9, with 0 mod LP_HPMOD 200.  * but can't use the normal RNG since can_limitbreak must 201.  * return the same state on the same turn. 202.  * This also has to depend on things that do NOT change during 203.  * save and restore,  and also should only change between turns 204.  */  205.  #if 0 /* Probably overkill */ 206. #define LB_CYCLE 259993L	/* number of turns before the pattern repeats */ 207. #define LB_BASE1 ((long) (monstermoves + u.uhpmax + 300L)) 208. #define LB_BASE2 ((long) (moves + u.uenmax + u.ulevel + 300L)) 209. #define LB_STRIP 6	/* Remove the last few bits as they tend to be less random */ 210. #endif 211.   212.  #define LB_CYCLE 101L	/* number of turns before the pattern repeats */ 213. #define LB_BASE1 ((long) (monstermoves + u.uhpmax + 10L)) 214. #define LB_BASE2 ((long) (moves + u.uenmax + u.ulevel + 10L)) 215. #define LB_STRIP 3	/* Remove the last few bits as they tend to be less random */ 216.   217.  #define LB_HPMOD ((long) ((u.uhp * 10 / u.uhpmax > 2) ? \ 218.          			(u.uhp * 10 / u.uhpmax) : 2)) 219.  220.  #define can_limitbreak (!Upolyd && (u.uhp*10 < u.uhpmax) && \  221.          		  (u.uhp == 1 || (!((((LB_BASE1 * \  222.          		  LB_BASE2) % LB_CYCLE) >> LB_STRIP) \ 223.         		  % LB_HPMOD)))) 224.          225.  /* Whether you know the tech */ 226. boolean 227. tech_known(tech) 228. 	short tech; 229. {  230.  	int i;  231. for (i = 0; i < MAXTECH; i++) { 232. 		if (techid(i) == tech) 233. 		     return TRUE; 234. 	}  235.  	return FALSE; 236. }  237.   238.  /* Called to prematurely stop a technique */ 239. void 240. aborttech(tech) 241. {  242.  	int i;  243. 244. 	i = get_tech_no(tech); 245. 	if (tech_list[i].t_inuse) { 246. 	    switch (tech_list[i].t_id) { 247. 		case T_RAGE: 248. 		    u.uhpmax -= tech_list[i].t_inuse - 1; 249. 		    if (u.uhpmax < 1) 250. 			u.uhpmax = 0; 251. 		    u.uhp -= tech_list[i].t_inuse - 1; 252. 		    if (u.uhp < 1) 253. 			u.uhp = 1; 254. 		    break; 255. 		case T_POWER_SURGE: 256. 		    u.uenmax -= tech_list[i].t_inuse - 1; 257. 		    if (u.uenmax < 1) 258. 			u.uenmax = 0; 259. 		    u.uen -= tech_list[i].t_inuse - 1; 260. 		    if (u.uen < 0) 261. 			u.uen = 0; 262. 		    break; 263. 	    }  264.  	    tech_list[i].t_inuse = 0; 265. 	}  266.  }  267.   268.  /* Called to teach a new tech. Level is starting tech level */ 269. void 270. learntech(tech, mask, tlevel) 271. 	short tech; 272. 	long mask; 273. 	int tlevel; 274. {  275.  	int i;  276. const struct innate_tech *tp; 277.  278.  	i = get_tech_no(tech); 279. 	if (tlevel > 0) { 280. 	    if (i < 0) { 281. 		i = get_tech_no(NO_TECH); 282. 		if (i < 0) { 283. 		    impossible("No room for new technique?"); 284. 		    return; 285. 		}  286.  	    }  287.  	    tlevel = u.ulevel ? u.ulevel - tlevel : 0; 288. 	    if (tech_list[i].t_id == NO_TECH) { 289. 		tech_list[i].t_id = tech; 290. 		tech_list[i].t_lev = tlevel; 291. 		tech_list[i].t_inuse = 0; /* not in use */ 292. 		tech_list[i].t_intrinsic = 0; 293. 	    }  294.  	    else if (tech_list[i].t_intrinsic & mask) { 295. 		impossible("Tech already known."); 296. 		return; 297. 	    }  298.  	    if (mask == FROMOUTSIDE) { 299. 		tech_list[i].t_intrinsic &= ~OUTSIDE_LEVEL; 300. 		tech_list[i].t_intrinsic |= tlevel & OUTSIDE_LEVEL; 301. 	    }  302.  	    if (tlevel < tech_list[i].t_lev) 303. 		tech_list[i].t_lev = tlevel; 304. 	    tech_list[i].t_intrinsic |= mask; 305. 	    tech_list[i].t_tout = 0; /* Can use immediately*/ 306. 	}  307.  	else if (tlevel < 0) { 308. 	    if (i < 0 || !(tech_list[i].t_intrinsic & mask)) { 309. 		impossible("Tech not known."); 310. 		return; 311. 	    }  312.  	    tech_list[i].t_intrinsic &= ~mask; 313. 	    if (!(tech_list[i].t_intrinsic & INTRINSIC)) { 314. 		if (tech_list[i].t_inuse) 315. 		    aborttech(tech); 316. 		tech_list[i].t_id = NO_TECH; 317. 		return; 318. 	    }  319.  	    /* Re-calculate lowest t_lev */ 320. 	    if (tech_list[i].t_intrinsic & FROMOUTSIDE) 321. 		tlevel = tech_list[i].t_intrinsic & OUTSIDE_LEVEL; 322. 	    if (tech_list[i].t_intrinsic & FROMEXPER) { 323. 		for(tp = role_tech; tp->tech_id; tp++) 324. 		    if (tp->tech_id == tech) 325. 			break; 326. 		if (!tp->tech_id) 327. 		    impossible("No inate technique for role?"); 328. 		else if (tlevel < 0 || tp->ulevel - tp->tech_lev < tlevel) 329. 		    tlevel = tp->ulevel - tp->tech_lev; 330. 	    }  331.  	    if (tech_list[i].t_intrinsic & FROMRACE) { 332. 		for(tp = race_tech; tp->tech_id; tp++) 333. 		    if (tp->tech_id == tech) 334. 			break; 335. 		if (!tp->tech_id) 336. 		    impossible("No inate technique for race?"); 337. 		else if (tlevel < 0 || tp->ulevel - tp->tech_lev < tlevel) 338. 		    tlevel = tp->ulevel - tp->tech_lev; 339. 	    }  340.  	    tech_list[i].t_lev = tlevel; 341. 	}  342.  	else 343. 	    impossible("Invalid Tech Level!"); 344. }  345.   346.  /*  347.   * Return TRUE if a tech was picked, with the tech index in the return 348.  * parameter. Otherwise return FALSE. 349.  */  350.  static boolean 351. gettech(tech_no) 352.         int *tech_no; 353. {  354.          int i, ntechs, idx; 355. 	char ilet, lets[BUFSZ], qbuf[QBUFSZ]; 356.  357.  	for (ntechs = i = 0; i < MAXTECH; i++) 358. 	    if (techid(i) != NO_TECH) ntechs++; 359. 	if (ntechs == 0)  { 360.             You("don't know any techniques right now."); 361. 	    return FALSE; 362. 	}  363.  	if (flags.menu_style == MENU_TRADITIONAL) { 364.             if (ntechs == 1)  Strcpy(lets, "a"); 365.             else if (ntechs < 27)  Sprintf(lets, "a-%c", 'a' + ntechs - 1); 366.             else if (ntechs == 27)  Sprintf(lets, "a-z A"); 367.             else Sprintf(lets, "a-z A-%c", 'A' + ntechs - 27); 368.  369.  	    for  { 370.                 Sprintf(qbuf, "Perform which technique? [%s ?]", lets); 371. 		if ((ilet = yn_function(qbuf, (char *)0, '\0')) == '?') 372. 		    break; 373.  374.  		if (index(quitchars, ilet)) 375. 		    return FALSE; 376.  377.  		if (letter(ilet) && ilet != '@') { 378. 		    /* in a-zA-Z, convert back to an index */ 379. 		    if (lowc(ilet) == ilet)     /* lower case */ 380. 			idx = ilet - 'a'; 381. 		    else 382. 			idx = ilet - 'A' + 26; 383.  384.                      if (idx < ntechs) 385. 			for(i = 0; i < MAXTECH; i++) 386. 			    if (techid(i) != NO_TECH) { 387. 				if (idx-- == 0) { 388. 				    *tech_no = i;  389. return TRUE; 390. 				}  391.  			    }  392.  		}  393.                  You("don't know that technique."); 394. 	    }  395.  	}  396.          return dotechmenu(PICK_ONE, tech_no); 397. }  398.   399.  static boolean 400. dotechmenu(how, tech_no) 401. 	int how; 402.         int *tech_no; 403. {  404.  	winid tmpwin; 405. 	int i, n, len, longest, techs_useable, tlevel; 406. 	char buf[BUFSZ], let = 'a'; 407. 	const char *prefix; 408. 	menu_item *selected; 409. 	anything any; 410.  411.  	tmpwin = create_nhwindow(NHW_MENU); 412. 	start_menu(tmpwin); 413. 	any.a_void = 0;         /* zero out all bits */ 414.  415.  	techs_useable = 0; 416.  417.  	if (!iflags.menu_tab_sep) { 418. 	    /* find the length of the longest tech */ 419. 	    for (longest = 0, i = 0; i < MAXTECH; i++) { 420. 		if (techid(i) == NO_TECH) continue; 421. 		if ((len = strlen(techname(i))) > longest) 422. 		    longest = len; 423. 	    }  424.  	    Sprintf(buf, "    %-*s Level   Status", longest, "Name"); 425. 	} else 426. 	    Sprintf(buf, "Name\tLevel\tStatus"); 427.  428.  	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 429.  430.  	for (i = 0; i < MAXTECH; i++) { 431. 	    if (techid(i) == NO_TECH) 432. 		continue; 433. 	    tlevel = techlev(i); 434. 	    if (!techtout(i) && tlevel > 0) { 435. 		/* Ready to use */ 436. 		techs_useable++; 437. 		prefix = ""; 438. 		any.a_int = i + 1; 439. 	    } else { 440. 		prefix = "    "; 441. 		any.a_int = 0; 442. 	    }  443.  #ifdef WIZARD 444. 	    if (wizard) 445. 		if (!iflags.menu_tab_sep) 446. 		    Sprintf(buf, "%s%-*s %2d%c%c%c   %s(%i)",  447.  			    prefix, longest, techname(i), tlevel,  448.  			    tech_list[i].t_intrinsic & FROMEXPER ? 'X' : ' ',  449.  			    tech_list[i].t_intrinsic & FROMRACE ? 'R' : ' ',  450.  			    tech_list[i].t_intrinsic & FROMOUTSIDE ? 'O' : ' ',  451.  			    tech_inuse(techid(i)) ? "Active" :  452.  			    tlevel <= 0 ? "Beyond recall" :  453.  			    can_limitbreak ? "LIMIT" :  454.  			    !techtout(i) ? "Prepared" :  455.  			    techtout(i) > 100 ? "Not Ready" : "Soon",  456.  			    techtout(i)); 457. 		else 458. 		    Sprintf(buf, "%s%s\t%2d%c%c%c\t%s(%i)",  459.  			    prefix, techname(i), tlevel,  460.  			    tech_list[i].t_intrinsic & FROMEXPER ? 'X' : ' ',  461.  			    tech_list[i].t_intrinsic & FROMRACE ? 'R' : ' ',  462.  			    tech_list[i].t_intrinsic & FROMOUTSIDE ? 'O' : ' ',  463.  			    tech_inuse(techid(i)) ? "Active" :  464.  			    tlevel <= 0 ? "Beyond recall" :  465.  			    can_limitbreak ? "LIMIT" :  466.  			    !techtout(i) ? "Prepared" :  467.  			    techtout(i) > 100 ? "Not Ready" : "Soon",  468.  			    techtout(i)); 469. 	    else 470. #endif 471. 	    if (!iflags.menu_tab_sep) 472. 		Sprintf(buf, "%s%-*s %5d   %s",  473.  			prefix, longest, techname(i), tlevel,  474.  			tech_inuse(techid(i)) ? "Active" :  475.  			tlevel <= 0 ? "Beyond recall" :  476.  			can_limitbreak ? "LIMIT" :  477.  			!techtout(i) ? "Prepared" :  478.  			techtout(i) > 100 ? "Not Ready" : "Soon"); 479. 	    else 480. 		Sprintf(buf, "%s%s\t%5d\t%s",  481.  			prefix, techname(i), tlevel,  482.  			tech_inuse(techid(i)) ? "Active" :  483.  			tlevel <= 0 ? "Beyond recall" :  484.  			can_limitbreak ? "LIMIT" :  485.  			!techtout(i) ? "Prepared" :  486.  			techtout(i) > 100 ? "Not Ready" : "Soon"); 487.  488.  	    add_menu(tmpwin, NO_GLYPH, &any,  489.  		    techtout(i) ? 0 : let, 0, ATR_NONE, buf, MENU_UNSELECTED); 490. 	    if (let++ == 'z') let = 'A'; 491. 	}  492.   493.  	if (!techs_useable) 494. 	    how = PICK_NONE; 495.  496.  	end_menu(tmpwin, how == PICK_ONE ? "Choose a technique" :  497.  					   "Currently known techniques"); 498.  499.  	n = select_menu(tmpwin, how, &selected); 500. 	destroy_nhwindow(tmpwin); 501. 	if (n > 0) { 502. 	    *tech_no = selected[0].item.a_int - 1; 503. 	    free((genericptr_t)selected); 504. 	    return TRUE; 505. 	}  506.  	return FALSE; 507. }  508.   509.  static int 510. get_tech_no(tech) 511. int tech; 512. {  513.  	int i;  514. 515. 	for (i = 0; i < MAXTECH; i++) { 516. 		if (techid(i) == tech) { 517. 			return(i); 518. 		}  519.  	}  520.  	return (-1); 521. }  522.   523.  int 524. dotech 525. {  526.  	int tech_no; 527.  528.  	if (gettech(&tech_no)) 529. 	    return techeffects(tech_no); 530. 	return 0; 531. }  532.   533.  static NEARDATA const char kits[] = { TOOL_CLASS, 0 }; 534.  535.  static struct obj * 536. use_medical_kit(type, feedback, verb) 537. int type; 538. boolean feedback; 539. char *verb; 540. {  541.      struct obj *obj, *otmp; 542.     makeknown(MEDICAL_KIT); 543.     if (!(obj = carrying(MEDICAL_KIT))) { 544. 	if (feedback) You("need a medical kit to do that."); 545. 	return (struct obj *)0; 546.     }  547.      for (otmp = invent; otmp; otmp = otmp->nobj) 548. 	if (otmp->otyp == MEDICAL_KIT && otmp != obj) 549. 	    break; 550.     if (otmp) {	/* More than one medical kit */ 551. 	obj = getobj(kits, verb); 552. 	if (!obj) 553. 	    return (struct obj *)0; 554.     }  555.      for (otmp = obj->cobj; otmp; otmp = otmp->nobj) 556. 	if (otmp->otyp == type) 557. 	    break; 558.     if (!otmp) { 559. 	if (feedback) 560. 	    You_cant("find any more %s in %s.",  561.  		    makeplural(simple_typename(type)), yname(obj)); 562. 	return (struct obj *)0; 563.     }  564.      return otmp; 565. }  566.   567.  /* gettech is reworked getspell */ 568. /* reworked class special effects code */ 569. /* adapted from specialpower in cmd.c */ 570. static int 571. techeffects(tech_no) 572. int tech_no; 573. {  574.  	/* These variables are used in various techs */ 575. 	struct obj *obj, *otmp; 576. 	const char *str; 577. 	struct monst *mtmp; 578. 	int num; 579. 	char Your_buf[BUFSZ]; 580. 	char allowall[2]; 581. 	int i, j, t_timeout = 0; 582.  583.   584.  	/* check timeout */ 585. 	if (tech_inuse(techid(tech_no))) { 586. 	    pline("This technique is already active!"); 587. 	    return (0); 588. 	}  589.          if (techtout(tech_no) && !can_limitbreak) { 590. 	    You("have to wait %s before using your technique again.",  591.                  (techtout(tech_no) > 100) ?  592.                          "for a while" : "a little longer"); 593. #ifdef WIZARD 594.             if (!wizard || (yn("Use technique anyways?") == 'n')) 595. #endif 596.                 return(0); 597.         }  598.   599.  	/* switch to the tech and do stuff */ 600.         switch (techid(tech_no)) { 601.             case T_RESEARCH: 602. 		/* WAC stolen from the spellcasters...'A' can identify from 603.         	   historical research*/ 604. 		if(Hallucination || Stunned || Confusion) { 605. 		    You("can't concentrate right now!"); 606. 		    return(0); 607. 		} else if((ACURR(A_INT) + ACURR(A_WIS)) < rnd(60)) { 608. 			pline("Nothing in your pack looks familiar."); 609.                     t_timeout = rn1(500,500); 610. 		    break; 611. 		} else if(invent) { 612. 			You("examine your possessions."); 613. 			identify_pack((int) ((techlev(tech_no) / 10) + 1)); 614. 		} else { 615. 			/* KMH -- fixed non-compliant string */ 616. 		    You("are already quite familiar with the contents of your pack."); 617. 		    break; 618. 		}  619.                  t_timeout = rn1(500,1500); 620. 		break; 621.             case T_EVISCERATE: 622. 		/* only when empty handed, in human form */ 623. 		if (Upolyd || uwep || uarmg) { 624. 		    You_cant("do this while %s!", Upolyd ? "polymorphed" :  625.  			    uwep ? "holding a weapon" : "wearing gloves"); 626. 		    return 0; 627. 		}  628.  		Your("fingernails extend into claws!"); 629. 		aggravate; 630. 		techt_inuse(tech_no) = d(2,4) + techlev(tech_no)/5 + 2; 631. 		t_timeout = rn1(1000,1000); 632. 		break; 633.             case T_BERSERK: 634. 		You("fly into a berserk rage!"); 635. 		techt_inuse(tech_no) = d(2,8) + 636.                		(techlev(tech_no)/5) + 2; 637. 		incr_itimeout(&HFast, techt_inuse(tech_no)); 638. 		t_timeout = rn1(1000,500); 639. 		break; 640.             case T_REINFORCE: 641. 		/* WAC spell-users can study their known spells*/ 642. 		if(Hallucination || Stunned || Confusion) { 643. 		    You("can't concentrate right now!"); 644. 		    break; 645.                	} else { 646. 		    You("concentrate..."); 647. 		    if (studyspell) t_timeout = rn1(1000,500); /*in spell.c*/ 648. 		}  649.                 break; 650.             case T_FLURRY: 651.                 Your("%s %s become blurs as they reach for your quiver!",  652.  			uarmg ? "gloved" : "bare",      /* Del Lamb */  653.  			makeplural(body_part(HAND))); 654.                 techt_inuse(tech_no) = rnd((int) (techlev(tech_no)/6 + 1)) + 2; 655.                 t_timeout = rn1(1000,500); 656. 		break; 657.             case T_PRACTICE: 658.                 if(!uwep || (weapon_type(uwep) == P_NONE)) { 659. 		    You("are not wielding a weapon!"); 660. 		    return(0); 661. 		} else if(uwep->known == TRUE) { 662.                     practice_weapon; 663. 		} else { 664.                     if (not_fully_identified(uwep)) { 665.                         You("examine %s.", doname(uwep)); 666.                             if (rnd(15) <= ACURR(A_INT)) { 667.                                 makeknown(uwep->otyp); 668.                                 uwep->known = TRUE; 669.                                 You("discover it is %s",doname(uwep)); 670.                                 } else 671.                      pline("Unfortunately, you didn't learn anything new."); 672.                     }  673.                  /*WAC Added practicing code - in weapon.c*/ 674.                     practice_weapon; 675. 		}  676.                  t_timeout = rn1(500,500); 677. 		break; 678.             case T_SURGERY: 679. 		if (Hallucination || Stunned || Confusion) { 680. 		    You("are in no condition to perform surgery!"); 681. 		    break; 682. 		}  683.  		if (Sick || Slimed) { 684. 		    if (carrying(SCALPEL)) { 685. 			pline("Using your scalpel (ow!), you cure your infection!"); 686. 			make_sick(0L, (char *)0, TRUE, SICK_ALL); 687. 			Slimed = 0; 688. 			if (Upolyd) { 689. 			    u.mh -= 5; 690. 			    if (u.mh < 1) 691. 				rehumanize; 692. 			} else if (u.uhp > 6) 693. 			    u.uhp -= 5; 694. 			else 695. 			    u.uhp = 1; 696.                         t_timeout = rn1(500,500); 697. 			flags.botl = TRUE; 698. 			break; 699. 		    } else pline("If only you had a scalpel..."); 700. 		}  701.  		if (Upolyd ? u.mh < u.mhmax : u.uhp < u.uhpmax) { 702. 		    otmp = use_medical_kit(BANDAGE, FALSE,  703.  			    "dress your wounds with"); 704. 		    if (otmp) { 705. 			check_unpaid(otmp); 706. 			if (otmp->quan > 1L) 707. 			    otmp->quan--; 708. 			else { 709. 			    obj_extract_self(otmp); 710. 			    obfree(otmp, (struct obj *)0); 711. 			}  712.  			pline("Using %s, you dress your wounds.", yname(otmp)); 713. 			healup(techlev(tech_no) * (rnd(2)+1) + rn1(5,5),  714.  			  0, FALSE, FALSE); 715. 		    } else { 716. 			You("strap your wounds as best you can."); 717. 			healup(techlev(tech_no) + rn1(5,5), 0, FALSE, FALSE); 718. 		    }  719.                      t_timeout = rn1(1000,500); 720. 		    flags.botl = TRUE; 721. 		} else You("don't need your healing powers!"); 722. 		break; 723.             case T_HEAL_HANDS: 724. 		if (Slimed) { 725. 		    Your("body is on fire!"); 726. 		    burn_away_slime; 727. 		    t_timeout = 3000; 728. 		} else if (Sick) { 729. 		    You("lay your hands on the foul sickness..."); 730. 		    make_sick(0L, (char*)0, TRUE, SICK_ALL); 731. 		    t_timeout = 3000; 732. 		} else if (Upolyd ? u.mh < u.mhmax : u.uhp < u.uhpmax) { 733. 		    pline("A warm glow spreads through your body!"); 734. 		    healup(techlev(tech_no) * 4, 0, FALSE, FALSE); 735. 		    t_timeout = 3000; 736. 		} else 737. 		    pline(nothing_happens); 738. 		break; 739.             case T_KIII: 740. 		You("scream \"KIIILLL!\""); 741. 		aggravate; 742.                 techt_inuse(tech_no) = rnd((int) (techlev(tech_no)/6 + 1)) + 2; 743.                 t_timeout = rn1(1000,500); 744. 		break; 745. #ifdef STEED 746. 	    case T_CALM_STEED: 747.                 if (u.usteed) { 748.                         pline("%s gets tamer.", Monnam(u.usteed)); 749.                         tamedog(u.usteed, (struct obj *) 0); 750.                         t_timeout = rn1(1000,500); 751.                 } else 752.                         Your("technique is only effective when riding a monster."); 753.                 break; 754. #endif 755.             case T_TURN_UNDEAD: 756.                 return(turn_undead); 757. 	    case T_VANISH: 758. 		if (Invisible && Fast) { 759. 			You("are already quite nimble and undetectable."); 760. 		}  761.                  techt_inuse(tech_no) = rn1(50,50) + techlev(tech_no); 762. 		if (!Invisible) pline("In a puff of smoke,  you disappear!"); 763. 		if (!Fast) You("feel more nimble!"); 764. 		incr_itimeout(&HInvis, techt_inuse(tech_no)); 765. 		incr_itimeout(&HFast, techt_inuse(tech_no)); 766. 		newsym(u.ux,u.uy);      /* update position */ 767. 		t_timeout = rn1(1000,500); 768. 		break; 769. 	    case T_CRIT_STRIKE: 770. 		if (!getdir((char *)0)) return(0); 771. 		if (!u.dx && !u.dy) { 772. 		    /* Hopefully a mistake ;B */ 773. 		    You("decide against that idea."); 774. 		    return(0); 775. 		}  776.  		mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 777. 		if (!mtmp) { 778. 		    You("perform a flashy twirl!"); 779. 		    return (0); 780. 		} else { 781. 		    int oldhp = mtmp->mhp; 782. 		    int tmp; 783.  784.  		    if (!attack(mtmp)) return(0); 785. 		    if (!DEADMONSTER(mtmp) && mtmp->mhp < oldhp &&  786.  			    !noncorporeal(mtmp->data) && !unsolid(mtmp->data)) { 787. 			You("strike %s vital organs!", s_suffix(mon_nam(mtmp))); 788. 			/* Base damage is always something, though it may be  789. * reduced to zero if the hero is hampered. However, 790. 			 * since techlev will never be zero, stiking vital 791. 			 * organs will always do _some_ damage. 792. 			 */  793.  			tmp = mtmp->mhp > 1 ? mtmp->mhp / 2 : 1; 794. 			if (!humanoid(mtmp->data) || is_golem(mtmp->data) ||  795.  				mtmp->data->mlet == S_CENTAUR) { 796. 			    You("are hampered by the differences in anatomy."); 797. 			    tmp /= 2; 798. 			}  799.  			tmp += techlev(tech_no); 800. 			t_timeout = rn1(1000, 500); 801. 			hurtmon(mtmp, tmp); 802. 		    }  803.  		}  804.  		break; 805. 	    case T_CUTTHROAT: 806. 		if (!is_blade(uwep)) { 807. 			You("need a blade to perform cutthroat!"); 808. 			return (0); 809. 		}  810.  	    	if (!getdir((char *)0)) return(0); 811. 		if (!u.dx && !u.dy) { 812. 			/* Hopefully a mistake ;B */ 813. 			pline("Things may be going badly,  but that's extreme."); 814. 			return(0); 815. 		}  816.  		mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 817. 		if (!mtmp) { 818. 			You("attack...nothing!"); 819. 			return (0); 820. 		} else { 821. 			int oldhp = mtmp->mhp; 822. 			  823.  			if (!attack(mtmp)) return(0); 824. 			if (!DEADMONSTER(mtmp) && mtmp->mhp < oldhp) { 825. 				int tmp = 0; 826. 				if (!has_head(mtmp->data) || u.uswallow) { 827. 					You("can't perform cutthroat on %s!",mon_nam(mtmp)); 828. 				}  829.  				if (rn2(5) < (techlev(tech_no)/10 + 1)) { 830. 					You("sever %s head!", s_suffix(mon_nam(mtmp))); 831. 					tmp = mtmp->mhp; 832. 				} else { 833. 					You("hurt %s badly!", s_suffix(mon_nam(mtmp))); 834. 					tmp = mtmp->mhp / 2; 835. 				}  836.  				tmp += techlev(tech_no); 837. 				t_timeout = rn1(1000,500); 838. 				hurtmon(mtmp, tmp); 839. 			}  840.  		}  841.  		break; 842. 	    case T_BLESSING: 843. 		allowall[0] = ALL_CLASSES; allowall[1] = '\0'; 844. 		  845.  		if ( !(obj = getobj(allowall, "bless"))) return(0); 846. 		pline("An aura of holiness surrounds your hands!"); 847.                 if (!Blind) (void) Shk_Your(Your_buf, obj); 848. 		if (obj->cursed) { 849.                 	if (!Blind) 850.                     		pline("%s %s %s.",Your_buf,  851.  						  aobjnam(obj, "softly glow"),  852.  						  hcolor(NH_AMBER)); 853. 				uncurse(obj); 854. 				obj->bknown=1; 855. 		} else if(!obj->blessed) { 856. 			if (!Blind) { 857. 				str = hcolor(NH_LIGHT_BLUE); 858. 				pline("%s %s with a%s %s aura.",  859.  					  Your_buf,  860.  					  aobjnam(obj, "softly glow"),  861.  					  index(vowels, *str) ? "n" : "", str); 862. 			}  863.  			bless(obj); 864. 			obj->bknown=1; 865. 		} else { 866. 			if (obj->bknown) { 867. 				pline ("That object is already blessed!"); 868. 				return(0); 869. 			}  870.  			obj->bknown=1; 871. 			pline("The aura fades."); 872. 		}  873.  		t_timeout = rn1(1000,500); 874. 		break; 875. 	    case T_E_FIST: 876. 	    	blitz_e_fist; 877. #if 0 878. 		str = makeplural(body_part(HAND)); 879.                 You("focus the powers of the elements into your %s", str); 880.                 techt_inuse(tech_no) = rnd((int) (techlev(tech_no)/3 + 1)) + d(1,4) + 2; 881. #endif 882. 		t_timeout = rn1(1000,500); 883. 	    	break; 884. 	    case T_PRIMAL_ROAR: 885. 	    	You("let out a bloodcurdling roar!"); 886. 	    	aggravate; 887.  888.  		techt_inuse(tech_no) = d(2,6) + (techlev(tech_no)) + 2; 889.  890.  		incr_itimeout(&HFast, techt_inuse(tech_no)); 891.  892.  	    	for(i = -5; i <= 5; i++) for(j = -5; j <= 5; j++) 893. 		    if(isok(u.ux+i, u.uy+j) && (mtmp = m_at(u.ux+i, u.uy+j))) { 894. 		    	if (mtmp->mtame != 0 && !mtmp->isspell) { 895. 		    	    struct permonst *ptr = mtmp->data; 896. 			    struct monst *mtmp2; 897. 		    	    int ttime = techt_inuse(tech_no); 898. 		    	    int type = little_to_big(monsndx(ptr)); 899. 		    	     900.  		    	    mtmp2 = tamedog(mtmp, (struct obj *) 0); 901. 			    if (mtmp2) 902. 				mtmp = mtmp2; 903.  904.  		    	    if (type && type != monsndx(ptr)) { 905. 				ptr = &mons[type]; 906. 		    	    	mon_spec_poly(mtmp, ptr, ttime, FALSE,  907.  					canseemon(mtmp), FALSE, TRUE); 908. 		    	    }  909.  		    	}  910.  		    }  911.  		t_timeout = rn1(1000,500); 912. 	    	break; 913. 	    case T_LIQUID_LEAP: { 914. 	    	coord cc; 915. 	    	int dx, dy, sx, sy, range; 916.  917.  		pline("Where do you want to leap to?"); 918.     		cc.x = sx = u.ux; 919. 		cc.y = sy = u.uy; 920.  921.  		getpos(&cc, TRUE, "the desired position"); 922. 		if (cc.x == -10) return 0; /* user pressed esc */ 923.  924.  		dx = cc.x - u.ux; 925. 		dy = cc.y - u.uy; 926. 		/* allow diagonals */ 927. 	    	if (dx && dy && dx != dy && dx != -dy) { 928. 		    You("can only leap in straight lines!"); 929. 		    return 0; 930. 	    	} else if (distu(cc.x, cc.y) > 19 + techlev(tech_no)) { 931. 		    pline("Too far!"); 932. 		    return 0; 933. 		} else if (m_at(cc.x, cc.y) || !isok(cc.x, cc.y) ||  934.  			IS_ROCK(levl[cc.x][cc.y].typ) ||  935.  			sobj_at(BOULDER, cc.x, cc.y) ||  936.  			closed_door(cc.x, cc.y)) { 937. 		    You_cant("flow there!"); /* MAR */ 938. 		    return 0; 939. 		} else { 940. 		    You("liquify!"); 941. 		    if (Punished) { 942. 			You("slip out of the iron chain."); 943. 			unpunish; 944. 		    }  945.  		    if(u.utrap) { 946. 			switch(u.utraptype) { 947. 			    case TT_BEARTRAP: 948. 				You("slide out of the bear trap."); 949. 				break; 950. 			    case TT_PIT: 951. 				You("leap from the pit!"); 952. 				break; 953. 			    case TT_WEB: 954. 				You("flow through the web!"); 955. 				break; 956. 			    case TT_LAVA: 957. 				You("separate from the lava!"); 958. 				u.utrap = 0; 959. 				break; 960. 			    case TT_INFLOOR: 961. 				u.utrap = 0; 962. 				You("ooze out of the floor!"); 963. 			}  964.  			u.utrap = 0; 965. 		    }  966.  		    /* Fry the things in the path ;B */ 967. 		    if (dx) range = dx; 968. 		    else range = dy; 969. 		    if (range < 0) range = -range; 970. 		     971.  		    dx = sgn(dx); 972. 		    dy = sgn(dy); 973. 		     974.  		    while (range-- > 0) { 975. 		    	int tmp_invul = 0; 976. 		    	  977.  		    	if (!Invulnerable) Invulnerable = tmp_invul = 1; 978. 			sx += dx; sy += dy; 979. 			tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, AD_ACID-1)); 980. 			tmp_at(sx,sy); 981. 			delay_output; /* wait a little */ 982. 		    	if ((mtmp = m_at(sx, sy)) != 0) { 983. 			    int chance; 984. 			     985.  			    chance = rn2(20); 986. 		    	    if (!chance || (3 - chance) > AC_VALUE(find_mac(mtmp))) 987. 		    	    	break; 988. 			    setmangry(mtmp); 989. 		    	    You("catch %s in your acid trail!", mon_nam(mtmp)); 990. 		    	    if (!resists_acid(mtmp)) { 991. 				int tmp = 1; 992. 				/* Need to add a to-hit */ 993. 				tmp += d(2,4); 994. 				tmp += rn2((int) (techlev(tech_no)/5 + 1)); 995. 				if (!Blind) pline_The("acid burns %s!", mon_nam(mtmp)); 996. 				hurtmon(mtmp, tmp); 997. 			    } else if (!Blind) pline_The("acid doesn't affect %s!", mon_nam(mtmp)); 998. 			}  999.  			/* Clean up */ 1000. 			tmp_at(DISP_END,0); 1001. 			if (tmp_invul) Invulnerable = 0; 1002. 		   }  1003.  1004. 		    /* A little Sokoban guilt... */ 1005. 		    if (In_sokoban(&u.uz)) 1006. 			change_luck(-1); 1007. 		   You("reform!"); 1008. 		   teleds(cc.x, cc.y, FALSE); 1009. 		   nomul(-1); 1010. 		   nomovemsg = ""; 1011. 	   	}  1012. 		t_timeout = rn1(1000,500); 1013. 	   	break; 1014. 	   }  1015.             case T_SIGIL_TEMPEST: 1016. 		/* Have enough power? */ 1017. 		num = 50 - techlev(tech_no)/5; 1018. 		if (u.uen < num) { 1019. 			You("don't have enough power to invoke the sigil!"); 1020. 			return (0); 1021. 		} 1022. 		u.uen -= num; 1023. 1024. 		/* Invoke */ 1025. 		You("invoke the sigil of tempest!"); 1026.                techt_inuse(tech_no) = d(1,6) + rnd(techlev(tech_no)/5 + 1) + 2; 1027. 		u_wipe_engr(2); 1028. 		return(0); 1029. 		break; 1030.            case T_SIGIL_CONTROL: 1031. 		/* Have enough power? */ 1032. 		num = 30 - techlev(tech_no)/5; 1033. 		if (u.uen < num) { 1034. 			You("don't have enough power to invoke the sigil!"); 1035. 			return (0); 1036. 		} 1037. 		u.uen -= num; 1038. 1039. 		/* Invoke */ 1040. 		You("invoke the sigil of control!"); 1041.                techt_inuse(tech_no) = d(1,4) + rnd(techlev(tech_no)/5 + 1) + 2; 1042. 		u_wipe_engr(2); 1043. 		return(0); 1044. 		break; 1045.            case T_SIGIL_DISCHARGE: 1046. 		/* Have enough power? */ 1047. 		num = 100 - techlev(tech_no)/5; 1048. 		if (u.uen < num) { 1049. 			You("don't have enough power to invoke the sigil!"); 1050. 			return (0); 1051. 		} 1052. 		u.uen -= num; 1053. 1054. 		/* Invoke */ 1055. 		You("invoke the sigil of discharge!"); 1056.                techt_inuse(tech_no) = d(1,4) + rnd(techlev(tech_no)/5 + 1) + 2; 1057. 		u_wipe_engr(2); 1058. 		return(0); 1059. 		break; 1060.            case T_RAISE_ZOMBIES: 1061.            	You("chant the ancient curse..."); 1062. 		for(i = -1; i <= 1; i++) for(j = -1; j <= 1; j++) { 1063. 		   int corpsenm; 1064. 1065. 		    if (!isok(u.ux+i, u.uy+j)) continue; 1066. 		   for (obj = level.objects[u.ux+i][u.uy+j]; obj; obj = otmp) { 1067. 			otmp = obj->nexthere; 1068. 1069. 			if (obj->otyp != CORPSE) continue; 1070. 			/* Only generate undead */ 1071. 			corpsenm = mon_to_zombie(obj->corpsenm); 1072. 			if (corpsenm != -1 && !cant_create(&corpsenm, TRUE) && 1073. 			  (!obj->oxlth || obj->oattached != OATTACHED_MONST)) { 1074. 			   /* Maintain approx. proportion of oeaten to cnutrit 1075. 			    * so that the zombie's HP relate roughly to how 1076. 			    * much of the original corpse was left. 1077. 			    */  1078. 			    if (obj->oeaten) 1079. 				obj->oeaten = 1080. 					eaten_stat(mons[corpsenm].cnutrit, obj); 1081. 			   obj->corpsenm = corpsenm; 1082. 			   mtmp = revive(obj); 1083. 			   if (mtmp) { 1084. 				if (!resist(mtmp, SPBOOK_CLASS, 0, TELL)) { 1085. 				  mtmp = tamedog(mtmp, (struct obj *) 0); 1086. 				  You("dominate %s!", mon_nam(mtmp)); 1087. 				} else setmangry(mtmp); 1088. 			   }  1089. 			}  1090. 		    }  1091. 		}  1092. 		nomul(-2); /* You need to recover */ 1093. 		nomovemsg = 0; 1094. 		t_timeout = rn1(1000,500); 1095. 		break; 1096.            case T_REVIVE: 1097. 		if (u.uswallow) { 1098. 		   You(no_elbow_room); 1099. 		   return 0; 1100. 		} 1101.             	num = 100 - techlev(tech_no); /* WAC make this depend on mon? */ 1102.             	if ((Upolyd && u.mh <= num) || (!Upolyd && u.uhp <= num)){ 1103. 		   You("don't have the strength to perform revivification!"); 1104. 		   return 0; 1105.            	}  1106.  1107.             	obj = getobj((const char *)revivables, "revive"); 1108.            	if (!obj) return (0); 1109.            	mtmp = revive(obj); 1110.            	if (mtmp) { 1111. #ifdef BLACKMARKET 1112. 		   if (Is_blackmarket(&u.uz)) 1113. 			setmangry(mtmp); 1114. 		   else 1115. #endif 1116. 		   if (mtmp->isshk) 1117. 			make_happy_shk(mtmp, FALSE); 1118. 		   else if (!resist(mtmp, SPBOOK_CLASS, 0, NOTELL)) 1119. 			(void) tamedog(mtmp, (struct obj *) 0); 1120. 		} 1121.             	if (Upolyd) u.mh -= num; 1122.            	else u.uhp -= num; 1123. 		t_timeout = rn1(1000,500); 1124.            	break; 1125. 	   case T_WARD_FIRE: 1126. 		/* Already have it intrinsically? */ 1127. 		if (HFire_resistance & FROMOUTSIDE) return (0); 1128. 1129. 		You("invoke the ward against flame!"); 1130. 		HFire_resistance += rn1(100,50); 1131. 		HFire_resistance += techlev(tech_no); 1132. 		t_timeout = rn1(1000,500); 1133. 1134. 	    	break; 1135. 	   case T_WARD_COLD: 1136. 		/* Already have it intrinsically? */ 1137. 		if (HCold_resistance & FROMOUTSIDE) return (0); 1138. 1139. 		You("invoke the ward against ice!"); 1140. 		HCold_resistance += rn1(100,50); 1141. 		HCold_resistance += techlev(tech_no); 1142. 		t_timeout = rn1(1000,500); 1143. 1144. 	    	break; 1145. 	   case T_WARD_ELEC: 1146. 		/* Already have it intrinsically? */ 1147. 		if (HShock_resistance & FROMOUTSIDE) return (0); 1148. 1149. 		You("invoke the ward against lightning!"); 1150. 		HShock_resistance += rn1(100,50); 1151. 		HShock_resistance += techlev(tech_no); 1152. 		t_timeout = rn1(1000,500); 1153. 1154. 	    	break; 1155. 	   case T_TINKER: 1156. 		if (Blind) { 1157. 			You("can't do any tinkering if you can't see!"); 1158. 			return (0); 1159. 		} 1160. 		if (!uwep) { 1161. 			You("aren't holding an object to work on!"); 1162. 			return (0); 1163. 		} 1164. 		You("are holding %s.", doname(uwep)); 1165. 		if (yn("Start tinkering on this?") != 'y') return(0); 1166. 		You("start working on %s",doname(uwep)); 1167. 		delay=-150 + techlev(tech_no); 1168. 		set_occupation(tinker, "tinkering", 0); 1169. 		break; 1170. 	   case T_RAGE: 1171. 		if (Upolyd) { 1172. 			You("cannot focus your anger!"); 1173. 			return(0); 1174. 		} 1175. 	    	You("feel the anger inside you erupt!"); 1176. 		num = 50 + (4 * techlev(tech_no)); 1177. 	   	techt_inuse(tech_no) = num + 1; 1178. 		u.uhpmax += num; 1179. 		u.uhp += num; 1180. 		t_timeout = rn1(1000,500); 1181. 		break; 1182. 	   case T_BLINK: 1183. 	   	You("feel the flow of time slow down."); 1184.                techt_inuse(tech_no) = rnd(techlev(tech_no) + 1) + 2; 1185. 		t_timeout = rn1(1000,500); 1186. 	   	break; 1187.            case T_CHI_STRIKE: 1188.            	if (!blitz_chi_strike) return(0); 1189.                t_timeout = rn1(1000,500); 1190. 		break; 1191.            case T_DRAW_ENERGY: 1192.            	if (u.uen == u.uenmax) { 1193.            		if (Hallucination) You("are fully charged!"); 1194. 			else You("cannot hold any more energy!"); 1195. 			return(0); 1196.            	}  1197.                 You("begin drawing energy from your surroundings!"); 1198. 		delay=-15; 1199. 		set_occupation(draw_energy, "drawing energy", 0); 1200.                t_timeout = rn1(1000,500); 1201. 		break; 1202.            case T_CHI_HEALING: 1203.            	if (u.uen < 1) { 1204.            		You("are too weak to attempt this!"); 1205.            		return(0); 1206.            	}  1207. 		You("direct your internal energy to restoring your body!"); 1208.                techt_inuse(tech_no) = techlev(tech_no)*2 + 4; 1209.                t_timeout = rn1(1000,500); 1210. 		break; 1211. 	   case T_DISARM: 1212. 	   	if (P_SKILL(weapon_type(uwep)) == P_NONE) { 1213. 	   		You("aren't wielding a proper weapon!"); 1214. 	   		return(0); 1215. 	   	}  1216. 	    	if ((P_SKILL(weapon_type(uwep)) < P_SKILLED) || (Blind)) { 1217. 	   		You("aren't capable of doing this!"); 1218. 	   		return(0); 1219. 	   	}  1220. 		if (u.uswallow) { 1221. 	   		pline("What do you think %s is?  A sword swallower?",  1222. 				mon_nam(u.ustuck)); 1223. 	   		return(0); 1224. 		} 1225.  1226. 	    	if (!getdir((char *)0)) return(0); 1227. 		if (!u.dx && !u.dy) { 1228. 			/* Hopefully a mistake ;B */ 1229. 			pline("Why don't you try wielding something else instead."); 1230. 			return(0); 1231. 		} 1232. 		mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 1233. 		if (!mtmp || !canspotmon(mtmp)) { 1234. 			if (memory_is_invisible(u.ux + u.dx, u.uy + u.dy)) 1235. 			   You("don't know where to aim for!"); 1236. 			else 1237. 			   You("don't see anything there!"); 1238. 			return (0); 1239. 		} 1240. 	    	obj = MON_WEP(mtmp);   /* can be null */ 1241. 	   	if (!obj) { 1242. 	   		You_cant("disarm an unarmed foe!"); 1243. 	   		return(0); 1244. 	   	}  1245. 		/* Blindness dealt with above */ 1246. 		if (!mon_visible(mtmp) 1247. #ifdef INVISIBLE_OBJECTS  1248. 				|| obj->oinvis && !See_invisible  1249. #endif  1250. 				) { 1251. 	   		You_cant("see %s weapon!", s_suffix(mon_nam(mtmp))); 1252. 	   		return(0); 1253. 		} 1254. 		num = ((rn2(techlev(tech_no) + 15))  1255. 			* (P_SKILL(weapon_type(uwep)) - P_SKILLED + 1)) / 10; 1256. 1257. 		You("attempt to disarm %s...",mon_nam(mtmp)); 1258. 		/* WAC can't yank out cursed items */ 1259.                if (num > 0 && (!Fumbling || !rn2(10)) && !obj->cursed) { 1260. 		   int roll; 1261. 		   obj_extract_self(obj); 1262. 		   possibly_unwield(mtmp, FALSE); 1263. 		   setmnotwielded(mtmp, obj); 1264. 		   roll = rn2(num + 1); 1265. 		   if (roll > 3) roll = 3; 1266. 		   switch (roll) { 1267. 			case 2: 1268. 			   /* to floor near you */ 1269. 			   You("knock %s %s to the %s!",  1270. 				s_suffix(mon_nam(mtmp)),  1271. 				xname(obj),  1272. 				surface(u.ux, u.uy)); 1273. 			   if (obj->otyp == CRYSKNIFE &&  1274. 				    (!obj->oerodeproof || !rn2(10))) { 1275. 				obj->otyp = WORM_TOOTH; 1276. 				obj->oerodeproof = 0; 1277. 			   }  1278. 			    place_object(obj, u.ux, u.uy); 1279. 			   stackobj(obj); 1280. 			   break; 1281. 			case 3: 1282. #if 0 1283. 			   if (!rn2(25)) { 1284. 				/* proficient at disarming, but maybe not 1285. 				  so proficient at catching weapons */ 1286. 				int hitu, hitvalu; 1287. 1288. 				hitvalu = 8 + obj->spe; 1289. 				hitu = thitu(hitvalu, 1290. 					dmgval(obj, &youmonst),  1291. 					obj, xname(obj)); 1292. 				if (hitu) 1293. 				   pline("%s hits you as you try to snatch it!",  1294. 					    The(xname(obj))); 1295. 				place_object(obj, u.ux, u.uy); 1296. 				stackobj(obj); 1297. 				break; 1298. 			   }  1299. #endif /* 0 */ 1300. 			   /* right into your inventory */ 1301. 			   You("snatch %s %s!", s_suffix(mon_nam(mtmp)),  1302. 				    xname(obj)); 1303. 			   if (obj->otyp == CORPSE &&  1304. 				    touch_petrifies(&mons[obj->corpsenm]) &&  1305. 				    !uarmg && !Stone_resistance &&  1306. 				    !(poly_when_stoned(youmonst.data) && 1307. 					polymon(PM_STONE_GOLEM))) { 1308. 				char kbuf[BUFSZ]; 1309. 1310. 				Sprintf(kbuf, "%s corpse",  1311. 					an(mons[obj->corpsenm].mname)); 1312. 				pline("Snatching %s is a fatal mistake.", kbuf); 1313. 				instapetrify(kbuf); 1314. 			   }  1315. 			    obj = hold_another_object(obj, "You drop %s!",  1316. 				    doname(obj), (const char *)0); 1317. 			   break; 1318. 			default: 1319. 			   /* to floor beneath mon */ 1320. 			   You("knock %s from %s grasp!", the(xname(obj)),  1321. 				    s_suffix(mon_nam(mtmp))); 1322. 			   if (obj->otyp == CRYSKNIFE &&  1323. 				    (!obj->oerodeproof || !rn2(10))) { 1324. 				obj->otyp = WORM_TOOTH; 1325. 				obj->oerodeproof = 0; 1326. 			   }  1327. 			    place_object(obj, mtmp->mx, mtmp->my); 1328. 			   stackobj(obj); 1329. 			   break; 1330. 		   }  1331. 		} else if (mtmp->mcanmove && !mtmp->msleeping) 1332. 		   pline("%s evades your attack.", Monnam(mtmp)); 1333. 		else 1334. 		   You("fail to dislodge %s %s.", s_suffix(mon_nam(mtmp)),  1335. 			    xname(obj)); 1336. 		wakeup(mtmp); 1337. 		if (!mtmp->mcanmove && !rn2(10)) { 1338. 		   mtmp->mcanmove = 1; 1339. 		   mtmp->mfrozen = 0; 1340. 		} 1341. 		break; 1342. 	   case T_DAZZLE: 1343. 	   	/* Short range stun attack */ 1344. 	   	if (Blind) { 1345. 	   		You("can't see anything!"); 1346. 	   		return(0); 1347. 	   	}  1348. 	    	if (!getdir((char *)0)) return(0); 1349. 		if (!u.dx && !u.dy) { 1350. 			/* Hopefully a mistake ;B */ 1351. 			You("can't see yourself!"); 1352. 			return(0); 1353. 		} 1354. 		for(i = 0; (i  <= ((techlev(tech_no) / 8) + 1) 1355. 			&& isok(u.ux + (i*u.dx), u.uy + (i*u.dy))); i++) { 1356. 		   mtmp = m_at(u.ux + (i*u.dx), u.uy + (i*u.dy)); 1357. 		   if (mtmp && canseemon(mtmp)) break; 1358. 		} 1359. 		if (!mtmp || !canseemon(mtmp)) { 1360. 			You("fail to make eye contact with anything!"); 1361. 			return (0); 1362. 		} 1363.                 You("stare at %s.", mon_nam(mtmp)); 1364.                if (!haseyes(mtmp->data)) 1365.                	pline("..but %s has no eyes!", mon_nam(mtmp)); 1366.                else if (!mtmp->mcansee) 1367.                	pline("..but %s cannot see you!", mon_nam(mtmp)); 1368.                if ((rn2(6) + rn2(6) + (techlev(tech_no) - mtmp->m_lev)) > 10) { 1369. 			You("dazzle %s!", mon_nam(mtmp)); 1370. 			mtmp->mcanmove = 0; 1371. 			mtmp->mfrozen = rnd(10); 1372. 		} else { 1373.                       pline("%s breaks the stare!", Monnam(mtmp)); 1374. 		} 1375.                	t_timeout = rn1(50,25); 1376. 	   	break; 1377. 	   case T_BLITZ: 1378. 	   	if (uwep || (u.twoweap && uswapwep)) { 1379. 			You("can't do this while wielding a weapon!"); 1380. 	   		return(0); 1381. 	   	} else if (uarms) { 1382. 			You("can't do this while holding a shield!"); 1383. 	   		return(0); 1384. 	   	}  1385. 	    	if (!doblitz) return (0); 1386. 		 1387.                 t_timeout = rn1(1000,500); 1388. 	   	break; 1389.            case T_PUMMEL: 1390. 	   	if (uwep || (u.twoweap && uswapwep)) { 1391. 			You("can't do this while wielding a weapon!"); 1392. 	   		return(0); 1393. 	   	} else if (uarms) { 1394. 			You("can't do this while holding a shield!"); 1395. 	   		return(0); 1396. 	   	}  1397. 		if (!getdir((char *)0)) return(0); 1398. 		if (!u.dx && !u.dy) { 1399. 			You("flex your muscles."); 1400. 			return(0); 1401. 		} 1402.             	if (!blitz_pummel) return(0); 1403.                t_timeout = rn1(1000,500); 1404. 		break; 1405.            case T_G_SLAM: 1406. 	   	if (uwep || (u.twoweap && uswapwep)) { 1407. 			You("can't do this while wielding a weapon!"); 1408. 	   		return(0); 1409. 	   	} else if (uarms) { 1410. 			You("can't do this while holding a shield!"); 1411. 	   		return(0); 1412. 	   	}  1413. 		if (!getdir((char *)0)) return(0); 1414. 		if (!u.dx && !u.dy) { 1415. 			You("flex your muscles."); 1416. 			return(0); 1417. 		} 1418.             	if (!blitz_g_slam) return(0); 1419.                t_timeout = rn1(1000,500); 1420. 		break; 1421.            case T_DASH: 1422. 		if (!getdir((char *)0)) return(0); 1423. 		if (!u.dx && !u.dy) { 1424. 			You("stretch."); 1425. 			return(0); 1426. 		} 1427.             	if (!blitz_dash) return(0); 1428.                t_timeout = rn1(50, 25); 1429. 		break; 1430.            case T_POWER_SURGE: 1431.            	if (!blitz_power_surge) return(0); 1432. 		t_timeout = rn1(1000,500); 1433. 		break; 1434.            case T_SPIRIT_BOMB: 1435. 	   	if (uwep || (u.twoweap && uswapwep)) { 1436. 			You("can't do this while wielding a weapon!"); 1437. 	   		return(0); 1438. 	   	} else if (uarms) { 1439. 			You("can't do this while holding a shield!"); 1440. 	   		return(0); 1441. 	   	}  1442. 		if (!getdir((char *)0)) return(0); 1443.            	if (!blitz_spirit_bomb) return(0); 1444. 		t_timeout = rn1(1000,500); 1445. 		break; 1446. 	   case T_DRAW_BLOOD: 1447. 		if (!maybe_polyd(is_vampire(youmonst.data), 1448. 		 Race_if(PM_VAMPIRE))) { 1449. 		   /* ALI 1450. 		    * Otherwise we get problems with what we create: 1451. 		    * potions of vampire blood would no longer be  1452. * appropriate. 1453. 		    */  1454. 		    You("must be in your natural form to draw blood."); 1455. 		   return(0); 1456. 		} 1457. 		obj = use_medical_kit(PHIAL, TRUE, "draw blood with"); 1458. 		if (!obj) 1459. 		   return 0; 1460. 		if (u.ulevel <= 1) { 1461. 		   You_cant("seem to find a vein."); 1462. 		   return 0; 1463. 		} 1464. 		check_unpaid(obj); 1465. 		if (obj->quan > 1L) 1466. 		   obj->quan--; 1467. 		else { 1468. 		   obj_extract_self(obj); 1469. 		   obfree(obj, (struct obj *)0); 1470. 		} 1471. 		pline("Using your medical kit, you draw off a phial of your blood."); 1472. 		losexp("drawing blood", TRUE); 1473. 		if (u.uexp > 0) 1474. 		   u.uexp = newuexp(u.ulevel - 1); 1475. 		otmp = mksobj(POT_VAMPIRE_BLOOD, FALSE, FALSE); 1476. 		otmp->cursed = obj->cursed; 1477. 		otmp->blessed = obj->blessed; 1478. 		(void) hold_another_object(otmp, 1479. 			"You fill, but have to drop, %s!", doname(otmp),  1480. 			(const char *)0); 1481. 		t_timeout = rn1(1000, 500); 1482. 		break; 1483. 	   default: 1484. 	   	pline ("Error!  No such effect (%i)", tech_no); 1485. 		break; 1486.        }  1487.         if (!can_limitbreak) 1488. 	   techtout(tech_no) = (t_timeout * (100 - techlev(tech_no))/100); 1489. 1490. 	/*By default,  action should take a turn*/ 1491. 	return(1); 1492. } 1493.  1494. /* Whether or not a tech is in use. 1495. * 0 if not in use, turns left if in use. Tech is done when techinuse == 1 1496. */  1497. int 1498. tech_inuse(tech_id) 1499. int tech_id; 1500. { 1501.         int i;  1502. 1503.        if (tech_id < 1 || tech_id > MAXTECH) { 1504.                impossible ("invalid tech: %d", tech_id); 1505.                return(0); 1506.        }  1507.         for (i = 0; i < MAXTECH; i++) { 1508.                if (techid(i) == tech_id) { 1509.                        return (techt_inuse(i)); 1510.                }  1511.         }  1512. 	return (0); 1513. } 1514.  1515. void 1516. tech_timeout 1517. { 1518. 	int i;  1519. 1520.        for (i = 0; i < MAXTECH; i++) { 1521. 	   if (techid(i) == NO_TECH) 1522. 		continue; 1523. 	   if (techt_inuse(i)) { 1524. 	   	/* Check if technique is done */ 1525. 	       if (!(--techt_inuse(i))) 1526. 	       switch (techid(i)) { 1527. 		   case T_EVISCERATE: 1528. 			You("retract your claws."); 1529. 			/* You're using bare hands now, so new msg for next attack */ 1530. 			unweapon=TRUE; 1531. 			/* Lose berserk status */ 1532. 			repeat_hit = 0; 1533. 			break; 1534. 		   case T_BERSERK: 1535. 			The("red haze in your mind clears."); 1536. 			break; 1537. 		   case T_KIII: 1538. 			You("calm down."); 1539. 			break; 1540. 		   case T_FLURRY: 1541. 			You("relax."); 1542. 			break; 1543. 		   case T_E_FIST: 1544. 			You("feel the power dissipate."); 1545. 			break; 1546. 		   case T_SIGIL_TEMPEST: 1547. 			pline_The("sigil of tempest fades."); 1548. 			break; 1549. 		   case T_SIGIL_CONTROL: 1550. 			pline_The("sigil of control fades."); 1551. 			break; 1552. 		   case T_SIGIL_DISCHARGE: 1553. 			pline_The("sigil of discharge fades."); 1554. 			break; 1555. 		   case T_RAGE: 1556. 			Your("anger cools."); 1557. 			break; 1558. 		   case T_POWER_SURGE: 1559. 			pline_The("awesome power within you fades."); 1560. 			break; 1561. 		   case T_BLINK: 1562. 			You("sense the flow of time returning to normal."); 1563. 			break; 1564. 		   case T_CHI_STRIKE: 1565. 			You("feel the power in your hands dissipate."); 1566. 			break; 1567. 		   case T_CHI_HEALING: 1568. 			You("feel the healing power dissipate."); 1569. 			break; 1570. 	           default: 1571. 	           	break; 1572. 	       } else switch (techid(i)) { 1573. 	       /* During the technique */ 1574. 		   case T_RAGE: 1575. 			/* Bleed but don't kill */ 1576. 			if (u.uhpmax > 1) u.uhpmax--; 1577. 			if (u.uhp > 1) u.uhp--; 1578. 			break; 1579. 		   case T_POWER_SURGE: 1580. 			/* Bleed off power. Can go to zero as 0 power is not fatal */ 1581. 			if (u.uenmax > 1) u.uenmax--; 1582. 			if (u.uen > 0) u.uen--; 1583. 			break; 1584. 	           default: 1585. 	           	break; 1586. 	       }  1587. 	    }  1588.  1589. 	    if (techtout(i) > 0) techtout(i)--; 1590.        }  1591. }  1592.  1593. void 1594. docalm 1595. { 1596. 	int i, tech, n = 0; 1597. 1598. 	for (i = 0; i < MAXTECH; i++) { 1599. 	   tech = techid(i); 1600. 	   if (tech != NO_TECH && techt_inuse(i)) { 1601. 		aborttech(tech); 1602. 		n++; 1603. 	   }  1604. 	}  1605. 	if (n) 1606. 	   You("calm down."); 1607. } 1608.  1609. static void 1610. hurtmon(mtmp, tmp) 1611. struct monst *mtmp; 1612. int tmp; 1613. { 1614. 	mtmp->mhp -= tmp; 1615. 	if (mtmp->mhp < 1) killed (mtmp); 1616. #ifdef SHOW_DMG 1617. 	else showdmg(tmp); 1618. #endif 1619. } 1620.  1621. static const struct 	innate_tech * 1622. role_tech 1623. { 1624. 	switch (Role_switch) { 1625. 		case PM_ARCHEOLOGIST:	return (arc_tech); 1626. 		case PM_BARBARIAN:	return (bar_tech); 1627. 		case PM_CAVEMAN:	return (cav_tech); 1628. 		case PM_FLAME_MAGE:	return (fla_tech); 1629. 		case PM_HEALER:		return (hea_tech); 1630. 		case PM_ICE_MAGE:	return (ice_tech); 1631. 		case PM_KNIGHT:		return (kni_tech); 1632. 		case PM_MONK: 		return (mon_tech); 1633. 		case PM_NECROMANCER:	return (nec_tech); 1634. 		case PM_PRIEST:		return (pri_tech); 1635. 		case PM_RANGER:		return (ran_tech); 1636. 		case PM_ROGUE:		return (rog_tech); 1637. 		case PM_SAMURAI:	return (sam_tech); 1638. #ifdef TOURIST 1639. 		case PM_TOURIST:	return (tou_tech); 1640. #endif 1641. 		case PM_UNDEAD_SLAYER:	return (und_tech); 1642. 		case PM_VALKYRIE:	return (val_tech); 1643. 		case PM_WIZARD:		return (wiz_tech); 1644. #ifdef YEOMAN 1645. 		case PM_YEOMAN:		return (yeo_tech); 1646. #endif 1647. 		default: 		return ((struct innate_tech *) 0); 1648. 	} 1649. }  1650.  1651. static const struct     innate_tech * 1652. race_tech 1653. { 1654. 	switch (Race_switch) { 1655. 		case PM_DOPPELGANGER:	return (dop_tech); 1656. #ifdef DWARF 1657. 		case PM_DWARF:		return (dwa_tech); 1658. #endif 1659. 		case PM_ELF: 1660. 		case PM_DROW:		return (elf_tech); 1661. 		case PM_GNOME:		return (gno_tech); 1662. 		case PM_HOBBIT:		return (hob_tech); 1663. 		case PM_HUMAN_WEREWOLF:	return (lyc_tech); 1664. 		case PM_VAMPIRE:	return (vam_tech); 1665. 		default: 		return ((struct innate_tech *) 0); 1666. 	} 1667. }  1668.  1669. void 1670. adjtech(oldlevel,newlevel) 1671. int oldlevel, newlevel; 1672. { 1673. 	const struct   innate_tech 1674. 		*tech = role_tech, *rtech = race_tech; 1675. 	long mask = FROMEXPER; 1676. 1677. 	while (tech || rtech) { 1678. 	   /* Have we finished with the tech lists? */ 1679. 	    if (!tech || !tech->tech_id) { 1680. 	   	/* Try the race intrinsics */ 1681. 	   	if (!rtech || !rtech->tech_id) break; 1682. 	   	tech = rtech; 1683. 	   	rtech = (struct innate_tech *) 0; 1684. 		mask = FROMRACE; 1685. 	   }  1686. 		  1687. 	    for(tech->tech_id; tech++) 1688. 		if(oldlevel < tech->ulevel && newlevel >= tech->ulevel) { 1689. 		   if (tech->ulevel != 1 && !tech_known(tech->tech_id)) 1690. 			You("learn how to perform %s!", 1691. 			  tech_names[tech->tech_id]); 1692. 		   learntech(tech->tech_id, mask, tech->tech_lev); 1693. 		} else if (oldlevel >= tech->ulevel && newlevel < tech->ulevel 1694. 		    && tech->ulevel != 1) { 1695. 		   learntech(tech->tech_id, mask, -1); 1696. 		   if (!tech_known(tech->tech_id)) 1697. 			You("lose the ability to perform %s!", 1698. 			  tech_names[tech->tech_id]); 1699. 		} 1700. 	}  1701. }  1702.  1703. int 1704. mon_to_zombie(monnum) 1705. int monnum; 1706. { 1707. 	if ((&mons[monnum])->mlet == S_ZOMBIE) return monnum;  /* is already zombie */ 1708. 	if ((&mons[monnum])->mlet == S_KOBOLD) return PM_KOBOLD_ZOMBIE; 1709. 	if ((&mons[monnum])->mlet == S_GNOME) return PM_GNOME_ZOMBIE; 1710. 	if (is_orc(&mons[monnum])) return PM_ORC_ZOMBIE; 1711. 	if (is_dwarf(&mons[monnum])) return PM_DWARF_ZOMBIE; 1712. 	if (is_elf(&mons[monnum])) return PM_ELF_ZOMBIE; 1713. 	if (is_human(&mons[monnum])) return PM_HUMAN_ZOMBIE; 1714. 	if (monnum == PM_ETTIN) return PM_ETTIN_ZOMBIE; 1715. 	if (is_giant(&mons[monnum])) return PM_GIANT_ZOMBIE; 1716. 	/* Is it humanoid? */ 1717. 	if (!humanoid(&mons[monnum])) return (-1); 1718. 	/* Otherwise, return a ghoul or ghast */ 1719. 	if (!rn2(4)) return PM_GHAST; 1720. 	else return PM_GHOUL; 1721. } 1722.  1723.  1724. /*WAC tinker code*/ 1725. STATIC_PTR int 1726. tinker 1727. { 1728. 	int chance; 1729. 	struct obj *otmp = uwep; 1730. 1731.  1732. 	if (delay) {    /* not if (delay++), so at end delay == 0 */ 1733. 		delay++; 1734. #if 0 1735. 		use_skill(P_TINKER, 1); /* Tinker skill */ 1736. #endif 1737. 		/*WAC a bit of practice so even if you're interrupted 1738. 		you won't be wasting your time ;B*/ 1739. 		return(1); /* still busy */ 1740. 	} 1741.  1742. 	if (!uwep) 1743. 		return (0); 1744. 1745. 	You("finish your tinkering."); 1746. 	chance = 5; 1747. /*	chance += PSKILL(P_TINKER); */ 1748. 	if (rnl(10) < chance) { 1749. 		upgrade_obj(otmp); 1750. 	} else { 1751. 		/* object downgrade - But for now,  nothing :) */  1752. 	}  1753.  1754. 	setuwep(otmp, FALSE);  1755. 	You("now hold %s!", doname(otmp));  1756. 	return(0);  1757. }  1758.  1759. /*WAC  draw energy from surrounding objects */  1760. STATIC_PTR int  1761. draw_energy  1762. {  1763. 	int powbonus = 1;  1764. 	if (delay) {    /* not if (delay++), so at end delay == 0 */  1765. 		delay++;  1766. 		confdir;  1767. 		if(isok(u.ux + u.dx, u.uy + u.dy)) {  1768. 			switch((&levl[u.ux + u.dx][u.uy + u.dy])->typ) {  1769. 			    case ALTAR: /* Divine power */  1770. 			    	powbonus =  (u.uenmax > 28 ? u.uenmax / 4 1771. 			   			: 7);  1772. 				break;  1773. 			    case THRONE: /* Regal == pseudo divine */  1774. 			    	powbonus =  (u.uenmax > 36 ? u.uenmax / 6 1775. 			   			: 6);			    		 	  1776. 				break;  1777. 			    case CLOUD: /* Air */  1778. 			    case TREE: /* Earth */  1779. 			    case LAVAPOOL: /* Fire */  1780. 			    case ICE: /* Water - most ordered form */  1781. 			    	powbonus = 5;  1782. 				break;  1783. 			    case AIR:  1784. 			    case MOAT: /* Doesn't freeze */  1785. 			    case WATER:  1786. 			    	powbonus = 4;  1787. 				break;  1788. 			    case POOL: /* Can dry up */  1789. 			    	powbonus = 3;  1790. 				break;  1791. 			    case FOUNTAIN:  1792. 			    	powbonus = 2;  1793. 				break;  1794. 			    case SINK:  /* Cleansing water */  1795. 			    	if (!rn2(3)) powbonus = 2;  1796. 				break;  1797. 			    case TOILET: /* Water Power...but also waste! */  1798. 			    	if (rn2(100) < 50)  1799. 			    		powbonus = 2;  1800. 			    	else powbonus = -2;  1801. 				break;  1802. 			    case GRAVE:  1803. 			    	powbonus = -4; 1804. 				break; 1805. 			   default: 1806. 				break; 1807. 			} 1808. 		}  1809. 		u.uen += powbonus; 1810. 		if (u.uen > u.uenmax) { 1811. 			delay = 0; 1812. 			u.uen = u.uenmax; 1813. 		} 1814. 		if (u.uen < 1) u.uen = 0; 1815. 		flags.botl = 1; 1816. 		return(1); /* still busy */ 1817. 	} 1818. 	You("finish drawing energy from your surroundings."); 1819. 	return(0); 1820. } 1821.  1822. static const char 1823. 	*Enter_Blitz = "Enter Blitz Command[. to end]: "; 1824. 1825. /* Keep commands that reference the same blitz together 1826. * Keep the BLITZ_START before the BLITZ_CHAIN before the BLITZ_END 1827. */  1828. static const struct blitz_tab blitzes[] = { 1829. 	{"LLDDR", 5, blitz_chi_strike, T_CHI_STRIKE, BLITZ_START}, 1830. 	{"LLDDRDR", 7, blitz_chi_strike, T_CHI_STRIKE, BLITZ_START}, 1831. 	{"RR", 2, blitz_dash, T_DASH, BLITZ_START}, 1832. 	{"LL", 2, blitz_dash, T_DASH, BLITZ_START}, 1833. 	{"UURRDDL", 7, blitz_e_fist, T_E_FIST, BLITZ_START}, 1834. 	{"URURRDDLDL", 10, blitz_e_fist, T_E_FIST, BLITZ_START}, 1835. 	{"DDRRDDRR", 8, blitz_power_surge, T_POWER_SURGE, BLITZ_START}, 1836. 	{"DRDRDRDR", 8, blitz_power_surge, T_POWER_SURGE, BLITZ_START}, 1837. 	{"LRL", 3, blitz_pummel, T_PUMMEL, BLITZ_CHAIN}, 1838. 	{"RLR", 3, blitz_pummel, T_PUMMEL, BLITZ_CHAIN}, 1839. 	{"DDDD", 4, blitz_g_slam, T_G_SLAM, BLITZ_END}, 1840. 	{"DUDUUDDD", 8, blitz_spirit_bomb, T_SPIRIT_BOMB, BLITZ_END}, 1841. 	{"", 0, (void *)0, 0, BLITZ_END} /* Array terminator */ 1842. }; 1843.  1844. #define MAX_BLITZ 50 1845. #define MIN_CHAIN 2 1846. #define MAX_CHAIN 5 1847. 1848. /* parse blitz input */ 1849. static int 1850. doblitz 1851. { 1852. 	int i, j, dx, dy, bdone = 0, tech_no; 1853. 	char buf[BUFSZ]; 1854. 	char *bp; 1855. 	int blitz_chain[MAX_CHAIN], blitz_num; 1856.         1857. 	tech_no = (get_tech_no(T_BLITZ)); 1858. 1859. 	if (tech_no == -1) { 1860. 		return(0); 1861. 	} 1862. 	  1863. 	if (u.uen < 10) { 1864. 		You("are too weak to attempt this!"); 1865.            	return(0); 1866. 	} 1867.  1868. 	bp = buf; 1869. 	 1870. 	if (!getdir((char *)0)) return(0); 1871. 	if (!u.dx && !u.dy) { 1872. 		return(0); 1873. 	} 1874. 	  1875. 	dx = u.dx; 1876. 	dy = u.dy; 1877. 1878. 	doblitzlist; 1879. 1880.     	for (i= 0; i < MAX_BLITZ; i++) { 1881. 		if (!getdir(Enter_Blitz)) return(0); /* Get directional input */ 1882.    		if (!u.dx && !u.dy && !u.dz) break; 1883.    		if (u.dx == -1) { 1884.    			*(bp) = 'L'; 1885.    			bp++; 1886.    		} else if (u.dx == 1) { 1887.    			*(bp) = 'R'; 1888.    			bp++; 1889.    		}  1890.     		if (u.dy == -1) { 1891.    			*(bp) = 'U'; 1892.    			bp++; 1893.    		} else if (u.dy == 1) { 1894.    			*(bp) = 'D'; 1895.    			bp++; 1896.    		}  1897.     		if (u.dz == -1) { 1898.    			*(bp) = '>'; 1899.    			bp++; 1900.    		} else if (u.dz == 1) { 1901.    			*(bp) = '<'; 1902.    			bp++; 1903.    		}  1904.     	}  1905. 	*(bp) = '.'; 1906. 	bp++; 1907. 	*(bp) = '\0'; 1908. 	bp = buf; 1909. 1910. 	/* Point of no return - You've entered and terminated a blitz, so... */ 1911.     	u.uen -= 10; 1912. 1913.     	/* parse input */ 1914.    	/* You can't put two of the same blitz in a row */ 1915.    	blitz_num = 0; 1916.    	while(strncmp(bp, ".", 1)) { 1917. 	   bdone = 0; 1918. 	   for (j = 0; blitzes[j].blitz_len; j++) { 1919. 	   	if (blitz_num >= MAX_CHAIN ||  1920. 	    	    blitz_num >= (MIN_CHAIN + (techlev(tech_no) / 10))) 1921. 	   		break; /* Trying to chain too many blitz commands */ 1922. 		else if (!strncmp(bp, blitzes[j].blitz_cmd, blitzes[j].blitz_len)) { 1923. 	   		/* Trying to chain in a command you don't know yet */ 1924. 			if (!tech_known(blitzes[j].blitz_tech)) 1925. 				break; 1926. 	   		if (blitz_num) { 1927. 				/* Check if trying to chain two of the exact same 1928. 				 * commands in a row 1929. 				 */ 1930. 	    			if (j == blitz_chain[(blitz_num - 1)]) 1931. 	   				break; 1932. 	   			/* Trying to chain after chain finishing command */ 1933. 	   			if (blitzes[blitz_chain[(blitz_num - 1)]].blitz_type  1934. 	    							== BLITZ_END) 1935. 	   				break; 1936. 	   			/* Trying to put a chain starter after starting 1937. 	   			 * a chain 1938. 	   			 * Note that it's OK to put two chain starters in a  1939. * row 1940. 	   			 */  1941. 	    			if ((blitzes[j].blitz_type == BLITZ_START) &&  1942. 	    			    (blitzes[blitz_chain[(blitz_num - 1)]].blitz_type 1943. 	   							!= BLITZ_START)) 1944. 	   				break; 1945. 	   		}  1946. 			bp += blitzes[j].blitz_len; 1947. 			blitz_chain[blitz_num] = j; 1948. blitz_num++; 1949. 			bdone = 1; 1950. 			break; 1951. 		} 1952. 	    }  1953. 	    if (!bdone) { 1954. 		You("stumble!"); 1955. 		return(1); 1956. 	   }  1957.     	}  1958. 	for (i = 0; i < blitz_num; i++) { 1959. 	   u.dx = dx; 1960. 	   u.dy = dy; 1961. 	   if (!( (*blitzes[blitz_chain[i]].blitz_funct) )) break; 1962. 	} 1963. 	  1964.     	/* done */ 1965. 	return(1); 1966. } 1967.  1968. static void 1969. doblitzlist 1970. { 1971. 	winid tmpwin; 1972. 	int i, n; 1973. char buf[BUFSZ]; 1974. 	menu_item *selected; 1975. 	anything any; 1976. 1977. 	tmpwin = create_nhwindow(NHW_MENU); 1978. 	start_menu(tmpwin); 1979. 	any.a_void = 0;        /* zero out all bits */ 1980. 1981.         Sprintf(buf, "%16s %10s %-17s", "[LU = Left Up]", "[U = Up]", "[RU = Right Up]"); 1982. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 1983.        Sprintf(buf, "%16s %10s %-17s", "[L = Left]", "", "[R = Right]"); 1984. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 1985.        Sprintf(buf, "%16s %10s %-17s", "[LD = Left Down]", "[D = Down]", "[RD = Right Down]"); 1986. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 1987. 1988.         Sprintf(buf, "%-30s %10s   %s", "Name", "Type", "Command"); 1989. 	add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_UNSELECTED); 1990. 1991.         for (i = 0; blitzes[i].blitz_len; i++) { 1992. 	   if (tech_known(blitzes[i].blitz_tech)) { 1993.                Sprintf(buf, "%-30s %10s   %s",  1994.                     (i && blitzes[i].blitz_tech == blitzes[(i-1)].blitz_tech ? 1995.                    	"" : tech_names[blitzes[i].blitz_tech]),  1996.                     (blitzes[i].blitz_type == BLITZ_START ? 1997.                    	"starter" : 1998.                    	(blitzes[i].blitz_type == BLITZ_CHAIN ?  1999. 	                    	"chain" :  2000. 	                    	(blitzes[i].blitz_type == BLITZ_END ? 2001.                    			"finisher" : "unknown"))),  2002.                     blitzes[i].blitz_cmd); 2003. 2004. 		add_menu(tmpwin, NO_GLYPH, &any,  2005.                          0, 0, ATR_NONE, buf, MENU_UNSELECTED); 2006. 	   }  2007. 	}  2008.         end_menu(tmpwin, "Currently known blitz manoeuvers"); 2009. 2010. 	n = select_menu(tmpwin, PICK_NONE, &selected); 2011. 	destroy_nhwindow(tmpwin); 2012. 	return; 2013. } 2014.  2015. static int 2016. blitz_chi_strike 2017. { 2018. 	int tech_no; 2019. 	 2020. 	tech_no = (get_tech_no(T_CHI_STRIKE)); 2021. 2022. 	if (tech_no == -1) { 2023. 		return(0); 2024. 	} 2025.  2026. 	if (u.uen < 1) { 2027. 		You("are too weak to attempt this!"); 2028.            	return(0); 2029. 	} 2030. 	You("feel energy surge through your hands!"); 2031. 	techt_inuse(tech_no) = techlev(tech_no) + 4; 2032. 	return(1); 2033. } 2034.  2035. static int 2036. blitz_e_fist 2037. { 2038. 	int tech_no; 2039. 	const char *str; 2040. 	 2041. 	tech_no = (get_tech_no(T_E_FIST)); 2042. 2043. 	if (tech_no == -1) { 2044. 		return(0); 2045. 	} 2046. 	  2047. 	str = makeplural(body_part(HAND)); 2048. 	You("focus the powers of the elements into your %s.", str); 2049. 	techt_inuse(tech_no) = rnd((int) (techlev(tech_no)/3 + 1)) + d(1,4) + 2; 2050. 	return 1; 2051. } 2052.  2053. /* Assumes u.dx, u.dy already set up */ 2054. static int 2055. blitz_pummel 2056. { 2057. 	int i = 0, tech_no; 2058. 	struct monst *mtmp; 2059. 	tech_no = (get_tech_no(T_PUMMEL)); 2060. 2061. 	if (tech_no == -1) { 2062. 		return(0); 2063. 	} 2064.  2065. 	You("let loose a barrage of blows!"); 2066. 2067. 	mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 2068. 	if (!mtmp) { 2069. 		You("strike nothing."); 2070. 		return (0); 2071. 	} 2072. 	if (!attack(mtmp)) return (0); 2073. 	 2074. 	/* Perform the extra attacks 2075. 	 */ 2076. 	for (i = 0; (i < 4); i++) { 2077. 	   if (rn2(70) > (techlev(tech_no) + 30)) break; 2078. 	   mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 2079. 	   if (!mtmp) return (1); 2080. 	   if (!attack(mtmp)) return (1); 2081. 	} 2082. 	  2083. 	return(1); 2084. } 2085.  2086. /* Assumes u.dx, u.dy already set up */ 2087. static int 2088. blitz_g_slam 2089. { 2090. 	int tech_no, tmp, canhitmon, objenchant; 2091. 	struct monst *mtmp; 2092. 	struct trap *chasm; 2093. 2094. 	tech_no = (get_tech_no(T_G_SLAM)); 2095. 2096. 	if (tech_no == -1) { 2097. 		return(0); 2098. 	} 2099.  2100. 	mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 2101. 	if (!mtmp) { 2102. 		You("strike nothing."); 2103. 		return (0); 2104. 	} 2105. 	if (!attack(mtmp)) return (0); 2106. 2107. 	/* Slam the monster into the ground */ 2108. 	mtmp = m_at(u.ux + u.dx, u.uy + u.dy); 2109. 	if (!mtmp || u.uswallow) return(1); 2110. 2111. 	You("hurl %s downwards...", mon_nam(mtmp)); 2112. 	if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) return(1); 2113. 2114. 	if (need_four(mtmp)) canhitmon = 4; 2115. 	else if (need_three(mtmp)) canhitmon = 3; 2116. 	else if (need_two(mtmp)) canhitmon = 2; 2117. 	else if (need_one(mtmp)) canhitmon = 1; 2118. 	else canhitmon = 0; 2119. 	if (Upolyd) { 2120. 	   if (hit_as_four(&youmonst))	objenchant = 4; 2121. 	   else if (hit_as_three(&youmonst)) objenchant = 3; 2122. 	   else if (hit_as_two(&youmonst)) objenchant = 2; 2123. 	   else if (hit_as_one(&youmonst)) objenchant = 1; 2124. 	   else if (need_four(&youmonst)) objenchant = 4; 2125. 	   else if (need_three(&youmonst)) objenchant = 3; 2126. 	   else if (need_two(&youmonst)) objenchant = 2; 2127. 	   else if (need_one(&youmonst)) objenchant = 1; 2128. 	   else objenchant = 0; 2129. 	} else 2130. 	   objenchant = u.ulevel / 4; 2131. 2132. 	tmp = (5 + rnd(6) + (techlev(tech_no) / 5)); 2133. 	 2134. 	chasm = maketrap(u.ux + u.dx, u.uy + u.dy, PIT); 2135. 	if (chasm) { 2136. 	   if (!is_flyer(mtmp->data) && !is_clinger(mtmp->data)) 2137. 		mtmp->mtrapped = 1; 2138. 	   chasm->tseen = 1; 2139. 	   levl[u.ux + u.dx][u.uy + u.dy].doormask = 0; 2140. 	   pline("%s slams into the ground, creating a crater!", Monnam(mtmp)); 2141. 	   tmp *= 2; 2142. 	} 2143.  2144. 	mselftouch(mtmp, "Falling, ", TRUE); 2145. 	if (!DEADMONSTER(mtmp)) { 2146. 	   if (objenchant < canhitmon) 2147. 		pline("%s doesn't seem to be harmed.", Monnam(mtmp)); 2148. 	   else if ((mtmp->mhp -= tmp) <= 0) { 2149. 		if(!cansee(u.ux + u.dx, u.uy + u.dy)) 2150. 		   pline("It is destroyed!"); 2151. 		else { 2152. 		   You("destroy %s!", 	  2153. 		    	mtmp->mtame  2154. 			    ? x_monnam(mtmp, ARTICLE_THE, "poor", 2155. 				mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE) 2156. 			    : mon_nam(mtmp)); 2157. 		} 2158. 		xkilled(mtmp,0); 2159. 	   }  2160. 	}  2161.  2162. 	return(1); 2163. } 2164.  2165. /* Assumes u.dx, u.dy already set up */ 2166. static int 2167. blitz_dash 2168. { 2169. 	int tech_no; 2170. 	tech_no = (get_tech_no(T_DASH)); 2171. 2172. 	if (tech_no == -1) { 2173. 		return(0); 2174. 	} 2175. 	  2176. 	if ((!Punished || carried(uball)) && !u.utrap) 2177. 	   You("dash forwards!"); 2178. 	hurtle(u.dx, u.dy, 2, FALSE); 2179. 	multi = 0;		/* No paralysis with dash */ 2180. 	return 1; 2181. } 2182.  2183. static int 2184. blitz_power_surge 2185. { 2186. 	int tech_no, num; 2187. 	 2188. 	tech_no = (get_tech_no(T_POWER_SURGE)); 2189. 2190. 	if (tech_no == -1) { 2191. 		return(0); 2192. 	} 2193.  2194. 	if (Upolyd) { 2195. 		You("cannot tap into your full potential in this form."); 2196. 		return(0); 2197. 	} 2198.     	You("tap into the full extent of your power!"); 2199. 	num = 50 + (2 * techlev(tech_no)); 2200.    	techt_inuse(tech_no) = num + 1; 2201. 	u.uenmax += num; 2202. 	u.uen = u.uenmax; 2203. 	return 1; 2204. } 2205.  2206. /* Assumes u.dx, u.dy already set up */ 2207. static int 2208. blitz_spirit_bomb 2209. { 2210. 	int tech_no, num; 2211. 	int sx = u.ux, sy = u.uy, i; 2212. 2213. 	tech_no = (get_tech_no(T_SPIRIT_BOMB)); 2214. 2215. 	if (tech_no == -1) { 2216. 		return(0); 2217. 	} 2218.  2219. 	You("gather your energy..."); 2220. 	 2221. 	if (u.uen < 10) { 2222. 		pline("But it fizzles out."); 2223. 		u.uen = 0; 2224. 	} 2225.  2226. 	num = 10 + (techlev(tech_no) / 5); 2227. 	num = (u.uen < num ? u.uen : num); 2228. 	 2229. 	u.uen -= num; 2230. 	 2231. 	for( i = 0; i < 2; i++) { 2232. 	   if (!isok(sx,sy) || !cansee(sx,sy) ||  2233. 	    		IS_STWALL(levl[sx][sy].typ) || u.uswallow) 2234. 	   	break; 2235. 2236. 	    /* Display the center of the explosion */ 2237. 	   tmp_at(DISP_FLASH, explosion_to_glyph(EXPL_MAGICAL, S_explode5)); 2238. 	   tmp_at(sx, sy); 2239. 	   delay_output; 2240. 	   tmp_at(DISP_END, 0); 2241. 2242. 	    sx += u.dx; 2243. 	   sy += u.dy; 2244. 	} 2245. 	/* Magical Explosion */ 2246. 	explode(sx, sy, 10, (d(3,6) + num), WAND_CLASS, EXPL_MAGICAL); 2247. 	return 1; 2248. } 2249.  2250. #ifdef DEBUG 2251. void 2252. wiz_debug_cmd /* in this case, allow controlled loss of techniques */ 2253. { 2254. 	int tech_no, id, n = 0; 2255. 	long mask; 2256. 	if (gettech(&tech_no)) { 2257. 		id = techid(tech_no); 2258. 		if (id == NO_TECH) { 2259. 		   impossible("Unknown technique ([%d])?", tech_no); 2260. 		   return; 2261. 		} 2262. 		mask = tech_list[tech_no].t_intrinsic; 2263. 		if (mask & FROMOUTSIDE) n++; 2264. 		if (mask & FROMRACE) n++; 2265. 		if (mask & FROMEXPER) n++; 2266. 		if (!n) { 2267. 		   impossible("No intrinsic masks set (0x%lX).", mask); 2268. 		   return; 2269. 		} 2270. 		n = rn2(n); 2271. 		if (mask & FROMOUTSIDE && !n--) mask = FROMOUTSIDE; 2272. 		if (mask & FROMRACE && !n--) mask = FROMRACE; 2273. 		if (mask & FROMEXPER && !n--) mask = FROMEXPER; 2274. 		learntech(id, mask, -1); 2275. 		if (!tech_known(id)) 2276. 		   You("lose the ability to perform %s.", tech_names[id]); 2277. 	} 2278. }  2279. #endif /* DEBUG */