1 /**
2 * \file ui-mon-lore.c
3 * \brief Monster memory UI
4 *
5 * Copyright (c) 1997-2007 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
19 #include "angband.h"
20 #include "init.h"
21 #include "mon-lore.h"
22 #include "ui-mon-lore.h"
23 #include "ui-output.h"
24 #include "ui-prefs.h"
25 #include "ui-term.h"
26 #include "z-textblock.h"
27
28 /**
29 * Place a monster recall title into a textblock.
30 *
31 * If graphics are turned on, this appends the title with the appropriate tile.
32 * Note: if the title is the only thing in the textblock, make sure to append a
33 * newline so that the textui stuff works properly.
34 *
35 * \param tb is the textblock we are placing the title into.
36 * \param race is the monster race we are describing.
37 */
lore_title(textblock * tb,const struct monster_race * race)38 void lore_title(textblock *tb, const struct monster_race *race)
39 {
40 byte standard_attr, optional_attr;
41 wchar_t standard_char, optional_char;
42
43 assert(race);
44
45 /* Get the chars */
46 standard_char = race->d_char;
47 optional_char = monster_x_char[race->ridx];
48
49 /* Get the attrs */
50 standard_attr = race->d_attr;
51 optional_attr = monster_x_attr[race->ridx];
52
53 /* A title (use "The" for non-uniques) */
54 if (!rf_has(race->flags, RF_UNIQUE))
55 textblock_append(tb, "The ");
56 else if (OPT(player, purple_uniques)) {
57 standard_attr = COLOUR_VIOLET;
58 if (!(optional_attr & 0x80))
59 optional_attr = COLOUR_VIOLET;
60 }
61
62 /* Dump the name and then append standard attr/char info */
63 textblock_append(tb, "%s", race->name);
64
65 textblock_append(tb, " ('");
66 textblock_append_pict(tb, standard_attr, standard_char);
67 textblock_append(tb, "')");
68
69 if (((optional_attr != standard_attr) || (optional_char != standard_char))
70 && (tile_width == 1) && (tile_height == 1)) {
71 /* Append the "optional" attr/char info */
72 textblock_append(tb, " ('");
73 textblock_append_pict(tb, optional_attr, optional_char);
74 textblock_append(tb, "')");
75 }
76 }
77
78 /**
79 * Place a full monster recall description (with title) into a textblock, with
80 * or without spoilers.
81 *
82 * \param tb is the textblock we are placing the description into.
83 * \param race is the monster race we are describing.
84 * \param original_lore is the known information about the monster race.
85 * \param spoilers indicates what information is used; `true` will display full
86 * information without subjective information and monster flavor,
87 * while `false` only shows what the player knows.
88 */
lore_description(textblock * tb,const struct monster_race * race,const struct monster_lore * original_lore,bool spoilers)89 void lore_description(textblock *tb, const struct monster_race *race,
90 const struct monster_lore *original_lore, bool spoilers)
91 {
92 struct monster_lore mutable_lore;
93 struct monster_lore *lore = &mutable_lore;
94 bitflag known_flags[RF_SIZE];
95
96 assert(tb && race && original_lore);
97
98 /* Hack -- create a copy of the monster-memory that we can modify */
99 memcpy(lore, original_lore, sizeof(struct monster_lore));
100
101 /* Now get the known monster flags */
102 monster_flags_known(race, lore, known_flags);
103
104 /* Spoilers -- know everything */
105 if (spoilers)
106 cheat_monster_lore(race, lore);
107
108 /* Appending the title here simplifies code in the callers. It also causes
109 * a crash when generating spoilers (we don't need titles for them anwyay)*/
110 if (!spoilers) {
111 lore_title(tb, race);
112 textblock_append(tb, "\n");
113 }
114
115 /* Show kills of monster vs. player(s) */
116 if (!spoilers)
117 lore_append_kills(tb, race, lore, known_flags);
118
119 lore_append_flavor(tb, race);
120
121 /* Describe the monster type, speed, life, and armor */
122 lore_append_movement(tb, race, lore, known_flags);
123
124 if (!spoilers)
125 lore_append_toughness(tb, race, lore, known_flags);
126
127 /* Describe the experience and item reward when killed */
128 if (!spoilers)
129 lore_append_exp(tb, race, lore, known_flags);
130
131 lore_append_drop(tb, race, lore, known_flags);
132
133 /* Describe the special properties of the monster */
134 lore_append_abilities(tb, race, lore, known_flags);
135 lore_append_awareness(tb, race, lore, known_flags);
136 lore_append_friends(tb, race, lore, known_flags);
137
138 /* Describe the spells, spell-like abilities and melee attacks */
139 lore_append_spells(tb, race, lore, known_flags);
140 lore_append_attack(tb, race, lore, known_flags);
141
142 /* Do we know everything */
143 if (lore_is_fully_known(race))
144 textblock_append(tb, "You know everything about this monster.");
145
146 /* Notice "Quest" monsters */
147 if (rf_has(race->flags, RF_QUESTOR))
148 textblock_append(tb, "You feel an intense desire to kill this monster... ");
149
150 textblock_append(tb, "\n");
151 }
152
153 /**
154 * Display monster recall modally and wait for a keypress.
155 *
156 * This is intended to be called when the main window is active (hence the
157 * message flushing).
158 *
159 * \param race is the monster race we are describing.
160 * \param lore is the known information about the monster race.
161 */
lore_show_interactive(const struct monster_race * race,const struct monster_lore * lore)162 void lore_show_interactive(const struct monster_race *race,
163 const struct monster_lore *lore)
164 {
165 textblock *tb;
166 assert(race && lore);
167
168 event_signal(EVENT_MESSAGE_FLUSH);
169
170 tb = textblock_new();
171 lore_description(tb, race, lore, false);
172 textui_textblock_show(tb, SCREEN_REGION, NULL);
173 textblock_free(tb);
174 }
175
176 /**
177 * Display monster recall statically.
178 *
179 * This is intended to be called in a subwindow, since it clears the entire
180 * window before drawing, and has no interactivity.
181 *
182 * \param race is the monster race we are describing.
183 * \param lore is the known information about the monster race.
184 */
lore_show_subwindow(const struct monster_race * race,const struct monster_lore * lore)185 void lore_show_subwindow(const struct monster_race *race,
186 const struct monster_lore *lore)
187 {
188 int y;
189 textblock *tb;
190
191 assert(race && lore);
192
193 /* Erase the window, since textui_textblock_place() only clears what it
194 * needs */
195 for (y = 0; y < Term->hgt; y++)
196 Term_erase(0, y, 255);
197
198 tb = textblock_new();
199 lore_description(tb, race, lore, false);
200 textui_textblock_place(tb, SCREEN_REGION, NULL);
201 textblock_free(tb);
202 }
203
204