1 | /* SCCS Id: @(#)pline.c 3.3 1999/11/28 */
2 | /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 | /* NetHack may be freely redistributed. See license for details. */
4 |
5 | #define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers */
6 | #include "hack.h"
7 | #include "epri.h"
8 |
9 | #ifdef OVLB
10 |
11 | static boolean no_repeat = FALSE;
12 |
13 | static char *FDECL(You_buf, (int));
14 |
15 | /*VARARGS1*/
16 | /* Note that these declarations rely on knowledge of the internals
17 | * of the variable argument handling stuff in "tradstdc.h"
18 | */
19 |
20 | #if defined(USE_STDARG) || defined(USE_VARARGS)
21 | static void FDECL(vpline, (const char *, va_list));
22 |
23 | void
24 | pline VA_DECL(const char *, line)
25 | VA_START(line);
26 | VA_INIT(line, char *);
27 | vpline(line, VA_ARGS);
28 | VA_END();
29 | }
30 |
31 | # ifdef USE_STDARG
32 | static void
33 | vpline(const char *line, va_list the_args) {
34 | # else
35 | static void
36 | vpline(line, the_args) const char *line; va_list the_args; {
37 | # endif
38 |
39 | #else /* USE_STDARG | USE_VARARG */
40 |
41 | #define vpline pline
42 |
43 | void
44 | pline VA_DECL(const char *, line)
45 | #endif /* USE_STDARG | USE_VARARG */
46 |
47 | char pbuf[BUFSZ];
48 | /* Do NOT use VA_START and VA_END in here... see above */
49 |
50 | if (!line || !*line) return;
51 | if (index(line, '%')) {
52 | Vsprintf(pbuf,line,VA_ARGS);
53 | line = pbuf;
54 | }
55 | if (!iflags.window_inited) {
56 | raw_print(line);
57 | return;
58 | }
59 | #ifndef MAC
60 | if (no_repeat && !strcmp(line, toplines))
61 | return;
62 | #endif /* MAC */
63 | if (vision_full_recalc) vision_recalc(0);
64 | if (u.ux) flush_screen(1); /* %% */
65 | putstr(WIN_MESSAGE, 0, line);
66 | }
67 |
68 | /*VARARGS1*/
69 | void
70 | Norep VA_DECL(const char *, line)
71 | VA_START(line);
72 | VA_INIT(line, const char *);
73 | no_repeat = TRUE;
74 | vpline(line, VA_ARGS);
75 | no_repeat = FALSE;
76 | VA_END();
77 | return;
78 | }
79 |
80 | /* work buffer for You(), &c and verbalize() */
81 | static char *you_buf = 0;
82 | static int you_buf_siz = 0;
83 |
84 | static char *
85 | You_buf(siz)
86 | int siz;
87 | {
88 | if (siz > you_buf_siz) {
89 | if (you_buf) free((genericptr_t) you_buf);
90 | you_buf_siz = siz + 10;
91 | you_buf = (char *) alloc((unsigned) you_buf_siz);
92 | }
93 | return you_buf;
94 | }
95 |
96 | void
97 | free_youbuf()
98 | {
99 | if (you_buf) free((genericptr_t) you_buf), you_buf = (char *)0;
100 | you_buf_siz = 0;
101 | }
102 |
103 | /* `prefix' must be a string literal, not a pointer */
104 | #define YouPrefix(pointer,prefix,text) \
105 | Strcpy((pointer = You_buf((int)(strlen(text) + sizeof prefix))), prefix)
106 |
107 | #define YouMessage(pointer,prefix,text) \
108 | strcat((YouPrefix(pointer, prefix, text), pointer), text)
109 |
110 | /*VARARGS1*/
111 | void
112 | You VA_DECL(const char *, line)
113 | char *tmp;
114 | VA_START(line);
115 | VA_INIT(line, const char *);
116 | vpline(YouMessage(tmp, "You ", line), VA_ARGS);
117 | VA_END();
118 | }
119 |
120 | /*VARARGS1*/
121 | void
122 | Your VA_DECL(const char *,line)
123 | char *tmp;
124 | VA_START(line);
125 | VA_INIT(line, const char *);
126 | vpline(YouMessage(tmp, "Your ", line), VA_ARGS);
127 | VA_END();
128 | }
129 |
130 | /*VARARGS1*/
131 | void
132 | You_feel VA_DECL(const char *,line)
133 | char *tmp;
134 | VA_START(line);
135 | VA_INIT(line, const char *);
136 | vpline(YouMessage(tmp, "You feel ", line), VA_ARGS);
137 | VA_END();
138 | }
139 |
140 |
141 | /*VARARGS1*/
142 | void
143 | You_cant VA_DECL(const char *,line)
144 | char *tmp;
145 | VA_START(line);
146 | VA_INIT(line, const char *);
147 | vpline(YouMessage(tmp, "You can't ", line), VA_ARGS);
148 | VA_END();
149 | }
150 |
151 | /*VARARGS1*/
152 | void
153 | pline_The VA_DECL(const char *,line)
154 | char *tmp;
155 | VA_START(line);
156 | VA_INIT(line, const char *);
157 | vpline(YouMessage(tmp, "The ", line), VA_ARGS);
158 | VA_END();
159 | }
160 |
161 | /*VARARGS1*/
162 | void
163 | There VA_DECL(const char *,line)
164 | char *tmp;
165 | VA_START(line);
166 | VA_INIT(line, const char *);
167 | vpline(YouMessage(tmp, "There ", line), VA_ARGS);
168 | VA_END();
169 | }
170 |
171 | /*VARARGS1*/
172 | void
173 | You_hear VA_DECL(const char *,line)
174 | char *tmp;
175 | VA_START(line);
176 | VA_INIT(line, const char *);
177 | if (Underwater)
178 | YouPrefix(tmp, "You barely hear ", line);
179 | else if (u.usleep)
180 | YouPrefix(tmp, "You dream that you hear ", line);
181 | else
182 | YouPrefix(tmp, "You hear ", line);
183 | vpline(strcat(tmp, line), VA_ARGS);
184 | VA_END();
185 | }
186 |
187 | /*VARARGS1*/
188 | void
189 | verbalize VA_DECL(const char *,line)
190 | char *tmp;
191 | if (!flags.soundok) return;
192 | VA_START(line);
193 | VA_INIT(line, const char *);
194 | tmp = You_buf((int)strlen(line) + sizeof "\"\"");
195 | Strcpy(tmp, "\"");
196 | Strcat(tmp, line);
197 | Strcat(tmp, "\"");
198 | vpline(tmp, VA_ARGS);
199 | VA_END();
200 | }
201 |
202 | /*VARARGS1*/
203 | /* Note that these declarations rely on knowledge of the internals
204 | * of the variable argument handling stuff in "tradstdc.h"
205 | */
206 |
207 | #if defined(USE_STDARG) || defined(USE_VARARGS)
208 | static void FDECL(vraw_printf,(const char *,va_list));
209 |
210 | void
211 | raw_printf VA_DECL(const char *, line)
212 | VA_START(line);
213 | VA_INIT(line, char *);
214 | vraw_printf(line, VA_ARGS);
215 | VA_END();
216 | }
217 |
218 | # ifdef USE_STDARG
219 | static void
220 | vraw_printf(const char *line, va_list the_args) {
221 | # else
222 | static void
223 | vraw_printf(line, the_args) const char *line; va_list the_args; {
224 | # endif
225 |
226 | #else /* USE_STDARG | USE_VARARG */
227 |
228 | void
229 | raw_printf VA_DECL(const char *, line)
230 | #endif
231 | /* Do NOT use VA_START and VA_END in here... see above */
232 |
233 | if(!index(line, '%'))
234 | raw_print(line);
235 | else {
236 | char pbuf[BUFSZ];
237 | Vsprintf(pbuf,line,VA_ARGS);
238 | raw_print(pbuf);
239 | }
240 | }
241 |
242 |
243 | /*VARARGS1*/
244 | void
245 | impossible VA_DECL(const char *, s)
246 | VA_START(s);
247 | VA_INIT(s, const char *);
248 | vpline(s,VA_ARGS);
249 | pline("Program in disorder - perhaps you'd better #quit.");
250 | VA_END();
251 | }
252 |
253 | const char *
254 | align_str(alignment)
255 | aligntyp alignment;
256 | {
257 | switch ((int)alignment) {
258 | case A_CHAOTIC: return "chaotic";
259 | case A_NEUTRAL: return "neutral";
260 | case A_LAWFUL: return "lawful";
261 | case A_NONE: return "unaligned";
262 | }
263 | return "unknown";
264 | }
265 |
266 | void
267 | mstatusline(mtmp)
268 | register struct monst *mtmp;
269 | {
270 | aligntyp alignment;
271 | char info[BUFSZ], monnambuf[BUFSZ];
272 |
273 | if (mtmp->ispriest || mtmp->data == &mons[PM_ALIGNED_PRIEST]
274 | || mtmp->data == &mons[PM_ANGEL])
275 | alignment = EPRI(mtmp)->shralign;
276 | else
277 | alignment = mtmp->data->maligntyp;
278 | alignment = (alignment > 0) ? A_LAWFUL :
279 | (alignment < 0) ? A_CHAOTIC :
280 | A_NEUTRAL;
281 |
282 | info[0] = 0;
283 | if (mtmp->mtame) { Strcat(info, ", tame");
284 | #ifdef WIZARD
285 | if (wizard) Sprintf(eos(info), " (%d)", mtmp->mtame);
286 | #endif
287 | }
288 | else if (mtmp->mpeaceful) Strcat(info, ", peaceful");
289 | if (mtmp->meating) Strcat(info, ", eating");
290 | if (mtmp->mcan) Strcat(info, ", cancelled");
291 | if (mtmp->mconf) Strcat(info, ", confused");
292 | if (mtmp->mblinded || !mtmp->mcansee)
293 | Strcat(info, ", blind");
294 | if (mtmp->mstun) Strcat(info, ", stunned");
295 | if (mtmp->msleeping) Strcat(info, ", asleep");
296 | #if 0 /* unfortunately mfrozen covers temporary sleep and being busy
297 | (donning armor, for instance) as well as paralysis */
298 | else if (mtmp->mfrozen) Strcat(info, ", paralyzed");
299 | #else
300 | else if (mtmp->mfrozen || !mtmp->mcanmove)
301 | Strcat(info, ", can't move");
302 | #endif
303 | /* [arbitrary reason why it isn't moving] */
304 | else if (mtmp->mstrategy & STRAT_WAITMASK)
305 | Strcat(info, ", meditating");
306 | else if (mtmp->mflee) Strcat(info, ", scared");
307 | if (mtmp->mtrapped) Strcat(info, ", trapped");
308 | if (mtmp->mspeed) Strcat(info,
309 | mtmp->mspeed == MFAST ? ", fast" :
310 | mtmp->mspeed == MSLOW ? ", slow" :
311 | ", ???? speed");
312 | if (mtmp->mundetected) Strcat(info, ", concealed");
313 | if (mtmp->minvis) Strcat(info, ", invisible");
314 | if (mtmp == u.ustuck) Strcat(info,
315 | (sticks(youmonst.data)) ? ", held by you" :
316 | u.uswallow ? (is_animal(u.ustuck->data) ?
317 | ", swallowed you" :
318 | ", engulfed you") :
319 | ", holding you");
320 | #ifdef STEED
321 | if (mtmp == u.usteed) Strcat(info, ", carrying you");
322 | #endif
323 |
324 | /* avoid "Status of the invisible newt ..., invisible" */
325 | /* and unlike a normal mon_nam, use "saddled" even if it has a name */
326 | Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *)0,
327 | (SUPPRESS_IT|SUPPRESS_INVISIBLE), FALSE));
328 |
329 | pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.",
330 | monnambuf,
331 | align_str(alignment),
332 | mtmp->m_lev,
333 | mtmp->mhp,
334 | mtmp->mhpmax,
335 | find_mac(mtmp),
336 | info);
337 | }
338 |
339 | void
340 | ustatusline()
341 | {
342 | char info[BUFSZ];
343 |
344 | info[0] = '\0';
345 | if (Sick) {
346 | Strcat(info, ", dying from");
347 | if (u.usick_type & SICK_VOMITABLE)
348 | Strcat(info, " food poisoning");
349 | if (u.usick_type & SICK_NONVOMITABLE) {
350 | if (u.usick_type & SICK_VOMITABLE)
351 | Strcat(info, " and");
352 | Strcat(info, " illness");
353 | }
354 | }
355 | if (Stoned) Strcat(info, ", solidifying");
356 | if (Slimed) Strcat(info, ", becoming slimy");
357 | if (Strangled) Strcat(info, ", being strangled");
358 | if (Vomiting) Strcat(info, ", nauseated"); /* !"nauseous" */
359 | if (Confusion) Strcat(info, ", confused");
360 | if (Blind) {
361 | Strcat(info, ", blind");
362 | if (u.ucreamed) {
363 | if ((long)u.ucreamed < Blinded || Blindfolded
364 | || !haseyes(youmonst.data))
365 | Strcat(info, ", cover");
366 | Strcat(info, "ed by sticky goop");
367 | } /* note: "goop" == "glop"; variation is intentional */
368 | }
369 | if (Stunned) Strcat(info, ", stunned");
370 | #ifdef STEED
371 | if (!u.usteed)
372 | #endif
373 | if (Wounded_legs) {
374 | const char *what = body_part(LEG);
375 | if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
376 | what = makeplural(what);
377 | Sprintf(eos(info), ", injured %s", what);
378 | }
379 | if (Glib) Sprintf(eos(info), ", slippery %s",
380 | makeplural(body_part(HAND)));
381 | if (u.utrap) Strcat(info, ", trapped");
382 | if (Fast) Strcat(info, Very_fast ?
383 | ", very fast" : ", fast");
384 | if (u.uundetected) Strcat(info, ", concealed");
385 | if (Invis) Strcat(info, ", invisible");
386 | if (u.ustuck) {
387 | if (sticks(youmonst.data))
388 | Strcat(info, ", holding ");
389 | else
390 | Strcat(info, ", held by ");
391 | Strcat(info, mon_nam(u.ustuck));
392 | }
393 |
394 | pline("Status of %s (%s%s): Level %d HP %d(%d) AC %d%s.",
395 | plname,
396 | (u.ualign.record >= 20) ? "piously " :
397 | (u.ualign.record > 13) ? "devoutly " :
398 | (u.ualign.record > 8) ? "fervently " :
399 | (u.ualign.record > 3) ? "stridently " :
400 | (u.ualign.record == 3) ? "" :
401 | (u.ualign.record >= 1) ? "haltingly " :
402 | (u.ualign.record == 0) ? "nominally " :
403 | "insufficiently ",
404 | align_str(u.ualign.type),
405 | Upolyd ? mons[u.umonnum].mlevel : u.ulevel,
406 | Upolyd ? u.mh : u.uhp,
407 | Upolyd ? u.mhmax : u.uhpmax,
408 | u.uac,
409 | info);
410 | }
411 |
412 | void
413 | self_invis_message()
414 | {
415 | pline("%s %s.",
416 | Hallucination ? "Far out, man! You" : "Gee! All of a sudden, you",
417 | See_invisible ? "can see right through yourself" :
418 | "can't see yourself");
419 | }
420 |
421 | #endif /* OVLB */
422 | /*pline.c*/