Source:NetHack 3.0.0/dokick.c

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

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

1.   /*	SCCS Id: @(#)dokick.c	3.0	89/6/9 2.   /* Copyright (c) Izchak Miller, Mike Stephenson, Steve Linhart, 1989. */ 3.    /* NetHack may be freely redistributed. See license for details. */ 4.     5.    #include	"hack.h"  6.    #include	"eshk.h"  7. 8.   #define martial	((pl_character[0] == 'S' || pl_character[0] == 'P')) 9.    10.   #ifdef KICK 11.   12.   # ifdef WORM 13.  extern boolean notonhead; 14.  # endif 15.   16.   static void 17.  kickdmg(mon, clumsy) 18.  register struct monst *mon; 19.  register boolean clumsy; 20.  {  21.   	register int mdx, mdy; 22.  	register int dmg = (((uarmg &&  23.   				uarmg->otyp == GAUNTLETS_OF_POWER) ? 24.  				25 : ACURR(A_STR) > 18 ? 18 : ACURR(A_STR))+ 25.   				ACURR(A_DEX)+ACURR(A_CON))/15; 26.   27.   	/* excessive wt affects dex, so it affects dmg */ 28.  	if(clumsy) dmg = dmg/2; 29.   30.   	/* kicking a dragon or an elephant will not harm it */ 31.  	if(thick_skinned(mon->data)) dmg = 0; 32.  	  33.    34.   	/* squeeze some guilt feelings... */ 35.   	if(mon->mtame) { 36.  # ifdef SOUNDS 37.  	    if (rn2(10)) yelp(mon); 38.  	    else growl(mon); /* give them a moment's worry */ 39.  # endif 40.  	    mon->mtame--; 41.  	    mon->mflee = mon->mtame ? 1 : 0; 42.   # ifdef HISX 43.  	    mon->mfleetim = mon->mfleetim + (dmg ? rnd(dmg) : 1); 44.  # else 45.  	    mon->mfleetim += (dmg ? rnd(dmg) : 1); 46.  # endif 47.  	}  48.   	  49.   	mon->mhp -= (!martial ? rnd(dmg) : rnd(dmg)+rnd(ACURR(A_DEX)/2)); 50.  	if(mon->mhp < 1) { 51.  		killed(mon); 52.  		return; 53.  	}  54.   	if(martial && !bigmonst(mon->data) && !rn2(3) && !mon->mfroz) { 55.  	    	/* see if the monster has a place to move into */ 56.  	    	mdx = mon->mx + u.dx; 57.  	    	mdy = mon->my + u.dy; 58.  	    	if(goodpos(mdx, mdy)) { 59.  			pline("%s reels from the blow.", Monnam(mon)); 60.  			levl[mon->mx][mon->my].mmask = 0; 61.  			levl[mdx][mdy].mmask = 1; 62.  			mon->mx = mdx; 63.  			mon->my = mdy; 64.  			pmon(mon); 65.  			set_apparxy(mon); 66.  	    	}  67.   	}  68.    69.   /*	it is unchivalrous to attack the defenseless or from behind */ 70.  	if (pl_character[0] == 'K' && u.ualigntyp == U_LAWFUL &&  71.   		u.ualign > -10 && (mon->mfroz || mon->msleep || mon->mflee)) 72.  	    	adjalign(-1); 73.   74.   }  75.    76.   static void 77.  kick_monster(x, y)  78. register int x, y; 79. { 80.   	register boolean clumsy = FALSE; 81.  	register struct monst *mon = m_at(x, y); 82.  	register int i, j;  83. 84.  	/* no need to check POLYSELF since only ghosts, which you can't turn */ 85.  	/* into, are noncorporeal */ 86.  	if(noncorporeal(mon->data)) { 87.  		Your("kick passes through!"); 88.  		return; 89.  	}  90.    91.   	if(special_case(mon)) return; 92.   93.   	setmangry(mon); 94.   95.   	if(Levitation && !rn2(3) && verysmall(mon->data) &&  96.   			!is_floater(mon->data) && !is_flyer(mon->data)) { 97.  		You("are floating in the air, and miss wildly!"); 98.  		return; 99.  	}  100.   101.  	i = abs(inv_weight); 102. 	j = weight_cap; 103.  104.  	if(i < (j*3)/10) { 105. 		if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) { 106.  			if(martial && !rn2(2)) goto doit; 107. 			Your("clumsy kick does no damage."); 108. 			return; 109. 		}  110.  		if(i < j/10) clumsy = TRUE; 111. 		else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE; 112. 	}  113.   114.  	if(Fumbling) clumsy = TRUE; 115.  116.  	else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25)) 117. 		clumsy = TRUE; 118. doit: 119. 	kludge("You kick %s.", mon_nam(mon)); 120. 	if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) && 121.  	   mon->mcansee && !thick_skinned(mon->data) &&  122.  	   !mon->mfroz && !mon->mstun && !mon->mconf) { 123. 		mnexto(mon); 124. 		if(mon->mx != x || mon->my != y) { 125. 		    kludge("%s jumps, %s evading your %skick.", Monnam(mon),  126.  				clumsy ? "easily" : "nimbly",  127.  				clumsy ? "clumsy " : ""); 128. 		    return; 129. 		} /* else fall to the next case */ 130. 	}  131.  	kickdmg(mon, clumsy); 132. }  133.  #endif /* KICK */ 134.  135.  /* return TRUE if caught, FALSE otherwise */ 136. boolean 137. ghitm(mtmp, amount) 138. register struct monst *mtmp; 139. register long amount; 140. {  141.  	if(!likes_gold(mtmp->data) && !mtmp->isshk  142.  #if defined(ALTARS) && defined(THEOLOGY)  143.  		&& !mtmp->ispriest  144.  #endif  145.  		) 146. 		wakeup(mtmp); 147. 	else { 148. 		mtmp->msleep = 0; 149. 		mtmp->meating = 0; 150. 		if(!rn2(4)) setmangry(mtmp); /* not always pleasing */ 151. 		  152.  		/* greedy monsters catch gold */ 153. 		pline("%s catches the gold.", Monnam(mtmp)); 154. 		mtmp->mgold += amount; 155. 		if (mtmp->isshk) { 156. 			long robbed = ESHK(mtmp)->robbed; 157.  158.  			if (robbed) { 159. 				robbed -= amount; 160. 				if (robbed < 0) robbed = 0; 161. 				pline("The amount %scovers %s recent losses.",  162.  					!robbed ? "" : "partially ",  163.  					ESHK(mtmp)->ismale ? "his" : "her"); 164. 				ESHK(mtmp)->robbed = robbed; 165. 				if(!robbed) 166. 					make_happy_shk(mtmp); 167. 			} else { 168. 				if(mtmp->mpeaceful) { 169. 				    ESHK(mtmp)->credit += amount; 170. 				    You("have %ld zorkmids in credit.",  171.  						ESHK(mtmp)->credit); 172. 				} else verbalize("Thanks, scum!"); 173. 			}  174.  		}  175.  #if defined(ALTARS) && defined(THEOLOGY) 176. 		else if(mtmp->ispriest) { 177. 			if(mtmp->mpeaceful) 178. 			    verbalize("Thank you for your contribution."); 179. 			else verbalize("Thanks, scum!"); 180. 		}  181.  #endif 182. 		return(1); 183. 	}  184.  	return(0); 185.  186.  }  187.   188.  boolean 189. bad_kick_throw_pos(x,y) 190. xchar x,y; 191. {  192.  	register struct rm *lvl = &(levl[x][y]); 193.  194.  	return(!ACCESSIBLE(lvl->typ) || lvl->typ == SDOOR ||  195.  	    (IS_DOOR(lvl->typ) && (lvl->doormask & (D_CLOSED | D_LOCKED))) ); 196. }  197.   198.  struct monst * 199. ghit(ddx, ddy, range) 200. register int ddx, ddy, range; 201. {  202.  	register struct monst *mtmp = (struct monst *) 0; 203.  204.  	bhitpos.x = u.ux; 205. 	bhitpos.y = u.uy; 206.  207.  	tmp_at(-1, GOLD_SYM);	/* open call */ 208. 	tmp_at(-3, (int)AT_GLD); 209. 	while(range-- > 0) { 210. 		bhitpos.x += ddx; 211. 		bhitpos.y += ddy; 212. 		if(levl[bhitpos.x][bhitpos.y].mmask) { 213. 			mtmp = m_at(bhitpos.x,bhitpos.y); 214. 			tmp_at(-1, -1); /* close call */ 215. 			return(mtmp); 216. 		}  217.  		/* stop on a zorkmid */ 218. 		if(levl[bhitpos.x][bhitpos.y].gmask ||  219.  		     	    levl[bhitpos.x][bhitpos.y].omask) { 220. 			tmp_at(-1, -1); /* close call */ 221. 			return (struct monst *)0; 222. 		}  223.  		if(bad_kick_throw_pos(bhitpos.x,bhitpos.y)) { 224. 			bhitpos.x -= ddx; 225. 			bhitpos.y -= ddy; 226. 			break; 227. 		}  228.  		tmp_at(bhitpos.x, bhitpos.y); 229. 	}  230.  	tmp_at(-1, -1); 231. 	return(struct monst *)0; 232. }  233.   234.  #ifdef KICK 235. static int 236. kick_object(x, y)  237. register int x, y; 238. { 239.  	register int range, odx, ody, cnt = 0; 240. 	register struct monst *mon; 241. 	register struct gold *gold; 242. 	register struct obj *otmp, *obj; 243. 	register boolean costly = FALSE; 244.  245.  	/* if a pile, the "top" object gets kicked */ 246. 	for (otmp = fobj; otmp; otmp = otmp->nobj) 247. 		if(otmp->ox == x && otmp->oy == y)  248. if(!otmp->cobj) 249. 			if (otmp != uchain) { 250. 			    cnt++; 251. 			    if(cnt == 1) obj = otmp; 252. 			}  253.   254.  	/* range < 2 means the object will not move. */ 255.  	/* maybe dexterity should also figure here. */ 256.  	if(cnt) range = (int)((ACURR(A_STR) > 18 ? 20 : 257.  				ACURR(A_STR))/2 - obj->owt/4); 258. 	else range = rnd((int)ACURR(A_STR)); 259.  260.  	if(range < 1) range = 1; /* safety... */ 261.  	if(martial) range = range + rnd(3); 262.  263.  	/* see if the object has a place to move into */ 264. 	odx = x + u.dx; 265. 	ody = y + u.dy; 266. 	if(bad_kick_throw_pos(odx,ody)) 267. 	    range = 1; 268.  269.  	if(Fumbling && !rn2(3)) { 270. 		Your("clumsy kick missed."); 271. 		return(1); 272. 	}  273.   274.  	if(!cnt && levl[x][y].gmask) { 275. 		long zm; 276. 		gold = g_at(x, y); 277. 		zm = gold->amount; 278. 		if(range < 2 || zm > 300L) /* arbitrary */ 279. 		    return(0); 280. 		else { 281. 		    freegold(gold); 282. 		    if(!levl[x][y].mmask) newsym(x, y); 283. 		    if(mon = ghit(u.dx, u.dy, range)) { 284. 			setmangry(mon); /* not a means for payment to shk */ 285. 			if(ghitm(mon, zm)) /* was it caught? */ 286.  			    return(1); 287. 		    }  288.  		    mkgold(zm, bhitpos.x, bhitpos.y); 289. 		    if(cansee(bhitpos.x, bhitpos.y)) prl(bhitpos.x,bhitpos.y); 290. 		}  291.  		return(1); 292. 	}  293.   294.  	if(obj->otyp == BOULDER || obj == uball) 295. 		return(0); 296.  297.  	/* a box gets a chance of breaking open here */ 298. 	if(Is_box(obj)) { 299. 		boolean otrp = obj->otrapped; 300.  301.  		if (!obj->olocked && (!rn2(3) || 302. 					(martial && !rn2(2)))) { 303. 		    pline("The lid slams open, then falls shut."); 304. 		    if(otrp) goto gotcha; 305. 		    return(1); 306. 		} else if (obj->olocked &&  307.  				(!rn2(5) || (martial && !rn2(2)))) { 308. 		    You("break open the lock!"); 309. 		    obj->olocked = 0; 310. 	            if(otrp) { 311. gotcha: 312. 		        chest_trap(obj, LEG); 313. 		    }  314.  		    return(1); 315. 		}  316.  		/* let it fall through to the next cases... */ 317.  	}  318.   319.  	if(Levitation && !rn2(3)) { 320. 		You("miss."); /* do not identify the object */ 321. 		return(1); 322. 	}  323.   324.  	/* fragile objects should not be kicked */ 325. 	if (breaks(obj, FALSE)) return(1); 326.  327.  	costly = costly_spot(x, y); 328.  329.  	/* potions get a chance of breaking here */ 330. 	if(obj->olet == POTION_SYM) { 331. 		if(rn2(2)) { 332. 		    You("smash the %s!", xname(obj)); 333. 		    if(costly) addtobill(obj, FALSE); 334. 		    potionbreathe(obj); 335. 		    delobj(obj);	/* takes care of omask */ 336. 		    return(1); 337. 		}  338.  	}  339.   340.  	/* too heavy to move. make sure not to call bhit */ 341. 	/* in this function when range < 2 (a display bug */  342.  	/* results otherwise). */ 343.  	if(range <= 2) { 344. 	    if(Is_box(obj)) pline("THUD!"); 345. 	    else pline("Thump!"); 346. 	    if(!rn2(3) || martial) return(1); 347. 	    return(0); 348. 	}  349.   350.  	if(cnt > 1) { 351. 		/* Needed to fool bhit's display-cleanup to show */ 352. 		/* immediately the next object in the pile. We */ 353. 		/* know here that the object will move, so there */ 354. 		/* is no need to worry about omask. */ 355.  		obj->ox = u.ux; 356. 		obj->oy = u.uy; 357. 	} else { 358. 		levl[x][y].omask = 0; 359. 		if(!levl[x][y].gmask) newsym(x, y); 360. 	}  361.   362.  	mon = bhit(u.dx, u.dy, range, obj->olet,  363.  			(int (*)) 0, (int (*)) 0, obj); 364. 	if(mon) { 365. # ifdef WORM 366. 		if (mon->mx != bhitpos.x || mon->my != bhitpos.y)  367. notonhead = TRUE; 368. # endif 369. 		/* awake monster if sleeping */ 370. 		wakeup(mon); 371. 		if(thitmonst(mon, obj)) return(1); 372. 	}  373.  	if(costly && !costly_spot(bhitpos.x,bhitpos.y)) addtobill(obj, FALSE); 374. 	obj->ox = bhitpos.x;  375. obj->oy = bhitpos.y; 376. levl[obj->ox][obj->oy].omask = 1; 377. 	stackobj(obj); 378. 	return(1); 379. }  380.  #endif /* KICK */ 381.  382.   383.  int 384. dokick {		/* try to kick the door down - noisy! */ 385.          register int x, y;  386. register struct rm *maploc; 387. 	register int avrg_attrib = (ACURR(A_STR)+ACURR(A_DEX)+ACURR(A_CON))/3; 388.  389.  #ifdef POLYSELF 390. 	if(nolimbs(uasmon)) { 391. 		You("have no legs to kick with."); 392. 		return(0); 393. 	}  394.  	if(verysmall(uasmon)) { 395. 		You("are too small to do any kicking."); 396. 		return(0); 397. 	}  398.  #endif 399. 	if(Wounded_legs) { 400. 		Your("%s %s in no shape for kicking.",  401.  		      ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES)  402.  			? makeplural(body_part(LEG)) : body_part(LEG),  403.  		      ((Wounded_legs & BOTH_SIDES)==BOTH_SIDES) ? "are" : "is"); 404. 		return(0); 405. 	}  406.   407.  	if(inv_weight > 0) { 408. 		Your("load is too heavy to balance yourself for a kick."); 409. 		return(0); 410. 	}  411.   412.          if(u.utrap) { 413. 		switch (u.utraptype) { 414. 		    case TT_PIT: 415. 			pline("There's nothing to kick down here."); 416. 		    case TT_WEB: 417. 		    case TT_BEARTRAP: 418. 			You("can't move your %s!", body_part(LEG)); 419. 		}  420.  		return(0); 421. 	}  422.   423.  	if(!getdir(1)) return(0); 424. 	if(!u.dx && !u.dy) return(0); 425.  426.  	x = u.ux + u.dx; 427. 	y = u.uy + u.dy; 428.  429.  	if(u.uswallow) { 430. 		switch(rn2(3)) { 431. 		case 0:  You("can't move your %s!", body_part(LEG)); 432. 			 break; 433. 		case 1:  pline("%s burps loudly.", Monnam(u.ustuck)); break; 434. 		default: Your("feeble kick has no effect."); break; 435. 		}  436.  		return(1); 437. 	}  438.   439.  	wake_nearby; 440. 	u_wipe_engr(2); 441.  442.  	maploc = &levl[x][y]; 443.  444.  #ifdef KICK 445. 	/* The next four main loops should stay in */ 446. 	/* their present order: monsters, objects, */ 447. 	/* non-doors, doors. */ 448.   449.  	if(maploc->mmask) { 450. 		kick_monster(x, y); 451. 		return(1); 452. 	}  453.   454.  	if((maploc->omask || maploc->gmask) && !Levitation) { 455. 		if(kick_object(x, y)) return(1); 456. 		else goto ouch; 457. 	}  458.   459.  	if(!IS_DOOR(maploc->typ)) { 460. 		if(maploc->typ == SDOOR) { 461. 		    if(rn2(30) < avrg_attrib) { 462. 			pline("Crash!  You kick open a secret door!"); 463. 			maploc->typ = DOOR; 464. 			atl(x, y, (char) DOOR_SYM); 465. 			if(maploc->doormask & D_TRAPPED) { 466. 			    b_trapped("door"); 467. 			    maploc->doormask = D_NODOOR; 468. 			} else 469. 			    maploc->doormask = D_ISOPEN; 470. 			return(1); 471. 		    } else goto ouch; 472. 		}  473.  		if(maploc->typ == SCORR) { 474. 		    if(rn2(30) < avrg_attrib) { 475. 			pline("Crash!  You kick open a secret passage!"); 476. 			maploc->typ = CORR; 477. 			atl(x, y, (char) CORR_SYM); 478. 			return(1); 479. 		    } else goto ouch; 480. 		}  481.  # ifdef THRONES 482. 		if(IS_THRONE(maploc->typ)) { 483. 		    register int i;  484. if((u.uluck < 0 || maploc->doormask) && !rn2(3)) { 485. 			pline("CRASH!  You destroy the throne."); 486. 			maploc->typ = ROOM; 487. 			maploc->doormask = 0; /* don't leave loose ends.. */ 488.  			mkgold((long)rnd(200), x, y); 489. 			prl(x, y); 490. 			return(1); 491. 		    } else if(u.uluck && !rn2(3) && !maploc->doormask) { 492. 			You("kick loose some ornamental coins and gems!"); 493. 			mkgold((300L+(long)rn2(201)), x, y); 494. 			i = u.uluck + 1; 495. 			if(i > 6) i = 6; 496. 			while(i--) (void) mkobj_at(GEM_SYM, x, y); 497. 			prl(x, y); 498. 			/* prevent endless milking */ 499. 			maploc->doormask = T_LOOTED; 500. 			return(1); 501. 		    } else if (!rn2(4)) { 502. 			register struct trap *ttmp = 503. 					maketrap(u.ux,u.uy,TRAPDOOR); 504. 			dotrap(ttmp); 505. 			return(1); 506. 		    }  507.  		    goto ouch; 508. 		}  509.  # endif 510. # ifdef ALTARS 511. 		if(IS_ALTAR(maploc->typ)) { 512. 		    You("kick the altar."); 513. 		    if(!rn2(3)) goto ouch; 514. #  ifdef THEOLOGY 515. 		    altar_wrath(x, y); 516. #  endif 517. 		    return(1); 518. 		}  519.  # endif 520. # ifdef SINKS 521. 		if(IS_SINK(maploc->typ)) { 522. 		    if(rn2(5)) { 523. 			if(flags.soundok) 524. 			    pline("Klunk!  The pipes vibrate noisily."); 525. 			else pline("Klunk!"); 526. 		        return(1); 527. 		    } else if(!rn2(3) &&  528.  			      !(mons[PM_BLACK_PUDDING].geno & G_GENOD)) { 529. 			pline("A %s ooze gushes up from the drain!",  530.  			      Hallucination ? hcolor : black); 531. 			pmon(makemon(&mons[PM_BLACK_PUDDING], x, y)); 532. 			return(1); 533. #  ifdef HARD 534. 		    } else if(!rn2(3) &&  535.  #   ifndef POLYSELF  536.  			      poly_gender != 2 &&  537.  #   endif  538.  			      !(mons[poly_gender == 1 ? PM_INCUBUS : PM_SUCCUBUS].geno & G_GENOD)) { 539. 			/* can't resist... */ 540.  			pline("The dish washer returns!"); 541. 			pmon(makemon(&mons[poly_gender == 1 ? PM_INCUBUS : PM_SUCCUBUS], x, y)); 542. 			return(1); 543. #  endif 544. 		    } else if(!rn2(3)) { 545. 			pline("Flupp!  Muddy waste pops up from the drain."); 546. 			if(!maploc->doormask) { /* only once per sink */ 547. 			    if(!Blind) 548. 				You("see a ring shining in its midst."); 549. 			    (void) mkobj_at(RING_SYM, x, y); 550. 			    prl(x, y); 551. 			    maploc->doormask = T_LOOTED; 552. 			}  553.  			return(1); 554. 		    }  555.  		    goto ouch; 556. 		}  557.  # endif 558. 		if(maploc->typ == STAIRS  559.  # ifdef STRONGHOLD  560.  					|| maploc->typ == LADDER  561.  # endif  562.  		  ) goto ouch; 563. 		if(IS_STWALL(maploc->typ)) { 564. ouch: 565. 		    pline("Ouch!  That hurts!"); 566. 		    if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); 567. 		    losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), "dumb move"); 568. 		    return(1); 569. 		}  570.  # ifdef STRONGHOLD 571. 		if (is_drawbridge_wall(x,y) >= 0) { 572. 		    pline("The drawbridge is unaffected."); 573. 		    return(1); 574. 		}  575.  # endif 576. 		goto dumb; 577. 	}  578.  #endif /* KICK */ 579.  580.  	if(maploc->doormask == D_ISOPEN ||  581.  	   maploc->doormask == D_BROKEN ||  582.  	   maploc->doormask == D_NODOOR) { 583. #ifdef KICK 584. dumb: 585. #endif 586. 		if (martial || ACURR(A_DEX) >= 16) { 587. 			You("kick at empty space."); 588. 		} else { 589. 			pline("Dumb move!  You strain a muscle."); 590. 			set_wounded_legs(RIGHT_SIDE, 5 + rnd(5)); 591. 		}  592.  		return(0); 593. 	}  594.   595.  	/* door is known to be CLOSED or LOCKED */ 596. 	if(rnl(35) < avrg_attrib + (!martial ? 0 : ACURR(A_DEX))) { 597. 		/* break the door */ 598. 		if(maploc->doormask & D_TRAPPED) { 599. 		    pline("As you kick the door, it explodes!"); 600. 		    b_trapped("door"); 601. 		    maploc->doormask = D_NODOOR; 602. 		} else if(ACURR(A_STR) > 18 && !rn2(5) && !in_shop(x, y)) { 603. 		    pline("As you kick the door, it shatters to pieces!"); 604. 		    maploc->doormask = D_NODOOR; 605. 		} else { 606. 		    pline("As you kick the door, it crashes open!"); 607. 		    maploc->doormask = D_BROKEN; 608. 		    if(in_shop(x, y) && !in_shop(u.ux, u.uy)) 609. 			pay_for_door(x, y, "break"); 610. 		}  611.  	} else	pline("WHAMMM!!!"); 612.  613.  	return(1); 614. }