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