PageRenderTime 64ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/src/trap.c

https://github.com/NickMcConnell/Beleriand
C | 2313 lines | 1284 code | 484 blank | 545 comment | 425 complexity | 164a6dc569bf8b5df933f9094ee9d286 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * File: trap.c
  3. * Purpose: Trap triggering, selection, and placement
  4. *
  5. * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
  6. *
  7. * This work is free software; you can redistribute it and/or modify it
  8. * under the terms of either:
  9. *
  10. * a) the GNU General Public License as published by the Free Software
  11. * Foundation, version 2, or
  12. *
  13. * b) the "Angband licence":
  14. * This software may be copied and distributed for educational, research,
  15. * and not for profit purposes provided that this copyright and statement
  16. * are included in all such copies. Other copyrights may also apply.
  17. */
  18. #include "angband.h"
  19. #include "cave.h"
  20. #include "generate.h"
  21. #include "monster.h"
  22. #include "spells.h"
  23. #include "squelch.h"
  24. #include "trap.h"
  25. #include "ui-menu.h"
  26. /**
  27. * Is there a specific kind of trap in this grid?
  28. */
  29. bool cave_trap_specific(int y, int x, int t_idx)
  30. {
  31. int i;
  32. /* First, check the trap marker */
  33. if (!cave_has(cave_info[y][x], CAVE_TRAP))
  34. return (FALSE);
  35. /* Scan the current trap list */
  36. for (i = 0; i < trap_max; i++) {
  37. /* Point to this trap */
  38. trap_type *t_ptr = &trap_list[i];
  39. /* Find a trap in this position */
  40. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  41. /* We found a trap of the right kind */
  42. if (t_ptr->t_idx == t_idx)
  43. return (TRUE);
  44. }
  45. }
  46. /* Report failure */
  47. return (FALSE);
  48. }
  49. /**
  50. * Is there a trap with a given flag in this grid?
  51. */
  52. bool cave_trap_flag(int y, int x, int flag)
  53. {
  54. int i;
  55. /* First, check the trap marker */
  56. if (!cave_has(cave_info[y][x], CAVE_TRAP))
  57. return (FALSE);
  58. /* Scan the current trap list */
  59. for (i = 0; i < trap_max; i++) {
  60. /* Point to this trap */
  61. trap_type *t_ptr = &trap_list[i];
  62. /* Find a trap in this position */
  63. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  64. /* We found a trap with the right flag */
  65. if (trf_has(t_ptr->flags, flag))
  66. return (TRUE);
  67. }
  68. }
  69. /* Report failure */
  70. return (FALSE);
  71. }
  72. /**
  73. * Check for a basic monster trap
  74. */
  75. bool cave_basic_monster_trap(int y, int x)
  76. {
  77. /* Look for a monster trap */
  78. return (cave_trap_specific(y, x, MTRAP_BASE));
  79. }
  80. /**
  81. * Check for an advanced monster trap
  82. */
  83. bool cave_advanced_monster_trap(int y, int x)
  84. {
  85. /* Look for a monster trap */
  86. return (cave_trap_flag(y, x, TRF_M_TRAP) &&
  87. !cave_trap_specific(y, x, MTRAP_BASE));
  88. }
  89. /**
  90. * Check for any monster trap
  91. */
  92. bool cave_monster_trap(int y, int x)
  93. {
  94. /* Look for a monster trap */
  95. return (cave_trap_flag(y, x, TRF_M_TRAP));
  96. }
  97. /**
  98. * Return the index of a monster trap
  99. */
  100. int monster_trap_idx(int y, int x)
  101. {
  102. int i;
  103. if (!cave_monster_trap(y, x))
  104. return -1;
  105. /* Scan the current trap list */
  106. for (i = 0; i < trap_max; i++) {
  107. /* Point to this trap */
  108. trap_type *t_ptr = &trap_list[i];
  109. /* Find a monster trap in this position */
  110. if ((t_ptr->fy == y) && (t_ptr->fx == x) &&
  111. trf_has(t_ptr->flags, TRF_M_TRAP))
  112. return (i);
  113. }
  114. /* Paranoia */
  115. return -1;
  116. }
  117. /**
  118. * Determine if a trap actually exists in this grid.
  119. *
  120. * Called with vis = 0 to accept any trap, = 1 to accept only visible
  121. * traps, and = -1 to accept only invisible traps.
  122. *
  123. * Clear the CAVE_TRAP flag if none exist.
  124. */
  125. static bool verify_trap(int y, int x, int vis)
  126. {
  127. int i;
  128. bool trap = FALSE;
  129. /* Scan the current trap list */
  130. for (i = 0; i < trap_max; i++) {
  131. /* Point to this trap */
  132. trap_type *t_ptr = &trap_list[i];
  133. /* Find a trap in this position */
  134. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  135. /* Accept any trap */
  136. if (!vis)
  137. return (TRUE);
  138. /* Accept traps that match visibility requirements */
  139. if (vis == 1) {
  140. if (trf_has(t_ptr->flags, TRF_VISIBLE))
  141. return (TRUE);
  142. }
  143. if (vis == -1) {
  144. if (!trf_has(t_ptr->flags, TRF_VISIBLE))
  145. return (TRUE);
  146. }
  147. /* Note that a trap does exist */
  148. trap = TRUE;
  149. }
  150. }
  151. /* No traps in this location. */
  152. if (!trap) {
  153. /* No traps */
  154. cave_off(cave_info[y][x], CAVE_TRAP);
  155. /* No reason to mark this grid, ... */
  156. cave_off(cave_info[y][x], CAVE_MARK);
  157. /* ... unless certain conditions apply */
  158. note_spot(y, x);
  159. }
  160. /* Report failure */
  161. return (FALSE);
  162. }
  163. /**
  164. * Is there a visible trap in this grid?
  165. */
  166. bool cave_visible_trap(int y, int x)
  167. {
  168. /* Look for a visible trap */
  169. return (cave_trap_flag(y, x, TRF_VISIBLE));
  170. }
  171. /**
  172. * Is there an invisible trap in this grid?
  173. */
  174. bool cave_invisible_trap(int y, int x)
  175. {
  176. /* First, check the trap marker */
  177. if (!cave_has(cave_info[y][x], CAVE_TRAP))
  178. return (FALSE);
  179. /* Verify trap, require that it be invisible */
  180. return (verify_trap(y, x, -1));
  181. }
  182. /**
  183. * Is there a player trap in this grid?
  184. */
  185. bool cave_player_trap(int y, int x)
  186. {
  187. /* Look for a player trap */
  188. return (cave_trap_flag(y, x, TRF_TRAP));
  189. }
  190. /**
  191. * Return the index of any visible trap
  192. */
  193. int visible_trap_idx(int y, int x)
  194. {
  195. int i;
  196. if (!cave_visible_trap(y, x))
  197. return -1;
  198. /* Scan the current trap list */
  199. for (i = 0; i < trap_max; i++) {
  200. /* Point to this trap */
  201. trap_type *t_ptr = &trap_list[i];
  202. /* Find a visible trap in this position */
  203. if ((t_ptr->fy == y) && (t_ptr->fx == x) &&
  204. trf_has(t_ptr->flags, TRF_VISIBLE))
  205. return (i);
  206. }
  207. /* Paranoia */
  208. return -1;
  209. }
  210. /**
  211. * Is there a web in this grid?
  212. */
  213. bool cave_web(int y, int x)
  214. {
  215. return (cave_trap_specific(y, x, OBST_WEB));
  216. }
  217. /**
  218. * Get the graphics of a listed trap.
  219. *
  220. * We should probably have better handling of stacked traps, but that can
  221. * wait until we do, in fact, have stacked traps under normal conditions.
  222. *
  223. */
  224. bool get_trap_graphics(int t_idx, int *a, wchar_t * c,
  225. bool require_visible)
  226. {
  227. trap_type *t_ptr = &trap_list[t_idx];
  228. /* Trap is visible, or we don't care */
  229. if (!require_visible || trf_has(t_ptr->flags, TRF_VISIBLE)) {
  230. /* Get the graphics */
  231. *a = t_ptr->kind->x_attr;
  232. *c = t_ptr->kind->x_char;
  233. /* We found a trap */
  234. return (TRUE);
  235. }
  236. /* No traps found with the requirement */
  237. return (FALSE);
  238. }
  239. /**
  240. * Reveal some of the traps in a grid
  241. */
  242. bool reveal_trap(int y, int x, int chance, bool domsg)
  243. {
  244. int i;
  245. int found_trap = 0;
  246. /* Check the trap marker */
  247. if (!cave_has(cave_info[y][x], CAVE_TRAP))
  248. return (FALSE);
  249. /* Scan the current trap list */
  250. for (i = 0; i < trap_max; i++) {
  251. /* Point to this trap */
  252. trap_type *t_ptr = &trap_list[i];
  253. /* Find a trap in this position */
  254. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  255. /* Trap is invisible */
  256. if (!trf_has(t_ptr->flags, TRF_VISIBLE)) {
  257. /* See the trap */
  258. trf_on(t_ptr->flags, TRF_VISIBLE);
  259. cave_on(cave_info[y][x], CAVE_MARK);
  260. /* We found a trap */
  261. found_trap++;
  262. /* If chance is < 100, sometimes stop */
  263. if ((chance < 100) && (randint1(100) > chance))
  264. break;
  265. }
  266. }
  267. }
  268. /* We found at least one trap (or loose rock) */
  269. if (found_trap) {
  270. /* We want to talk about it */
  271. if (domsg) {
  272. if (found_trap == 1)
  273. msg("You have found a trap.");
  274. else
  275. msg("You have found %d traps.", found_trap);
  276. }
  277. /* Memorize */
  278. cave_on(cave_info[y][x], CAVE_MARK);
  279. /* Redraw */
  280. light_spot(y, x);
  281. }
  282. /* Return TRUE if we found any traps */
  283. return (found_trap != 0);
  284. }
  285. /**
  286. * Count the number of player traps in this location.
  287. *
  288. * Called with vis = 0 to accept any trap, = 1 to accept only visible
  289. * traps, and = -1 to accept only invisible traps.
  290. */
  291. int num_traps(int y, int x, int vis)
  292. {
  293. int i, num;
  294. /* Scan the current trap list */
  295. for (num = 0, i = 0; i < trap_max; i++) {
  296. /* Point to this trap */
  297. trap_type *t_ptr = &trap_list[i];
  298. /* Find all traps in this position */
  299. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  300. /* Require that trap be capable of affecting the character */
  301. if (!trf_has(t_ptr->kind->flags, TRF_TRAP))
  302. continue;
  303. /* Require correct visibility */
  304. if (vis >= 1) {
  305. if (trf_has(t_ptr->flags, TRF_VISIBLE))
  306. num++;
  307. } else if (vis <= -1) {
  308. if (!trf_has(t_ptr->flags, TRF_VISIBLE))
  309. num++;
  310. } else {
  311. num++;
  312. }
  313. }
  314. }
  315. /* Return the number of traps */
  316. return (num);
  317. }
  318. /**
  319. * Hack -- instantiate a trap
  320. *
  321. * This function has been altered in Oangband to (in a hard-coded fashion)
  322. * control trap level. -LM-
  323. */
  324. static int pick_trap(int feat, int trap_level)
  325. {
  326. int trap = 0;
  327. feature_type *f_ptr = &f_info[feat];
  328. trap_kind *trap_ptr;
  329. bool trap_is_okay = FALSE;
  330. /* Paranoia */
  331. if (!tf_has(f_ptr->flags, TF_TRAP))
  332. return -1;
  333. /* Try to create a trap appropriate to the level. Make certain that at
  334. * least one trap type can be made on any possible level. -LM- */
  335. while (!trap_is_okay) {
  336. /* Pick at random. */
  337. trap = TRAP_HEAD + randint0(TRAP_TAIL - TRAP_HEAD + 1);
  338. /* Get this trap */
  339. trap_ptr = &trap_info[trap];
  340. /* Require that trap_level not be too low */
  341. if (trap_ptr->min_depth > trap_level)
  342. continue;
  343. /* Assume legal until proven otherwise. */
  344. trap_is_okay = TRUE;
  345. /* Tree? */
  346. if (tf_has(f_ptr->flags, TF_TREE) &&
  347. !trf_has(trap_ptr->flags, TRF_TREE))
  348. trap_is_okay = FALSE;
  349. /* Floor? */
  350. if (tf_has(f_ptr->flags, TF_FLOOR) &&
  351. !trf_has(trap_ptr->flags, TRF_FLOOR))
  352. trap_is_okay = FALSE;
  353. /* Check legality. */
  354. switch (trap) {
  355. /* trap doors */
  356. case TRAP_TRAPDOOR:
  357. {
  358. /* Hack -- no trap doors on quest levels */
  359. if (is_quest(p_ptr->stage))
  360. trap_is_okay = FALSE;
  361. /* Hack -- no trap doors at the bottom of dungeons */
  362. if (chunk_list[p_ptr->stage].z_pos == 127)
  363. trap_is_okay = FALSE;
  364. /* Trap doors only in dungeons for now */
  365. if (chunk_list[p_ptr->stage].z_pos == 0)
  366. trap_is_okay = FALSE;
  367. break;
  368. }
  369. case TRAP_PIT:
  370. case TRAP_DART:
  371. case TRAP_SPOT:
  372. case TRAP_GAS:
  373. case TRAP_SUMMON:
  374. case TRAP_ALTER:
  375. case TRAP_HEX:
  376. case TRAP_PORTAL:
  377. case TRAP_MURDER:
  378. case TRAP_BRANCH:
  379. {
  380. /* No special restrictions */
  381. break;
  382. }
  383. /* Any other selection is not defined. */
  384. default:
  385. {
  386. trap_is_okay = FALSE;
  387. break;
  388. }
  389. }
  390. }
  391. /* Return our chosen trap */
  392. return (trap);
  393. }
  394. /**
  395. * Determine if a cave grid is allowed to have traps in it.
  396. */
  397. bool cave_trap_allowed(int y, int x)
  398. {
  399. /*
  400. * We currently forbid multiple traps in a grid under normal conditions.
  401. * If this changes, various bits of code elsewhere will have to change too.
  402. */
  403. if (cave_has(cave_info[y][x], CAVE_TRAP))
  404. return (FALSE);
  405. /* Check the feature trap flag */
  406. return (tf_has(f_info[cave_feat[y][x]].flags, TF_TRAP));
  407. }
  408. /**
  409. * Make a new trap of the given type. Return TRUE if successful.
  410. *
  411. * We choose a trap at random if the index is not legal.
  412. *
  413. * This should be the only function that places traps in the dungeon
  414. * except the savefile loading code.
  415. */
  416. bool place_trap(int y, int x, int t_idx, int trap_level)
  417. {
  418. int i;
  419. /* Require the correct terrain */
  420. if (!cave_trap_allowed(y, x))
  421. return (FALSE);
  422. /* Hack -- don't use up all the trap slots during dungeon generation */
  423. if (!character_dungeon) {
  424. if (trap_max > z_info->t_max - 50)
  425. return (FALSE);
  426. }
  427. /* We've been called with an illegal index; choose a random trap */
  428. if ((t_idx <= 0) || (t_idx >= z_info->trap_max)) {
  429. t_idx = pick_trap(cave_feat[y][x], trap_level);
  430. }
  431. /* Note failure */
  432. if (t_idx < 0)
  433. return (FALSE);
  434. /* Scan the entire trap list */
  435. for (i = 1; i < z_info->t_max; i++) {
  436. /* Point to this trap */
  437. trap_type *t_ptr = &trap_list[i];
  438. /* This space is available */
  439. if (!t_ptr->t_idx) {
  440. /* Fill in the trap index */
  441. t_ptr->t_idx = t_idx;
  442. t_ptr->kind = &trap_info[t_idx];
  443. /* Fill in the trap details */
  444. t_ptr->fy = y;
  445. t_ptr->fx = x;
  446. trf_copy(t_ptr->flags, trap_info[t_ptr->t_idx].flags);
  447. /* Adjust trap count if necessary */
  448. if (i + 1 > trap_max)
  449. trap_max = i + 1;
  450. /* We created a rune */
  451. if (trf_has(t_ptr->flags, TRF_RUNE))
  452. num_runes_on_level[t_idx - 1]++;
  453. /* We created a monster trap */
  454. if (trf_has(t_ptr->flags, TRF_M_TRAP))
  455. num_trap_on_level++;
  456. /* Toggle on the trap marker */
  457. cave_on(cave_info[y][x], CAVE_TRAP);
  458. /* Redraw the grid */
  459. light_spot(y, x);
  460. /* Report success */
  461. return (TRUE);
  462. }
  463. }
  464. /* No luck -- report failure */
  465. return (FALSE);
  466. }
  467. /**
  468. * Determine if a trap affects the player.
  469. * Always miss 5% of the time, Always hit 5% of the time.
  470. * Otherwise, match trap power against player armor.
  471. */
  472. static int check_trap_hit(int power)
  473. {
  474. int k, ac;
  475. bool hit = FALSE;
  476. /* This function is called from the trap attack code, which generally uses
  477. * the simple RNG. We temporarily switch over to the complex RNG for true
  478. * randomness. - LM- */
  479. Rand_quick = FALSE;
  480. /* Percentile dice */
  481. k = randint0(100);
  482. /* 5% minimum chance to hit, 5% minimum chance to miss */
  483. if (k < 10)
  484. hit = (k < 5);
  485. /* Total armor */
  486. ac = p_ptr->state.ac + p_ptr->state.to_a;
  487. /* Power competes against Armor */
  488. if ((power > 0) && (randint1(power) >= (ac * 3 / 4)))
  489. hit = TRUE;
  490. /* Resume use of the simple RNG. */
  491. Rand_quick = TRUE;
  492. /* Return hit or miss. */
  493. return (hit);
  494. }
  495. /**
  496. * Handle player hitting a real trap. Rewritten in Oangband to allow a
  497. * greater variety of traps, with effects controlled by dungeon level.
  498. * To allow a trap to choose one of a variety of effects consistantly,
  499. * the quick RNG is often used, and xy coordinates input as a seed value.
  500. */
  501. void hit_trap_aux(int y, int x, int trap)
  502. {
  503. int i, j, k, num;
  504. int dam = 0;
  505. int nastyness, selection;
  506. trap_type *t_ptr = &trap_list[trap];
  507. const char *name = t_ptr->kind->name;
  508. /* Use the "simple" RNG to insure that traps are consistant. */
  509. Rand_quick = TRUE;
  510. /* Use the coordinates of the trap to seed the RNG. */
  511. Rand_value = y * x;
  512. /* Disturb the player */
  513. disturb(0, 0);
  514. /* Analyze XXX XXX XXX */
  515. switch (t_ptr->t_idx) {
  516. /* trap door. */
  517. case TRAP_TRAPDOOR:
  518. {
  519. Rand_quick = FALSE;
  520. msg("You fall through a trap door!");
  521. if (p_ptr->state.ffall) {
  522. notice_obj(OF_FEATHER, 0);
  523. msg("You float gently down to the next level.");
  524. } else {
  525. dam = damroll(2, 8);
  526. take_hit(dam, name);
  527. }
  528. chunk_change(1, 0, 0);
  529. Rand_quick = TRUE;
  530. break;
  531. }
  532. /* pits. */
  533. case TRAP_PIT:
  534. {
  535. /* determine how dangerous the trap is allowed to be. */
  536. nastyness = randint1(p_ptr->danger);
  537. if (randint1(20) == 1)
  538. nastyness += 20;
  539. else if (randint1(5) == 1)
  540. nastyness += 10;
  541. /* Player is now in pit. */
  542. monster_swap(p_ptr->py, p_ptr->px, y, x);
  543. /* Center on player. */
  544. y = p_ptr->py;
  545. x = p_ptr->px;
  546. /* pit of daggers. */
  547. if ((nastyness > 80) && (randint1(3) != 3)) {
  548. msg("You fall into a pit of daggers!");
  549. if (p_ptr->state.ffall) {
  550. notice_obj(OF_FEATHER, 0);
  551. msg("You float gently to the floor of the pit.");
  552. msg("You carefully avoid setting off the daggers.");
  553. }
  554. else {
  555. /* a trap of morgul. */
  556. if (randint1(6) == 1) {
  557. Rand_quick = FALSE;
  558. msg("A single coldly gleaming dagger pierces you deeply!");
  559. msg("You feel a deadly chill slowly withering your soul.");
  560. /* activate the Black Breath. */
  561. p_ptr->black_breath = TRUE;
  562. /* lots of damage. */
  563. dam = damroll(20, 15);
  564. /* undead may be attracted. */
  565. if (randint1(2) == 1) {
  566. msg("Undead suddenly appear and call you to them!");
  567. k = randint1(3) + 2;
  568. for (i = 0; i < k; i++) {
  569. summon_specific(y, x, FALSE, p_ptr->danger,
  570. SUMMON_UNDEAD);
  571. }
  572. }
  573. /* morgul-traps are one-time only. */
  574. remove_trap(y, x, FALSE, trap);
  575. Rand_quick = TRUE;
  576. }
  577. else {
  578. Rand_quick = FALSE;
  579. /* activate the ordinary daggers. */
  580. msg("Daggers pierce you everywhere!");
  581. k = randint1(10) + 5;
  582. for (i = 0; i < k; i++) {
  583. dam += damroll(3, 4);
  584. }
  585. Rand_quick = TRUE;
  586. }
  587. /* cut the player. */
  588. (void) inc_timed(TMD_CUT, randint1(dam), TRUE);
  589. /* Take the damage. */
  590. take_hit(dam, name);
  591. }
  592. }
  593. /* poisoned spiked pit. */
  594. else if ((nastyness > 55) && (randint1(3) != 3)) {
  595. msg("You fall into a spiked pit!");
  596. if (p_ptr->state.ffall) {
  597. notice_obj(OF_FEATHER, 0);
  598. msg("You float gently to the floor of the pit.");
  599. msg("You carefully avoid touching the spikes.");
  600. }
  601. else {
  602. Rand_quick = FALSE;
  603. /* Base damage */
  604. dam = damroll(2, 6);
  605. /* Extra spike damage */
  606. if (randint0(100) < 85) {
  607. bool was_poisoned;
  608. msg("You are impaled on poisonous spikes!");
  609. dam = dam * (randint1(6) + 3);
  610. (void) inc_timed(TMD_CUT, randint1(dam), TRUE);
  611. was_poisoned = pois_hit(dam);
  612. if (!was_poisoned)
  613. msg("The poison does not affect you!");
  614. }
  615. /* Take the damage */
  616. take_hit(dam, name);
  617. Rand_quick = TRUE;
  618. }
  619. }
  620. /* spiked pit. */
  621. else if ((nastyness > 30) && (randint1(3) != 3)) {
  622. msg("You fall into a spiked pit!");
  623. if (p_ptr->state.ffall) {
  624. notice_obj(OF_FEATHER, 0);
  625. msg("You float gently to the floor of the pit.");
  626. msg("You carefully avoid touching the spikes.");
  627. }
  628. else {
  629. Rand_quick = FALSE;
  630. /* Base damage */
  631. dam = damroll(2, 6);
  632. /* Extra spike damage */
  633. if (randint0(100) < 85) {
  634. msg("You are impaled!");
  635. dam = dam * (2 + randint1(4));
  636. (void) inc_timed(TMD_CUT, randint1(dam), TRUE);
  637. }
  638. /* Take the damage */
  639. take_hit(dam, name);
  640. Rand_quick = TRUE;
  641. }
  642. }
  643. /* ordinary pit in all other cases. */
  644. else {
  645. msg("You fall into a pit!");
  646. if (p_ptr->state.ffall) {
  647. notice_obj(OF_FEATHER, 0);
  648. msg("You float gently to the bottom of the pit.");
  649. } else {
  650. Rand_quick = FALSE;
  651. dam = damroll(2, 6);
  652. take_hit(dam, name);
  653. Rand_quick = TRUE;
  654. }
  655. }
  656. /* Change to pit terrain */
  657. remove_trap(y, x, FALSE, trap);
  658. cave_set_feat(y, x, FEAT_PIT);
  659. break;
  660. }
  661. /* stat-reducing dart traps. */
  662. case TRAP_DART:
  663. {
  664. /* decide if the dart hits. */
  665. if (check_trap_hit(50 + p_ptr->danger)) {
  666. /* select a stat to drain. */
  667. selection = randint0(6);
  668. Rand_quick = FALSE;
  669. msg("A small dart hits you!");
  670. dam = damroll(1, 4);
  671. take_hit(dam, name);
  672. /* Determine how dangerous the trap is allowed to be. */
  673. nastyness = randint1(p_ptr->danger);
  674. /* decide how much to drain the stat by. */
  675. if ((nastyness > 50) && (randint1(3) == 1)) {
  676. num = randint1(4);
  677. } else
  678. num = 1;
  679. /* drain the stat. */
  680. for (i = 0; i < num; i++) {
  681. (void) do_dec_stat(selection);
  682. }
  683. Rand_quick = TRUE;
  684. } else {
  685. msg("A small dart barely misses you.");
  686. }
  687. break;
  688. }
  689. /* discolored spots. */
  690. case TRAP_SPOT:
  691. {
  692. /* determine how dangerous the trap is allowed to be. */
  693. nastyness = randint1(p_ptr->danger);
  694. if (randint1(5) == 1)
  695. nastyness += 10;
  696. /* pick a elemental attack type. */
  697. selection = randint1(4);
  698. /* electicity trap. */
  699. if (selection == 1) {
  700. if ((nastyness >= 50) && (randint1(2) == 1)) {
  701. Rand_quick = FALSE;
  702. msg("You are struck by lightning!");
  703. dam = damroll(6, 30);
  704. Rand_quick = TRUE;
  705. } else {
  706. Rand_quick = FALSE;
  707. msg("You get zapped!");
  708. dam = damroll(4, 8);
  709. Rand_quick = TRUE;
  710. }
  711. Rand_quick = FALSE;
  712. elec_dam(dam, "an electricity trap");
  713. Rand_quick = TRUE;
  714. }
  715. /* frost trap. */
  716. if (selection == 2) {
  717. if ((nastyness >= 50) && (randint1(2) == 1)) {
  718. Rand_quick = FALSE;
  719. msg("You are lost within a blizzard!");
  720. dam = damroll(6, 30);
  721. Rand_quick = TRUE;
  722. } else {
  723. Rand_quick = FALSE;
  724. msg("You are coated in frost!");
  725. dam = damroll(4, 8);
  726. Rand_quick = TRUE;
  727. }
  728. Rand_quick = FALSE;
  729. cold_dam(dam, "a frost trap");
  730. Rand_quick = TRUE;
  731. }
  732. /* fire trap. */
  733. if (selection == 3) {
  734. if ((nastyness >= 50) && (randint1(2) == 1)) {
  735. Rand_quick = FALSE;
  736. msg("You are enveloped in a column of fire!");
  737. dam = damroll(6, 30);
  738. Rand_quick = TRUE;
  739. } else {
  740. Rand_quick = FALSE;
  741. msg("You are surrounded by flames!");
  742. dam = damroll(4, 8);
  743. Rand_quick = TRUE;
  744. }
  745. Rand_quick = FALSE;
  746. fire_dam(dam, "a fire trap");
  747. Rand_quick = TRUE;
  748. }
  749. /* acid trap. */
  750. if (selection == 4) {
  751. if ((nastyness >= 50) && (randint1(2) == 1)) {
  752. Rand_quick = FALSE;
  753. msg("A cauldron of acid is tipped over your head!");
  754. dam = damroll(6, 30);
  755. Rand_quick = TRUE;
  756. } else {
  757. Rand_quick = FALSE;
  758. msg("You are splashed with acid!");
  759. dam = damroll(4, 8);
  760. Rand_quick = TRUE;
  761. }
  762. Rand_quick = FALSE;
  763. acid_dam(dam, "an acid trap");
  764. Rand_quick = TRUE;
  765. }
  766. break;
  767. }
  768. /* gas traps. */
  769. case TRAP_GAS:
  770. {
  771. selection = randint1(4);
  772. /* blinding trap. */
  773. if (selection == 1) {
  774. msg("You are surrounded by a black gas!");
  775. if (!p_ptr->state.no_blind) {
  776. Rand_quick = FALSE;
  777. (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE);
  778. Rand_quick = TRUE;
  779. }
  780. } else
  781. notice_obj(OF_SEEING, 0);
  782. /* confusing trap. */
  783. if (selection == 2) {
  784. msg("You are surrounded by a gas of scintillating colors!");
  785. if (!p_resist_good(P_RES_CONFU)) {
  786. Rand_quick = FALSE;
  787. (void) inc_timed(TMD_CONFUSED, randint0(20) + 10,
  788. TRUE);
  789. Rand_quick = TRUE;
  790. } else
  791. notice_other(IF_RES_CONFU, 0);
  792. }
  793. /* poisoning trap. */
  794. if (selection == 3) {
  795. msg("You are surrounded by a pungent green gas!");
  796. Rand_quick = FALSE;
  797. pois_hit(25);
  798. Rand_quick = TRUE;
  799. }
  800. /* sleeping trap. */
  801. if (selection == 4) {
  802. msg("You are surrounded by a strange white mist!");
  803. if (!p_ptr->state.free_act) {
  804. (void) inc_timed(TMD_PARALYZED, randint0(10) + 5,
  805. TRUE);
  806. } else
  807. notice_obj(OF_FREE_ACT, 0);
  808. }
  809. break;
  810. }
  811. /* summoning traps. */
  812. case TRAP_SUMMON:
  813. {
  814. sound(MSG_SUM_MONSTER);
  815. /* sometimes summon thieves. */
  816. if ((p_ptr->danger > 8) && (randint1(5) == 1)) {
  817. msg("You have aroused a den of thieves!");
  818. Rand_quick = FALSE;
  819. num = 2 + randint1(3);
  820. for (i = 0; i < num; i++) {
  821. (void) summon_specific(y, x, FALSE, p_ptr->danger,
  822. SUMMON_THIEF);
  823. }
  824. Rand_quick = TRUE;
  825. }
  826. /* sometimes summon a nasty unique. */
  827. else if (randint1(8) == 1) {
  828. msg("You are enveloped in a cloud of smoke!");
  829. Rand_quick = FALSE;
  830. (void) summon_specific(y, x, FALSE, p_ptr->danger + 5,
  831. SUMMON_UNIQUE);
  832. Rand_quick = TRUE;
  833. }
  834. /* otherwise, the ordinary summon monsters. */
  835. else {
  836. msg("You are enveloped in a cloud of smoke!");
  837. Rand_quick = FALSE;
  838. num = 2 + randint1(3);
  839. for (i = 0; i < num; i++) {
  840. (void) summon_specific(y, x, FALSE, p_ptr->danger, 0);
  841. }
  842. Rand_quick = TRUE;
  843. }
  844. /* these are all one-time traps. */
  845. remove_trap(y, x, FALSE, trap);
  846. break;
  847. }
  848. /* dungeon alteration traps. */
  849. case TRAP_ALTER:
  850. {
  851. /* determine how dangerous the trap is allowed to be. */
  852. nastyness = randint1(p_ptr->danger);
  853. if (randint1(5) == 1)
  854. nastyness += 10;
  855. /* make room for alterations. */
  856. remove_trap(y, x, FALSE, trap);
  857. /* Everything truely random from here on. */
  858. Rand_quick = FALSE;
  859. /* dungeon destruction trap. */
  860. if ((nastyness > 60) && (randint1(12) == 1)) {
  861. msg("A ear-splitting howl shatters your mind as the dungeon is smashed by hammer blows!");
  862. (void) destroy_level(FALSE);
  863. /* the player is hard-hit. */
  864. (void) inc_timed(TMD_CONFUSED, randint0(20) + 10, TRUE);
  865. (void) inc_timed(TMD_BLIND, randint0(30) + 15, TRUE);
  866. (void) inc_timed(TMD_STUN, randint1(50) + 50, TRUE);
  867. dam = damroll(15, 15);
  868. take_hit(dam, name);
  869. }
  870. /* earthquake trap. */
  871. else if ((nastyness > 20) && (randint1(4) == 1)) {
  872. msg("A tremor shakes the earth around you");
  873. earthquake(y, x, 10, FALSE);
  874. }
  875. /* falling rock trap. */
  876. else if ((nastyness > 4) && (randint1(2) == 1)) {
  877. msg("A rock falls on your head.");
  878. dam = damroll(2, 10);
  879. take_hit(dam, name);
  880. (void) inc_timed(TMD_STUN, randint1(10) + 10, TRUE);
  881. }
  882. /* a few pebbles. */
  883. else {
  884. msg("A bunch of pebbles rain down on you.");
  885. dam = damroll(1, 8);
  886. take_hit(dam, name);
  887. }
  888. Rand_quick = TRUE;
  889. break;
  890. }
  891. /* various char and equipment-alteration traps, lumped together to
  892. * avoid any one effect being too common (some of them can be rather
  893. * nasty). */
  894. case TRAP_HEX:
  895. {
  896. /* determine how dangerous the trap is allowed to be. */
  897. nastyness = randint0(100);
  898. /* these are all one-time traps. */
  899. remove_trap(y, x, FALSE, trap);
  900. /* Everything truely random from here on. */
  901. Rand_quick = FALSE;
  902. /* trap of drain wands. */
  903. if (nastyness < 15) {
  904. /* Hold the object information. */
  905. object_type *o_ptr;
  906. /* Find an item */
  907. for (i = 0; i < 20; i++) {
  908. /* Pick an item */
  909. i = randint0(INVEN_PACK - p_ptr->pack_size_reduce);
  910. /* Obtain the item */
  911. o_ptr = &p_ptr->inventory[i];
  912. /* use "num" to decide if a item can be uncharged. By
  913. * default, assume it can't. */
  914. num = 0;
  915. /* Skip non-objects */
  916. if (!o_ptr->k_idx)
  917. continue;
  918. /* Drain charged wands/staffs/rods */
  919. if ((o_ptr->tval == TV_STAFF)
  920. || (o_ptr->tval == TV_WAND)
  921. || (o_ptr->tval == TV_ROD)) {
  922. /* case of charged wands/staffs. */
  923. if (((o_ptr->tval == TV_STAFF)
  924. || (o_ptr->tval == TV_WAND)) && (o_ptr->pval))
  925. num = 1;
  926. /* case of charged rods. */
  927. if ((o_ptr->tval == TV_ROD)
  928. && (o_ptr->timeout < randcalc(o_ptr->time, 0,
  929. MINIMISE)))
  930. num = 1;
  931. if (num == 1) {
  932. /* Message */
  933. msg("Energy drains from your pack!");
  934. /* Uncharge */
  935. if ((o_ptr->tval == TV_STAFF)
  936. || (o_ptr->tval == TV_WAND))
  937. o_ptr->pval = 0;
  938. if (o_ptr->tval == TV_ROD)
  939. o_ptr->timeout =
  940. randcalc(o_ptr->time, 0,
  941. RANDOMISE) * o_ptr->number *
  942. 2;
  943. /* Combine / Reorder the pack */
  944. p_ptr->notice |= (PN_COMBINE | PN_REORDER);
  945. /* not more than one inventory slot effected. */
  946. break;
  947. } else
  948. continue;
  949. }
  950. }
  951. }
  952. /* trap of forgetting. */
  953. else if (nastyness < 35) {
  954. if (check_save(100)) {
  955. msg("You hang on to your memories!");
  956. } else if (lose_all_info()) {
  957. msg("Your memories fade away.");
  958. }
  959. }
  960. /* trap of alter reality. */
  961. //else if (nastyness < 50)
  962. //{
  963. //msg("The world changes!");
  964. /* Leaving */
  965. // p_ptr->leaving = TRUE;
  966. //}
  967. /* trap of remold player. */
  968. else if (nastyness < 75) {
  969. int max1, cur1, max2, cur2, ii, jj;
  970. msg("You feel yourself being twisted by wild magic!");
  971. if (check_save(100)) {
  972. msg("You resist the effects!");
  973. } else {
  974. msg("Your body starts to scramble...");
  975. /* Pick a pair of stats */
  976. ii = randint0(6);
  977. for (jj = ii; jj == ii; jj = randint0(6)) /* loop */
  978. ;
  979. max1 = p_ptr->stat_max[ii];
  980. cur1 = p_ptr->stat_cur[ii];
  981. max2 = p_ptr->stat_max[jj];
  982. cur2 = p_ptr->stat_cur[jj];
  983. p_ptr->stat_max[ii] = max2;
  984. p_ptr->stat_cur[ii] = cur2;
  985. p_ptr->stat_max[jj] = max1;
  986. p_ptr->stat_cur[jj] = cur1;
  987. p_ptr->update |= (PU_BONUS);
  988. }
  989. }
  990. /* time ball trap. */
  991. else if (nastyness < 90) {
  992. msg("You feel time itself assault you!");
  993. /* Target the player with a radius 0 ball attack. */
  994. fire_meteor(0, GF_TIME, p_ptr->py, p_ptr->px, 75, 0, TRUE);
  995. }
  996. /* trap of bugs gone berserk. */
  997. else {
  998. /* explain what the dickens is going on. */
  999. msg("GRUESOME Gnawing Bugs leap out at you!");
  1000. if (!p_resist_good(P_RES_CONFU)) {
  1001. (void) inc_timed(TMD_CONFUSED, randint0(20) + 10,
  1002. TRUE);
  1003. } else
  1004. notice_other(IF_RES_CONFU, 0);
  1005. if (!p_resist_good(P_RES_CHAOS)) {
  1006. (void) inc_timed(TMD_IMAGE, randint1(40), TRUE);
  1007. } else
  1008. notice_other(IF_RES_CHAOS, 0);
  1009. /* XXX (hard coded) summon 3-6 bugs. */
  1010. k = randint1(4) + 2;
  1011. for (i = 0; i < k; ++i) {
  1012. /* Look for a location */
  1013. for (j = 0; j < 20; ++j) {
  1014. feature_type *f_ptr;
  1015. /* Pick a (scattered) distance. */
  1016. int d = (j / 10) + randint1(3);
  1017. /* Pick a location */
  1018. scatter(&y, &x, y, x, d, 0);
  1019. /* Require passable terrain */
  1020. f_ptr = &f_info[cave_feat[y][x]];
  1021. if (!tf_has(f_ptr->flags, TF_PASSABLE))
  1022. continue;
  1023. /* Hack -- no summon on glyph of warding */
  1024. if (cave_trap_specific(y, x, RUNE_PROTECT))
  1025. continue;
  1026. /* Okay */
  1027. break;
  1028. }
  1029. /* Attempt to place the awake bug */
  1030. place_monster_aux(y, x, 453, FALSE, TRUE);
  1031. }
  1032. /* herald the arrival of bugs. */
  1033. msg("AAAAAAAHHHH! THEY'RE EVERYWHERE!");
  1034. }
  1035. Rand_quick = TRUE;
  1036. break;
  1037. }
  1038. /* teleport trap */
  1039. case TRAP_PORTAL:
  1040. {
  1041. if (chunk_list[p_ptr->stage].z_pos != 0)
  1042. msg("You teleport across the dungeon.");
  1043. else
  1044. msg("You teleport across the wilderness.");
  1045. Rand_quick = FALSE;
  1046. teleport_player(250, FALSE);
  1047. Rand_quick = TRUE;
  1048. break;
  1049. }
  1050. /* murder holes. */
  1051. case TRAP_MURDER:
  1052. {
  1053. /* hold the object info. */
  1054. object_type *o_ptr;
  1055. object_type object_type_body;
  1056. /* hold the missile type and name. */
  1057. int sval = 0;
  1058. int tval = 0;
  1059. const char *missile_name = "";
  1060. /* Determine the missile type and base damage. */
  1061. if (randint1(3) == 1) {
  1062. if (p_ptr->danger < 40) {
  1063. missile_name = "shot";
  1064. dam = damroll(2, 3);
  1065. tval = TV_SHOT;
  1066. sval = SV_AMMO_NORMAL;
  1067. } else {
  1068. missile_name = "seeker shot";
  1069. dam = damroll(3, 7);
  1070. tval = TV_SHOT;
  1071. sval = SV_AMMO_HEAVY;
  1072. }
  1073. }
  1074. else if (randint1(2) == 1) {
  1075. if (p_ptr->danger < 55) {
  1076. missile_name = "arrow";
  1077. dam = damroll(2, 4);
  1078. tval = TV_ARROW;
  1079. sval = SV_AMMO_NORMAL;
  1080. } else {
  1081. missile_name = "seeker arrow";
  1082. dam = damroll(3, 9);
  1083. tval = TV_ARROW;
  1084. sval = SV_AMMO_HEAVY;
  1085. }
  1086. }
  1087. else {
  1088. if (p_ptr->danger < 65) {
  1089. missile_name = "bolt";
  1090. dam = damroll(2, 5);
  1091. tval = TV_BOLT;
  1092. sval = SV_AMMO_NORMAL;
  1093. } else {
  1094. missile_name = "seeker bolt";
  1095. dam = damroll(3, 11);
  1096. tval = TV_BOLT;
  1097. sval = SV_AMMO_HEAVY;
  1098. }
  1099. }
  1100. /* determine if the missile hits. */
  1101. if (check_trap_hit(75 + p_ptr->danger)) {
  1102. msg("A %s hits you from above.", missile_name);
  1103. Rand_quick = FALSE;
  1104. /* critical hits. */
  1105. if (randint1(2) == 1) {
  1106. msg("It was well-aimed!");
  1107. dam *= 1 + randint1(2);
  1108. }
  1109. if (randint1(2) == 1) {
  1110. msg("It gouges you!");
  1111. dam = 3 * dam / 2;
  1112. /* cut the player. */
  1113. (void) inc_timed(TMD_CUT, randint1(dam), TRUE);
  1114. }
  1115. Rand_quick = TRUE;
  1116. take_hit(dam, name);
  1117. }
  1118. /* Explain what just happened. */
  1119. else
  1120. msg("A %s wizzes by your head.", missile_name);
  1121. /* these will eventually run out of ammo. */
  1122. Rand_quick = FALSE;
  1123. if (randint0(8) == 0)
  1124. remove_trap(y, x, FALSE, trap);
  1125. Rand_quick = TRUE;
  1126. /* Get local object */
  1127. o_ptr = &object_type_body;
  1128. /* Make a missile, identify it, and drop it near the player. */
  1129. object_prep(o_ptr, lookup_kind(tval, sval), MINIMISE);
  1130. object_aware(o_ptr);
  1131. object_known(o_ptr);
  1132. drop_near(o_ptr, -1, y, x, TRUE);
  1133. break;
  1134. }
  1135. /* falling tree branch */
  1136. case TRAP_BRANCH:
  1137. {
  1138. /* determine if the missile hits. */
  1139. if (check_trap_hit(75 + p_ptr->danger)) {
  1140. /* Take damage */
  1141. dam = damroll(3, 5);
  1142. msg("A branch hits you from above.");
  1143. Rand_quick = FALSE;
  1144. /* critical hits. */
  1145. if (randint1(2) == 1) {
  1146. msg("It was heavy!");
  1147. dam = 3 * dam / 2;
  1148. /* stun the player. */
  1149. (void) inc_timed(TMD_STUN, randint1(dam), TRUE);
  1150. }
  1151. Rand_quick = TRUE;
  1152. take_hit(dam, name);
  1153. }
  1154. /* Explain what just happened. */
  1155. else
  1156. msg("A falling branch just misses you.");
  1157. /* No more */
  1158. remove_trap(y, x, FALSE, trap);
  1159. break;
  1160. }
  1161. }
  1162. /* Revert to usage of the complex RNG. */
  1163. Rand_quick = FALSE;
  1164. }
  1165. /**
  1166. * Hit a trap.
  1167. */
  1168. extern void hit_trap(int y, int x)
  1169. {
  1170. int i;
  1171. /* Count the hidden traps here */
  1172. int num = num_traps(y, x, -1);
  1173. /* Oops. We've walked right into trouble. */
  1174. if (num == 1)
  1175. msg("You stumble upon a trap!");
  1176. else if (num > 1)
  1177. msg("You stumble upon some traps!");
  1178. /* Scan the current trap list */
  1179. for (i = 0; i < trap_max; i++) {
  1180. /* Point to this trap */
  1181. trap_type *t_ptr = &trap_list[i];
  1182. /* Find all traps in this position */
  1183. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  1184. /* Fire off the trap */
  1185. hit_trap_aux(y, x, i);
  1186. /* Trap becomes visible (always XXX) */
  1187. trf_on(t_ptr->flags, TRF_VISIBLE);
  1188. cave_on(cave_info[y][x], CAVE_MARK);
  1189. }
  1190. }
  1191. /* Verify traps (remove marker if appropriate) */
  1192. (void) verify_trap(y, x, 0);
  1193. }
  1194. /**
  1195. * Hack -- possible victim outcry. -LM-
  1196. */
  1197. static const char *desc_victim_outcry[] = {
  1198. "'My money, where's my money?'",
  1199. "'Thief! Thief! Thief! Baggins! We hates it forever!'",
  1200. "'Tell me, have you seen a purse wandering around?'",
  1201. "'Thieves, Fire, Murder!'",
  1202. "''Ere, 'oo are you?'",
  1203. "'Hey, look what I've copped!'",
  1204. "'How dare you!'",
  1205. "'Help yourself again, thief, there is plenty and to spare!'",
  1206. "'All the world detests a thief.'",
  1207. "'Catch me this thief!'",
  1208. "'Hi! Ho! Robbery!'",
  1209. "'My gold, my precious gold!'",
  1210. "'My gold is costly, thief!'",
  1211. "'Your blood for my gold? Agreed!'",
  1212. "'I scrimp, I save, and now it's gone!'",
  1213. "'Robbers like you are part of the problem!'",
  1214. "'Banditti! This place is just not safe anymore!'",
  1215. "'Ruined! I'm ruined!'",
  1216. "'Where, where is the common decency?'",
  1217. "'Your knavish tricks end here and now!'",
  1218. };
  1219. /**
  1220. * Rogues may steal gold from monsters. The monster needs to have
  1221. * something to steal (it must drop some form of loot), and should
  1222. * preferably be asleep. Humanoids and dragons are a rogue's favorite
  1223. * targets. Steal too often on a level, and monsters will be more wary,
  1224. * and the hue and cry will be eventually be raised. Having every
  1225. * monster on the level awake and aggravated is not pleasant. -LM-
  1226. */
  1227. extern void py_steal(int y, int x)
  1228. {
  1229. const char *act = NULL;
  1230. monster_type *m_ptr = &m_list[cave_m_idx[y][x]];
  1231. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  1232. char m_name[80];
  1233. int i;
  1234. int effect, theft_protection;
  1235. int filching_power = 0;
  1236. int purse = 0;
  1237. bool thief = FALSE;
  1238. bool success = FALSE;
  1239. /* Check intent */
  1240. if ((m_ptr->hostile != -1)
  1241. && !get_check("Do you want to steal from this being?")) {
  1242. py_attack(y, x, FALSE);
  1243. return;
  1244. }
  1245. /* Hard limit on theft. */
  1246. if (number_of_thefts_on_level > 4) {
  1247. msg("Everyone is keeping a lookout for you. You can steal nothing here.");
  1248. return;
  1249. }
  1250. /* Determine the cunning of the thief. */
  1251. filching_power = 2 * p_ptr->lev;
  1252. /* Penalize some conditions */
  1253. if (p_ptr->timed[TMD_BLIND] || no_light())
  1254. filching_power = filching_power / 10;
  1255. if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE])
  1256. filching_power = filching_power / 10;
  1257. /* Determine how much protection the monster has. */
  1258. theft_protection = (7 * (r_ptr->level + 2) / 4);
  1259. theft_protection += (m_ptr->mspeed - p_ptr->state.pspeed);
  1260. if (theft_protection < 1)
  1261. theft_protection = 1;
  1262. /* Send a thief to catch a thief. */
  1263. for (i = 0; i < 4; i++) {
  1264. /* Extract infomation about the blow effect */
  1265. effect = r_ptr->blow[i].effect;
  1266. if (effect == RBE_EAT_GOLD)
  1267. thief = TRUE;
  1268. if (effect == RBE_EAT_ITEM)
  1269. thief = TRUE;
  1270. }
  1271. if (thief)
  1272. theft_protection += 30;
  1273. if (m_ptr->csleep)
  1274. theft_protection = 3 * theft_protection / 5;
  1275. /* Special player stealth magics aid stealing, but are lost in the process */
  1276. if (p_ptr->timed[TMD_SSTEALTH]) {
  1277. theft_protection = 3 * theft_protection / 5;
  1278. (void) clear_timed(TMD_SSTEALTH, TRUE);
  1279. }
  1280. /* The more you steal on a level, the more wary the monsters. */
  1281. theft_protection += number_of_thefts_on_level * 15;
  1282. /* Did the theft succeed? */
  1283. if (randint1(theft_protection) < filching_power)
  1284. success = TRUE;
  1285. /* If the theft succeeded, determine the value of the purse. */
  1286. if (success) {
  1287. purse = (r_ptr->level + 1) + randint1(3 * (r_ptr->level + 1) / 2);
  1288. /* Uniques are juicy targets. */
  1289. if (rf_has(r_ptr->flags, RF_UNIQUE))
  1290. purse *= 3;
  1291. /* But some monsters are dirt poor. */
  1292. if (!(rf_has(r_ptr->flags, RF_DROP_60))
  1293. || rf_has(r_ptr->flags, RF_DROP_90)
  1294. || rf_has(r_ptr->flags, RF_DROP_1D2)
  1295. || rf_has(r_ptr->flags, RF_DROP_2D2)
  1296. || rf_has(r_ptr->flags, RF_DROP_3D2)
  1297. || rf_has(r_ptr->flags, RF_DROP_4D2))
  1298. purse = 0;
  1299. /* Some monster races are far better to steal from than others. */
  1300. if ((r_ptr->d_char == 'D') || (r_ptr->d_char == 'd')
  1301. || (r_ptr->d_char == 'p') || (r_ptr->d_char == 'h'))
  1302. purse *= 2 + randint1(3) + randint1(r_ptr->level / 20);
  1303. else if ((r_ptr->d_char == 'P') || (r_ptr->d_char == 'o')
  1304. || (r_ptr->d_char == 'O') || (r_ptr->d_char == 'T')
  1305. || (r_ptr->d_char == 'n') || (r_ptr->d_char == 'W')
  1306. || (r_ptr->d_char == 'k') || (r_ptr->d_char == 'L')
  1307. || (r_ptr->d_char == 'V') || (r_ptr->d_char == 'y'))
  1308. purse *= 1 + randint1(3) + randint1(r_ptr->level / 30);
  1309. /* Pickings are scarce in a land of many thieves. */
  1310. //BELE purse = purse * (p_ptr->danger + 5) / (p_ptr->recall[0] + 5);
  1311. purse = purse * (p_ptr->danger + 5) / (p_ptr->danger + 5);
  1312. /* Increase player gold. */
  1313. p_ptr->au += purse;
  1314. /* Limit to avoid buffer overflow */
  1315. if (p_ptr->au > PY_MAX_GOLD)
  1316. p_ptr->au = PY_MAX_GOLD;
  1317. /* Redraw gold */
  1318. p_ptr->redraw |= (PR_GOLD);
  1319. /* Announce the good news. */
  1320. if (purse)
  1321. msg("You burgle %d gold.", purse);
  1322. /* Pockets are empty. */
  1323. else
  1324. msg("You burgle only dust.");
  1325. }
  1326. /* The victim normally, but not always, wakes up and is aggravated. */
  1327. if (randint1(4) != 1) {
  1328. m_ptr->csleep = 0;
  1329. m_ptr->mflag |= (MFLAG_ACTV);
  1330. if (m_ptr->mspeed < r_ptr->speed + 3)
  1331. m_ptr->mspeed += 10;
  1332. /* Become hostile */
  1333. m_ptr->hostile = -1;
  1334. /* Occasionally, amuse the player with a message. */
  1335. if ((randint1(5) == 1) && (purse)
  1336. && (rf_has(r_ptr->flags, RF_SMART))) {
  1337. monster_desc(m_name, sizeof(m_name), m_ptr, 0);
  1338. act = desc_victim_outcry[randint0(20)];
  1339. my_strcap(m_name);
  1340. msg("%s cries out %s", m_name, act);
  1341. }
  1342. /* Otherwise, simply explain what happened. */
  1343. else {
  1344. monster_desc(m_name, sizeof(m_name), m_ptr, 0);
  1345. msg("You have aroused %s.", m_name);
  1346. }
  1347. }
  1348. /* The thief also speeds up, but only for just long enough to escape. */
  1349. if (!p_ptr->timed[TMD_FAST])
  1350. p_ptr->timed[TMD_FAST] += 2;
  1351. /* Recalculate bonuses */
  1352. p_ptr->update |= (PU_BONUS);
  1353. /* Handle stuff */
  1354. handle_stuff(p_ptr);
  1355. /* Increment the number of thefts, and possibly raise the hue and cry. */
  1356. number_of_thefts_on_level++;
  1357. if (number_of_thefts_on_level > 4) {
  1358. /* Notify the player of the trouble he's in. */
  1359. msg("All the level is in an uproar over your misdeeds!");
  1360. /* Aggravate and speed up all monsters on level. */
  1361. (void) aggravate_monsters(1, TRUE);
  1362. }
  1363. else if ((number_of_thefts_on_level > 2) || (randint1(8) == 1)) {
  1364. msg("You hear hunting parties scouring the area for a notorious burgler.");
  1365. /* Aggravate monsters nearby. */
  1366. (void) aggravate_monsters(1, FALSE);
  1367. }
  1368. /* Rogue "Hit and Run" attack. */
  1369. if (p_ptr->special_attack & (ATTACK_FLEE)) {
  1370. /* Cancel the fleeing spell */
  1371. p_ptr->special_attack &= ~(ATTACK_FLEE);
  1372. /* Message */
  1373. msg("You escape into the shadows!");
  1374. /* Teleport. */
  1375. teleport_player(6 + p_ptr->lev / 5, TRUE);
  1376. /* Redraw the state */
  1377. p_ptr->redraw |= (PR_STATUS);
  1378. }
  1379. }
  1380. /**
  1381. * Rogues may set traps. Only one such trap may exist at any one time,
  1382. * but an old trap can be disarmed to free up equipment for a new trap.
  1383. * -LM-
  1384. */
  1385. extern bool py_set_trap(int y, int x)
  1386. {
  1387. int max_traps;
  1388. max_traps =
  1389. 1 + ((p_ptr->lev >= 25) ? 1 : 0) +
  1390. (player_has(PF_EXTRA_TRAP) ? 1 : 0);
  1391. if (p_ptr->timed[TMD_BLIND] || no_light()) {
  1392. msg("You can not see to set a trap.");
  1393. return FALSE;
  1394. }
  1395. if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) {
  1396. msg("You are too confused.");
  1397. return FALSE;
  1398. }
  1399. /* Paranoia -- Forbid more than max_traps being set. */
  1400. if (num_trap_on_level >= max_traps) {
  1401. msg("You must disarm your existing trap to free up your equipment.");
  1402. return FALSE;
  1403. }
  1404. /* No setting traps while shapeshifted */
  1405. if (SCHANGE) {
  1406. msg("You can not set traps while shapechanged.");
  1407. msg("Use the ']' command to return to your normal form.");
  1408. return FALSE;
  1409. }
  1410. #if 0
  1411. /* Scan all objects in the grid */
  1412. for (this_o_idx = cave_o_idx[y][x]; this_o_idx;
  1413. this_o_idx = next_o_idx) {
  1414. /* Acquire object */
  1415. o_ptr = &o_list[this_o_idx];
  1416. /* Acquire next object */
  1417. next_o_idx = o_ptr->next_o_idx;
  1418. /* Artifact */
  1419. if (o_ptr->name1) {
  1420. msg("There is an indestructible object here.");
  1421. return FALSE;
  1422. }
  1423. /* Visible object to be destroyed */
  1424. if (!squelch_hide_item(o_ptr))
  1425. destroy_message = TRUE;
  1426. }
  1427. /* Verify */
  1428. if (cave_o_idx[y][x]) {
  1429. if (destroy_message)
  1430. if (!get_check("Destroy all items and set a trap?"))
  1431. return FALSE;
  1432. for (this_o_idx = cave_o_idx[y][x]; this_o_idx;
  1433. this_o_idx = next_o_idx) {
  1434. /* Acquire object */
  1435. o_ptr = &o_list[this_o_idx];
  1436. /* Acquire next object */
  1437. next_o_idx = o_ptr->next_o_idx;
  1438. /* Delete the object */
  1439. delete_object_idx(this_o_idx);
  1440. }
  1441. /* Redraw */
  1442. light_spot(y, x);
  1443. }
  1444. #endif
  1445. /* Set the trap, and draw it. */
  1446. place_trap(y, x, MTRAP_BASE, 0);
  1447. /* Notify the player. */
  1448. msg("You set a monster trap.");
  1449. /* A trap has been set */
  1450. return TRUE;
  1451. }
  1452. /**
  1453. * Trap coordinates
  1454. */
  1455. static int mtrap_y = 0;
  1456. static int mtrap_x = 0;
  1457. static char *mtrap_desc[] = {
  1458. "Sturdy Trap (less likely to break)",
  1459. "Netted Trap (effective versus flyers)",
  1460. "Confusion Trap (confuses monsters)",
  1461. "Poison Gas Trap (creates a toxic cloud)",
  1462. "Spirit Trap (effective versus spirits)",
  1463. "Lightning Trap (shoots a lightning bolt)",
  1464. "Explosive Trap (causes area damage)",
  1465. "Portal Trap (teleports monsters)",
  1466. "Stasis Trap (freezes time for a monster)",
  1467. "Drain Life Trap (hurts living monsters)",
  1468. "Unmagic Trap (damages and reduces mana)",
  1469. "Dispelling Trap (hurts all monsters in sight)",
  1470. "Genocide Trap (removes nearby like monsters)"
  1471. };
  1472. char mtrap_tag(menu_type * menu, int oid)
  1473. {
  1474. return I2A(oid);
  1475. }
  1476. /**
  1477. * Display an entry on the sval menu
  1478. */
  1479. void mtrap_display(menu_type * menu, int oid, bool cursor, int row,
  1480. int col, int width)
  1481. {
  1482. const u16b *choice = menu_priv(menu);
  1483. int idx = choice[oid];
  1484. byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
  1485. /* Print it */
  1486. c_put_str(attr, format("%s", mtrap_desc[idx]), row, col);
  1487. }
  1488. /**
  1489. * Deal with events on the trap menu
  1490. */
  1491. bool mtrap_action(menu_type * menu, const ui_event * db, int oid)
  1492. {
  1493. u16b *choice = menu_priv(menu);
  1494. int idx = choice[oid];
  1495. /* Get the old trap */
  1496. int old_trap = monster_trap_idx(mtrap_y, mtrap_x);
  1497. /* Remove the old trap */
  1498. remove_trap(mtrap_y, mtrap_x, FALSE, old_trap);
  1499. /* Place the new trap */
  1500. place_trap(mtrap_y, mtrap_x, MTRAP_BASE + 1 + idx, 0);
  1501. return FALSE;
  1502. }
  1503. /**
  1504. * Display list of monster traps.
  1505. */
  1506. bool mtrap_menu(void)
  1507. {
  1508. menu_type menu;
  1509. menu_iter menu_f = { mtrap_tag, 0, mtrap_display, mtrap_action, 0 };
  1510. region area = { 15, 1, 48, -1 };
  1511. ui_event evt = { 0 };
  1512. size_t i, num = 0;
  1513. u16b *choice;
  1514. /* See how many traps available */
  1515. if (player_has(PF_EXTRA_TRAP))
  1516. num = 1 + (p_ptr->lev / 4);
  1517. else
  1518. num = 1 + (p_ptr->lev / 6);
  1519. /* Create the array */
  1520. choice = C_ZNEW(num, u16b);
  1521. /* Obvious */
  1522. for (i = 0; i < num; i++) {
  1523. choice[i] = i;
  1524. }
  1525. /* Clear space */
  1526. area.page_rows = num + 2;
  1527. /* Return here if there are no traps */
  1528. if (!num) {
  1529. FREE(choice);
  1530. return FALSE;
  1531. }
  1532. /* Save the screen and clear it */
  1533. screen_save();
  1534. /* Help text */
  1535. /* Set up the menu */
  1536. WIPE(&menu, menu);
  1537. menu_init(&menu, MN_SKIN_SCROLL, &menu_f);
  1538. menu.title = "Choose an advanced monster trap (ESC to cancel):";
  1539. menu_setpriv(&menu, num, choice);
  1540. menu_layout(&menu, &area);
  1541. prt("", area.row + 1, area.col);
  1542. /* Select an entry */
  1543. evt = menu_select(&menu, 0, TRUE);
  1544. /* Free memory */
  1545. FREE(choice);
  1546. /* Load screen */
  1547. screen_load();
  1548. return (evt.type != EVT_ESCAPE);
  1549. }
  1550. /**
  1551. * Turn a basic monster trap into an advanced one -BR-
  1552. */
  1553. extern bool py_modify_trap(int y, int x)
  1554. {
  1555. if (p_ptr->timed[TMD_BLIND] || no_light()) {
  1556. msg("You can not see to modify your trap.");
  1557. return FALSE;
  1558. }
  1559. if (p_ptr->timed[TMD_CONFUSED] || p_ptr->timed[TMD_IMAGE]) {
  1560. msg("You are too confused.");
  1561. return FALSE;
  1562. }
  1563. /* No setting traps while shapeshifted */
  1564. if (SCHANGE) {
  1565. msg("You can not set traps while shapechanged.");
  1566. msg("Use the ']' command to return to your normal form.");
  1567. return FALSE;
  1568. }
  1569. mtrap_y = y;
  1570. mtrap_x = x;
  1571. /* get choice */
  1572. if (mtrap_menu()) {
  1573. /* Notify the player. */
  1574. msg("You modify the monster trap.");
  1575. }
  1576. /* Trap was modified */
  1577. return TRUE;
  1578. }
  1579. /**
  1580. * Delete/Remove all the traps when the player leaves the level
  1581. */
  1582. void wipe_trap_list(void)
  1583. {
  1584. int i;
  1585. /* Delete all the traps */
  1586. for (i = trap_max - 1; i >= 0; i--) {
  1587. trap_type *t_ptr = &trap_list[i];
  1588. /* Wipe the trap */
  1589. WIPE(t_ptr, trap_type);
  1590. }
  1591. /* Reset "trap_max" */
  1592. trap_max = 0;
  1593. /* Reset the number of glyphs on the level. */
  1594. for (i = 0; i < RUNE_TAIL; i++)
  1595. num_runes_on_level[i] = 0;
  1596. /* Reset the number of monster traps on the level. */
  1597. num_trap_on_level = 0;
  1598. }
  1599. /**
  1600. * Remove a trap
  1601. */
  1602. static void remove_trap_aux(trap_type * t_ptr, int y, int x, bool domsg)
  1603. {
  1604. /* We are clearing a web */
  1605. if (trf_has(t_ptr->flags, TRF_WEB)) {
  1606. if (domsg)
  1607. msg("You clear the web.");
  1608. }
  1609. /* We are deleting a rune */
  1610. else if (trf_has(t_ptr->flags, TRF_RUNE)) {
  1611. if (domsg)
  1612. msg("You have removed the %s.", t_ptr->kind->name);
  1613. num_runes_on_level[t_ptr->t_idx - 1]--;
  1614. } else if (domsg)
  1615. msgt(MSG_DISARM, "You have disarmed the %s.", t_ptr->kind->name);
  1616. /* We are deleting a monster trap */
  1617. if (trf_has(t_ptr->flags, TRF_M_TRAP))
  1618. num_trap_on_level--;
  1619. /* Wipe the trap */
  1620. cave_off(cave_info[y][x], CAVE_TRAP);
  1621. (void) WIPE(t_ptr, trap_type);
  1622. }
  1623. /**
  1624. * Remove traps.
  1625. *
  1626. * If called with t_idx < 0, will remove all traps in the location given.
  1627. * Otherwise, will remove the trap with the given index.
  1628. *
  1629. * Return TRUE if no traps now exist in this grid.
  1630. */
  1631. bool remove_trap(int y, int x, bool domsg, int t_idx)
  1632. {
  1633. int i;
  1634. bool trap_exists;
  1635. /* Called with a specific index */
  1636. if (t_idx >= 0) {
  1637. /* Point to this trap */
  1638. trap_type *t_ptr = &trap_list[t_idx];
  1639. /* Remove it */
  1640. remove_trap_aux(t_ptr, y, x, domsg);
  1641. /* Note when trap list actually gets shorter */
  1642. if (t_idx == trap_max - 1)
  1643. trap_max--;
  1644. }
  1645. /* No specific index -- remove all traps here */
  1646. else {
  1647. /* Scan the current trap list (backwards) */
  1648. for (i = trap_max - 1; i >= 0; i--) {
  1649. /* Point to this trap */
  1650. trap_type *t_ptr = &trap_list[i];
  1651. /* Find all traps in this position */
  1652. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  1653. /* Remove it */
  1654. remove_trap_aux(t_ptr, y, x, domsg);
  1655. /* Note when trap list actually gets shorter */
  1656. if (i == trap_max - 1)
  1657. trap_max--;
  1658. }
  1659. }
  1660. }
  1661. /* Refresh grids that the character can see */
  1662. if (player_can_see_bold(y, x))
  1663. light_spot(y, x);
  1664. /* Verify traps (remove marker if appropriate) */
  1665. trap_exists = verify_trap(y, x, 0);
  1666. /* Report whether any traps exist in this grid */
  1667. return (trap_exists);
  1668. }
  1669. /**
  1670. * Remove all traps of a specific kind from a location.
  1671. */
  1672. void remove_trap_kind(int y, int x, bool domsg, int t_idx)
  1673. {
  1674. int i;
  1675. /* Scan the current trap list */
  1676. for (i = 0; i < trap_max; i++) {
  1677. /* Point to this trap */
  1678. trap_type *t_ptr = &trap_list[i];
  1679. /* Find a trap in this position */
  1680. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  1681. /* Require that it be of this type */
  1682. if (t_ptr->t_idx == t_idx)
  1683. (void) remove_trap(y, x, domsg, i);
  1684. }
  1685. }
  1686. }
  1687. /* Trap menu code */
  1688. /**
  1689. * Choice of trap
  1690. */
  1691. static int trap_choice = 0;
  1692. /**
  1693. * Label for trap
  1694. */
  1695. static char trap_tag(menu_type * menu, int oid)
  1696. {
  1697. return I2A(oid);
  1698. }
  1699. /**
  1700. * Display an entry on the trap menu
  1701. */
  1702. void trap_display(menu_type * menu, int oid, bool cursor, int row, int col,
  1703. int width)
  1704. {
  1705. const u16b *choice = menu_priv(menu);
  1706. byte attr = (cursor ? TERM_L_BLUE : TERM_WHITE);
  1707. c_prt(attr, trap_list[choice[oid]].kind->name, row, col);
  1708. }
  1709. /**
  1710. * Deal with events on the jump menu
  1711. */
  1712. bool trap_action(menu_type * menu, const ui_event * evt, int oid)
  1713. {
  1714. u16b *choice = menu_priv(menu);
  1715. int idx = choice[oid];
  1716. if (evt->type == EVT_SELECT) {
  1717. trap_choice = idx;
  1718. return FALSE;
  1719. } else
  1720. return TRUE;
  1721. }
  1722. /**
  1723. * Display list of places to jump to.
  1724. */
  1725. bool trap_menu(int y, int x, int *idx)
  1726. {
  1727. menu_type menu;
  1728. menu_iter menu_f = { trap_tag, 0, trap_display, trap_action, 0 };
  1729. region area = { 15, 1, 48, -1 };
  1730. ui_event evt = { 0 };
  1731. int cursor = 0, j = 0;
  1732. int i;
  1733. u16b *choice;
  1734. /* Create the array */
  1735. choice = C_ZNEW(trap_max, u16b);
  1736. /* Scan the current trap list */
  1737. for (j = 0, i = 0; i < trap_max; i++) {
  1738. /* Point to this trap */
  1739. trap_type *t_ptr = &trap_list[i];
  1740. /* Find a trap in this position */
  1741. if ((t_ptr->fy == y) && (t_ptr->fx == x)) {
  1742. /* Trap must be visible */
  1743. if (!trf_has(t_ptr->flags, TRF_VISIBLE))
  1744. continue;
  1745. /* Count all traps */
  1746. choice[j++] = i;
  1747. /* Remember last trap index */
  1748. *idx = i;
  1749. }
  1750. }
  1751. /* We have no visible traps */
  1752. if (!j)
  1753. return (FALSE);
  1754. /* We have one trap (usual case) */
  1755. if (j == 1)
  1756. return (TRUE);
  1757. /* Clear space */
  1758. area.page_rows = j + 2;
  1759. /* Save the screen and clear it */
  1760. screen_save();
  1761. /* Set up the menu */
  1762. WIPE(&menu, menu);
  1763. menu.title = "Which trap do you choose?";
  1764. menu.cmd_keys = " \n\r";
  1765. menu_init(&menu, MN_SKIN_SCROLL, &menu_f);
  1766. menu_setpriv(&menu, j, choice);
  1767. menu_layout(&menu, &area);
  1768. /* Select an entry */
  1769. evt = menu_select(&menu, cursor, TRUE);
  1770. /* Set it */
  1771. if (evt.type == EVT_SELECT)
  1772. *idx = trap_choice;
  1773. /* Free memory */
  1774. FREE(choice);
  1775. /* Load screen */

Large files files are truncated, but you can click here to view the full file