From Wikihack
Below is the full text to src/dokick.c from NetHack 3.4.3. To link to a particular line, write [[dokick.c#line123]], for example.
[edit] Top of file
1. /* SCCS Id: @(#)dokick.c 3.4 2003/12/04 */
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 is_bigfoot(x) ((x) == &mons[PM_SASQUATCH])
9. #define martial() (martial_bonus() || is_bigfoot(youmonst.data) || \
10. (uarmf && uarmf->otyp == KICKING_BOOTS))
11.
12. static NEARDATA struct rm *maploc;
13. static NEARDATA const char *gate_str;
14.
15. extern boolean notonhead; /* for long worms */
16.
17. STATIC_DCL void FDECL(kickdmg, (struct monst *, BOOLEAN_P));
18. STATIC_DCL void FDECL(kick_monster, (XCHAR_P, XCHAR_P));
19. STATIC_DCL int FDECL(kick_object, (XCHAR_P, XCHAR_P));
20. STATIC_DCL char *FDECL(kickstr, (char *));
21. STATIC_DCL void FDECL(otransit_msg, (struct obj *, BOOLEAN_P, long));
22. STATIC_DCL void FDECL(drop_to, (coord *,SCHAR_P));
23.
24. static NEARDATA struct obj *kickobj;
25.
26. static const char kick_passes_thru[] = "kick passes harmlessly through";
27.
[edit] kickdmg
28. STATIC_OVL void
29. kickdmg(mon, clumsy)
30. register struct monst *mon;
31. register boolean clumsy;
32. {
33. register int mdx, mdy;
34. register int dmg = ( ACURRSTR + ACURR(A_DEX) + ACURR(A_CON) )/ 15;
35. int kick_skill = P_NONE;
36. int blessed_foot_damage = 0;
37. boolean trapkilled = FALSE;
38.
39. if (uarmf && uarmf->otyp == KICKING_BOOTS)
40. dmg += 5;
41.
42. /* excessive wt affects dex, so it affects dmg */
43. if (clumsy) dmg /= 2;
44.
45. /* kicking a dragon or an elephant will not harm it */
46. if (thick_skinned(mon->data)) dmg = 0;
47.
48. /* attacking a shade is useless */
49. if (mon->data == &mons[PM_SHADE])
50. dmg = 0;
51.
52. if ((is_undead(mon->data) || is_demon(mon->data)) && uarmf &&
53. uarmf->blessed)
54. blessed_foot_damage = 1;
55.
56. if (mon->data == &mons[PM_SHADE] && !blessed_foot_damage) {
57. pline_The("%s.", kick_passes_thru);
58. /* doesn't exercise skill or abuse alignment or frighten pet,
59. and shades have no passive counterattack */
60. return;
61. }
62.
63. if(mon->m_ap_type) seemimic(mon);
64.
65. check_caitiff(mon);
66.
67. /* squeeze some guilt feelings... */
68. if(mon->mtame) {
69. abuse_dog(mon);
70. if (mon->mtame)
71. monflee(mon, (dmg ? rnd(dmg) : 1), FALSE, FALSE);
72. else
73. mon->mflee = 0;
74. }
75.
76. if (dmg > 0) {
77. /* convert potential damage to actual damage */
78. dmg = rnd(dmg);
79. if (martial()) {
80. if (dmg > 1) kick_skill = P_MARTIAL_ARTS;
81. dmg += rn2(ACURR(A_DEX)/2 + 1);
82. }
83. /* a good kick exercises your dex */
84. exercise(A_DEX, TRUE);
85. }
86. if (blessed_foot_damage) dmg += rnd(4);
87. if (uarmf) dmg += uarmf->spe;
88. dmg += u.udaminc; /* add ring(s) of increase damage */
89. if (dmg > 0)
90. mon->mhp -= dmg;
91. if (mon->mhp > 0 && martial() && !bigmonst(mon->data) && !rn2(3) &&
92. mon->mcanmove && mon != u.ustuck && !mon->mtrapped) {
93. /* see if the monster has a place to move into */
94. mdx = mon->mx + u.dx;
95. mdy = mon->my + u.dy;
96. if(goodpos(mdx, mdy, mon, 0)) {
97. pline("%s reels from the blow.", Monnam(mon));
98. if (m_in_out_region(mon, mdx, mdy)) {
99. remove_monster(mon->mx, mon->my);
100. newsym(mon->mx, mon->my);
101. place_monster(mon, mdx, mdy);
102. newsym(mon->mx, mon->my);
103. set_apparxy(mon);
104. if (mintrap(mon) == 2) trapkilled = TRUE;
105. }
106. }
107. }
108.
109. (void) passive(mon, TRUE, mon->mhp > 0, AT_KICK);
110. if (mon->mhp <= 0 && !trapkilled) killed(mon);
111.
112. /* may bring up a dialog, so put this after all messages */
113. if (kick_skill != P_NONE) /* exercise proficiency */
114. use_skill(kick_skill, 1);
115. }
116.
[edit] kick_monster
117. STATIC_OVL void
118. kick_monster(x, y)
119. register xchar x, y;
120. {
121. register boolean clumsy = FALSE;
122. register struct monst *mon = m_at(x, y);
123. register int i, j;
124.
125. bhitpos.x = x;
126. bhitpos.y = y;
127. if (attack_checks(mon, (struct obj *)0)) return;
128. setmangry(mon);
129.
130. /* Kick attacks by kicking monsters are normal attacks, not special.
131. * This is almost always worthless, since you can either take one turn
132. * and do all your kicks, or else take one turn and attack the monster
133. * normally, getting all your attacks _including_ all your kicks.
134. * If you have >1 kick attack, you get all of them.
135. */
136. if (Upolyd && attacktype(youmonst.data, AT_KICK)) {
137. struct attack *uattk;
138. int sum;
139. schar tmp = find_roll_to_hit(mon);
140.
141. for (i = 0; i < NATTK; i++) {
142. /* first of two kicks might have provoked counterattack
143. that has incapacitated the hero (ie, floating eye) */
144. if (multi < 0) break;
145.
146. uattk = &youmonst.data->mattk[i];
147. /* we only care about kicking attacks here */
148. if (uattk->aatyp != AT_KICK) continue;
149.
150. if (mon->data == &mons[PM_SHADE] &&
151. (!uarmf || !uarmf->blessed)) {
152. /* doesn't matter whether it would have hit or missed,
153. and shades have no passive counterattack */
154. Your("%s %s.", kick_passes_thru, mon_nam(mon));
155. break; /* skip any additional kicks */
156. } else if (tmp > rnd(20)) {
157. You("kick %s.", mon_nam(mon));
158. sum = damageum(mon, uattk);
159. (void)passive(mon, (boolean)(sum > 0), (sum != 2), AT_KICK);
160. if (sum == 2)
161. break; /* Defender died */
162. } else {
163. missum(mon, uattk);
164. (void)passive(mon, 0, 1, AT_KICK);
165. }
166. }
167. return;
168. }
169.
170. if(Levitation && !rn2(3) && verysmall(mon->data) &&
171. !is_flyer(mon->data)) {
172. pline("Floating in the air, you miss wildly!");
173. exercise(A_DEX, FALSE);
174. (void) passive(mon, FALSE, 1, AT_KICK);
175. return;
176. }
177.
178. i = -inv_weight();
179. j = weight_cap();
180.
181. if(i < (j*3)/10) {
182. if(!rn2((i < j/10) ? 2 : (i < j/5) ? 3 : 4)) {
183. if(martial() && !rn2(2)) goto doit;
184. Your("clumsy kick does no damage.");
185. (void) passive(mon, FALSE, 1, AT_KICK);
186. return;
187. }
188. if(i < j/10) clumsy = TRUE;
189. else if(!rn2((i < j/5) ? 2 : 3)) clumsy = TRUE;
190. }
191.
192. if(Fumbling) clumsy = TRUE;
193.
194. else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25))
195. clumsy = TRUE;
196. doit:
197. You("kick %s.", mon_nam(mon));
198. if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) &&
199. mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) &&
200. mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove &&
201. !mon->mstun && !mon->mconf && !mon->msleeping &&
202. mon->data->mmove >= 12) {
203. if(!nohands(mon->data) && !rn2(martial() ? 5 : 3)) {
204. pline("%s blocks your %skick.", Monnam(mon),
205. clumsy ? "clumsy " : "");
206. (void) passive(mon, FALSE, 1, AT_KICK);
207. return;
208. } else {
209. mnexto(mon);
210. if(mon->mx != x || mon->my != y) {
211. if(glyph_is_invisible(levl[x][y].glyph)) {
212. unmap_object(x, y);
213. newsym(x, y);
214. }
215. pline("%s %s, %s evading your %skick.", Monnam(mon),
216. (can_teleport(mon->data) ? "teleports" :
217. is_floater(mon->data) ? "floats" :
218. is_flyer(mon->data) ? "swoops" :
219. (nolimbs(mon->data) || slithy(mon->data)) ?
220. "slides" : "jumps"),
221. clumsy ? "easily" : "nimbly",
222. clumsy ? "clumsy " : "");
223. (void) passive(mon, FALSE, 1, AT_KICK);
224. return;
225. }
226. }
227. }
228. kickdmg(mon, clumsy);
229. }
230.
231. /*
232. * Return TRUE if caught (the gold taken care of), FALSE otherwise.
233. * The gold object is *not* attached to the fobj chain!
234. */
235. boolean
236. ghitm(mtmp, gold)
237. register struct monst *mtmp;
238. register struct obj *gold;
239. {
240. boolean msg_given = FALSE;
241.
242. if(!likes_gold(mtmp->data) && !mtmp->isshk && !mtmp->ispriest
243. && !is_mercenary(mtmp->data)) {
244. wakeup(mtmp);
245. } else if (!mtmp->mcanmove) {
246. /* too light to do real damage */
247. if (canseemon(mtmp)) {
248. pline_The("%s harmlessly %s %s.", xname(gold),
249. otense(gold, "hit"), mon_nam(mtmp));
250. msg_given = TRUE;
251. }
252. } else {
253. #ifdef GOLDOBJ
254. long value = gold->quan * objects[gold->otyp].oc_cost;
255. #endif
256. mtmp->msleeping = 0;
257. mtmp->meating = 0;
258. if(!rn2(4)) setmangry(mtmp); /* not always pleasing */
259.
260. /* greedy monsters catch gold */
261. if (cansee(mtmp->mx, mtmp->my))
262. pline("%s catches the gold.", Monnam(mtmp));
263. #ifndef GOLDOBJ
264. mtmp->mgold += gold->quan;
265. #endif
266. if (mtmp->isshk) {
267. long robbed = ESHK(mtmp)->robbed;
268.
269. if (robbed) {
270. #ifndef GOLDOBJ
271. robbed -= gold->quan;
272. #else
273. robbed -= value;
274. #endif
275. if (robbed < 0) robbed = 0;
276. pline_The("amount %scovers %s recent losses.",
277. !robbed ? "" : "partially ",
278. mhis(mtmp));
279. ESHK(mtmp)->robbed = robbed;
280. if(!robbed)
281. make_happy_shk(mtmp, FALSE);
282. } else {
283. if(mtmp->mpeaceful) {
284. #ifndef GOLDOBJ
285. ESHK(mtmp)->credit += gold->quan;
286. #else
287. ESHK(mtmp)->credit += value;
288. #endif
289. You("have %ld %s in credit.",
290. ESHK(mtmp)->credit,
291. currency(ESHK(mtmp)->credit));
292. } else verbalize("Thanks, scum!");
293. }
294. } else if (mtmp->ispriest) {
295. if (mtmp->mpeaceful)
296. verbalize("Thank you for your contribution.");
297. else verbalize("Thanks, scum!");
298. } else if (is_mercenary(mtmp->data)) {
299. long goldreqd = 0L;
300.
301. if (rn2(3)) {
302. if (mtmp->data == &mons[PM_SOLDIER])
303. goldreqd = 100L;
304. else if (mtmp->data == &mons[PM_SERGEANT])
305. goldreqd = 250L;
306. else if (mtmp->data == &mons[PM_LIEUTENANT])
307. goldreqd = 500L;
308. else if (mtmp->data == &mons[PM_CAPTAIN])
309. goldreqd = 750L;
310.
311. if (goldreqd) {
312. #ifndef GOLDOBJ
313. if (gold->quan > goldreqd +
314. (u.ugold + u.ulevel*rn2(5))/ACURR(A_CHA))
315. #else
316. if (value > goldreqd +
317. (money_cnt(invent) + u.ulevel*rn2(5))/ACURR(A_CHA))
318. #endif
319. mtmp->mpeaceful = TRUE;
320. }
321. }
322. if (mtmp->mpeaceful)
323. verbalize("That should do. Now beat it!");
324. else verbalize("That's not enough, coward!");
325. }
326.
327. #ifndef GOLDOBJ
328. dealloc_obj(gold);
329. #else
330. add_to_minv(mtmp, gold);
331. #endif
332. return TRUE;
333. }
334.
335. if (!msg_given) miss(xname(gold), mtmp);
336. return FALSE;
337. }
338.
[edit] container_impact_dmg
339. /* container is kicked, dropped, thrown or otherwise impacted by player.
340. * Assumes container is on floor. Checks contents for possible damage. */
341. void
342. container_impact_dmg(obj)
343. struct obj *obj;
344. {
345. struct monst *shkp;
346. struct obj *otmp, *otmp2;
347. long loss = 0L;
348. boolean costly, insider;
349. xchar x = obj->ox, y = obj->oy;
350.
351. /* only consider normal containers */
352. if (!Is_container(obj) || Is_mbag(obj)) return;
353.
354. costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
355. costly_spot(x, y));
356. insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
357. *in_rooms(x, y, SHOPBASE) == *u.ushops);
358.
359. for (otmp = obj->cobj; otmp; otmp = otmp2) {
360. const char *result = (char *)0;
361.
362. otmp2 = otmp->nobj;
363. if (objects[otmp->otyp].oc_material == GLASS &&
364. otmp->oclass != GEM_CLASS && !obj_resists(otmp, 33, 100)) {
365. result = "shatter";
366. } else if (otmp->otyp == EGG && !rn2(3)) {
367. result = "cracking";
368. }
369. if (result) {
370. if (otmp->otyp == MIRROR) change_luck(-2);
371.
372. /* eggs laid by you. penalty is -1 per egg, max 5,
373. * but it's always exactly 1 that breaks */
374. if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
375. change_luck(-1);
376. You_hear("a muffled %s.", result);
377. if (costly)
378. loss += stolen_value(otmp, x, y,
379. (boolean)shkp->mpeaceful, TRUE);
380. if (otmp->quan > 1L)
381. useup(otmp);
382. else {
383. obj_extract_self(otmp);
384. obfree(otmp, (struct obj *) 0);
385. }
386. }
387. }
388. if (costly && loss) {
389. if (!insider) {
390. You("caused %ld %s worth of damage!", loss, currency(loss));
391. make_angry_shk(shkp, x, y);
392. } else {
393. You("owe %s %ld %s for objects destroyed.",
394. mon_nam(shkp), loss, currency(loss));
395. }
396. }
397. }
398.
[edit] kick_object
399. STATIC_OVL int
400. kick_object(x, y)
401. xchar x, y;
402. {
403. int range;
404. register struct monst *mon, *shkp;
405. struct trap *trap;
406. char bhitroom;
407. boolean costly, isgold, slide = FALSE;
408.
409. /* if a pile, the "top" object gets kicked */
410. kickobj = level.objects[x][y];
411.
412. /* kickobj should always be set due to conditions of call */
413. if(!kickobj || kickobj->otyp == BOULDER
414. || kickobj == uball || kickobj == uchain)
415. return(0);
416.
417. if ((trap = t_at(x,y)) != 0 &&
418. (((trap->ttyp == PIT ||
419. trap->ttyp == SPIKED_PIT) && !Passes_walls) ||
420. trap->ttyp == WEB)) {
421. if (!trap->tseen) find_trap(trap);
422. You_cant("kick %s that's in a %s!", something,
423. Hallucination ? "tizzy" :
424. (trap->ttyp == WEB) ? "web" : "pit");
425. return 1;
426. }
427.
428. if(Fumbling && !rn2(3)) {
429. Your("clumsy kick missed.");
430. return(1);
431. }
432.
433. if(kickobj->otyp == CORPSE && touch_petrifies(&mons[kickobj->corpsenm])
434. && !Stone_resistance && !uarmf) {
435. char kbuf[BUFSZ];
436.
437. You("kick the %s with your bare %s.",
438. corpse_xname(kickobj, TRUE), makeplural(body_part(FOOT)));
439. if (!(poly_when_stoned(youmonst.data) && polymon(PM_STONE_GOLEM))) {
440. You("turn to stone...");
441. killer_format = KILLED_BY;
442. /* KMH -- otmp should be kickobj */
443. Sprintf(kbuf, "kicking %s without boots",
444. an(corpse_xname(kickobj, TRUE)));
445. killer = kbuf;
446. done(STONING);
447. }
448. }
449.
450. /* range < 2 means the object will not move. */
451. /* maybe dexterity should also figure here. */
452. range = (int)((ACURRSTR)/2 - kickobj->owt/40);
453.
454. if(martial()) range += rnd(3);
455.
456. if (is_pool(x, y)) {
457. /* you're in the water too; significantly reduce range */
458. range = range / 3 + 1; /* {1,2}=>1, {3,4,5}=>2, {6,7,8}=>3 */
459. } else {
460. if (is_ice(x, y)) range += rnd(3), slide = TRUE;
461. if (kickobj->greased) range += rnd(3), slide = TRUE;
462. }
463.
464. /* Mjollnir is magically too heavy to kick */
465. if(kickobj->oartifact == ART_MJOLLNIR) range = 1;
466.
467. /* see if the object has a place to move into */
468. if(!ZAP_POS(levl[x+u.dx][y+u.dy].typ) || closed_door(x+u.dx, y+u.dy))
469. range = 1;
470.
471. costly = ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) &&
472. costly_spot(x, y));
473. isgold = (kickobj->oclass == COIN_CLASS);
474.
475. if (IS_ROCK(levl[x][y].typ) || closed_door(x, y)) {
476. if ((!martial() && rn2(20) > ACURR(A_DEX)) ||
477. IS_ROCK(levl[u.ux][u.uy].typ) || closed_door(u.ux, u.uy)) {
478. if (Blind)
479. pline("It doesn't come loose.");
480. else
481. pline("%s %sn't come loose.",
482. The(distant_name(kickobj, xname)),
483. otense(kickobj, "do"));
484. return (!rn2(3) || martial());
485. }
486. if (Blind)
487. pline("It comes loose.");
488. else
489. pline("%s %s loose.",
490. The(distant_name(kickobj, xname)),
491. otense(kickobj, "come"));
492. obj_extract_self(kickobj);
493. newsym(x, y);
494. if (costly && (!costly_spot(u.ux, u.uy) ||
495. !index(u.urooms, *in_rooms(x, y, SHOPBASE))))
496. addtobill(kickobj, FALSE, FALSE, FALSE);
497. if (!flooreffects(kickobj, u.ux, u.uy, "fall")) {
498. place_object(kickobj, u.ux, u.uy);
499. stackobj(kickobj);
500. newsym(u.ux, u.uy);
501. }
502. return 1;
503. }
504.
505. /* a box gets a chance of breaking open here */
506. if(Is_box(kickobj)) {
507. boolean otrp = kickobj->otrapped;
508.
509. if(range < 2) pline("THUD!");
510.
511. container_impact_dmg(kickobj);
512.
513. if (kickobj->olocked) {
514. if (!rn2(5) || (martial() && !rn2(2))) {
515. You("break open the lock!");
516. kickobj->olocked = 0;
517. kickobj->obroken = 1;
518. if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
519. return(1);
520. }
521. } else {
522. if (!rn2(3) || (martial() && !rn2(2))) {
523. pline_The("lid slams open, then falls shut.");
524. if (otrp) (void) chest_trap(kickobj, LEG, FALSE);
525. return(1);
526. }
527. }
528. if(range < 2) return(1);
529. /* else let it fall through to the next cases... */
530. }
531.
532. /* fragile objects should not be kicked */
533. if (hero_breaks(kickobj, kickobj->ox, kickobj->oy, FALSE)) return 1;
534.
535. /* too heavy to move. range is calculated as potential distance from
536. * player, so range == 2 means the object may move up to one square
537. * from its current position
538. */
539. if(range < 2 || (isgold && kickobj->quan > 300L)) {
540. if(!Is_box(kickobj)) pline("Thump!");
541. return(!rn2(3) || martial());
542. }
543.
544. if (kickobj->quan > 1L && !isgold) kickobj = splitobj(kickobj, 1L);
545.
546. if (slide && !Blind)
547. pline("Whee! %s %s across the %s.", Doname2(kickobj),
548. otense(kickobj, "slide"), surface(x,y));
549.
550. obj_extract_self(kickobj);
551. (void) snuff_candle(kickobj);
552. newsym(x, y);
553. mon = bhit(u.dx, u.dy, range, KICKED_WEAPON,
554. (int FDECL((*),(MONST_P,OBJ_P)))0,
555. (int FDECL((*),(OBJ_P,OBJ_P)))0,
556. kickobj);
557.
558. if(mon) {
559. if (mon->isshk &&
560. kickobj->where == OBJ_MINVENT && kickobj->ocarry == mon)
561. return 1; /* alert shk caught it */
562. notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
563. if (isgold ? ghitm(mon, kickobj) : /* caught? */
564. thitmonst(mon, kickobj)) /* hit && used up? */
565. return(1);
566. }
567.
568. /* the object might have fallen down a hole */
569. if (kickobj->where == OBJ_MIGRATING) {
570. if (costly) {
571. if(isgold)
572. costly_gold(x, y, kickobj->quan);
573. else (void)stolen_value(kickobj, x, y,
574. (boolean)shkp->mpeaceful, FALSE);
575. }
576. return 1;
577. }
578.
579. bhitroom = *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE);
580. if (costly && (!costly_spot(bhitpos.x, bhitpos.y) ||
581. *in_rooms(x, y, SHOPBASE) != bhitroom)) {
582. if(isgold)
583. costly_gold(x, y, kickobj->quan);
584. else (void)stolen_value(kickobj, x, y,
585. (boolean)shkp->mpeaceful, FALSE);
586. }
587.
588. if(flooreffects(kickobj,bhitpos.x,bhitpos.y,"fall")) return(1);
589. place_object(kickobj, bhitpos.x, bhitpos.y);
590. stackobj(kickobj);
591. newsym(kickobj->ox, kickobj->oy);
592. return(1);
593. }
594.
[edit] kickstr
595. STATIC_OVL char *
596. kickstr(buf)
597. char *buf;
598. {
599. const char *what;
600.
601. if (kickobj) what = distant_name(kickobj,doname);
602. else if (IS_DOOR(maploc->typ)) what = "a door";
603. else if (IS_TREE(maploc->typ)) what = "a tree";
604. else if (IS_STWALL(maploc->typ)) what = "a wall";
605. else if (IS_ROCK(maploc->typ)) what = "a rock";
606. else if (IS_THRONE(maploc->typ)) what = "a throne";
607. else if (IS_FOUNTAIN(maploc->typ)) what = "a fountain";
608. else if (IS_GRAVE(maploc->typ)) what = "a headstone";
609. #ifdef SINKS
610. else if (IS_SINK(maploc->typ)) what = "a sink";
611. #endif
612. else if (IS_ALTAR(maploc->typ)) what = "an altar";
613. else if (IS_DRAWBRIDGE(maploc->typ)) what = "a drawbridge";
614. else if (maploc->typ == STAIRS) what = "the stairs";
615. else if (maploc->typ == LADDER) what = "a ladder";
616. else if (maploc->typ == IRONBARS) what = "an iron bar";
617. else what = "something weird";
618. return strcat(strcpy(buf, "kicking "), what);
619. }
620.
[edit] dokick
621. int
622. dokick()
623. {
624. int x, y;
625. int avrg_attrib;
626. register struct monst *mtmp;
627. boolean no_kick = FALSE;
628. char buf[BUFSZ];
629.
630. if (nolimbs(youmonst.data) || slithy(youmonst.data)) {
631. You("have no legs to kick with.");
632. no_kick = TRUE;
633. } else if (verysmall(youmonst.data)) {
634. You("are too small to do any kicking.");
635. no_kick = TRUE;
636. #ifdef STEED
637. } else if (u.usteed) {
638. if (yn_function("Kick your steed?", ynchars, 'y') == 'y') {
639. You("kick %s.", mon_nam(u.usteed));
640. kick_steed();
641. return 1;
642. } else {
643. return 0;
644. }
645. #endif
646. } else if (Wounded_legs) {
647. /* note: jump() has similar code */
648. long wl = (EWounded_legs & BOTH_SIDES);
649. const char *bp = body_part(LEG);
650.
651. if (wl == BOTH_SIDES) bp = makeplural(bp);
652. Your("%s%s %s in no shape for kicking.",
653. (wl == LEFT_SIDE) ? "left " :
654. (wl == RIGHT_SIDE) ? "right " : "",
655. bp, (wl == BOTH_SIDES) ? "are" : "is");
656. no_kick = TRUE;
657. } else if (near_capacity() > SLT_ENCUMBER) {
658. Your("load is too heavy to balance yourself for a kick.");
659. no_kick = TRUE;
660. } else if (youmonst.data->mlet == S_LIZARD) {
661. Your("legs cannot kick effectively.");
662. no_kick = TRUE;
663. } else if (u.uinwater && !rn2(2)) {
664. Your("slow motion kick doesn't hit anything.");
665. no_kick = TRUE;
666. } else if (u.utrap) {
667. switch (u.utraptype) {
668. case TT_PIT:
669. pline("There's not enough room to kick down here.");
670. break;
671. case TT_WEB:
672. case TT_BEARTRAP:
673. You_cant("move your %s!", body_part(LEG));
674. break;
675. default:
676. break;
677. }
678. no_kick = TRUE;
679. }
680.
681. if (no_kick) {
682. /* ignore direction typed before player notices kick failed */
683. display_nhwindow(WIN_MESSAGE, TRUE); /* --More-- */
684. return 0;
685. }
686.
687. if(!getdir((char *)0)) return(0);
688. if(!u.dx && !u.dy) return(0);
689.
690. x = u.ux + u.dx;
691. y = u.uy + u.dy;
692.
693. /* KMH -- Kicking boots always succeed */
694. if (uarmf && uarmf->otyp == KICKING_BOOTS)
695. avrg_attrib = 99;
696. else
697. avrg_attrib = (ACURRSTR+ACURR(A_DEX)+ACURR(A_CON))/3;
698.
699. if(u.uswallow) {
700. switch(rn2(3)) {
701. case 0: You_cant("move your %s!", body_part(LEG));
702. break;
703. case 1: if (is_animal(u.ustuck->data)) {
704. pline("%s burps loudly.", Monnam(u.ustuck));
705. break;
706. }
707. default: Your("feeble kick has no effect."); break;
708. }
709. return(1);
710. }
711. if (Levitation) {
712. int xx, yy;
713.
714. xx = u.ux - u.dx;
715. yy = u.uy - u.dy;
716. /* doors can be opened while levitating, so they must be
717. * reachable for bracing purposes
718. * Possible extension: allow bracing against stuff on the side?
719. */
720. if (isok(xx,yy) && !IS_ROCK(levl[xx][yy].typ) &&
721. !IS_DOOR(levl[xx][yy].typ) &&
722. (!Is_airlevel(&u.uz) || !OBJ_AT(xx,yy))) {
723. You("have nothing to brace yourself against.");
724. return(0);
725. }
726. }
727.
728. wake_nearby();
729. u_wipe_engr(2);
730.
731. maploc = &levl[x][y];
732.
733. /* The next five tests should stay in */
734. /* their present order: monsters, pools, */
735. /* objects, non-doors, doors. */
736.
737. if(MON_AT(x, y)) {
738. struct permonst *mdat;
739.
740. mtmp = m_at(x, y);
741. mdat = mtmp->data;
742. if (!mtmp->mpeaceful || !canspotmon(mtmp))
743. flags.forcefight = TRUE; /* attack even if invisible */
744. kick_monster(x, y);
745. flags.forcefight = FALSE;
746. /* see comment in attack_checks() */
747. if (!DEADMONSTER(mtmp) &&
748. !canspotmon(mtmp) &&
749. /* check x and y; a monster that evades your kick by
750. jumping to an unseen square doesn't leave an I behind */
751. mtmp->mx == x && mtmp->my == y &&
752. !glyph_is_invisible(levl[x][y].glyph) &&
753. !(u.uswallow && mtmp == u.ustuck))
754. map_invisible(x, y);
755. if((Is_airlevel(&u.uz) || Levitation) && flags.move) {
756. int range;
757.
758. range = ((int)youmonst.data->cwt + (weight_cap() + inv_weight()));
759. if (range < 1) range = 1; /* divide by zero avoidance */
760. range = (3*(int)mdat->cwt) / range;
761.
762. if(range < 1) range = 1;
763. hurtle(-u.dx, -u.dy, range, TRUE);
764. }
765. return(1);
766. }
767. if (glyph_is_invisible(levl[x][y].glyph)) {
768. unmap_object(x, y);
769. newsym(x, y);
770. }
771. if (is_pool(x, y) ^ !!u.uinwater) {
772. /* objects normally can't be removed from water by kicking */
773. You("splash some water around.");
774. return 1;
775. }
776.
777. kickobj = (struct obj *)0;
778. if (OBJ_AT(x, y) &&
779. (!Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
780. || sobj_at(BOULDER,x,y))) {
781. if(kick_object(x, y)) {
782. if(Is_airlevel(&u.uz))
783. hurtle(-u.dx, -u.dy, 1, TRUE); /* assume it's light */
784. return(1);
785. }
786. goto ouch;
787. }
788.
789. if(!IS_DOOR(maploc->typ)) {
790. if(maploc->typ == SDOOR) {
791. if(!Levitation && rn2(30) < avrg_attrib) {
792. cvt_sdoor_to_door(maploc); /* ->typ = DOOR */
793. pline("Crash! %s a secret door!",
794. /* don't "kick open" when it's locked
795. unless it also happens to be trapped */
796. (maploc->doormask & (D_LOCKED|D_TRAPPED)) == D_LOCKED ?
797. "Your kick uncovers" : "You kick open");
798. exercise(A_DEX, TRUE);
799. if(maploc->doormask & D_TRAPPED) {
800. maploc->doormask = D_NODOOR;
801. b_trapped("door", FOOT);
802. } else if (maploc->doormask != D_NODOOR &&
803. !(maploc->doormask & D_LOCKED))
804. maploc->doormask = D_ISOPEN;
805. if (Blind)
806. feel_location(x,y); /* we know it's gone */
807. else
808. newsym(x,y);
809. if (maploc->doormask == D_ISOPEN ||
810. maploc->doormask == D_NODOOR)
811. unblock_point(x,y); /* vision */
812. return(1);
813. } else goto ouch;
814. }
815. if(maploc->typ == SCORR) {
816. if(!Levitation && rn2(30) < avrg_attrib) {
817. pline("Crash! You kick open a secret passage!");
818. exercise(A_DEX, TRUE);
819. maploc->typ = CORR;
820. if (Blind)
821. feel_location(x,y); /* we know it's gone */
822. else
823. newsym(x,y);
824. unblock_point(x,y); /* vision */
825. return(1);
826. } else goto ouch;
827. }
828. if(IS_THRONE(maploc->typ)) {
829. register int i;
830. if(Levitation) goto dumb;
831. if((Luck < 0 || maploc->doormask) && !rn2(3)) {
832. maploc->typ = ROOM;
833. maploc->doormask = 0; /* don't leave loose ends.. */
834. (void) mkgold((long)rnd(200), x, y);
835. if (Blind)
836. pline("CRASH! You destroy it.");
837. else {
838. pline("CRASH! You destroy the throne.");
839. newsym(x, y);
840. }
841. exercise(A_DEX, TRUE);
842. return(1);
843. } else if(Luck > 0 && !rn2(3) && !maploc->looted) {
844. (void) mkgold((long) rn1(201, 300), x, y);
845. i = Luck + 1;
846. if(i > 6) i = 6;
847. while(i--)
848. (void) mksobj_at(rnd_class(DILITHIUM_CRYSTAL,
849. LUCKSTONE-1), x, y, FALSE, TRUE);
850. if (Blind)
851. You("kick %s loose!", something);
852. else {
853. You("kick loose some ornamental coins and gems!");
854. newsym(x, y);
855. }
856. /* prevent endless milking */
857. maploc->looted = T_LOOTED;
858. return(1);
859. } else if (!rn2(4)) {
860. if(dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)) {
861. fall_through(FALSE);
862. return(1);
863. } else goto ouch;
864. }
865. goto ouch;
866. }
867. if(IS_ALTAR(maploc->typ)) {
868. if(Levitation) goto dumb;
869. You("kick %s.",(Blind ? something : "the altar"));
870. if(!rn2(3)) goto ouch;
871. altar_wrath(x, y);
872. exercise(A_DEX, TRUE);
873. return(1);
874. }
875. if(IS_FOUNTAIN(maploc->typ)) {
876. if(Levitation) goto dumb;
877. You("kick %s.",(Blind ? something : "the fountain"));
878. if(!rn2(3)) goto ouch;
879. /* make metal boots rust */
880. if(uarmf && rn2(3))
881. if (!rust_dmg(uarmf, "metal boots", 1, FALSE, &youmonst)) {
882. Your("boots get wet.");
883. /* could cause short-lived fumbling here */
884. }
885. exercise(A_DEX, TRUE);
886. return(1);
887. }
888. if(IS_GRAVE(maploc->typ) || maploc->typ == IRONBARS)
889. goto ouch;
890. if(IS_TREE(maploc->typ)) {
891. struct obj *treefruit;
892. /* nothing, fruit or trouble? 75:23.5:1.5% */
893. if (rn2(3)) {
894. if ( !rn2(6) && !(mvitals[PM_KILLER_BEE].mvflags & G_GONE) )
895. You_hear("a low buzzing."); /* a warning */
896. goto ouch;
897. }
898. if (rn2(15) && !(maploc->looted & TREE_LOOTED) &&
899. (treefruit = rnd_treefruit_at(x, y))) {
900. long nfruit = 8L-rnl(7), nfall;
901. short frtype = treefruit->otyp;
902. treefruit->quan = nfruit;
903. if (is_plural(treefruit))
904. pline("Some %s fall from the tree!", xname(treefruit));
905. else
906. pline("%s falls from the tree!", An(xname(treefruit)));
907. nfall = scatter(x,y,2,MAY_HIT,treefruit);
908. if (nfall != nfruit) {
909. /* scatter left some in the tree, but treefruit
910. * may not refer to the correct object */
911. treefruit = mksobj(frtype, TRUE, FALSE);
912. treefruit->quan = nfruit-nfall;
913. pline("%ld %s got caught in the branches.",
914. nfruit-nfall, xname(treefruit));
915. dealloc_obj(treefruit);
916. }
917. exercise(A_DEX, TRUE);
918. exercise(A_WIS, TRUE); /* discovered a new food source! */
919. newsym(x, y);
920. maploc->looted |= TREE_LOOTED;
921. return(1);
922. } else if (!(maploc->looted & TREE_SWARM)) {
923. int cnt = rnl(4) + 2;
924. int made = 0;
925. coord mm;
926. mm.x = x; mm.y = y;
927. while (cnt--) {
928. if (enexto(&mm, mm.x, mm.y, &mons[PM_KILLER_BEE])
929. && makemon(&mons[PM_KILLER_BEE],
930. mm.x, mm.y, MM_ANGRY))
931. made++;
932. }
933. if ( made )
934. pline("You've attracted the tree's former occupants!");
935. else
936. You("smell stale honey.");
937. maploc->looted |= TREE_SWARM;
938. return(1);
939. }
940. goto ouch;
941. }
942. #ifdef SINKS
943. if(IS_SINK(maploc->typ)) {
944. int gend = poly_gender();
945. short washerndx = (gend == 1 || (gend == 2 && rn2(2))) ?
946. PM_INCUBUS : PM_SUCCUBUS;
947.
948. if(Levitation) goto dumb;
949. if(rn2(5)) {
950. if(flags.soundok)
951. pline("Klunk! The pipes vibrate noisily.");
952. else pline("Klunk!");
953. exercise(A_DEX, TRUE);
954. return(1);
955. } else if(!(maploc->looted & S_LPUDDING) && !rn2(3) &&
956. !(mvitals[PM_BLACK_PUDDING].mvflags & G_GONE)) {
957. if (Blind)
958. You_hear("a gushing sound.");
959. else
960. pline("A %s ooze gushes up from the drain!",
961. hcolor(NH_BLACK));
962. (void) makemon(&mons[PM_BLACK_PUDDING],
963. x, y, NO_MM_FLAGS);
964. exercise(A_DEX, TRUE);
965. newsym(x,y);
966. maploc->looted |= S_LPUDDING;
967. return(1);
968. } else if(!(maploc->looted & S_LDWASHER) && !rn2(3) &&
969. !(mvitals[washerndx].mvflags & G_GONE)) {
970. /* can't resist... */
971. pline("%s returns!", (Blind ? Something :
972. "The dish washer"));
973. if (makemon(&mons[washerndx], x, y, NO_MM_FLAGS))
974. newsym(x,y);
975. maploc->looted |= S_LDWASHER;
976. exercise(A_DEX, TRUE);
977. return(1);
978. } else if(!rn2(3)) {
979. pline("Flupp! %s.", (Blind ?
980. "You hear a sloshing sound" :
981. "Muddy waste pops up from the drain"));
982. if(!(maploc->looted & S_LRING)) { /* once per sink */
983. if (!Blind)
984. You("see a ring shining in its midst.");
985. (void) mkobj_at(RING_CLASS, x, y, TRUE);
986. newsym(x, y);
987. exercise(A_DEX, TRUE);
988. exercise(A_WIS, TRUE); /* a discovery! */
989. maploc->looted |= S_LRING;
990. }
991. return(1);
992. }
993. goto ouch;
994. }
995. #endif
996. if (maploc->typ == STAIRS || maploc->typ == LADDER ||
997. IS_STWALL(maploc->typ)) {
998. if(!IS_STWALL(maploc->typ) && maploc->ladder == LA_DOWN)
999. goto dumb;
1000. ouch:
1001. pline("Ouch! That hurts!");
1002. exercise(A_DEX, FALSE);
1003. exercise(A_STR, FALSE);
1004. if (Blind) feel_location(x,y); /* we know we hit it */
1005. if (is_drawbridge_wall(x,y) >= 0) {
1006. pline_The("drawbridge is unaffected.");
1007. /* update maploc to refer to the drawbridge */
1008. (void) find_drawbridge(&x,&y);
1009. maploc = &levl[x][y];
1010. }
1011. if(!rn2(3)) set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
1012. losehp(rnd(ACURR(A_CON) > 15 ? 3 : 5), kickstr(buf),
1013. KILLED_BY);
1014. if(Is_airlevel(&u.uz) || Levitation)
1015. hurtle(-u.dx, -u.dy, rn1(2,4), TRUE); /* assume it's heavy */
1016. return(1);
1017. }
1018. goto dumb;
1019. }
1020.
1021. if(maploc->doormask == D_ISOPEN ||
1022. maploc->doormask == D_BROKEN ||
1023. maploc->doormask == D_NODOOR) {
1024. dumb:
1025. exercise(A_DEX, FALSE);
1026. if (martial() || ACURR(A_DEX) >= 16 || rn2(3)) {
1027. You("kick at empty space.");
1028. if (Blind) feel_location(x,y);
1029. } else {
1030. pline("Dumb move! You strain a muscle.");
1031. exercise(A_STR, FALSE);
1032. set_wounded_legs(RIGHT_SIDE, 5 + rnd(5));
1033. }
1034. if ((Is_airlevel(&u.uz) || Levitation) && rn2(2)) {
1035. hurtle(-u.dx, -u.dy, 1, TRUE);
1036. return 1; /* you moved, so use up a turn */
1037. }
1038. return(0);
1039. }
1040.
1041. /* not enough leverage to kick open doors while levitating */
1042. if(Levitation) goto ouch;
1043.
1044. exercise(A_DEX, TRUE);
1045. /* door is known to be CLOSED or LOCKED */
1046. if(rnl(35) < avrg_attrib + (!martial() ? 0 : ACURR(A_DEX))) {
1047. boolean shopdoor = *in_rooms(x, y, SHOPBASE) ? TRUE : FALSE;
1048. /* break the door */
1049. if(maploc->doormask & D_TRAPPED) {
1050. if (flags.verbose) You("kick the door.");
1051. exercise(A_STR, FALSE);
1052. maploc->doormask = D_NODOOR;
1053. b_trapped("door", FOOT);
1054. } else if(ACURR(A_STR) > 18 && !rn2(5) && !shopdoor) {
1055. pline("As you kick the door, it shatters to pieces!");
1056. exercise(A_STR, TRUE);
1057. maploc->doormask = D_NODOOR;
1058. } else {
1059. pline("As you kick the door, it crashes open!");
1060. exercise(A_STR, TRUE);
1061. maploc->doormask = D_BROKEN;
1062. }
1063. if (Blind)
1064. feel_location(x,y); /* we know we broke it */
1065. else
1066. newsym(x,y);
1067. unblock_point(x,y); /* vision */
1068. if (shopdoor) {
1069. add_damage(x, y, 400L);
1070. pay_for_damage("break", FALSE);
1071. }
1072. if (in_town(x, y))
1073. for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1074. if (DEADMONSTER(mtmp)) continue;
1075. if((mtmp->data == &mons[PM_WATCHMAN] ||
1076. mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
1077. couldsee(mtmp->mx, mtmp->my) &&
1078. mtmp->mpeaceful) {
1079. if (canspotmon(mtmp))
1080. pline("%s yells:", Amonnam(mtmp));
1081. else
1082. You_hear("someone yell:");
1083. verbalize("Halt, thief! You're under arrest!");
1084. (void) angry_guards(FALSE);
1085. break;
1086. }
1087. }
1088. } else {
1089. if (Blind) feel_location(x,y); /* we know we hit it */
1090. exercise(A_STR, TRUE);
1091. pline("WHAMMM!!!");
1092. if (in_town(x, y))
1093. for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
1094. if (DEADMONSTER(mtmp)) continue;
1095. if ((mtmp->data == &mons[PM_WATCHMAN] ||
1096. mtmp->data == &mons[PM_WATCH_CAPTAIN]) &&
1097. mtmp->mpeaceful && couldsee(mtmp->mx, mtmp->my)) {
1098. if (canspotmon(mtmp))
1099. pline("%s yells:", Amonnam(mtmp));
1100. else
1101. You_hear("someone yell:");
1102. if(levl[x][y].looted & D_WARNED) {
1103. verbalize("Halt, vandal! You're under arrest!");
1104. (void) angry_guards(FALSE);
1105. } else {
1106. verbalize("Hey, stop damaging that door!");
1107. levl[x][y].looted |= D_WARNED;
1108. }
1109. break;
1110. }
1111. }
1112. }
1113. return(1);
1114. }
1115.
[edit] drop_to
1116. STATIC_OVL void
1117. drop_to(cc, loc)
1118. coord *cc;
1119. schar loc;
1120. {
1121. /* cover all the MIGR_xxx choices generated by down_gate() */
1122. switch (loc) {
1123. case MIGR_RANDOM: /* trap door or hole */
1124. if (Is_stronghold(&u.uz)) {
1125. cc->x = valley_level.dnum;
1126. cc->y = valley_level.dlevel;
1127. break;
1128. } else if (In_endgame(&u.uz) || Is_botlevel(&u.uz)) {
1129. cc->y = cc->x = 0;
1130. break;
1131. } /* else fall to the next cases */
1132. case MIGR_STAIRS_UP:
1133. case MIGR_LADDER_UP:
1134. cc->x = u.uz.dnum;
1135. cc->y = u.uz.dlevel + 1;
1136. break;
1137. case MIGR_SSTAIRS:
1138. cc->x = sstairs.tolev.dnum;
1139. cc->y = sstairs.tolev.dlevel;
1140. break;
1141. default:
1142. case MIGR_NOWHERE:
1143. /* y==0 means "nowhere", in which case x doesn't matter */
1144. cc->y = cc->x = 0;
1145. break;
1146. }
1147. }
1148.
[edit] impact_drop
1149. void
1150. impact_drop(missile, x, y, dlev)
1151. struct obj *missile;
1152. xchar x, y, dlev;
1153. {
1154. schar toloc;
1155. register struct obj *obj, *obj2;
1156. register struct monst *shkp;
1157. long oct, dct, price, debit, robbed;
1158. boolean angry, costly, isrock;
1159. coord cc;
1160.
1161. if(!OBJ_AT(x, y)) return;
1162.
1163. toloc = down_gate(x, y);
1164. drop_to(&cc, toloc);
1165. if (!cc.y) return;
1166.
1167. if (dlev) {
1168. /* send objects next to player falling through trap door.
1169. * checked in obj_delivery().
1170. */
1171. toloc = MIGR_NEAR_PLAYER;
1172. cc.y = dlev;
1173. }
1174.
1175. costly = costly_spot(x, y);
1176. price = debit = robbed = 0L;
1177. angry = FALSE;
1178. shkp = (struct monst *) 0;
1179. /* if 'costly', we must keep a record of ESHK(shkp) before
1180. * it undergoes changes through the calls to stolen_value.
1181. * the angry bit must be reset, if needed, in this fn, since
1182. * stolen_value is called under the 'silent' flag to avoid
1183. * unsavory pline repetitions.
1184. */
1185. if(costly) {
1186. if ((shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) != 0) {
1187. debit = ESHK(shkp)->debit;
1188. robbed = ESHK(shkp)->robbed;
1189. angry = !shkp->mpeaceful;
1190. }
1191. }
1192.
1193. isrock = (missile && missile->otyp == ROCK);
1194. oct = dct = 0L;
1195. for(obj = level.objects[x][y]; obj; obj = obj2) {
1196. obj2 = obj->nexthere;
1197. if(obj == missile) continue;
1198. /* number of objects in the pile */
1199. oct += obj->quan;
1200. if(obj == uball || obj == uchain) continue;
1201. /* boulders can fall too, but rarely & never due to rocks */
1202. if((isrock && obj->otyp == BOULDER) ||
1203. rn2(obj->otyp == BOULDER ? 30 : 3)) continue;
1204. obj_extract_self(obj);
1205.
1206. if(costly) {
1207. price += stolen_value(obj, x, y,
1208. (costly_spot(u.ux, u.uy) &&
1209. index(u.urooms, *in_rooms(x, y, SHOPBASE))),
1210. TRUE);
1211. /* set obj->no_charge to 0 */
1212. if (Has_contents(obj))
1213. picked_container(obj); /* does the right thing */
1214. if (obj->oclass != COIN_CLASS)
1215. obj->no_charge = 0;
1216. }
1217.
1218. add_to_migration(obj);
1219. obj->ox = cc.x;
1220. obj->oy = cc.y;
1221. obj->owornmask = (long)toloc;
1222.
1223. /* number of fallen objects */
1224. dct += obj->quan;
1225. }
1226.
1227. if (dct && cansee(x,y)) { /* at least one object fell */
1228. const char *what = (dct == 1L ? "object falls" : "objects fall");
1229.
1230. if (missile)
1231. pline("From the impact, %sother %s.",
1232. dct == oct ? "the " : dct == 1L ? "an" : "", what);
1233. else if (oct == dct)
1234. pline("%s adjacent %s %s.",
1235. dct == 1L ? "The" : "All the", what, gate_str);
1236. else
1237. pline("%s adjacent %s %s.",
1238. dct == 1L ? "One of the" : "Some of the",
1239. dct == 1L ? "objects falls" : what, gate_str);
1240. }
1241.
1242. if(costly && shkp && price) {
1243. if(ESHK(shkp)->robbed > robbed) {
1244. You("removed %ld %s worth of goods!", price, currency(price));
1245. if(cansee(shkp->mx, shkp->my)) {
1246. if(ESHK(shkp)->customer[0] == 0)
1247. (void) strncpy(ESHK(shkp)->customer,
1248. plname, PL_NSIZ);
1249. if(angry)
1250. pline("%s is infuriated!", Monnam(shkp));
1251. else pline("\"%s, you are a thief!\"", plname);
1252. } else You_hear("a scream, \"Thief!\"");
1253. hot_pursuit(shkp);
1254. (void) angry_guards(FALSE);
1255. return;
1256. }
1257. if(ESHK(shkp)->debit > debit) {
1258. long amt = (ESHK(shkp)->debit - debit);
1259. You("owe %s %ld %s for goods lost.",
1260. Monnam(shkp),
1261. amt, currency(amt));
1262. }
1263. }
1264.
1265. }
1266.
[edit] ship_object
1267. /* NOTE: ship_object assumes otmp was FREED from fobj or invent.
1268. * <x,y> is the point of drop. otmp is _not_ an <x,y> resident:
1269. * otmp is either a kicked, dropped, or thrown object.
1270. */
1271. boolean
1272. ship_object(otmp, x, y, shop_floor_obj)
1273. xchar x, y;
1274. struct obj *otmp;
1275. boolean shop_floor_obj;
1276. {
1277. schar toloc;
1278. xchar ox, oy;
1279. coord cc;
1280. struct obj *obj;
1281. struct trap *t;
1282. boolean nodrop, unpaid, container, impact = FALSE;
1283. long n = 0L;
1284.
1285. if (!otmp) return(FALSE);
1286. if ((toloc = down_gate(x, y)) == MIGR_NOWHERE) return(FALSE);
1287. drop_to(&cc, toloc);
1288. if (!cc.y) return(FALSE);
1289.
1290. /* objects other than attached iron ball always fall down ladder,
1291. but have a chance of staying otherwise */
1292. nodrop = (otmp == uball) || (otmp == uchain) ||
1293. (toloc != MIGR_LADDER_UP && rn2(3));
1294.
1295. container = Has_contents(otmp);
1296. unpaid = (otmp->unpaid || (container && count_unpaid(otmp->cobj)));
1297.
1298. if(OBJ_AT(x, y)) {
1299. for(obj = level.objects[x][y]; obj; obj = obj->nexthere)
1300. if(obj != otmp) n += obj->quan;
1301. if(n) impact = TRUE;
1302. }
1303. /* boulders never fall through trap doors, but they might knock
1304. other things down before plugging the hole */
1305. if (otmp->otyp == BOULDER &&
1306. ((t = t_at(x, y)) != 0) &&
1307. (t->ttyp == TRAPDOOR || t->ttyp == HOLE)) {
1308. if (impact) impact_drop(otmp, x, y, 0);
1309. return FALSE; /* let caller finish the drop */
1310. }
1311.
1312. if (cansee(x, y))
1313. otransit_msg(otmp, nodrop, n);
1314.
1315. if (nodrop) {
1316. if (impact) impact_drop(otmp, x, y, 0);
1317. return(FALSE);
1318. }
1319.
1320. if(unpaid || shop_floor_obj) {
1321. if(unpaid) {
1322. subfrombill(otmp, shop_keeper(*u.ushops));
1323. (void)stolen_value(otmp, u.ux, u.uy, TRUE, FALSE);
1324. } else {
1325. ox = otmp->ox;
1326. oy = otmp->oy;
1327. (void)stolen_value(otmp, ox, oy,
1328. (costly_spot(u.ux, u.uy) &&
1329. index(u.urooms, *in_rooms(ox, oy, SHOPBASE))),
1330. FALSE);
1331. }
1332. /* set otmp->no_charge to 0 */
1333. if(container)
1334. picked_container(otmp); /* happens to do the right thing */
1335. if(otmp->oclass != COIN_CLASS)
1336. otmp->no_charge = 0;
1337. }
1338.
1339. if (otmp == uwep) setuwep((struct obj *)0);
1340. if (otmp == uquiver) setuqwep((struct obj *)0);
1341. if (otmp == uswapwep) setuswapwep((struct obj *)0);
1342.
1343. /* some things break rather than ship */
1344. if (breaktest(otmp)) {
1345. const char *result;
1346.
1347. if (objects[otmp->otyp].oc_material == GLASS
1348. #ifdef TOURIST
1349. || otmp->otyp == EXPENSIVE_CAMERA
1350. #endif
1351. ) {
1352. if (otmp->otyp == MIRROR)
1353. change_luck(-2);
1354. result = "crash";
1355. } else {
1356. /* penalty for breaking eggs laid by you */
1357. if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
1358. change_luck((schar) -min(otmp->quan, 5L));
1359. result = "splat";
1360. }
1361. You_hear("a muffled %s.",result);
1362. obj_extract_self(otmp);
1363. obfree(otmp, (struct obj *) 0);
1364. return TRUE;
1365. }
1366.
1367. add_to_migration(otmp);
1368. otmp->ox = cc.x;
1369. otmp->oy = cc.y;
1370. otmp->owornmask = (long)toloc;
1371. /* boulder from rolling boulder trap, no longer part of the trap */
1372. if (otmp->otyp == BOULDER) otmp->otrapped = 0;
1373.
1374. if(impact) {
1375. /* the objs impacted may be in a shop other than
1376. * the one in which the hero is located. another
1377. * check for a shk is made in impact_drop. it is, e.g.,
1378. * possible to kick/throw an object belonging to one
1379. * shop into another shop through a gap in the wall,
1380. * and cause objects belonging to the other shop to
1381. * fall down a trap door--thereby getting two shopkeepers
1382. * angry at the hero in one shot.
1383. */
1384. impact_drop(otmp, x, y, 0);
1385. newsym(x,y);
1386. }
1387. return(TRUE);
1388. }
1389.
[edit] obj_delivery
1390. void
1391. obj_delivery()
1392. {
1393. register struct obj *otmp, *otmp2;
1394. register int nx, ny;
1395. long where;
1396.
1397. for (otmp = migrating_objs; otmp; otmp = otmp2) {
1398. otmp2 = otmp->nobj;
1399. if (otmp->ox != u.uz.dnum || otmp->oy != u.uz.dlevel) continue;
1400.
1401. obj_extract_self(otmp);
1402. where = otmp->owornmask; /* destination code */
1403. otmp->owornmask = 0L;
1404.
1405. switch ((int)where) {
1406. case MIGR_STAIRS_UP: nx = xupstair, ny = yupstair;
1407. break;
1408. case MIGR_LADDER_UP: nx = xupladder, ny = yupladder;
1409. break;
1410. case MIGR_SSTAIRS: nx = sstairs.sx, ny = sstairs.sy;
1411. break;
1412. case MIGR_NEAR_PLAYER: nx = u.ux, ny = u.uy;
1413. break;
1414. default:
1415. case MIGR_RANDOM: nx = ny = 0;
1416. break;
1417. }
1418. if (nx > 0) {
1419. place_object(otmp, nx, ny);
1420. stackobj(otmp);
1421. (void)scatter(nx, ny, rnd(2), 0, otmp);
1422. } else { /* random location */
1423. /* set dummy coordinates because there's no
1424. current position for rloco() to update */
1425. otmp->ox = otmp->oy = 0;
1426. rloco(otmp);
1427. }
1428. }
1429. }
1430.
[edit] otransit_msg
1431. STATIC_OVL void
1432. otransit_msg(otmp, nodrop, num)
1433. register struct obj *otmp;
1434. register boolean nodrop;
1435. long num;
1436. {
1437. char obuf[BUFSZ];
1438.
1439. Sprintf(obuf, "%s%s",
1440. (otmp->otyp == CORPSE &&
1441. type_is_pname(&mons[otmp->corpsenm])) ? "" : "The ",
1442. xname(otmp));
1443.
1444. if(num) { /* means: other objects are impacted */
1445. Sprintf(eos(obuf), " %s %s object%s",
1446. otense(otmp, "hit"),
1447. num == 1L ? "another" : "other",
1448. num > 1L ? "s" : "");
1449. if(nodrop)
1450. Sprintf(eos(obuf), ".");
1451. else
1452. Sprintf(eos(obuf), " and %s %s.",
1453. otense(otmp, "fall"), gate_str);
1454. pline("%s", obuf);
1455. } else if(!nodrop)
1456. pline("%s %s %s.", obuf, otense(otmp, "fall"), gate_str);
1457. }
1458.
[edit] down_gate
1459. /* migration destination for objects which fall down to next level */
1460. schar
1461. down_gate(x, y)
1462. xchar x, y;
1463. {
1464. struct trap *ttmp;
1465.
1466. gate_str = 0;
1467. /* this matches the player restriction in goto_level() */
1468. if (on_level(&u.uz, &qstart_level) && !ok_to_quest())
1469. return MIGR_NOWHERE;
1470.
1471. if ((xdnstair == x && ydnstair == y) ||
1472. (sstairs.sx == x && sstairs.sy == y && !sstairs.up)) {
1473. gate_str = "down the stairs";
1474. return (xdnstair == x && ydnstair == y) ?
1475. MIGR_STAIRS_UP : MIGR_SSTAIRS;
1476. }
1477. if (xdnladder == x && ydnladder == y) {
1478. gate_str = "down the ladder";
1479. return MIGR_LADDER_UP;
1480. }
1481.
1482. if (((ttmp = t_at(x, y)) != 0 && ttmp->tseen) &&
1483. (ttmp->ttyp == TRAPDOOR || ttmp->ttyp == HOLE)) {
1484. gate_str = (ttmp->ttyp == TRAPDOOR) ?
1485. "through the trap door" : "through the hole";
1486. return MIGR_RANDOM;
1487. }
1488. return MIGR_NOWHERE;
1489. }
1490.
1491. /*dokick.c*/