1 /* NetHack 3.6 pline.c $NHDT-Date: 1432512770 2015/05/25 00:12:50 $ $NHDT-Branch: master $:$NHDT-Revision: 1.42 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #define NEED_VARARGS /* Uses ... */ /* comment line for pre-compiled headers \
9 static boolean no_repeat = FALSE;
10 static char prevmsg[BUFSZ];
12 static char *FDECL(You_buf, (int));
15 /* Note that these declarations rely on knowledge of the internals
16 * of the variable argument handling stuff in "tradstdc.h"
19 #if defined(USE_STDARG) || defined(USE_VARARGS)
20 static void FDECL(vpline, (const char *, va_list));
23 VA_DECL(const char *, line)
26 VA_INIT(line, char *);
27 vpline(line, VA_ARGS);
33 vpline(const char *line, va_list the_args)
36 vpline(line, the_args)
41 #else /* USE_STDARG | USE_VARARG */
46 VA_DECL(const char *, line)
47 #endif /* USE_STDARG | USE_VARARG */
48 { /* start of vpline() or of nested block in USE_OLDARG's pline() */
52 /* Do NOT use VA_START and VA_END in here... see above */
57 if (program_state.done_hup)
60 if (program_state.wizkit_wishing)
63 if (index(line, '%')) {
64 Vsprintf(pbuf, line, VA_ARGS);
67 if ((ln = (int) strlen(line)) > BUFSZ - 1) {
68 if (line != pbuf) /* no '%' was present */
69 (void) strncpy(pbuf, line, BUFSZ - 1); /* caveat: unterminated */
70 /* truncate, preserving the final 3 characters:
71 "___ extremely long text" -> "___ extremely l...ext"
72 (this may be suboptimal if overflow is less than 3) */
73 (void) strncpy(pbuf + BUFSZ - 1 - 6, "...", 3);
74 /* avoid strncpy; buffers could overlap if excess is small */
75 pbuf[BUFSZ - 1 - 3] = line[ln - 3];
76 pbuf[BUFSZ - 1 - 2] = line[ln - 2];
77 pbuf[BUFSZ - 1 - 1] = line[ln - 1];
78 pbuf[BUFSZ - 1] = '\0';
81 if (!iflags.window_inited) {
83 iflags.last_msg = PLNMSG_UNKNOWN;
87 if (no_repeat && !strcmp(line, toplines))
90 if (vision_full_recalc)
93 flush_screen(1); /* %% */
94 msgtyp = msgtype_type(line);
95 if (msgtyp == MSGTYP_NOSHOW) return;
96 if (msgtyp == MSGTYP_NOREP && !strcmp(line, prevmsg)) return;
97 putstr(WIN_MESSAGE, 0, line);
98 /* this gets cleared after every pline message */
99 iflags.last_msg = PLNMSG_UNKNOWN;
100 strncpy(prevmsg, line, BUFSZ);
101 if (msgtyp == MSGTYP_STOP) display_nhwindow(WIN_MESSAGE, TRUE); /* --more-- */
103 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
104 /* provide closing brace for the nested block
105 which immediately follows USE_OLDARGS's VA_DECL() */
112 VA_DECL(const char *, line)
115 VA_INIT(line, const char *);
117 vpline(line, VA_ARGS);
123 /* work buffer for You(), &c and verbalize() */
124 static char *you_buf = 0;
125 static int you_buf_siz = 0;
131 if (siz > you_buf_siz) {
133 free((genericptr_t) you_buf);
134 you_buf_siz = siz + 10;
135 you_buf = (char *) alloc((unsigned) you_buf_siz);
144 free((genericptr_t) you_buf), you_buf = (char *) 0;
148 /* `prefix' must be a string literal, not a pointer */
149 #define YouPrefix(pointer, prefix, text) \
150 Strcpy((pointer = You_buf((int) (strlen(text) + sizeof prefix))), prefix)
152 #define YouMessage(pointer, prefix, text) \
153 strcat((YouPrefix(pointer, prefix, text), pointer), text)
157 VA_DECL(const char *, line)
161 VA_INIT(line, const char *);
162 vpline(YouMessage(tmp, "You ", line), VA_ARGS);
168 VA_DECL(const char *, line)
172 VA_INIT(line, const char *);
173 vpline(YouMessage(tmp, "Your ", line), VA_ARGS);
179 VA_DECL(const char *, line)
183 VA_INIT(line, const char *);
185 YouPrefix(tmp, "You dream that you feel ", line);
187 YouPrefix(tmp, "You feel ", line);
188 vpline(strcat(tmp, line), VA_ARGS);
194 VA_DECL(const char *, line)
198 VA_INIT(line, const char *);
199 vpline(YouMessage(tmp, "You can't ", line), VA_ARGS);
205 VA_DECL(const char *, line)
209 VA_INIT(line, const char *);
210 vpline(YouMessage(tmp, "The ", line), VA_ARGS);
216 VA_DECL(const char *, line)
220 VA_INIT(line, const char *);
221 vpline(YouMessage(tmp, "There ", line), VA_ARGS);
227 VA_DECL(const char *, line)
231 if (Deaf || !flags.acoustics)
234 VA_INIT(line, const char *);
236 YouPrefix(tmp, "You barely hear ", line);
238 YouPrefix(tmp, "You dream that you hear ", line);
240 YouPrefix(tmp, "You hear ", line);
241 vpline(strcat(tmp, line), VA_ARGS);
247 VA_DECL(const char *, line)
252 VA_INIT(line, const char *);
254 YouPrefix(tmp, "You dream that you see ", line);
255 else if (Blind) /* caller should have caught this... */
256 YouPrefix(tmp, "You sense ", line);
258 YouPrefix(tmp, "You see ", line);
259 vpline(strcat(tmp, line), VA_ARGS);
263 /* Print a message inside double-quotes.
264 * The caller is responsible for checking deafness.
265 * Gods can speak directly to you in spite of deafness.
269 VA_DECL(const char *, line)
274 VA_INIT(line, const char *);
275 tmp = You_buf((int) strlen(line) + sizeof "\"\"");
279 vpline(tmp, VA_ARGS);
284 /* Note that these declarations rely on knowledge of the internals
285 * of the variable argument handling stuff in "tradstdc.h"
288 #if defined(USE_STDARG) || defined(USE_VARARGS)
289 static void FDECL(vraw_printf, (const char *, va_list));
292 VA_DECL(const char *, line)
295 VA_INIT(line, char *);
296 vraw_printf(line, VA_ARGS);
302 vraw_printf(const char *line, va_list the_args)
305 vraw_printf(line, the_args)
310 #else /* USE_STDARG | USE_VARARG */
313 VA_DECL(const char *, line)
316 char pbuf[3 * BUFSZ];
318 /* Do NOT use VA_START and VA_END in here... see above */
320 if (index(line, '%')) {
321 Vsprintf(pbuf, line, VA_ARGS);
324 if ((ln = (int) strlen(line)) > BUFSZ - 1) {
326 line = strncpy(pbuf, line, BUFSZ - 1);
327 /* unlike pline, we don't futz around to keep last few chars */
328 pbuf[BUFSZ - 1] = '\0'; /* terminate strncpy or truncate vsprintf */
331 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
332 VA_END(); /* (see vpline) */
338 VA_DECL(const char *, s)
340 char pbuf[2 * BUFSZ];
342 VA_INIT(s, const char *);
343 if (program_state.in_impossible)
344 panic("impossible called impossible");
346 program_state.in_impossible = 1;
347 Vsprintf(pbuf, s, VA_ARGS);
348 pbuf[BUFSZ - 1] = '\0'; /* sanity */
349 paniclog("impossible", pbuf);
351 pline("Program in disorder - perhaps you'd better #quit.");
352 program_state.in_impossible = 0;
360 switch ((int) alignment) {
375 register struct monst *mtmp;
377 aligntyp alignment = mon_aligntyp(mtmp);
378 char info[BUFSZ], monnambuf[BUFSZ];
382 Strcat(info, ", tame");
384 Sprintf(eos(info), " (%d", mtmp->mtame);
386 Sprintf(eos(info), "; hungry %ld; apport %d",
387 EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport);
390 } else if (mtmp->mpeaceful)
391 Strcat(info, ", peaceful");
392 if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
393 /* don't reveal the innate form (chameleon, vampire, &c),
394 just expose the fact that this current form isn't it */
395 Strcat(info, ", shapechanger");
396 /* pets eating mimic corpses mimic while eating, so this comes first */
398 Strcat(info, ", eating");
399 /* a stethoscope exposes mimic before getting here so this
400 won't be relevant for it, but wand of probing doesn't */
402 Sprintf(eos(info), ", mimicking %s",
403 (mtmp->m_ap_type == M_AP_FURNITURE)
404 ? an(defsyms[mtmp->mappearance].explanation)
405 : (mtmp->m_ap_type == M_AP_OBJECT)
406 ? ((mtmp->mappearance == GOLD_PIECE)
408 : an(simple_typename(mtmp->mappearance)))
409 : (mtmp->m_ap_type == M_AP_MONSTER)
410 ? an(mons[mtmp->mappearance].mname)
411 : something); /* impossible... */
413 Strcat(info, ", cancelled");
415 Strcat(info, ", confused");
416 if (mtmp->mblinded || !mtmp->mcansee)
417 Strcat(info, ", blind");
419 Strcat(info, ", stunned");
421 Strcat(info, ", asleep");
422 #if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
423 (donning armor, for instance) as well as paralysis */
424 else if (mtmp->mfrozen) Strcat(info, ", paralyzed");
426 else if (mtmp->mfrozen || !mtmp->mcanmove)
427 Strcat(info, ", can't move");
429 /* [arbitrary reason why it isn't moving] */
430 else if (mtmp->mstrategy & STRAT_WAITMASK)
431 Strcat(info, ", meditating");
433 Strcat(info, ", scared");
435 Strcat(info, ", trapped");
437 Strcat(info, mtmp->mspeed == MFAST ? ", fast" : mtmp->mspeed == MSLOW
440 if (mtmp->mundetected)
441 Strcat(info, ", concealed");
443 Strcat(info, ", invisible");
444 if (mtmp == u.ustuck)
445 Strcat(info, sticks(youmonst.data)
447 : !u.uswallow ? ", holding you"
448 : attacktype_fordmg(u.ustuck->data,
451 : is_animal(u.ustuck->data)
453 : ", engulfing you");
454 if (mtmp == u.usteed)
455 Strcat(info, ", carrying you");
457 /* avoid "Status of the invisible newt ..., invisible" */
458 /* and unlike a normal mon_nam, use "saddled" even if it has a name */
459 Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
460 (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE));
462 pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", monnambuf,
463 align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax,
464 find_mac(mtmp), info);
474 Strcat(info, ", dying from");
475 if (u.usick_type & SICK_VOMITABLE)
476 Strcat(info, " food poisoning");
477 if (u.usick_type & SICK_NONVOMITABLE) {
478 if (u.usick_type & SICK_VOMITABLE)
479 Strcat(info, " and");
480 Strcat(info, " illness");
484 Strcat(info, ", solidifying");
486 Strcat(info, ", becoming slimy");
488 Strcat(info, ", being strangled");
490 Strcat(info, ", nauseated"); /* !"nauseous" */
492 Strcat(info, ", confused");
494 Strcat(info, ", blind");
496 if ((long) u.ucreamed < Blinded || Blindfolded
497 || !haseyes(youmonst.data))
498 Strcat(info, ", cover");
499 Strcat(info, "ed by sticky goop");
500 } /* note: "goop" == "glop"; variation is intentional */
503 Strcat(info, ", stunned");
504 if (!u.usteed && Wounded_legs) {
505 const char *what = body_part(LEG);
506 if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
507 what = makeplural(what);
508 Sprintf(eos(info), ", injured %s", what);
511 Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND)));
513 Strcat(info, ", trapped");
515 Strcat(info, Very_fast ? ", very fast" : ", fast");
517 Strcat(info, ", concealed");
519 Strcat(info, ", invisible");
521 if (sticks(youmonst.data))
522 Strcat(info, ", holding ");
524 Strcat(info, ", held by ");
525 Strcat(info, mon_nam(u.ustuck));
528 pline("Status of %s (%s%s): Level %d HP %d(%d) AC %d%s.", plname,
529 (u.ualign.record >= 20)
531 : (u.ualign.record > 13)
533 : (u.ualign.record > 8)
535 : (u.ualign.record > 3)
537 : (u.ualign.record == 3)
539 : (u.ualign.record >= 1)
541 : (u.ualign.record == 0)
544 align_str(u.ualign.type),
545 Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
546 Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
553 Hallucination ? "Far out, man! You" : "Gee! All of a sudden, you",
554 See_invisible ? "can see right through yourself"
555 : "can't see yourself");
559 pudding_merge_message(otmp, otmp2)
564 cansee(otmp->ox, otmp->oy) || cansee(otmp2->ox, otmp2->oy);
565 boolean onfloor = otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR;
566 boolean inpack = carried(otmp) || carried(otmp2);
568 /* the player will know something happened inside his own inventory */
569 if ((!Blind && visible) || inpack) {
572 You_see("parts of the floor melting!");
574 Your("pack reaches out and grabs something!");
576 /* even though we can see where they should be,
577 * they'll be out of our view (minvent or container)
578 * so don't actually show anything */
579 } else if (onfloor || inpack) {
580 pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
581 inpack ? " inside your pack" : "");
584 You_hear("a faint sloshing sound.");