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