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*/