PageRenderTime 54ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/src/monster2.c

https://github.com/NickMcConnell/Beleriand
C | 4842 lines | 2665 code | 937 blank | 1240 comment | 818 complexity | 3e481455d0ae8766e0139bb6846f0c6e MD5 | raw file

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

  1. /** \file monster2.c
  2. \brief Monster generation, learning and removal
  3. * Monster processing, compacting, generation, goody drops, deletion,
  4. * place the player, monsters, and their escorts at a given location,
  5. * generation of monsters, summoning, monster reaction to pain
  6. * levels, monster learning.
  7. *
  8. * Copyright (c) 2009 Nick McConnell, Leon Marrick & Bahman Rabii,
  9. * Ben Harrison, James E. Wilson, Robert A. Koeneke
  10. *
  11. * This work is free software; you can redistribute it and/or modify it
  12. * under the terms of either:
  13. *
  14. * a) the GNU General Public License as published by the Free Software
  15. * Foundation, version 2, or
  16. *
  17. * b) the "Angband licence":
  18. * This software may be copied and distributed for educational, research,
  19. * and not for profit purposes provided that this copyright and statement
  20. * are included in all such copies. Other copyrights may also apply.
  21. */
  22. #include "angband.h"
  23. #include "cave.h"
  24. #include "generate.h"
  25. #include "history.h"
  26. #include "monster.h"
  27. #include "player.h"
  28. #include "target.h"
  29. #include "trap.h"
  30. /**
  31. * Delete a monster by index.
  32. *
  33. * When a monster is deleted, all of its objects are deleted.
  34. */
  35. void delete_monster_idx(int i)
  36. {
  37. int x, y;
  38. monster_type *m_ptr = &m_list[i];
  39. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  40. monster_lore *l_ptr = &l_list[m_ptr->r_idx];
  41. s16b this_o_idx, next_o_idx = 0;
  42. /* Get location */
  43. y = m_ptr->fy;
  44. x = m_ptr->fx;
  45. /* Hack -- Reduce the racial counter */
  46. r_ptr->cur_num--;
  47. /* Hack -- count the number of "reproducers" */
  48. if (rf_has(r_ptr->flags, RF_MULTIPLY))
  49. num_repro--;
  50. /* Hack -- remove target monster */
  51. if (target_get_monster() == i)
  52. target_set_monster(0);
  53. /* Hack -- remove tracked monster */
  54. if (p_ptr->health_who == i)
  55. health_track(0);
  56. /* Monster is gone */
  57. cave_m_idx[y][x] = 0;
  58. /* Total Hack -- If the monster was a player ghost, remove it from the
  59. * monster memory, ensure that it never appears again, clear its bones
  60. * file selector and allow the next ghost to speak. */
  61. if (rf_has(r_ptr->flags, RF_PLAYER_GHOST)) {
  62. l_ptr->sights = 0;
  63. l_ptr->deaths = 0;
  64. l_ptr->pkills = 0;
  65. l_ptr->tkills = 0;
  66. bones_selector = 0;
  67. ghost_has_spoken = FALSE;
  68. r_ptr->rarity = 0;
  69. }
  70. /* Delete objects */
  71. for (this_o_idx = m_ptr->hold_o_idx; this_o_idx;
  72. this_o_idx = next_o_idx) {
  73. object_type *o_ptr;
  74. /* Acquire object */
  75. o_ptr = &o_list[this_o_idx];
  76. /* Acquire next object */
  77. next_o_idx = o_ptr->next_o_idx;
  78. /* Hack -- efficiency */
  79. o_ptr->held_m_idx = 0;
  80. /* Delete the object */
  81. delete_object_idx(this_o_idx);
  82. }
  83. /* Wipe the Monster */
  84. (void) WIPE(m_ptr, monster_type);
  85. /* Count monsters */
  86. m_cnt--;
  87. /* Visual update */
  88. light_spot(y, x);
  89. }
  90. /**
  91. * Delete the monster, if any, at a given location
  92. */
  93. void delete_monster(int y, int x)
  94. {
  95. /* Paranoia */
  96. if (!in_bounds(y, x))
  97. return;
  98. /* Delete the monster (if any) */
  99. if (cave_m_idx[y][x] > 0)
  100. delete_monster_idx(cave_m_idx[y][x]);
  101. }
  102. /**
  103. * Move an object from index i1 to index i2 in the object list
  104. */
  105. static void compact_monsters_aux(int i1, int i2)
  106. {
  107. int y, x;
  108. monster_type *m_ptr;
  109. s16b this_o_idx, next_o_idx = 0;
  110. /* Do nothing */
  111. if (i1 == i2)
  112. return;
  113. /* Old monster */
  114. m_ptr = &m_list[i1];
  115. /* Location */
  116. y = m_ptr->fy;
  117. x = m_ptr->fx;
  118. /* Update the cave */
  119. cave_m_idx[y][x] = i2;
  120. /* Repair objects being carried by monster */
  121. for (this_o_idx = m_ptr->hold_o_idx; this_o_idx;
  122. this_o_idx = next_o_idx) {
  123. object_type *o_ptr;
  124. /* Acquire object */
  125. o_ptr = &o_list[this_o_idx];
  126. /* Acquire next object */
  127. next_o_idx = o_ptr->next_o_idx;
  128. /* Reset monster pointer */
  129. o_ptr->held_m_idx = i2;
  130. }
  131. /* Hack -- Update the target */
  132. if (target_get_monster() == i1)
  133. target_set_monster(i2);
  134. /* Hack -- Update the health bar */
  135. if (p_ptr->health_who == i1)
  136. p_ptr->health_who = i2;
  137. /* Hack -- move monster */
  138. (void) COPY(&m_list[i2], &m_list[i1], monster_type);
  139. /* Hack -- wipe hole */
  140. (void) WIPE(&m_list[i1], monster_type);
  141. }
  142. /**
  143. * Compact and Reorder the monster list
  144. *
  145. * This function can be very dangerous, use with caution!
  146. *
  147. * When actually "compacting" monsters, we base the saving throw
  148. * on a combination of monster level, distance from player, and
  149. * current "desperation".
  150. *
  151. * After "compacting" (if needed), we "reorder" the monsters into a more
  152. * compact order, and we reset the allocation info, and the "live" array.
  153. */
  154. void compact_monsters(int size)
  155. {
  156. int i, j, num, cnt;
  157. int cur_lev, cur_dis, chance;
  158. /* Message (only if compacting) */
  159. if (size)
  160. msg("Compacting monsters...");
  161. /* Compact at least 'size' objects */
  162. for (num = 0, cnt = 1; num < size; cnt++) {
  163. /* Get more vicious each iteration */
  164. cur_lev = 5 * cnt;
  165. /* Get closer each iteration */
  166. cur_dis = 5 * (20 - cnt);
  167. j = 0;
  168. /* Check all the monsters */
  169. for (i = 1; i < m_max; i++) {
  170. monster_type *m_ptr = &m_list[i];
  171. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  172. /* Paranoia -- skip "dead" monsters */
  173. if (!m_ptr->r_idx) {
  174. if (j++ >= size)
  175. return;
  176. else
  177. continue;
  178. }
  179. /* Hack -- High level monsters start out "immune" */
  180. if (r_ptr->level > cur_lev)
  181. continue;
  182. /* Ignore nearby monsters */
  183. if ((cur_dis > 0) && (m_ptr->cdis < cur_dis))
  184. continue;
  185. /* Saving throw chance */
  186. chance = 90;
  187. /* Only compact "Quest" Monsters in emergencies */
  188. if ((rf_has(r_ptr->flags, RF_QUESTOR)) && (cnt < 1000))
  189. chance = 100;
  190. /* Try not to compact Unique Monsters */
  191. if (rf_has(r_ptr->flags, RF_UNIQUE))
  192. chance = 99;
  193. /* All monsters get a saving throw */
  194. if (randint0(100) < chance)
  195. continue;
  196. /* Delete the monster */
  197. delete_monster_idx(i);
  198. /* Count the monster */
  199. num++;
  200. }
  201. }
  202. /* Excise dead monsters (backwards!) */
  203. for (i = m_max - 1; i >= 1; i--) {
  204. /* Get the i'th monster */
  205. monster_type *m_ptr = &m_list[i];
  206. /* Skip real monsters */
  207. if (m_ptr->r_idx)
  208. continue;
  209. /* Move last monster into open hole */
  210. compact_monsters_aux(m_max - 1, i);
  211. /* Compress "m_max" */
  212. m_max--;
  213. }
  214. }
  215. /**
  216. * Delete/Remove all the monsters when the player leaves the level
  217. *
  218. * This is an efficient method of simulating multiple calls to the
  219. * "delete_monster()" function, with no visual effects.
  220. */
  221. void wipe_m_list(void)
  222. {
  223. int i;
  224. /* Delete all the monsters */
  225. for (i = m_max - 1; i >= 1; i--) {
  226. monster_type *m_ptr = &m_list[i];
  227. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  228. monster_lore *l_ptr = &l_list[m_ptr->r_idx];
  229. /* Skip dead monsters */
  230. if (!m_ptr->r_idx)
  231. continue;
  232. /* Total Hack -- Clear player ghost information. */
  233. if (rf_has(r_ptr->flags, RF_PLAYER_GHOST)) {
  234. l_ptr->sights = 0;
  235. l_ptr->deaths = 0;
  236. l_ptr->pkills = 0;
  237. l_ptr->tkills = 0;
  238. bones_selector = 0;
  239. ghost_has_spoken = FALSE;
  240. r_ptr->rarity = 0;
  241. }
  242. /* Hack -- Reduce the racial counter */
  243. r_ptr->cur_num--;
  244. /* Monster is gone */
  245. cave_m_idx[m_ptr->fy][m_ptr->fx] = 0;
  246. /* Wipe the Monster */
  247. (void) WIPE(m_ptr, monster_type);
  248. }
  249. /* Hack - wipe the player */
  250. cave_m_idx[p_ptr->py][p_ptr->px] = 0;
  251. /* Reset "m_max" */
  252. m_max = 1;
  253. /* Reset "m_cnt" */
  254. m_cnt = 0;
  255. /* Hack -- reset "reproducer" count */
  256. num_repro = 0;
  257. /* Hack -- no more target */
  258. target_set_monster(0);
  259. /* Hack -- no more tracking */
  260. health_track(0);
  261. /* Hack -- make sure there is no player ghost */
  262. bones_selector = 0;
  263. }
  264. /**
  265. * Acquires and returns the index of a "free" monster.
  266. *
  267. * This routine should almost never fail, but it *can* happen.
  268. */
  269. s16b m_pop(void)
  270. {
  271. int i;
  272. /* Normal allocation */
  273. if (m_max < z_info->m_max) {
  274. /* Access the next hole */
  275. i = m_max;
  276. /* Expand the array */
  277. m_max++;
  278. /* Count monsters */
  279. m_cnt++;
  280. /* Return the index */
  281. return (i);
  282. }
  283. /* Recycle dead monsters */
  284. for (i = 1; i < m_max; i++) {
  285. monster_type *m_ptr;
  286. /* Acquire monster */
  287. m_ptr = &m_list[i];
  288. /* Skip live monsters */
  289. if (m_ptr->r_idx)
  290. continue;
  291. /* Count monsters */
  292. m_cnt++;
  293. /* Use this monster */
  294. return (i);
  295. }
  296. /* Warn the player (except during dungeon creation) */
  297. if (character_dungeon)
  298. msg("Too many monsters!");
  299. /* Try not to crash */
  300. return (0);
  301. }
  302. /**
  303. * Apply a "monster restriction function" to the "monster allocation table"
  304. */
  305. errr get_mon_num_prep(void)
  306. {
  307. int i;
  308. /* Scan the allocation table */
  309. for (i = 0; i < alloc_race_size; i++) {
  310. /* Get the entry */
  311. alloc_entry *entry = &alloc_race_table[i];
  312. /* Accept monsters which pass the restriction, if any */
  313. if (!get_mon_num_hook || (*get_mon_num_hook) (entry->index)) {
  314. /* Accept this monster */
  315. entry->prob2 = entry->prob1;
  316. }
  317. /* Do not use this monster */
  318. else {
  319. /* Decline this monster */
  320. entry->prob2 = 0;
  321. }
  322. }
  323. /* Success */
  324. return (0);
  325. }
  326. /**
  327. * Choose a monster race that seems "appropriate" to the given level
  328. *
  329. * We use this function, not only to pick a monster but to build a
  330. * table of probabilities. This table can be used again and again, if
  331. * certain conditions (generation level being the most important) don't
  332. * change.
  333. *
  334. * This function uses the "prob2" field of the "monster allocation table",
  335. * and various local information, to calculate the "prob3" field of the
  336. * same table, which is then used to choose an "appropriate" monster, in
  337. * a relatively efficient manner.
  338. *
  339. * Note that "town" monsters will *only* be created in the town, and
  340. * "normal" monsters will *never* be created in the town, unless the
  341. * "level" is "modified", for example, by polymorph or summoning.
  342. *
  343. * There is a small chance (1/40) of "boosting" the given depth by
  344. * a small amount (up to four levels), except in the town.
  345. *
  346. * It is (slightly) more likely to acquire a monster of the given level
  347. * than one of a lower level. This is done by choosing several monsters
  348. * appropriate to the given level and keeping the "hardest" one.
  349. *
  350. * Note that if no monsters are "appropriate", then this function will
  351. * fail, and return zero, but this should *almost* never happen.
  352. */
  353. s16b get_mon_num(int level)
  354. {
  355. int i, d;
  356. int r_idx;
  357. long value;
  358. int failure = 0;
  359. int temp_level = level;
  360. monster_race *r_ptr;
  361. alloc_entry *table = alloc_race_table;
  362. /* Low-level monsters avoid the deep dungeon. */
  363. int depth_rare = 2 * level / 3;
  364. int depth_very_rare = level / 3;
  365. /* Sometimes, monsters in the dungeon can be out of depth */
  366. if (p_ptr->danger != 0) {
  367. /* Occasional boost to maximum level */
  368. if (randint0(NASTY_MON) == 0) {
  369. /* Pick a level bonus */
  370. d = level / 10 + 1;
  371. /* Boost the level */
  372. temp_level += ((d < 5) ? d : 5);
  373. /* Occasional second boost */
  374. if (randint0(NASTY_MON) == 0) {
  375. /* Pick a level bonus */
  376. d = level / 10 + 1;
  377. /* Boost the level */
  378. temp_level += ((d < 5) ? d : 5);
  379. }
  380. }
  381. }
  382. /* Try hard to find a suitable monster */
  383. while (TRUE) {
  384. /* Reset sum of final monster probabilities. */
  385. alloc_race_total = 0L;
  386. /* Process probabilities */
  387. for (i = 0; i < alloc_race_size; i++) {
  388. /* Assume no probability */
  389. table[i].prob3 = 0;
  390. /* Ignore illegal monsters */
  391. if (!table[i].prob2)
  392. continue;
  393. /* Monsters are sorted by depth */
  394. if (table[i].level > temp_level)
  395. continue;
  396. /* Hack -- No town monsters in dungeon */
  397. if ((p_ptr->danger != 0) && (table[i].level < 1))
  398. continue;
  399. /* Get the monster index */
  400. r_idx = table[i].index;
  401. /* Get the actual race */
  402. r_ptr = &r_info[r_idx];
  403. /* Hack -- some monsters are unique */
  404. if ((rf_has(r_ptr->flags, RF_UNIQUE))
  405. && (r_ptr->cur_num >= r_ptr->max_num))
  406. continue;
  407. /* Forced-depth monsters only appear at their level. */
  408. if ((rf_has(r_ptr->flags, RF_FORCE_DEPTH))
  409. && (r_ptr->level != p_ptr->danger))
  410. continue;
  411. /* Hack - dungeon-only monsters */
  412. if ((rf_has(r_ptr->flags, RF_DUNGEON))
  413. && (chunk_list[p_ptr->stage].z_pos == 0))
  414. continue;
  415. /* Accept */
  416. table[i].prob3 = table[i].prob2;
  417. /* Now modifications for locality etc follow -NRM-
  418. BELE all gone */
  419. /* Keep low-level monsters rare */
  420. if (table[i].level < depth_rare)
  421. table[i].prob3 /= 4;
  422. if (table[i].level < depth_very_rare)
  423. table[i].prob3 /= 4;
  424. /* Sum up probabilities */
  425. alloc_race_total += table[i].prob3;
  426. }
  427. /* No legal monsters */
  428. if (alloc_race_total == 0) {
  429. failure++;
  430. if (failure == 1) {
  431. /* Try relaxing the level restrictions */
  432. if (p_ptr->themed_level)
  433. temp_level += 20;
  434. else
  435. temp_level += 10;
  436. } else {
  437. /* Our monster restrictions are too stringent. */
  438. return (0);
  439. }
  440. }
  441. /* Success */
  442. else
  443. break;
  444. }
  445. /* Pick a monster */
  446. value = randint0(alloc_race_total);
  447. /* Find the monster */
  448. for (i = 0; i < alloc_race_size; i++) {
  449. /* Found the entry */
  450. if (value < table[i].prob3)
  451. break;
  452. /* Decrement */
  453. value = value - table[i].prob3;
  454. }
  455. /* Result */
  456. return (table[i].index);
  457. }
  458. /**
  459. * A replacement for "get_mon_num()", for use when that function has
  460. * built up a suitable table of monster probabilities, and all we want
  461. * to do is pull another monster from it.
  462. *
  463. * Usage of this function has a curious and quite intentional effect:
  464. * on rare occasion, 1 in NASTY_MON times, the effective generation level
  465. * is raised somewhat. Most monsters will actually end up being in depth,
  466. * but not all...
  467. */
  468. s16b get_mon_num_quick(int level)
  469. {
  470. int i;
  471. long value;
  472. alloc_entry *table = alloc_race_table;
  473. /*
  474. * No monsters available. XXX XXX - try using the standard
  475. * function again, although it probably failed the first time.
  476. */
  477. if (!alloc_race_total)
  478. return (get_mon_num(level));
  479. /* Pick a monster */
  480. value = randint0(alloc_race_total);
  481. /* Find the monster */
  482. for (i = 0; i < alloc_race_size; i++) {
  483. /* Found the entry */
  484. if (value < table[i].prob3)
  485. break;
  486. /* Decrement */
  487. value = value - table[i].prob3;
  488. }
  489. /* Result */
  490. return (table[i].index);
  491. }
  492. /**
  493. * Mega-hack - Fix plural names of monsters
  494. *
  495. * Taken from PernAngband via EY, modified to fit NPP monster list
  496. *
  497. * Note: It should handle all regular Angband monsters.
  498. *
  499. * TODO: Specify monster name plurals in monster.txt instead.
  500. */
  501. void plural_aux(char *name, size_t max)
  502. {
  503. int name_len = strlen(name);
  504. if (strstr(name, " of ")) {
  505. char *aider = strstr(name, " of ");
  506. char dummy[80];
  507. int i = 0;
  508. char *ctr = name;
  509. while (ctr < aider) {
  510. dummy[i] = *ctr;
  511. ctr++;
  512. i++;
  513. }
  514. if (dummy[i - 1] == 's') {
  515. strcpy(&(dummy[i]), "es");
  516. i++;
  517. } else {
  518. strcpy(&(dummy[i]), "s");
  519. }
  520. strcpy(&(dummy[i + 1]), aider);
  521. my_strcpy(name, dummy, max);
  522. } else if ((strstr(name, "coins")) || (strstr(name, "gems"))) {
  523. char dummy[80];
  524. strcpy(dummy, "Piles of c");
  525. my_strcat(dummy, &(name[1]), sizeof(dummy));
  526. my_strcpy(name, dummy, max);
  527. return;
  528. }
  529. else if (strstr(name, "Greater Servant of")) {
  530. char dummy[80];
  531. strcpy(dummy, "Greater Servants of ");
  532. my_strcat(dummy, &(name[1]), sizeof(dummy));
  533. my_strcpy(name, dummy, max);
  534. return;
  535. } else if (strstr(name, "Lesser Servant of")) {
  536. char dummy[80];
  537. strcpy(dummy, "Greater Servants of ");
  538. my_strcat(dummy, &(name[1]), sizeof(dummy));
  539. my_strcpy(name, dummy, max);
  540. return;
  541. } else if (strstr(name, "Servant of")) {
  542. char dummy[80];
  543. strcpy(dummy, "Servants of ");
  544. my_strcat(dummy, &(name[1]), sizeof(dummy));
  545. my_strcpy(name, dummy, max);
  546. return;
  547. } else if (strstr(name, "Great Wyrm")) {
  548. char dummy[80];
  549. strcpy(dummy, "Great Wyrms ");
  550. my_strcat(dummy, &(name[1]), sizeof(dummy));
  551. my_strcpy(name, dummy, max);
  552. return;
  553. } else if (strstr(name, "Spawn of")) {
  554. char dummy[80];
  555. strcpy(dummy, "Spawn of ");
  556. my_strcat(dummy, &(name[1]), sizeof(dummy));
  557. my_strcpy(name, dummy, max);
  558. return;
  559. } else if (strstr(name, "Descendant of")) {
  560. char dummy[80];
  561. strcpy(dummy, "Descendant of ");
  562. my_strcat(dummy, &(name[1]), sizeof(dummy));
  563. my_strcpy(name, dummy, max);
  564. return;
  565. } else if ((strstr(name, "Manes")) || (name[name_len - 1] == 'u')
  566. || (strstr(name, "Yeti"))
  567. || (streq(&(name[name_len - 2]), "ua"))
  568. || (streq(&(name[name_len - 3]), "nee"))
  569. || (streq(&(name[name_len - 4]), "idhe"))) {
  570. return;
  571. } else if (name[name_len - 1] == 'y') {
  572. strcpy(&(name[name_len - 1]), "ies");
  573. } else if (streq(&(name[name_len - 4]), "ouse")) {
  574. strcpy(&(name[name_len - 4]), "ice");
  575. } else if (streq(&(name[name_len - 4]), "lung")) {
  576. strcpy(&(name[name_len - 4]), "lungen");
  577. } else if (streq(&(name[name_len - 3]), "sus")) {
  578. strcpy(&(name[name_len - 3]), "si");
  579. } else if (streq(&(name[name_len - 4]), "star")) {
  580. strcpy(&(name[name_len - 4]), "stari");
  581. } else if (streq(&(name[name_len - 3]), "aia")) {
  582. strcpy(&(name[name_len - 3]), "aiar");
  583. } else if (streq(&(name[name_len - 3]), "inu")) {
  584. strcpy(&(name[name_len - 3]), "inur");
  585. } else if (streq(&(name[name_len - 5]), "culus")) {
  586. strcpy(&(name[name_len - 5]), "culi");
  587. } else if (streq(&(name[name_len - 4]), "sman")) {
  588. strcpy(&(name[name_len - 4]), "smen");
  589. } else if (streq(&(name[name_len - 4]), "lman")) {
  590. strcpy(&(name[name_len - 4]), "lmen");
  591. } else if (streq(&(name[name_len - 2]), "ex")) {
  592. strcpy(&(name[name_len - 2]), "ices");
  593. } else if ((name[name_len - 1] == 'f')
  594. && (!streq(&(name[name_len - 2]), "ff"))) {
  595. strcpy(&(name[name_len - 1]), "ves");
  596. } else
  597. if (((streq(&(name[name_len - 2]), "ch"))
  598. || (name[name_len - 1] == 's'))
  599. && (!streq(&(name[name_len - 5]), "iarch"))) {
  600. strcpy(&(name[name_len]), "es");
  601. } else {
  602. strcpy(&(name[name_len]), "s");
  603. }
  604. }
  605. /**
  606. * Helper function for display monlist. Prints the number of creatures,
  607. * followed by either a singular or plural version of the race name as
  608. * appropriate.
  609. */
  610. static void get_mon_name(char *output_name, size_t max,
  611. const monster_race * r_ptr, int num)
  612. {
  613. char race_name[80];
  614. assert(r_ptr);
  615. my_strcpy(race_name, r_ptr->name, sizeof(race_name));
  616. /* Unique names don't have a number */
  617. if (rf_has(r_ptr->flags, RF_UNIQUE))
  618. my_strcpy(output_name, "[U] ", max);
  619. /* Normal races */
  620. else {
  621. my_strcpy(output_name, format("%3d ", num), max);
  622. /* Make it plural, if needed. */
  623. if (num > 1)
  624. plural_aux(race_name, sizeof(race_name));
  625. }
  626. /* Mix the quantity and the header. */
  627. my_strcat(output_name, race_name, max);
  628. }
  629. /*
  630. * Monster data for the visible monster list
  631. */
  632. typedef struct {
  633. u16b count; /* total number of this type visible */
  634. u16b asleep; /* number asleep (not in LOS) */
  635. u16b neutral; /* number neutral (not in LOS) */
  636. u16b los; /* number in LOS */
  637. u16b los_asleep; /* number asleep and in LOS */
  638. u16b los_neutral; /* number neutral and in LOS */
  639. byte attr; /* attr to use for drawing */
  640. } monster_vis;
  641. /*
  642. * Display visible monsters in a window
  643. */
  644. void display_monlist(void)
  645. {
  646. int ii;
  647. size_t i, j, k;
  648. int max;
  649. int line = 1, x = 0;
  650. int cur_x;
  651. unsigned total_count = 0, disp_count = 0, type_count = 0, los_count =
  652. 0;
  653. byte attr;
  654. char m_name[80];
  655. char buf[80];
  656. monster_type *m_ptr;
  657. monster_race *r_ptr;
  658. monster_race *r2_ptr;
  659. monster_vis *list;
  660. u16b *order;
  661. bool in_term = (Term != angband_term[0]);
  662. /* Hallucination is weird */
  663. if (p_ptr->timed[TMD_IMAGE]) {
  664. if (in_term)
  665. clear_from(0);
  666. Term_gotoxy(0, 0);
  667. text_out_to_screen(TERM_ORANGE,
  668. "Your hallucinations are too wild to see things clearly.");
  669. return;
  670. }
  671. /* Clear the term if in a subwindow, set x otherwise */
  672. if (in_term) {
  673. clear_from(0);
  674. max = Term->hgt - 1;
  675. } else {
  676. x = 13;
  677. max = Term->hgt - 2;
  678. }
  679. /* Allocate the primary array */
  680. list = C_ZNEW(z_info->r_max, monster_vis);
  681. /* Scan the list of monsters on the level */
  682. for (ii = 1; ii < m_max; ii++) {
  683. monster_vis *v;
  684. m_ptr = &m_list[ii];
  685. r_ptr = &r_info[m_ptr->r_idx];
  686. /* Only consider visible, known monsters */
  687. if (!m_ptr->ml)
  688. continue;
  689. /* Take a pointer to this monster visibility entry */
  690. v = &list[m_ptr->r_idx];
  691. /* Note each monster type and save its display attr (color) */
  692. if (!v->count)
  693. type_count++;
  694. if (!v->attr)
  695. v->attr = m_ptr->attr ? m_ptr->attr : r_ptr->x_attr;
  696. /* Check for LOS
  697. * Hack - we should use (m_ptr->mflag & (MFLAG_VIEW)) here,
  698. * but this does not catch monsters detected by ESP which are
  699. * targetable, so we cheat and use projectable() instead
  700. */
  701. if (projectable(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx,
  702. PROJECT_CHCK)) {
  703. /* Increment the total number of in-LOS monsters */
  704. los_count++;
  705. /* Increment the LOS count for this monster type */
  706. v->los++;
  707. /* Check if asleep or neutral and increment */
  708. if (m_ptr->hostile >= 0)
  709. v->los_neutral++;
  710. else if (m_ptr->csleep)
  711. v->los_asleep++;
  712. }
  713. /* Not in LOS so increment if asleep */
  714. else {
  715. if (m_ptr->hostile >= 0)
  716. v->neutral++;
  717. else if (m_ptr->csleep)
  718. v->asleep++;
  719. }
  720. /* Bump the count for this race, and the total count */
  721. v->count++;
  722. total_count++;
  723. }
  724. /* Note no visible monsters at all */
  725. if (!total_count) {
  726. /* Clear display and print note */
  727. c_prt(TERM_SLATE, "You see no monsters.", 0, 0);
  728. if (!in_term)
  729. Term_addstr(-1, TERM_WHITE, " (Press any key to continue.)");
  730. /* Free up memory */
  731. FREE(list);
  732. /* Done */
  733. return;
  734. }
  735. /* Allocate the secondary array */
  736. order = C_ZNEW(type_count, u16b);
  737. /* Sort, because we cannot rely on monster.txt being ordered */
  738. /* Populate the ordered array, starting at 1 to ignore @ */
  739. for (i = 1; i < z_info->r_max; i++) {
  740. /* No monsters of this race are visible */
  741. if (!list[i].count)
  742. continue;
  743. /* Get the monster info */
  744. r_ptr = &r_info[i];
  745. /* Fit this monster into the sorted array */
  746. for (j = 0; j < type_count; j++) {
  747. /* If we get to the end of the list, put this one in */
  748. if (!order[j]) {
  749. order[j] = i;
  750. break;
  751. }
  752. /* Get the monster info for comparison */
  753. r2_ptr = &r_info[order[j]];
  754. /* Monsters are sorted by depth */
  755. if (r_ptr->level > r2_ptr->level) {
  756. /* Move weaker monsters down the array */
  757. for (k = type_count - 1; k > j; k--) {
  758. order[k] = order[k - 1];
  759. }
  760. /* Put current monster in the right place */
  761. order[j] = i;
  762. break;
  763. }
  764. }
  765. }
  766. /* Message for monsters in LOS - even if there are none */
  767. if (!los_count)
  768. prt(format("You can see no monsters."), 0, 0);
  769. else
  770. prt(format("You can see %d monster%s", los_count, (los_count == 1
  771. ? ":" : "s:")),
  772. 0, 0);
  773. /* Print out in-LOS monsters in descending order */
  774. for (i = 0; (i < type_count) && (line < max); i++) {
  775. /* Skip if there are none of these in LOS */
  776. if (!list[order[i]].los)
  777. continue;
  778. /* Reset position */
  779. cur_x = x;
  780. /* Note that these have been displayed */
  781. disp_count += list[order[i]].los;
  782. /* Get monster race and name */
  783. r_ptr = &r_info[order[i]];
  784. get_mon_name(m_name, sizeof(m_name), r_ptr, list[order[i]].los);
  785. /* Display uniques in a special colour */
  786. if (rf_has(r_ptr->flags, RF_UNIQUE))
  787. attr = TERM_VIOLET;
  788. else if (r_ptr->level > p_ptr->danger)
  789. attr = TERM_RED;
  790. else
  791. attr = TERM_WHITE;
  792. /* Build the monster name */
  793. if (list[order[i]].los == 1) {
  794. if (list[order[i]].los_asleep == 1)
  795. strnfmt(buf, sizeof(buf), "%s (asleep) ", m_name);
  796. else if (list[order[i]].los_neutral == 1)
  797. strnfmt(buf, sizeof(buf), "%s (neutral) ", m_name);
  798. else
  799. strnfmt(buf, sizeof(buf), "%s ", m_name);
  800. } else {
  801. if (list[order[i]].los_asleep == 0) {
  802. if (list[order[i]].los_neutral == 0)
  803. strnfmt(buf, sizeof(buf), "%s", m_name);
  804. else
  805. strnfmt(buf, sizeof(buf), "%s (%d neutral) ",
  806. m_name, list[order[i]].los_neutral);
  807. } else {
  808. if (list[order[i]].los_neutral == 0)
  809. strnfmt(buf, sizeof(buf), "%s (%d asleep) ",
  810. m_name, list[order[i]].los_asleep);
  811. else
  812. strnfmt(buf, sizeof(buf),
  813. "%s (%d asleep, %d neutral) ", m_name,
  814. list[order[i]].los_asleep,
  815. list[order[i]].los_neutral);
  816. }
  817. }
  818. /* Display the pict */
  819. if ((tile_width == 1) && (tile_height == 1)) {
  820. Term_putch(cur_x++, line, list[order[i]].attr, r_ptr->x_char);
  821. Term_putch(cur_x++, line, TERM_WHITE, L' ');
  822. }
  823. /* Print and bump line counter */
  824. c_prt(attr, buf, line, cur_x);
  825. line++;
  826. /* Page wrap */
  827. if (!in_term && (line == max) && disp_count != total_count) {
  828. prt("-- more --", line, x);
  829. anykey();
  830. /* Clear the screen */
  831. for (line = 1; line <= max; line++)
  832. prt("", line, 0);
  833. /* Reprint Message */
  834. prt(format("You can see %d monster%s",
  835. los_count, (los_count > 0 ? (los_count == 1 ?
  836. ":" : "s:") : "s.")),
  837. 0, 0);
  838. /* Reset */
  839. line = 1;
  840. }
  841. }
  842. /* Message for monsters outside LOS, if there are any */
  843. if (total_count > los_count) {
  844. /* Leave a blank line */
  845. line++;
  846. prt(format("You are aware of %d %smonster%s",
  847. (total_count - los_count),
  848. (los_count > 0 ? "other " : ""),
  849. ((total_count - los_count) == 1 ? ":" : "s:")), line++,
  850. 0);
  851. }
  852. /* Print out non-LOS monsters in descending order */
  853. for (i = 0; (i < type_count) && (line < max); i++) {
  854. int out_of_los = list[order[i]].count - list[order[i]].los;
  855. /* Skip if there are none of these out of LOS */
  856. if (list[order[i]].count == list[order[i]].los)
  857. continue;
  858. /* Reset position */
  859. cur_x = x;
  860. /* Note that these have been displayed */
  861. disp_count += out_of_los;
  862. /* Get monster race and name */
  863. r_ptr = &r_info[order[i]];
  864. get_mon_name(m_name, sizeof(m_name), r_ptr, out_of_los);
  865. /* Display uniques in a special colour */
  866. if (rf_has(r_ptr->flags, RF_UNIQUE))
  867. attr = TERM_VIOLET;
  868. else if (r_ptr->level > p_ptr->danger)
  869. attr = TERM_RED;
  870. else
  871. attr = TERM_WHITE;
  872. /* Build the monster name */
  873. if (out_of_los == 1) {
  874. if (list[order[i]].asleep == 1)
  875. strnfmt(buf, sizeof(buf), "%s (asleep) ", m_name);
  876. else if (list[order[i]].neutral == 1)
  877. strnfmt(buf, sizeof(buf), "%s (neutral) ", m_name);
  878. else
  879. strnfmt(buf, sizeof(buf), "%s ", m_name);
  880. } else {
  881. if (list[order[i]].asleep == 0) {
  882. if (list[order[i]].neutral == 0)
  883. strnfmt(buf, sizeof(buf), "%s", m_name);
  884. else
  885. strnfmt(buf, sizeof(buf), "%s (%d neutral) ",
  886. m_name, list[order[i]].neutral);
  887. } else {
  888. if (list[order[i]].neutral == 0)
  889. strnfmt(buf, sizeof(buf), "%s (%d asleep) ",
  890. m_name, list[order[i]].asleep);
  891. else
  892. strnfmt(buf, sizeof(buf),
  893. "%s (%d asleep, %d neutral) ", m_name,
  894. list[order[i]].asleep, list[order[i]].neutral);
  895. }
  896. }
  897. /* Display the pict */
  898. if ((tile_width == 1) && (tile_height == 1)) {
  899. Term_putch(cur_x++, line, list[order[i]].attr, r_ptr->x_char);
  900. Term_putch(cur_x++, line, TERM_WHITE, L' ');
  901. }
  902. /* Print and bump line counter */
  903. c_prt(attr, buf, line, cur_x);
  904. line++;
  905. /* Page wrap */
  906. if (!in_term && (line == max) && disp_count != total_count) {
  907. prt("-- more --", line, x);
  908. anykey();
  909. /* Clear the screen */
  910. for (line = 1; line <= max; line++)
  911. prt("", line, 0);
  912. /* Reprint Message */
  913. prt(format("You are aware of %d %smonster%s",
  914. (total_count - los_count), (los_count > 0 ?
  915. "other " : ""),
  916. ((total_count - los_count) >
  917. 0 ? ((total_count - los_count) == 1 ? ":" : "s:")
  918. : "s.")), 0, 0);
  919. /* Reset */
  920. line = 1;
  921. }
  922. }
  923. /* Print "and others" message if we've run out of space */
  924. if (disp_count != total_count) {
  925. strnfmt(buf, sizeof buf, " ...and %d others.",
  926. total_count - disp_count);
  927. c_prt(TERM_WHITE, buf, line, x);
  928. }
  929. /* Otherwise clear a line at the end, for main-term display */
  930. else
  931. prt("", line, x);
  932. if (!in_term)
  933. Term_addstr(-1, TERM_WHITE, " (Press any key to continue.)");
  934. /* Free the arrays */
  935. FREE(list);
  936. FREE(order);
  937. }
  938. /**
  939. * Build a string describing a monster in some way.
  940. *
  941. * We can correctly describe monsters based on their visibility.
  942. * We can force all monsters to be treated as visible or invisible.
  943. * We can build nominatives, objectives, possessives, or reflexives.
  944. * We can selectively pronominalize hidden, visible, or all monsters.
  945. * We can use definite or indefinite descriptions for hidden monsters.
  946. * We can use definite or indefinite descriptions for visible monsters.
  947. *
  948. * Pronominalization involves the gender whenever possible and allowed,
  949. * so that by cleverly requesting pronominalization / visibility, you
  950. * can get messages like "You hit someone. She screams in agony!".
  951. *
  952. * Reflexives are acquired by requesting Objective plus Possessive.
  953. *
  954. * I am assuming that no monster name is more than 65 characters long,
  955. * so that "char desc[80];" is sufficiently large for any result, even
  956. * when the "offscreen" notation is added.
  957. *
  958. * Note that the "possessive" for certain unique monsters will look
  959. * really silly, as in "Morgoth, King of Darkness's". We should
  960. * perhaps add a flag to "remove" any "descriptives" in the name.
  961. *
  962. * Note that "offscreen" monsters will get a special "(offscreen)"
  963. * notation in their name if they are visible but offscreen. This
  964. * may look silly with possessives, as in "the rat's (offscreen)".
  965. * Perhaps the "offscreen" descriptor should be abbreviated.
  966. *
  967. * Mode Flags:
  968. * - 0x01 --> Objective (or Reflexive)
  969. * - 0x02 --> Possessive (or Reflexive)
  970. * - 0x04 --> Use indefinites for hidden monsters ("something")
  971. * - 0x08 --> Use indefinites for visible monsters ("a kobold")
  972. * - 0x10 --> Pronominalize hidden monsters
  973. * - 0x20 --> Pronominalize visible monsters
  974. * - 0x40 --> Assume the monster is hidden
  975. * - 0x80 --> Assume the monster is visible
  976. * - 0x100 --> Capitalise monster name
  977. *
  978. * Useful Modes:
  979. * - 0x00 --> Full nominative name ("the kobold") or "it"
  980. * - 0x04 --> Full nominative name ("the kobold") or "something"
  981. * - 0x80 --> Genocide resistance name ("the kobold")
  982. * - 0x88 --> Killing name ("a kobold")
  983. * - 0x22 --> Possessive, genderized if visable ("his") or "its"
  984. * - 0x23 --> Reflexive, genderized if visable ("himself") or "itself"
  985. */
  986. void monster_desc(char *desc, size_t max, monster_type * m_ptr, int mode)
  987. {
  988. const char *res;
  989. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  990. const char *name = r_ptr->name;
  991. char undead_name[40] = "oops";
  992. bool seen, pron;
  993. /* Can we "see" it (forced, or not hidden + visible) */
  994. seen = ((mode & (0x80)) || (!(mode & (0x40)) && m_ptr->ml));
  995. /* Sexed Pronouns (seen and forced, or unseen and allowed) */
  996. pron = ((seen && (mode & (0x20))) || (!seen && (mode & (0x10))));
  997. /* First, try using pronouns, or describing hidden monsters */
  998. if (!seen || pron) {
  999. /* an encoding of the monster "sex" */
  1000. int kind = 0x00;
  1001. /* Extract the gender (if applicable) */
  1002. if (rf_has(r_ptr->flags, RF_FEMALE))
  1003. kind = 0x20;
  1004. else if (rf_has(r_ptr->flags, RF_MALE))
  1005. kind = 0x10;
  1006. /* Ignore the gender (if desired) */
  1007. if (!m_ptr || !pron)
  1008. kind = 0x00;
  1009. /* Assume simple result */
  1010. res = "it";
  1011. /* Brute force: split on the possibilities */
  1012. switch (kind + (mode & 0x07)) {
  1013. /* Neuter, or unknown */
  1014. case 0x00:
  1015. res = "it";
  1016. break;
  1017. case 0x01:
  1018. res = "it";
  1019. break;
  1020. case 0x02:
  1021. res = "its";
  1022. break;
  1023. case 0x03:
  1024. res = "itself";
  1025. break;
  1026. case 0x04:
  1027. res = "something";
  1028. break;
  1029. case 0x05:
  1030. res = "something";
  1031. break;
  1032. case 0x06:
  1033. res = "something's";
  1034. break;
  1035. case 0x07:
  1036. res = "itself";
  1037. break;
  1038. /* Male (assume human if vague) */
  1039. case 0x10:
  1040. res = "he";
  1041. break;
  1042. case 0x11:
  1043. res = "him";
  1044. break;
  1045. case 0x12:
  1046. res = "his";
  1047. break;
  1048. case 0x13:
  1049. res = "himself";
  1050. break;
  1051. case 0x14:
  1052. res = "someone";
  1053. break;
  1054. case 0x15:
  1055. res = "someone";
  1056. break;
  1057. case 0x16:
  1058. res = "someone's";
  1059. break;
  1060. case 0x17:
  1061. res = "himself";
  1062. break;
  1063. /* Female (assume human if vague) */
  1064. case 0x20:
  1065. res = "she";
  1066. break;
  1067. case 0x21:
  1068. res = "her";
  1069. break;
  1070. case 0x22:
  1071. res = "her";
  1072. break;
  1073. case 0x23:
  1074. res = "herself";
  1075. break;
  1076. case 0x24:
  1077. res = "someone";
  1078. break;
  1079. case 0x25:
  1080. res = "someone";
  1081. break;
  1082. case 0x26:
  1083. res = "someone's";
  1084. break;
  1085. case 0x27:
  1086. res = "herself";
  1087. break;
  1088. }
  1089. /* Copy the result */
  1090. my_strcpy(desc, res, max);
  1091. }
  1092. /* Handle visible monsters, "reflexive" request */
  1093. else if ((mode & 0x02) && (mode & 0x01)) {
  1094. /* The monster is visible, so use its gender */
  1095. if (rf_has(r_ptr->flags, RF_FEMALE))
  1096. my_strcpy(desc, "herself", max);
  1097. else if (rf_has(r_ptr->flags, RF_MALE))
  1098. my_strcpy(desc, "himself", max);
  1099. else
  1100. my_strcpy(desc, "itself", max);
  1101. }
  1102. /* Handle all other visible monster requests */
  1103. else {
  1104. const char *race_name = NULL;
  1105. /* Get a racial prefix if necessary */
  1106. if (m_ptr->p_race != NON_RACIAL)
  1107. race_name = p_info[m_ptr->p_race].name;
  1108. /* It could be a player ghost. */
  1109. if (rf_has(r_ptr->flags, RF_PLAYER_GHOST)) {
  1110. /* Get the ghost name. */
  1111. my_strcpy(desc, ghost_name, max);
  1112. /* Get the undead name. */
  1113. my_strcpy(undead_name, r_ptr->name, max);
  1114. /* Build the ghost name. */
  1115. my_strcat(desc, ", the ", max);
  1116. my_strcat(desc, undead_name, max);
  1117. }
  1118. /* It could be a Unique */
  1119. else if (rf_has(r_ptr->flags, RF_UNIQUE)) {
  1120. /* Start with the name (thus nominative and objective) */
  1121. my_strcpy(desc, name, max);
  1122. }
  1123. /* It could be an indefinite monster */
  1124. else if (mode & 0x08) {
  1125. bool vowel;
  1126. char first[2];
  1127. if (race_name)
  1128. vowel = is_a_vowel(race_name[0]);
  1129. else
  1130. vowel = is_a_vowel(name[0]);
  1131. /* XXX Check plurality for "some" */
  1132. /* Indefinite monsters need an indefinite article */
  1133. my_strcpy(desc, vowel ? "an " : "a ", max);
  1134. /* Hack - no capital if there's a race name first */
  1135. if (race_name) {
  1136. my_strcat(desc, race_name, max);
  1137. my_strcat(desc, " ", max);
  1138. first[0] = tolower(name[0]);
  1139. first[1] = '\0';
  1140. my_strcat(desc, first, max);
  1141. my_strcat(desc, name + 1, max);
  1142. } else
  1143. my_strcat(desc, name, max);
  1144. }
  1145. /* It could be a normal, definite, monster */
  1146. else {
  1147. char first[2];
  1148. /* Definite monsters need a definite article */
  1149. my_strcpy(desc, "the ", max);
  1150. /* Hack - no capital if there's a race name first */
  1151. if (race_name) {
  1152. my_strcat(desc, race_name, max);
  1153. my_strcat(desc, " ", max);
  1154. first[0] = tolower(name[0]);
  1155. first[1] = '\0';
  1156. my_strcat(desc, first, max);
  1157. my_strcat(desc, name + 1, max);
  1158. } else
  1159. my_strcat(desc, name, max);
  1160. }
  1161. /* Handle the Possessive as a special afterthought */
  1162. if (mode & 0x02) {
  1163. /* XXX Check for trailing "s" */
  1164. /* Simply append "apostrophe" and "s" */
  1165. my_strcat(desc, "'s", max);
  1166. }
  1167. /* Mention "offscreen" monsters XXX XXX */
  1168. if (!panel_contains(m_ptr->fy, m_ptr->fx)) {
  1169. /* Append special notation */
  1170. my_strcat(desc, " (offscreen)", max);
  1171. }
  1172. }
  1173. if (mode & 0x100)
  1174. my_strcap(desc);
  1175. }
  1176. /**
  1177. * Build a string describing a monster race, currently used for quests.
  1178. *
  1179. * Assumes a singular monster. This may need to be run through the
  1180. * plural_aux function in the quest.c file. (Changes "wolf" to
  1181. * wolves, etc.....)
  1182. *
  1183. * I am assuming that no monster name is more than 65 characters long,
  1184. * so that "char desc[80];" is sufficiently large for any result, even
  1185. * when the "offscreen" notation is added.
  1186. *
  1187. */
  1188. void monster_desc_race(char *desc, size_t max, int r_idx)
  1189. {
  1190. monster_race *r_ptr = &r_info[r_idx];
  1191. /* Write the name */
  1192. my_strcpy(desc, r_ptr->name, max);
  1193. }
  1194. /**
  1195. * Learn about a monster (by "probing" it)
  1196. */
  1197. void lore_do_probe(int m_idx)
  1198. {
  1199. monster_type *m_ptr = &m_list[m_idx];
  1200. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  1201. monster_lore *l_ptr = &l_list[m_ptr->r_idx];
  1202. /* Hack -- Memorize some flags */
  1203. rf_copy(l_ptr->flags, r_ptr->flags);
  1204. /* Update monster recall window */
  1205. if (p_ptr->monster_race_idx == m_ptr->r_idx) {
  1206. /* Redraw stuff */
  1207. p_ptr->redraw |= (PR_MONSTER);
  1208. }
  1209. }
  1210. /**
  1211. * Take note that the given monster just dropped some treasure
  1212. *
  1213. * Note that learning the "GOOD"/"GREAT" flags gives information
  1214. * about the treasure (even when the monster is killed for the first
  1215. * time, such as uniques, and the treasure has not been examined yet).
  1216. *
  1217. * This "indirect" method is used to prevent the player from learning
  1218. * exactly how much treasure a monster can drop from observing only
  1219. * a single example of a drop. This method actually observes how much
  1220. * gold and items are dropped, and remembers that information to be
  1221. * described later by the monster recall code.
  1222. */
  1223. void lore_treasure(int m_idx, int num_item, int num_gold)
  1224. {
  1225. monster_type *m_ptr = &m_list[m_idx];
  1226. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  1227. monster_lore *l_ptr = &l_list[m_ptr->r_idx];
  1228. /* Note the number of things dropped */
  1229. if (num_item > l_ptr->drop_item)
  1230. l_ptr->drop_item = num_item;
  1231. if (num_gold > l_ptr->drop_gold)
  1232. l_ptr->drop_gold = num_gold;
  1233. /* Hack -- memorize the good/great/chest flags */
  1234. if (rf_has(r_ptr->flags, RF_DROP_GOOD))
  1235. rf_on(l_ptr->flags, RF_DROP_GOOD);
  1236. if (rf_has(r_ptr->flags, RF_DROP_GREAT))
  1237. rf_on(l_ptr->flags, RF_DROP_GREAT);
  1238. if (rf_has(r_ptr->flags, RF_DROP_CHEST))
  1239. rf_on(l_ptr->flags, RF_DROP_CHEST);
  1240. /* Update monster recall window */
  1241. if (p_ptr->monster_race_idx == m_ptr->r_idx) {
  1242. /* Redraw stuff */
  1243. p_ptr->redraw |= (PR_MONSTER);
  1244. }
  1245. }
  1246. /**
  1247. * This function updates the monster record of the given monster
  1248. *
  1249. * This involves extracting the distance to the player (if requested),
  1250. * and then checking for visibility (natural, infravision, see-invis,
  1251. * telepathy), updating the monster visibility flag, redrawing (or
  1252. * erasing) the monster when its visibility changes, and taking note
  1253. * of any interesting monster flags (cold-blooded, invisible, etc).
  1254. *
  1255. * Note the new "mflag" field which encodes several monster state flags,
  1256. * including "view" for when the monster is currently in line of sight,
  1257. * and "mark" for when the monster is currently visible via detection.
  1258. *
  1259. * The only monster fields that are changed here are "cdis" (the
  1260. * distance from the player), "ml" (visible to the player), and
  1261. * "mflag" (to maintain the MFLAG_VIEW flag).
  1262. *
  1263. * Note the special update_monsters() function which can be used to
  1264. * call this function once for every monster.
  1265. *
  1266. * Note the "full" flag which requests that the "cdis" field be updated,
  1267. * this is only needed when the monster (or the player) has moved.
  1268. *
  1269. * Every time a monster moves, we must call this function for that
  1270. * monster, and update the distance, and the visibility. Every time
  1271. * the player moves, we must call this function for every monster, and
  1272. * update the distance, and the visibility. Whenever the player "state"
  1273. * changes in certain ways ("blindness", "infravision", "telepathy",
  1274. * and "see invisible"), we must call this function for every monster,
  1275. * and update the visibility.
  1276. *
  1277. * Routines that change the "illumination" of a grid must also call this
  1278. * function for any monster in that grid, since the "visibility" of some
  1279. * monsters may be based on the illumination of their grid.
  1280. *
  1281. * Note that this function is called once per monster every time the
  1282. * player moves. When the player is running, this function is one
  1283. * of the primary bottlenecks, along with update_view() and the
  1284. * process_monsters() code, so efficiency is important.
  1285. *
  1286. * Note the optimized "inline" version of the distance() function.
  1287. *
  1288. * A monster is "visible" to the player if (1) it has been detected
  1289. * by the player, (2) it is close to the player and the player has
  1290. * telepathy, or (3) it is close to the player, and in line of sight
  1291. * of the player, and it is "illuminated" by some combination of
  1292. * infravision, torch light, or permanent light (invisible monsters
  1293. * are only affected by "light" if the player can see invisible).
  1294. *
  1295. * Monsters which are not on the current panel may be "visible" to
  1296. * the player, and their descriptions will include an "offscreen"
  1297. * reference. Currently, offscreen monsters cannot be targetted
  1298. * or viewed directly, but old targets will remain set. XXX XXX
  1299. *
  1300. * The player can choose to be disturbed by several things, including
  1301. * disturb_move (monster which is viewable moves in some way), and
  1302. * disturb_near (monster which is "easily" viewable moves in some
  1303. * way). Note that "moves" includes "appears" and "disappears".
  1304. */
  1305. void update_mon(int m_idx, bool full)
  1306. {
  1307. monster_type *m_ptr = &m_list[m_idx];
  1308. monster_race *r_ptr = &r_info[m_ptr->r_idx];
  1309. monster_lore *l_ptr = &l_list[m_ptr->r_idx];
  1310. int d;
  1311. /* Current location */
  1312. int fy = m_ptr->fy;
  1313. int fx = m_ptr->fx;
  1314. /* Seen at all */
  1315. bool flag = FALSE;
  1316. /* Seen by vision */
  1317. bool easy = FALSE;
  1318. /* Compute distance */
  1319. if (full) {
  1320. int py = p_ptr->py;
  1321. int px = p_ptr->px;
  1322. /* Distance components */
  1323. int dy = (py > fy) ? (py - fy) : (fy - py);
  1324. int dx = (px > fx) ? (px - fx) : (fx - px);
  1325. /* Approximate distance */
  1326. d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1));
  1327. /* Restrict distance */
  1328. if (d > 255)
  1329. d = 255;
  1330. /* Save the distance */
  1331. m_ptr->cdis = d;
  1332. }
  1333. /* Extract distance */
  1334. else {
  1335. /* Extract the distance */
  1336. d = m_ptr->cdis;
  1337. }
  1338. /* Detected */
  1339. if (m_ptr->mflag & (MFLAG_MARK))
  1340. flag = TRUE;
  1341. /* Nearby */
  1342. if (d <= (p_ptr->themed_level ? MAX_SIGHT / 2 : MAX_SIGHT)) {
  1343. /* Basic telepathy */
  1344. if (p_ptr->state.telepathy || p_ptr->timed[TMD_TELEPATHY]) {
  1345. /* Empty mind, no telepathy */
  1346. if (rf_has(r_ptr->flags, RF_EMPTY_MIND)) {
  1347. /* Memorize flags */
  1348. rf_on(l_ptr->flags, RF_EMPTY_MIND);
  1349. }
  1350. /* Weird mind, occasional telepathy */
  1351. else if (rf_has(r_ptr->flags, RF_WEIRD_MIND)) {
  1352. /* Monster is rarely detectable */
  1353. if (((turn / 10) % 10) == (m_idx % 10)) {
  1354. /* Detectable */
  1355. notice_obj(OF_TELEPATHY, 0);
  1356. flag = TRUE;
  1357. /* Memorize flags */
  1358. rf_on(l_ptr->flags, RF_WEIRD_MIND);
  1359. /* Hack -- Memorize mental flags */
  1360. if (rf_has(r_ptr->flags, RF_SMART))
  1361. rf_on(l_ptr->flags, RF_SMART);
  1362. if (rf_has(r_ptr->flags, RF_STUPID))
  1363. rf_on(l_ptr->flags, RF_STUPID);
  1364. }
  1365. }
  1366. /* Normal mind, allow telepathy */
  1367. else {
  1368. /* Detectable */
  1369. notice_obj(OF_TELEPATHY, 0);
  1370. flag = TRUE;
  1371. /* Hack -- Memorize mental flags */
  1372. if (rf_has(r_ptr->flags, RF_SMART))
  1373. rf_on(l_ptr->flags, RF_SMART);
  1374. if (rf_has(r_ptr->flags, RF_STUPID))
  1375. rf_on(l_ptr->flags, RF_STUPID);
  1376. }
  1377. }
  1378. /* Normal line of sight, and not blind */
  1379. if (player_has_los_bold(fy, fx) && !p_ptr->timed[TMD_BLIND]) {
  1380. bool do_invisible = FALSE;
  1381. bool do_cold_blood = FALSE;
  1382. /* Use "infravision" */
  1383. if (d <= p_ptr->state.see_infra) {
  1384. /* Handle "cold blooded" monsters */
  1385. if (rf_has(r_ptr->flags, RF_COLD_BLOOD)) {
  1386. /* Take note */
  1387. do_cold_blood = TRUE;
  1388. }
  1389. /* Handle "warm blooded" monsters */
  1390. else {
  1391. /* Easy to see */
  1392. easy = flag = TRUE;
  1393. }
  1394. }
  1395. /* Use "illumination" */
  1396. if (player_can_see_bold(fy, fx)) {
  1397. /* Handle "invisible" monsters */
  1398. if (rf_has(r_ptr->flags, RF_INVISIBLE)) {
  1399. /* Take note */
  1400. do_invisible = TRUE;
  1401. /* See invisible */
  1402. if (p_ptr->state.see_inv) {
  1403. /* Easy to see */
  1404. notice_obj(OF_SEE_INVIS, 0);
  1405. easy = flag = TRUE;
  1406. }
  1407. }
  1408. /* Handle "normal" monsters */
  1409. else {
  1410. /* Easy to see */
  1411. easy = flag = TRUE;
  1412. }
  1413. }
  1414. /* Visible */
  1415. if (flag) {
  1416. /* Memorize flags */
  1417. if (do_invisible)
  1418. rf_on(l_ptr->flags, RF_INVISIBLE);
  1419. if (do_cold_blood)
  1420. rf_on(l_ptr->flags, RF_COLD_BLOOD);
  1421. }
  1422. }
  1423. }
  1424. /* The monster is now visible */
  1425. if (flag) {
  1426. /* It was previously unseen */
  1427. if (!m_ptr->ml) {
  1428. /* Mark as visible */
  1429. m_ptr->ml = TRUE;
  1430. /* Draw the monster */
  1431. light_spot(fy, fx);
  1432. /* Update health bar as needed */
  1433. if (p_ptr->health_who == m_idx)
  1434. p_ptr->redraw |= (PR_HEALTH | PR_MON_MANA);
  1435. /* Hack -- Count "fresh" sightings */
  1436. if (l_ptr->sights < MAX_SHORT)
  1437. l_ptr->sights++;
  1438. /* Disturb on appearance */
  1439. if (OPT(disturb_move) && (m_ptr->hostile == -1))
  1440. disturb(1, 0);
  1441. /* Redraw stuff */
  1442. p_ptr->redraw |= PR_MONLIST;
  1443. }
  1444. }
  1445. /* The monster is not visible */
  1446. else {
  1447. /* It was previously seen */
  1448. if (m_ptr->ml) {
  1449. /* Mark as not visible */
  1450. m_ptr->ml = FALSE;
  1451. /* Erase the monster */
  1452. light_spot(fy, fx);
  1453. /* Update health bar as needed */
  1454. if (p_ptr->health_who == m_idx)
  1455. p_ptr->redraw |= (PR_HEALTH | PR_MON_MANA);
  1456. /* Disturb on disappearance */
  1457. if (OPT(disturb_move) && (m_ptr->hostile == -1))
  1458. disturb(1, 0);
  1459. /* Redraw stuff */
  1460. p_ptr->redraw |= PR_MONLIST;
  1461. }
  1462. }
  1463. /* The monster is now easily visible */
  1464. if (easy) {
  1465. /* Change */
  1466. if (!(m_ptr->mflag & (MFLAG_VIEW))) {
  1467. /* Mark as easily visible */
  1468. m_ptr->mflag |= (MFLAG_VIEW);
  1469. /* Disturb on appearance */
  1470. if (OPT(disturb_near) && (m_ptr->hostile == -1))
  1471. disturb(1, 0);
  1472. /* Re-draw monster window */
  1473. p_ptr->redraw |= PR_MONLIST;
  1474. }
  1475. }
  1476. /* The monster is not easily visible */
  1477. else {
  1478. /* Change */
  1479. if (m_ptr->mflag & (MFLAG_VIEW)) {
  1480. /* Mark as not easily visible */
  1481. m_ptr->mflag &= ~(MFLAG_VIEW);
  1482. /* Disturb on disappearance */
  1483. if (OPT(disturb_near) && (m_ptr->hostile == -1))
  1484. disturb(1, 0);
  1485. /* Re-draw monster window */
  1486. p_ptr->redraw |= PR_MONLIST;
  1487. }
  1488. }
  1489. }
  1490. /**
  1491. * This function simply updates all the (non-dead) monsters (see above).
  1492. */
  1493. void update_monsters(bool full)
  1494. {
  1495. int i;
  1496. /* Update each (live) monster */
  1497. for (i = 1; i < m_max; i++) {
  1498. monster_type *m_ptr = &m_list[i];
  1499. /* Skip dead monsters */
  1500. if (!m_ptr->r_idx)
  1501. continue;
  1502. /* Update the monster */
  1503. update_mon(i, full);
  1504. }
  1505. }
  1506. /**
  1507. * Make a monster carry an object
  1508. */
  1509. s16b monster_carry(int m_idx, object_type * j_ptr)
  1510. {
  1511. s16b o_idx;
  1512. s16b this_o_idx, next_o_idx = 0;
  1513. monster_type *m_ptr = &m_list[m_idx];
  1514. /* Scan objects already being held for combination */
  1515. for (this_o_idx = m_ptr->hold_o_idx; this_o_idx;
  1516. this_o_idx = next_o_idx) {
  1517. object_type *o_ptr;
  1518. /* Acquire object */
  1519. o_ptr = &o_list[this_o_idx];
  1520. /* Acquire next object */
  1521. next_o_idx = o_ptr->next_o_idx;
  1522. /* Check for combination */
  1523. if (object_similar(o_ptr, j_ptr, OSTACK_MONSTER)) {
  1524. /* Combine the items */
  1525. object_absorb(o_ptr, j_ptr);
  1526. /* Result */
  1527. return (this_o_idx);
  1528. }
  1529. }
  1530. /* Make an object */
  1531. o_idx = o_pop();
  1532. /* Success */
  1533. if (o_idx) {
  1534. object_type *o_ptr;
  1535. /* Get new object */
  1536. o_ptr = &o_list[o_idx];
  1537. /* Copy object */
  1538. object_copy(o_ptr, j_ptr);
  1539. /* Forget mark */
  1540. o_ptr->marked = FALSE;
  1541. /* Forget location */
  1542. o_ptr->iy = o_ptr->ix = 0;
  1543. /* Memorize monster */
  1544. o_ptr->held_m_idx = m_idx;
  1545. /* Build stack */
  1546. o_ptr->next_o_idx = m_ptr->hold_o_idx;
  1547. /* Build stack */
  1548. m_ptr->hold_o_idx = o_idx;
  1549. }
  1550. /* Result */
  1551. return (o_idx);
  1552. }
  1553. /**
  1554. * See whether all surrounding squares are trap detected
  1555. */
  1556. bool is_detected(int y, int x)
  1557. {
  1558. int d, xx, yy;
  1559. feature_type *f_ptr;
  1560. /* Check around (and under) the character */
  1561. for (d = 0; d < 9; d++) {
  1562. /* Extract adjacent (legal) location */
  1563. yy = y + ddy_ddd[d];
  1564. xx = x + ddx_ddd[d];
  1565. /* Paranoia */
  1566. if (!in_bounds_fully(yy, xx))
  1567. continue;
  1568. /* Only check trappable grids */
  1569. f_ptr = &f_info[cave_feat[yy][xx]];
  1570. if (!tf_has(f_ptr->flags, TF_TRAP))
  1571. continue;
  1572. /* Return false if undetected */
  1573. if (!cave_has(cave_info[yy][xx], CAVE_DTRAP))
  1574. return (FALSE);
  1575. }
  1576. /* Must be OK */
  1577. return (TRUE);
  1578. }
  1579. /**
  1580. * Swap the players/monsters (if any) at two locations XXX XXX XXX
  1581. */
  1582. void monster_swap(int y1, int x1, int y2, int x2)
  1583. {
  1584. int m1, m2;
  1585. int y_offset, x_offset;
  1586. int old_y_offset = p_ptr->py / CHUNK_HGT;
  1587. int old_x_offset = p_ptr->px / CHUNK_WID;
  1588. bool player_moved = FALSE;
  1589. monster_type *m_ptr;
  1590. /* Monsters */
  1591. m1 = cave_m_idx[y1][x1];
  1592. m2 = cave_m_idx[y2][x2];
  1593. /* Update grids */
  1594. cave_m_idx[y1][x1] = m2;
  1595. cave_m_idx[y2][x2] = m1;
  1596. /* Monster 1 */
  1597. if (m1 > 0) {
  1598. m_ptr = &m_list[m1];
  1599. /* Make sure it's really there */
  1600. if (m_ptr->r_idx != 0) {
  1601. /* Move monster */
  1602. m_ptr->fy = y2;
  1603. m_ptr->fx = x2;
  1604. /* Update monster */
  1605. update_mon(m1, TRUE);
  1606. /* Redraw monster list */
  1607. p_ptr->redraw |= (PR_MONLIST);
  1608. } else
  1609. delete_monster_idx(m1);
  1610. }
  1611. /* Player 1 */
  1612. else if (m1 < 0) {
  1613. /* Move player */
  1614. p_ptr->py = y2;
  1615. p_ptr->px = x2;
  1616. player_moved = TRUE;
  1617. }
  1618. /* Monster 2 */
  1619. if (m2 > 0) {
  1620. m_ptr = &m_list[m2];
  1621. /* Make sure it's really there */
  1622. if (m_ptr->r_idx != 0) {
  1623. /* Move monster */
  1624. m_ptr->fy = y1;
  1625. m_ptr->fx = x1;
  1626. /* Update monster */
  1627. update_mon(m2, TRUE);
  1628. /* Redraw monster list */
  1629. p_ptr->redraw |= (PR_MONLIST);
  1630. } else
  1631. delete_monster_idx(m2);
  1632. }
  1633. /* Player 2 */
  1634. else if (m2 < 0) {
  1635. /* Move player */
  1636. p_ptr->py = y1;
  1637. p_ptr->px = x1;
  1638. player_moved = TRUE;
  1639. }
  1640. /* Did the player move? */
  1641. if (player_moved) {
  1642. bool old_dtrap, new_dtrap;
  1643. /* Calculate changes in dtrap status */
  1644. old_dtrap = cave_has(cave_info[y1][x1], CAVE_DTRAP);
  1645. new_dtrap = is_detected(y2, x2);
  1646. /* Note the change in the detect status */
  1647. p_ptr->redraw |= (PR_DTRAP);
  1648. /* Update the panel */
  1649. p_ptr->update |= (PU_PANEL);
  1650. /* Update the visuals (and monster distances) */
  1651. p_ptr->update |= (PU_UPDATE_VIEW | PU_DISTANCE);
  1652. /* Redraw stuff */
  1653. p_ptr->redraw |= PR_MAP;
  1654. /* Redraw monster list */
  1655. p_ptr->redraw |= (PR_MONLIST);
  1656. /* Warn when leaving trap detected region */
  1657. if (OPT(disturb_detect) && old_dtrap && !new_dtrap) {
  1658. /* Disturb to break runs */
  1659. disturb(0, 0);
  1660. }
  1661. }
  1662. /* Redraw */
  1663. light_spot(y1, x1);
  1664. light_spot(y2, x2);
  1665. /* Deal with change of chunk */
  1666. y_offset = p_ptr->py / CHUNK_HGT;
  1667. x_offset = p_ptr->px / CHUNK_WID;
  1668. /* On the surface, re-align */
  1669. if (p_ptr->danger == 0) {
  1670. if ((y_offset != 1) || (x_offset != 1))
  1671. chunk_change(0, y_offset, x_offset);
  1672. }
  1673. /* In the dungeon, change stage */
  1674. else {
  1675. int y0 = old_y_offset - y_offset;
  1676. int x0 = old_x_offset - x_offset;
  1677. int adj_index = chunk_offset_to_adjacent(0, 1 - y0, 1 - x0);
  1678. if (adj_index != DIR_NONE) {
  1679. p_ptr->last_stage = p_ptr->stage;
  1680. p_ptr->stage = chunk_list[p_ptr->stage

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