4 * Summary: Functions used to print information about various game objects.
5 * Written by: Linley Henzell
17 // If you add any more description types, remember to also
18 // change item_description in externs.h
19 enum item_description_type
23 IDESC_SCROLLS
, // special field (like the others)
30 enum book_mem_or_forget
39 std::ostringstream body
;
47 void append_spells(std::string
&desc
, const item_def
&item
);
49 bool is_dumpable_artefact(const item_def
&item
, bool verbose
);
51 std::string
get_item_description(const item_def
&item
, bool verbose
,
52 bool dump
= false, bool noquote
= false);
54 std::string
god_title(god_type which_god
, species_type which_species
);
55 void describe_god(god_type which_god
, bool give_title
);
57 void describe_feature_wide(const coord_def
& pos
, bool show_quote
= false);
58 void get_feature_desc(const coord_def
&gc
, describe_info
&inf
);
60 void set_feature_desc_long(const std::string
&raw_name
,
61 const std::string
&desc
);
63 void set_feature_quote(const std::string
&raw_name
,
64 const std::string
"e
);
66 bool describe_item(item_def
&item
, bool allow_inscribe
= false,
67 bool shopping
= false);
68 void get_item_desc(const item_def
&item
, describe_info
&inf
,
70 void inscribe_item(item_def
&item
, bool msgwin
);
72 void append_weapon_stats(std::string
&description
, const item_def
&item
);
73 void append_armour_stats(std::string
&description
, const item_def
&item
);
74 void append_missile_info(std::string
&description
);
76 void describe_monsters(const monster_info
&mi
, bool force_seen
= false,
77 const std::string
&footer
= "",
78 bool wait_until_key_pressed
= true,
79 bool show_quote
= false);
81 void get_monster_db_desc(const monster_info
&mi
, describe_info
&inf
,
82 bool &has_stat_desc
, bool force_seen
= false);
84 void get_spell_desc(const spell_type spell
, describe_info
&inf
);
85 void describe_spell(spell_type spelled
, const item_def
* item
= NULL
);
87 std::string
short_ghost_description(const monster
*mon
, bool abbrev
= false);
88 std::string
get_ghost_description(const monster_info
&mi
, bool concise
= false);
90 std::string
get_skill_description(skill_type skill
, bool need_title
= false);
92 void describe_skill(skill_type skill
);
95 std::string
get_command_description(const command_type cmd
,
99 void print_description(const std::string
&desc
);
100 void print_description(const describe_info
&inf
);
102 void print_quote (const describe_info
&inf
);
103 void print_quote (const std::string
&desc
);
105 template<class T
> void process_description(T
&proc
, const describe_info
&inf
);
106 template<class T
> void process_quote(T
&proc
, const describe_info
&inf
);
108 void trim_randart_inscrip(item_def
& item
);
109 std::string
artefact_auto_inscription(const item_def
& item
);
110 void add_autoinscription(item_def
&item
, std::string ainscrip
);
111 void add_autoinscription(item_def
&item
);
112 void add_inscription(item_def
&item
, std::string inscrip
);
114 const char *trap_name(trap_type trap
);
115 int str_to_trap(const std::string
&s
);
117 int count_desc_lines(const std::string _desc
, const int width
);
122 alt_desc_proc(int _w
, int _h
) { w
= _w
; h
= _h
; }
124 int width() { return w
; }
125 int height() { return h
; }
128 void print(const std::string
&str
);
129 static int count_newlines(const std::string
&str
);
131 // Remove trailing newlines.
132 static void trim(std::string
&str
);
133 // rfind consecutive newlines and truncate.
134 static bool chop(std::string
&str
);
136 void get_string(std::string
&str
);
141 std::ostringstream ostr
;
144 /* ***********************************************************************
145 * template implementations
146 * *********************************************************************** */
147 // My kingdom for a closure.
149 inline void process_description(T
&proc
, const describe_info
&inf
)
151 const unsigned int line_width
= proc
.width();
152 const int height
= proc
.height();
156 // How many lines is the title; we also seem to be adding 1 to
158 int num_lines
= count_desc_lines(inf
.title
, line_width
) + 1;
160 int body_lines
= count_desc_lines(inf
.body
.str(), line_width
);
161 const int suffix_lines
= count_desc_lines(inf
.suffix
, line_width
);
162 const int prefix_lines
= count_desc_lines(inf
.prefix
, line_width
);
163 const int footer_lines
= count_desc_lines(inf
.footer
, line_width
)
164 + (inf
.footer
.empty() ? 0 : 1);
166 // Maybe skip the body if body + title would be too many lines.
167 if (inf
.title
.empty())
169 desc
= inf
.body
.str();
170 // There is a default 1 line addition for some reason.
171 num_lines
= body_lines
+ 1;
173 else if (body_lines
+ num_lines
+ 2 <= height
)
175 desc
= inf
.title
+ "\n\n";
176 desc
+= inf
.body
.str();
177 // Got 2 lines from the two \ns that weren't counted yet.
178 num_lines
+= body_lines
+ 2;
181 desc
= inf
.title
+ "\n";
183 // Prefer the footer over the suffix.
184 if (num_lines
+ suffix_lines
+ footer_lines
<= height
)
186 desc
= desc
+ inf
.suffix
;
187 num_lines
+= suffix_lines
;
190 // Prefer the footer over the prefix.
191 if (num_lines
+ prefix_lines
+ footer_lines
<= height
)
193 desc
= inf
.prefix
+ desc
;
194 num_lines
+= prefix_lines
;
197 if (!inf
.footer
.empty() && num_lines
+ footer_lines
<= height
)
199 const int bottom_line
= std::min(std::max(24, num_lines
+ 2),
200 height
- footer_lines
+ 1);
201 const int newlines
= bottom_line
- num_lines
;
205 desc
.append(newlines
, '\n');
206 desc
= desc
+ inf
.footer
;
210 std::string::size_type nextLine
= std::string::npos
;
211 unsigned int currentPos
= 0;
213 while (currentPos
< desc
.length())
218 // See if '\n' is within one line_width.
219 nextLine
= desc
.find('\n', currentPos
);
221 if (nextLine
>= currentPos
&& nextLine
< currentPos
+ line_width
)
223 proc
.print(desc
.substr(currentPos
, nextLine
-currentPos
));
224 currentPos
= nextLine
+ 1;
228 // Handle real line breaks. No substitutions necessary, just update
230 nextLine
= desc
.find('\n', currentPos
);
231 if (nextLine
>= currentPos
&& nextLine
< currentPos
+ line_width
)
233 proc
.print(desc
.substr(currentPos
, nextLine
-currentPos
));
234 currentPos
= nextLine
+ 1;
238 // No newline -- see if rest of string will fit.
239 if (currentPos
+ line_width
>= desc
.length())
241 proc
.print(desc
.substr(currentPos
));
246 // Ok, try to truncate at space.
247 nextLine
= desc
.rfind(' ', currentPos
+ line_width
);
251 proc
.print(desc
.substr(currentPos
, nextLine
- currentPos
));
252 currentPos
= nextLine
+ 1;
256 // Oops. Just truncate.
257 nextLine
= currentPos
+ line_width
;
259 nextLine
= std::min(inf
.body
.str().length(), nextLine
);
261 proc
.print(desc
.substr(currentPos
, nextLine
- currentPos
));
262 currentPos
= nextLine
;
267 inline void process_quote(T
&proc
, const describe_info
&inf
)
269 const unsigned int line_width
= proc
.width();
270 const int height
= proc
.height();
274 // How many lines is the title; we also seem to be adding 1 to
276 int num_lines
= count_desc_lines(inf
.title
, line_width
) + 1;
278 int body_lines
= count_desc_lines(inf
.quote
, line_width
);
280 // Maybe skip the body if body + title would be too many lines.
281 if (inf
.title
.empty())
284 // There is a default 1 line addition for some reason.
285 num_lines
= body_lines
+ 1;
287 else if (body_lines
+ num_lines
+ 2 <= height
)
289 desc
= inf
.title
+ "\n\n";
291 // Got 2 lines from the two \ns that weren't counted yet.
292 num_lines
+= body_lines
+ 2;
295 desc
= inf
.title
+ "\n";
297 if (num_lines
<= height
)
299 const int bottom_line
= std::min(std::max(24, num_lines
+ 2),
301 const int newlines
= bottom_line
- num_lines
;
305 desc
.append(newlines
, '\n');
309 std::string::size_type nextLine
= std::string::npos
;
310 unsigned int currentPos
= 0;
312 while (currentPos
< desc
.length())
317 // See if '\n' is within one line_width.
318 nextLine
= desc
.find('\n', currentPos
);
320 if (nextLine
>= currentPos
&& nextLine
< currentPos
+ line_width
)
322 proc
.print(desc
.substr(currentPos
, nextLine
-currentPos
));
323 currentPos
= nextLine
+ 1;
327 // Handle real line breaks. No substitutions necessary, just update
329 nextLine
= desc
.find('\n', currentPos
);
330 if (nextLine
>= currentPos
&& nextLine
< currentPos
+ line_width
)
332 proc
.print(desc
.substr(currentPos
, nextLine
-currentPos
));
333 currentPos
= nextLine
+ 1;
337 // No newline -- see if rest of string will fit.
338 if (currentPos
+ line_width
>= desc
.length())
340 proc
.print(desc
.substr(currentPos
));
345 // Ok, try to truncate at space.
346 nextLine
= desc
.rfind(' ', currentPos
+ line_width
);
350 proc
.print(desc
.substr(currentPos
, nextLine
- currentPos
));
351 currentPos
= nextLine
+ 1;
355 // Oops. Just truncate.
356 nextLine
= currentPos
+ line_width
;
358 nextLine
= std::min(inf
.body
.str().length(), nextLine
);
360 proc
.print(desc
.substr(currentPos
, nextLine
- currentPos
));
361 currentPos
= nextLine
;