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 *);
163 vpline(YouMessage(tmp, "You ", line), VA_ARGS);
165 vpline(YouMessage(tmp, "
\82 \82È
\82½
\82Í", line), VA_ARGS);
171 VA_DECL(const char *, line)
175 VA_INIT(line, const char *);
177 vpline(YouMessage(tmp, "Your ", line), VA_ARGS);
179 vpline(YouMessage(tmp, "
\82 \82È
\82½
\82Ì", line), VA_ARGS);
185 VA_DECL(const char *, line)
189 VA_INIT(line, const char *);
192 YouPrefix(tmp, "You dream that you feel ", line);
194 YouPrefix(tmp, "
\82 \82È
\82½
\82Í
\96²
\82Ì
\92\86\82Å", line);
197 YouPrefix(tmp, "You feel ", line);
199 YouPrefix(tmp, "
\82 \82È
\82½
\82Í", line);
200 vpline(strcat(tmp, line), VA_ARGS);
206 VA_DECL(const char *, line)
210 VA_INIT(line, const char *);
212 vpline(YouMessage(tmp, "You can't ", line), VA_ARGS);
214 vpline(YouMessage(tmp, "
\82 \82È
\82½
\82Í", line), VA_ARGS);
220 VA_DECL(const char *, line)
224 VA_INIT(line, const char *);
226 vpline(YouMessage(tmp, "The ", line), VA_ARGS);
228 vpline(YouMessage(tmp, "", line), VA_ARGS);
234 VA_DECL(const char *, line)
238 VA_INIT(line, const char *);
240 vpline(YouMessage(tmp, "There ", line), VA_ARGS);
242 vpline(YouMessage(tmp, "", line), VA_ARGS);
248 VA_DECL(const char *, line)
256 if (Deaf || !flags.acoustics)
259 VA_INIT(line, const char *);
262 YouPrefix(tmp, "You barely hear ", line);
264 YouPrefix(tmp, "You dream that you hear ", line);
266 YouPrefix(tmp, "You hear ", line);
267 vpline(strcat(tmp, line), VA_ARGS);
270 adj = "
\82©
\82·
\82©
\82É";
272 adj = "
\96²
\82Ì
\92\86\82Å";
275 tmp = You_buf(strlen(adj) + strlen(line) + sizeof("
\82 \82È
\82½
\82Í "));
277 p = (char *)strstr(line, "
\95·
\82±") ;
279 Strcpy(tmp, "
\82 \82È
\82½
\82Í");
282 if (p != NULL || (p = (char *)strstr(line, "
\95·
\82¢")) != NULL){
283 strncat(tmp, line, (p - line));
289 vpline(tmp, VA_ARGS);
296 VA_DECL(const char *, line)
301 VA_INIT(line, const char *);
304 YouPrefix(tmp, "You dream that you see ", line);
306 YouPrefix(tmp, "
\82 \82È
\82½
\82Í
\96²
\82Ì
\92\86\82Å", line);
307 #if 0 /*JP*//*
\82±
\82±
\82Í
\8cÄ
\82Ñ
\8fo
\82µ
\8c³
\82Å
\8f\88\97\9d\82·
\82é?*/
308 else if (Blind) /* caller should have caught this... */
309 YouPrefix(tmp, "You sense ", line);
313 YouPrefix(tmp, "You see ", line);
315 YouPrefix(tmp, "
\82 \82È
\82½
\82Í", line);
316 vpline(strcat(tmp, line), VA_ARGS);
320 /* Print a message inside double-quotes.
321 * The caller is responsible for checking deafness.
322 * Gods can speak directly to you in spite of deafness.
326 VA_DECL(const char *, line)
331 VA_INIT(line, const char *);
333 tmp = You_buf((int) strlen(line) + sizeof "\"\"");
338 tmp = You_buf((int) strlen(line) + sizeof "
\81u
\81v");
343 vpline(tmp, VA_ARGS);
348 /* Note that these declarations rely on knowledge of the internals
349 * of the variable argument handling stuff in "tradstdc.h"
352 #if defined(USE_STDARG) || defined(USE_VARARGS)
353 static void FDECL(vraw_printf, (const char *, va_list));
356 VA_DECL(const char *, line)
359 VA_INIT(line, char *);
360 vraw_printf(line, VA_ARGS);
366 vraw_printf(const char *line, va_list the_args)
369 vraw_printf(line, the_args)
374 #else /* USE_STDARG | USE_VARARG */
377 VA_DECL(const char *, line)
380 char pbuf[3 * BUFSZ];
382 /* Do NOT use VA_START and VA_END in here... see above */
384 if (index(line, '%')) {
385 Vsprintf(pbuf, line, VA_ARGS);
388 if ((ln = (int) strlen(line)) > BUFSZ - 1) {
390 line = strncpy(pbuf, line, BUFSZ - 1);
391 /* unlike pline, we don't futz around to keep last few chars */
392 pbuf[BUFSZ - 1] = '\0'; /* terminate strncpy or truncate vsprintf */
395 #if !(defined(USE_STDARG) || defined(USE_VARARGS))
396 VA_END(); /* (see vpline) */
402 VA_DECL(const char *, s)
404 char pbuf[2 * BUFSZ];
406 VA_INIT(s, const char *);
407 if (program_state.in_impossible)
408 panic("impossible called impossible");
410 program_state.in_impossible = 1;
411 Vsprintf(pbuf, s, VA_ARGS);
412 pbuf[BUFSZ - 1] = '\0'; /* sanity */
413 paniclog("impossible", pbuf);
416 pline("Program in disorder - perhaps you'd better #quit.");
418 pline("
\83v
\83\8d\83O
\83\89\83\80\82É
\8fá
\8aQ
\94
\90¶ - #quit
\82µ
\82½
\82Ù
\82¤
\82ª
\82æ
\82³
\82»
\82¤
\82¾
\81D");
419 program_state.in_impossible = 0;
427 switch ((int) alignment) {
442 return "
\92\81\8f\98";
457 register struct monst *mtmp;
459 aligntyp alignment = mon_aligntyp(mtmp);
460 char info[BUFSZ], monnambuf[BUFSZ];
465 Strcat(info, ", tame");
467 Strcat(info, ",
\8e\94\82¢
\82È
\82ç
\82³
\82ê
\82Ä
\82¢
\82é");
469 Sprintf(eos(info), " (%d", mtmp->mtame);
471 Sprintf(eos(info), "; hungry %ld; apport %d",
472 EDOG(mtmp)->hungrytime, EDOG(mtmp)->apport);
475 } else if (mtmp->mpeaceful)
477 Strcat(info, ", peaceful");
479 Strcat(info, ",
\97F
\8dD
\93I");
480 if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
481 /* don't reveal the innate form (chameleon, vampire, &c),
482 just expose the fact that this current form isn't it */
484 Strcat(info, ", shapechanger");
487 /* pets eating mimic corpses mimic while eating, so this comes first */
490 Strcat(info, ", eating");
492 Strcat(info, ",
\90H
\8e\96\92\86");
493 /* a stethoscope exposes mimic before getting here so this
494 won't be relevant for it, but wand of probing doesn't */
496 Sprintf(eos(info), ", mimicking %s",
497 (mtmp->m_ap_type == M_AP_FURNITURE)
498 ? an(defsyms[mtmp->mappearance].explanation)
499 : (mtmp->m_ap_type == M_AP_OBJECT)
500 ? ((mtmp->mappearance == GOLD_PIECE)
502 : an(simple_typename(mtmp->mappearance)))
503 : (mtmp->m_ap_type == M_AP_MONSTER)
504 ? an(mons[mtmp->mappearance].mname)
505 : something); /* impossible... */
508 Strcat(info, ", cancelled");
510 Strcat(info, ",
\96³
\97Í");
513 Strcat(info, ", confused");
515 Strcat(info, ",
\8d¬
\97\90\8fó
\91Ô");
516 if (mtmp->mblinded || !mtmp->mcansee)
518 Strcat(info, ", blind");
520 Strcat(info, ",
\96Ó
\96Ú");
523 Strcat(info, ", stunned");
525 Strcat(info, ",
\82
\82ç
\82
\82ç
\8fó
\91Ô");
528 Strcat(info, ", asleep");
530 Strcat(info, ",
\90\87\96°
\8fó
\91Ô");
531 #if 0 /* unfortunately mfrozen covers temporary sleep and being busy \
532 (donning armor, for instance) as well as paralysis */
533 else if (mtmp->mfrozen) Strcat(info, ", paralyzed");
535 else if (mtmp->mfrozen || !mtmp->mcanmove)
537 Strcat(info, ", can't move");
539 Strcat(info, ",
\93®
\82¯
\82È
\82¢");
541 /* [arbitrary reason why it isn't moving] */
542 else if (mtmp->mstrategy & STRAT_WAITMASK)
544 Strcat(info, ", meditating");
546 Strcat(info, ",
\96»
\91z
\92\86");
549 Strcat(info, ", scared");
551 Strcat(info, ",
\8b¯
\82¦
\82Ä
\82¢
\82é");
554 Strcat(info, ", trapped");
556 Strcat(info, ", ã©
\82É
\82©
\82©
\82Á
\82Ä
\82¢
\82é");
559 Strcat(info, mtmp->mspeed == MFAST ? ", fast" : mtmp->mspeed == MSLOW
563 Strcat(info, mtmp->mspeed == MFAST ? ",
\91f
\91\81\82¢" : mtmp->mspeed == MSLOW
565 : ",
\91¬
\93x
\95s
\96¾");
567 if (mtmp->mundetected)
569 Strcat(info, ", concealed");
571 Strcat(info, ",
\89B
\82ê
\82Ä
\82¢
\82é");
574 Strcat(info, ", invisible");
576 Strcat(info, ",
\95s
\89Â
\8e\8b");
577 if (mtmp == u.ustuck)
579 Strcat(info, sticks(youmonst.data)
581 : !u.uswallow ? ", holding you"
582 : attacktype_fordmg(u.ustuck->data,
585 : is_animal(u.ustuck->data)
587 : ", engulfing you");
589 Strcat(info, sticks(youmonst.data)
590 ? ",
\82 \82È
\82½
\82ª
\92Í
\82Ü
\82¦
\82Ä
\82¢
\82é"
591 : !u.uswallow ? ",
\92Í
\82Ü
\82¦
\82Ä
\82¢
\82é"
592 : attacktype_fordmg(u.ustuck->data,
594 ? ",
\8fÁ
\89»
\82µ
\82Ä
\82¢
\82é"
595 : is_animal(u.ustuck->data)
596 ? ",
\88ù
\82Ý
\8d\9e\82ñ
\82Å
\82¢
\82é"
597 : ",
\8aª
\82«
\8d\9e\82ñ
\82Å
\82¢
\82é");
599 if (mtmp == u.usteed)
601 Strcat(info, ", carrying you");
603 Strcat(info, ",
\82 \82È
\82½
\82ð
\8fæ
\82¹
\82Ä
\82¢
\82é");
605 /* avoid "Status of the invisible newt ..., invisible" */
606 /* and unlike a normal mon_nam, use "saddled" even if it has a name */
607 Strcpy(monnambuf, x_monnam(mtmp, ARTICLE_THE, (char *) 0,
608 (SUPPRESS_IT | SUPPRESS_INVISIBLE), FALSE));
611 pline("Status of %s (%s): Level %d HP %d(%d) AC %d%s.", monnambuf,
613 pline("%s
\82Ì
\8fó
\91Ô (%s)
\81F Level %d HP %d(%d) AC %d%s", monnambuf,
614 align_str(alignment), mtmp->m_lev, mtmp->mhp, mtmp->mhpmax,
615 find_mac(mtmp), info);
626 Strcat(info, ", dying from");
627 if (u.usick_type & SICK_VOMITABLE)
628 Strcat(info, " food poisoning");
629 if (u.usick_type & SICK_NONVOMITABLE) {
630 if (u.usick_type & SICK_VOMITABLE)
631 Strcat(info, " and");
632 Strcat(info, " illness");
636 if (u.usick_type & SICK_VOMITABLE)
637 Strcat(info, "
\90H
\92\86\93Å");
638 if (u.usick_type & SICK_NONVOMITABLE) {
639 if (u.usick_type & SICK_VOMITABLE)
640 Strcat(info, "
\82Æ");
641 Strcat(info, "
\95a
\8bC");
643 Strcat(info, "
\82Å
\8e\80\82É
\82Â
\82Â
\82 \82é");
648 Strcat(info, ", solidifying");
650 Strcat(info, ",
\90Î
\89»
\82µ
\82Â
\82Â
\82 \82é");
653 Strcat(info, ", becoming slimy");
655 Strcat(info, ",
\83X
\83\89\83C
\83\80\82É
\82È
\82è
\82Â
\82Â
\82 \82é");
658 Strcat(info, ", being strangled");
660 Strcat(info, ",
\8eñ
\82ð
\8di
\82ß
\82ç
\82ê
\82Ä
\82¢
\82é");
663 Strcat(info, ", nauseated"); /* !"nauseous" */
665 Strcat(info, ",
\93f
\82«
\8bC
\82ª
\82·
\82é");
669 Strcat(info, ", confused");
671 Strcat(info, ",
\8d¬
\97\90\8fó
\91Ô");
674 Strcat(info, ", blind");
676 if ((long) u.ucreamed < Blinded || Blindfolded
677 || !haseyes(youmonst.data))
678 Strcat(info, ", cover");
679 Strcat(info, "ed by sticky goop");
680 } /* note: "goop" == "glop"; variation is intentional */
684 Strcat(info, "
\82Ë
\82Î
\82Ë
\82Î
\82×
\82Æ
\82Â
\82
\82à
\82Ì
\82Å");
685 if ((long)u.ucreamed < Blinded || Blindfolded
686 || !haseyes(youmonst.data))
687 Strcat(info, "
\95¢
\82í
\82ê
\82Ä");
689 Strcat(info, "
\96Ó
\96Ú
\8fó
\91Ô");
694 Strcat(info, ", stunned");
696 Strcat(info, ",
\82
\82ç
\82
\82ç
\8fó
\91Ô");
697 if (!u.usteed && Wounded_legs) {
698 const char *what = body_part(LEG);
699 if ((Wounded_legs & BOTH_SIDES) == BOTH_SIDES)
700 what = makeplural(what);
702 Sprintf(eos(info), ", injured %s", what);
704 Sprintf(eos(info), ", %s
\82É
\82¯
\82ª
\82ð
\82µ
\82Ä
\82¢
\82é", what);
708 Sprintf(eos(info), ", slippery %s", makeplural(body_part(HAND)));
710 Sprintf(eos(info), ", %s
\82ª
\82Ê
\82é
\82Ê
\82é", makeplural(body_part(HAND)));
713 Strcat(info, ", trapped");
715 Strcat(info, ", ã©
\82É
\82©
\82©
\82Á
\82Ä
\82¢
\82é");
718 Strcat(info, Very_fast ? ", very fast" : ", fast");
720 Strcat(info, Very_fast ? ",
\82Æ
\82Ä
\82à
\91f
\91\81\82¢" : ",
\91f
\91\81\82¢");
723 Strcat(info, ", concealed");
725 Strcat(info, ",
\89B
\82ê
\82Ä
\82¢
\82é");
728 Strcat(info, ", invisible");
730 Strcat(info, ",
\95s
\89Â
\8e\8b");
733 if (sticks(youmonst.data))
734 Strcat(info, ", holding ");
736 Strcat(info, ", held by ");
737 Strcat(info, mon_nam(u.ustuck));
740 Strcat(info, mon_nam(u.ustuck));
741 if (sticks(youmonst.data))
742 Strcat(info, "
\82ð
\92Í
\82Ü
\82¦
\82Ä
\82¢
\82é");
744 Strcat(info, "
\82É
\92Í
\82Ü
\82¦
\82ç
\82ê
\82Ä
\82¢
\82é");
749 pline("Status of %s (%s%s): Level %d HP %d(%d) AC %d%s.", plname,
751 pline("%s
\82Ì
\8fó
\91Ô (%s %s)
\81F Level %d HP %d(%d) AC %d%s", plname,
752 (u.ualign.record >= 20)
757 : (u.ualign.record > 13)
762 : (u.ualign.record > 8)
767 : (u.ualign.record > 3)
771 ? "
\90º
\82Ì
\82©
\82ñ
\8d\82\82¢"
772 : (u.ualign.record == 3)
774 : (u.ualign.record >= 1)
779 : (u.ualign.record == 0)
788 align_str(u.ualign.type),
789 Upolyd ? mons[u.umonnum].mlevel : u.ulevel, Upolyd ? u.mh : u.uhp,
790 Upolyd ? u.mhmax : u.uhpmax, u.uac, info);
798 Hallucination ? "Far out, man! You" : "Gee! All of a sudden, you",
799 See_invisible ? "can see right through yourself"
800 : "can't see yourself");
802 pline("%s
\82 \82È
\82½
\82Í%s
\81D",
803 Hallucination ? "
\83\8f\81[
\83I
\81I" : "
\82°
\81I
\93Ë
\91R",
804 See_invisible ? "
\8e©
\95ª
\8e©
\90g
\82ª
\82¿
\82á
\82ñ
\82Æ
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½"
805 : "
\8e©
\95ª
\8e©
\90g
\82ª
\8c©
\82¦
\82È
\82
\82È
\82Á
\82½");
810 pudding_merge_message(otmp, otmp2)
815 cansee(otmp->ox, otmp->oy) || cansee(otmp2->ox, otmp2->oy);
816 boolean onfloor = otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR;
817 boolean inpack = carried(otmp) || carried(otmp2);
819 /* the player will know something happened inside his own inventory */
820 if ((!Blind && visible) || inpack) {
823 You_see("parts of the floor melting!");
825 Your("pack reaches out and grabs something!");
827 /* even though we can see where they should be,
828 * they'll be out of our view (minvent or container)
829 * so don't actually show anything */
830 } else if (onfloor || inpack) {
831 pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
832 inpack ? " inside your pack" : "");
835 You_hear("a faint sloshing sound.");