1/* SCCS Id: @(#)do_name.c 3.4 2003/01/14 */ 2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 3/* NetHack may be freely redistributed. See license for details. */ 4 5#include "hack.h" 6 7#ifdef OVLB 8 9STATIC_DCL void FDECL(do_oname, (struct obj *)); 10static void FDECL(getpos_help, (BOOLEAN_P,const char *)); 11 12extern const char what_is_an_unknown_object[]; /* from pager.c */ 13 14/* the response for '?' help request in getpos() */ 15static void 16getpos_help(force, goal) 17boolean force; 18const char *goal; 19{ 20 char sbuf[BUFSZ]; 21 boolean doing_what_is; 22 winid tmpwin = create_nhwindow(NHW_MENU); 23 24 Sprintf(sbuf, "Use [%s] to move the cursor to %s.", 25 iflags.num_pad ? "2468" : "hjkl", goal); 26 putstr(tmpwin, 0, sbuf); 27 putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time."); 28 putstr(tmpwin, 0, "Or enter a background symbol (ex. <)."); 29 /* disgusting hack; the alternate selection characters work for any 30 getpos call, but they only matter for dowhatis (and doquickwhatis) */ 31 doing_what_is = (goal == what_is_an_unknown_object); 32 Sprintf(sbuf, "Type a .%s when you are at the right place.", 33 doing_what_is ? " or , or ; or :" : ""); 34 putstr(tmpwin, 0, sbuf); 35 if (!force) 36 putstr(tmpwin, 0, "Type Space or Escape when you're done."); 37 putstr(tmpwin, 0, ""); 38 display_nhwindow(tmpwin, TRUE); 39 destroy_nhwindow(tmpwin); 40} 41 42int 43getpos(cc, force, goal) 44coord *cc; 45boolean force; 46const char *goal; 47{ 48 int result = 0; 49 int cx, cy, i, c; 50 int sidx, tx, ty; 51 boolean msg_given = TRUE; /* clear message window by default */ 52 static const char pick_chars[] = ".,;:"; 53 const char *cp; 54 const char *sdp; 55 if(iflags.num_pad) sdp = ndir; else sdp = sdir; /* DICE workaround */ 56 57 if (flags.verbose) { 58 pline("(For instructions type a ?)"); 59 msg_given = TRUE; 60 } 61 cx = cc->x; 62 cy = cc->y; 63#ifdef CLIPPING 64 cliparound(cx, cy); 65#endif 66 curs(WIN_MAP, cx,cy); 67 flush_screen(0); 68#ifdef MAC 69 lock_mouse_cursor(TRUE); 70#endif 71 for (;;) { 72 c = nh_poskey(&tx, &ty, &sidx); 73 if (c == '\033') { 74 cx = cy = -10; 75 msg_given = TRUE; /* force clear */ 76 result = -1; 77 break; 78 } 79 if(c == 0) { 80 if (!isok(tx, ty)) continue; 81 /* a mouse click event, just assign and return */ 82 cx = tx; 83 cy = ty; 84 break; 85 } 86 if ((cp = index(pick_chars, c)) != 0) { 87 /* '.' => 0, ',' => 1, ';' => 2, ':' => 3 */ 88 result = cp - pick_chars; 89 break; 90 } 91 for (i = 0; i < 8; i++) { 92 int dx, dy; 93 94 if (sdp[i] == c) { 95 /* a normal movement letter or digit */ 96 dx = xdir[i]; 97 dy = ydir[i]; 98 } else if (sdir[i] == lowc((char)c)) { 99 /* a shifted movement letter */ 100 dx = 8 * xdir[i]; 101 dy = 8 * ydir[i]; 102 } else 103 continue; 104 105 /* truncate at map edge; diagonal moves complicate this... */ 106 if (cx + dx < 1) { 107 dy -= sgn(dy) * (1 - (cx + dx)); 108 dx = 1 - cx; /* so that (cx+dx == 1) */ 109 } else if (cx + dx > COLNO-1) { 110 dy += sgn(dy) * ((COLNO-1) - (cx + dx)); 111 dx = (COLNO-1) - cx; 112 } 113 if (cy + dy < 0) { 114 dx -= sgn(dx) * (0 - (cy + dy)); 115 dy = 0 - cy; /* so that (cy+dy == 0) */ 116 } else if (cy + dy > ROWNO-1) { 117 dx += sgn(dx) * ((ROWNO-1) - (cy + dy)); 118 dy = (ROWNO-1) - cy; 119 } 120 cx += dx; 121 cy += dy; 122 goto nxtc; 123 } 124 125 if(c == '?'){ 126 getpos_help(force, goal); 127 } else { 128 if (!index(quitchars, c)) { 129 char matching[MAXPCHARS]; 130 int pass, lo_x, lo_y, hi_x, hi_y, k = 0; 131 (void)memset((genericptr_t)matching, 0, sizeof matching); 132 for (sidx = 1; sidx < MAXPCHARS; sidx++) 133 if (c == defsyms[sidx].sym || c == (int)showsyms[sidx]) 134 matching[sidx] = (char) ++k; 135 if (k) { 136 for (pass = 0; pass <= 1; pass++) { 137 /* pass 0: just past current pos to lower right; 138 pass 1: upper left corner to current pos */ 139 lo_y = (pass == 0) ? cy : 0; 140 hi_y = (pass == 0) ? ROWNO - 1 : cy; 141 for (ty = lo_y; ty <= hi_y; ty++) { 142 lo_x = (pass == 0 && ty == lo_y) ? cx + 1 : 1; 143 hi_x = (pass == 1 && ty == hi_y) ? cx : COLNO - 1; 144 for (tx = lo_x; tx <= hi_x; tx++) { 145 k = levl[tx][ty].glyph; 146 if (glyph_is_cmap(k) && 147 matching[glyph_to_cmap(k)]) { 148 cx = tx, cy = ty; 149 if (msg_given) { 150 clear_nhwindow(WIN_MESSAGE); 151 msg_given = FALSE; 152 } 153 goto nxtc; 154 } 155 } /* column */ 156 } /* row */ 157 } /* pass */ 158 pline("Can't find dungeon feature '%c'.", c); 159 msg_given = TRUE; 160 goto nxtc; 161 } else { 162 pline("Unknown direction: '%s' (%s).", 163 visctrl((char)c), 164 !force ? "aborted" : 165 iflags.num_pad ? "use 2468 or ." : "use hjkl or ."); 166 msg_given = TRUE; 167 } /* k => matching */ 168 } /* !quitchars */ 169 if (force) goto nxtc; 170 pline("Done."); 171 msg_given = FALSE; /* suppress clear */ 172 cx = -1; 173 cy = 0; 174 result = 0; /* not -1 */ 175 break; 176 } 177 nxtc: ; 178#ifdef CLIPPING 179 cliparound(cx, cy); 180#endif 181 curs(WIN_MAP,cx,cy); 182 flush_screen(0); 183 } 184#ifdef MAC 185 lock_mouse_cursor(FALSE); 186#endif 187 if (msg_given) clear_nhwindow(WIN_MESSAGE); 188 cc->x = cx; 189 cc->y = cy; 190 return result; 191} 192 193struct monst * 194christen_monst(mtmp, name) 195struct monst *mtmp; 196const char *name; 197{ 198 int lth; 199 struct monst *mtmp2; 200 char buf[PL_PSIZ]; 201 202 /* dogname & catname are PL_PSIZ arrays; object names have same limit */ 203 lth = *name ? (int)(strlen(name) + 1) : 0; 204 if(lth > PL_PSIZ){ 205 lth = PL_PSIZ; 206 name = strncpy(buf, name, PL_PSIZ - 1); 207 buf[PL_PSIZ - 1] = '\0'; 208 } 209 if (lth == mtmp->mnamelth) { 210 /* don't need to allocate a new monst struct */ 211 if (lth) Strcpy(NAME(mtmp), name); 212 return mtmp; 213 } 214 mtmp2 = newmonst(mtmp->mxlth + lth); 215 *mtmp2 = *mtmp; 216 (void) memcpy((genericptr_t)mtmp2->mextra, 217 (genericptr_t)mtmp->mextra, mtmp->mxlth); 218 mtmp2->mnamelth = lth; 219 if (lth) Strcpy(NAME(mtmp2), name); 220 replmon(mtmp,mtmp2); 221 return(mtmp2); 222} 223 224int 225do_mname() 226{ 227 char buf[BUFSZ]; 228 coord cc; 229 register int cx,cy; 230 register struct monst *mtmp; 231 char qbuf[QBUFSZ]; 232 233 if (Hallucination) { 234 You("would never recognize it anyway."); 235 return 0; 236 } 237 cc.x = u.ux; 238 cc.y = u.uy; 239 if (getpos(&cc, FALSE, "the monster you want to name") < 0 || 240 (cx = cc.x) < 0) 241 return 0; 242 cy = cc.y; 243 244 if (cx == u.ux && cy == u.uy) { 245#ifdef STEED 246 if (u.usteed && canspotmon(u.usteed)) 247 mtmp = u.usteed; 248 else { 249#endif 250 pline("This %s creature is called %s and cannot be renamed.", 251 ACURR(A_CHA) > 14 ? 252 (flags.female ? "beautiful" : "handsome") : 253 "ugly", 254 plname); 255 return(0); 256#ifdef STEED 257 } 258#endif 259 } else 260 mtmp = m_at(cx, cy); 261 262 if (!mtmp || (!sensemon(mtmp) && 263 (!(cansee(cx,cy) || see_with_infrared(mtmp)) || mtmp->mundetected 264 || mtmp->m_ap_type == M_AP_FURNITURE 265 || mtmp->m_ap_type == M_AP_OBJECT 266 || (mtmp->minvis && !See_invisible)))) { 267 pline("I see no monster there."); 268 return(0); 269 } 270 /* special case similar to the one in lookat() */ 271 (void) distant_monnam(mtmp, ARTICLE_THE, buf); 272 Sprintf(qbuf, "What do you want to call %s?", buf); 273 getlin(qbuf,buf); 274 if(!*buf || *buf == '\033') return(0); 275 /* strip leading and trailing spaces; unnames monster if all spaces */ 276 (void)mungspaces(buf); 277 278 if (mtmp->data->geno & G_UNIQ) 279 pline("%s doesn't like being called names!", Monnam(mtmp)); 280 else 281 (void) christen_monst(mtmp, buf); 282 return(0); 283} 284 285/* 286 * This routine changes the address of obj. Be careful not to call it 287 * when there might be pointers around in unknown places. For now: only 288 * when obj is in the inventory. 289 */ 290STATIC_OVL 291void 292do_oname(obj) 293register struct obj *obj; 294{ 295 char buf[BUFSZ], qbuf[QBUFSZ]; 296 const char *aname; 297 short objtyp; 298 299 Sprintf(qbuf, "What do you want to name %s %s?", 300 is_plural(obj) ? "these" : "this", xname(obj)); 301 getlin(qbuf, buf); 302 if(!*buf || *buf == '\033') return; 303 /* strip leading and trailing spaces; unnames item if all spaces */ 304 (void)mungspaces(buf); 305 306 /* relax restrictions over proper capitalization for artifacts */ 307 if ((aname = artifact_name(buf, &objtyp)) != 0 && objtyp == obj->otyp) 308 Strcpy(buf, aname); 309 310 if (obj->oartifact) { 311 pline_The("artifact seems to resist the attempt."); 312 return; 313 } else if (restrict_name(obj, buf) || exist_artifact(obj->otyp, buf)) { 314 int n = rn2((int)strlen(buf)); 315 register char c1, c2; 316 317 c1 = lowc(buf[n]); 318 do c2 = 'a' + rn2('z'-'a'); while (c1 == c2); 319 buf[n] = (buf[n] == c1) ? c2 : highc(c2); /* keep same case */ 320 pline("While engraving your %s slips.", body_part(HAND)); 321 display_nhwindow(WIN_MESSAGE, FALSE); 322 You("engrave: \"%s\".",buf); 323 } 324 obj = oname(obj, buf); 325} 326 327/* 328 * Allocate a new and possibly larger storage space for an obj. 329 */ 330struct obj * 331realloc_obj(obj, oextra_size, oextra_src, oname_size, name) 332struct obj *obj; 333int oextra_size; /* storage to allocate for oextra */ 334genericptr_t oextra_src; 335int oname_size; /* size of name string + 1 (null terminator) */ 336const char *name; 337{ 338 struct obj *otmp; 339 340 otmp = newobj(oextra_size + oname_size); 341 *otmp = *obj; /* the cobj pointer is copied to otmp */ 342 if (oextra_size) { 343 if (oextra_src) 344 (void) memcpy((genericptr_t)otmp->oextra, oextra_src, 345 oextra_size); 346 } else { 347 otmp->oattached = OATTACHED_NOTHING; 348 } 349 otmp->oxlth = oextra_size; 350 351 otmp->onamelth = oname_size; 352 otmp->timed = 0; /* not timed, yet */ 353 otmp->lamplit = 0; /* ditto */ 354 /* __GNUC__ note: if the assignment of otmp->onamelth immediately 355 precedes this `if' statement, a gcc bug will miscompile the 356 test on vax (`insv' instruction used to store bitfield does 357 not set condition codes, but optimizer behaves as if it did). 358 gcc-2.7.2.1 finally fixed this. */ 359 if (oname_size) { 360 if (name) 361 Strcpy(ONAME(otmp), name); 362 } 363 364 if (obj->owornmask) { 365 boolean save_twoweap = u.twoweap; 366 /* unwearing the old instance will clear dual-wield mode 367 if this object is either of the two weapons */ 368 setworn((struct obj *)0, obj->owornmask); 369 setworn(otmp, otmp->owornmask); 370 u.twoweap = save_twoweap; 371 } 372 373 /* replace obj with otmp */ 374 replace_object(obj, otmp); 375 376 /* fix ocontainer pointers */ 377 if (Has_contents(obj)) { 378 struct obj *inside; 379 380 for(inside = obj->cobj; inside; inside = inside->nobj) 381 inside->ocontainer = otmp; 382 } 383 384 /* move timers and light sources from obj to otmp */ 385 if (obj->timed) obj_move_timers(obj, otmp); 386 if (obj->lamplit) obj_move_light_source(obj, otmp); 387 388 /* objects possibly being manipulated by multi-turn occupations 389 which have been interrupted but might be subsequently resumed */ 390 if (obj->oclass == FOOD_CLASS) 391 food_substitution(obj, otmp); /* eat food or open tin */ 392 else if (obj->oclass == SPBOOK_CLASS) 393 book_substitution(obj, otmp); /* read spellbook */ 394 395 /* obfree(obj, otmp); now unnecessary: no pointers on bill */ 396 dealloc_obj(obj); /* let us hope nobody else saved a pointer */ 397 return otmp; 398} 399 400struct obj * 401oname(obj, name) 402struct obj *obj; 403const char *name; 404{ 405 int lth; 406 char buf[PL_PSIZ]; 407 408 lth = *name ? (int)(strlen(name) + 1) : 0; 409 if (lth > PL_PSIZ) { 410 lth = PL_PSIZ; 411 name = strncpy(buf, name, PL_PSIZ - 1); 412 buf[PL_PSIZ - 1] = '\0'; 413 } 414 /* If named artifact exists in the game, do not create another. 415 * Also trying to create an artifact shouldn't de-artifact 416 * it (e.g. Excalibur from prayer). In this case the object 417 * will retain its current name. */ 418 if (obj->oartifact || (lth && exist_artifact(obj->otyp, name))) 419 return obj; 420 421 if (lth == obj->onamelth) { 422 /* no need to replace entire object */ 423 if (lth) Strcpy(ONAME(obj), name); 424 } else { 425 obj = realloc_obj(obj, obj->oxlth, 426 (genericptr_t)obj->oextra, lth, name); 427 } 428 if (lth) artifact_exists(obj, name, TRUE); 429 if (obj->oartifact) { 430 /* can't dual-wield with artifact as secondary weapon */ 431 if (obj == uswapwep) untwoweapon(); 432 /* activate warning if you've just named your weapon "Sting" */ 433 if (obj == uwep) set_artifact_intrinsic(obj, TRUE, W_WEP); 434 } 435 if (carried(obj)) update_inventory(); 436 return obj; 437} 438 439static NEARDATA const char callable[] = { 440 SCROLL_CLASS, POTION_CLASS, WAND_CLASS, RING_CLASS, AMULET_CLASS, 441 GEM_CLASS, SPBOOK_CLASS, ARMOR_CLASS, TOOL_CLASS, 0 }; 442 443int 444ddocall() 445{ 446 register struct obj *obj; 447#ifdef REDO 448 char ch; 449#endif 450 char allowall[2]; 451 452 switch( 453#ifdef REDO 454 ch = 455#endif 456 ynq("Name an individual object?")) { 457 case 'q': 458 break; 459 case 'y': 460#ifdef REDO 461 savech(ch); 462#endif 463 allowall[0] = ALL_CLASSES; allowall[1] = '\0'; 464 obj = getobj(allowall, "name"); 465 if(obj) do_oname(obj); 466 break; 467 default : 468#ifdef REDO 469 savech(ch); 470#endif 471 obj = getobj(callable, "call"); 472 if (obj) { 473 /* behave as if examining it in inventory; 474 this might set dknown if it was picked up 475 while blind and the hero can now see */ 476 (void) xname(obj); 477 478 if (!obj->dknown) { 479 You("would never recognize another one."); 480 return 0; 481 } 482 docall(obj); 483 } 484 break; 485 } 486 return 0; 487} 488 489void 490docall(obj) 491register struct obj *obj; 492{ 493 char buf[BUFSZ], qbuf[QBUFSZ]; 494 struct obj otemp; 495 register char **str1; 496 497 if (!obj->dknown) return; /* probably blind */ 498 otemp = *obj; 499 otemp.quan = 1L; 500 otemp.onamelth = 0; 501 otemp.oxlth = 0; 502 if (objects[otemp.otyp].oc_class == POTION_CLASS && otemp.fromsink) 503 /* kludge, meaning it's sink water */ 504 Sprintf(qbuf,"Call a stream of %s fluid:", 505 OBJ_DESCR(objects[otemp.otyp])); 506 else 507 Sprintf(qbuf, "Call %s:", an(xname(&otemp))); 508 getlin(qbuf, buf); 509 if(!*buf || *buf == '\033') 510 return; 511 512 /* clear old name */ 513 str1 = &(objects[obj->otyp].oc_uname); 514 if(*str1) free((genericptr_t)*str1); 515 516 /* strip leading and trailing spaces; uncalls item if all spaces */ 517 (void)mungspaces(buf); 518 if (!*buf) { 519 if (*str1) { /* had name, so possibly remove from disco[] */ 520 /* strip name first, for the update_inventory() call 521 from undiscover_object() */ 522 *str1 = (char *)0; 523 undiscover_object(obj->otyp); 524 } 525 } else { 526 *str1 = strcpy((char *) alloc((unsigned)strlen(buf)+1), buf); 527 discover_object(obj->otyp, FALSE, TRUE); /* possibly add to disco[] */ 528 } 529} 530 531#endif /*OVLB*/ 532#ifdef OVL0 533 534static const char * const ghostnames[] = { 535 /* these names should have length < PL_NSIZ */ 536 /* Capitalize the names for aesthetics -dgk */ 537 "Adri", "Andries", "Andreas", "Bert", "David", "Dirk", "Emile", 538 "Frans", "Fred", "Greg", "Hether", "Jay", "John", "Jon", "Karnov", 539 "Kay", "Kenny", "Kevin", "Maud", "Michiel", "Mike", "Peter", "Robert", 540 "Ron", "Tom", "Wilmar", "Nick Danger", "Phoenix", "Jiro", "Mizue", 541 "Stephan", "Lance Braccus", "Shadowhawk" 542}; 543 544/* ghost names formerly set by x_monnam(), now by makemon() instead */ 545const char * 546rndghostname() 547{ 548 return rn2(7) ? ghostnames[rn2(SIZE(ghostnames))] : (const char *)plname; 549} 550 551/* Monster naming functions: 552 * x_monnam is the generic monster-naming function. 553 * seen unseen detected named 554 * mon_nam: the newt it the invisible orc Fido 555 * noit_mon_nam:the newt (as if detected) the invisible orc Fido 556 * l_monnam: newt it invisible orc dog called fido 557 * Monnam: The newt It The invisible orc Fido 558 * noit_Monnam: The newt (as if detected) The invisible orc Fido 559 * Adjmonnam: The poor newt It The poor invisible orc The poor Fido 560 * Amonnam: A newt It An invisible orc Fido 561 * a_monnam: a newt it an invisible orc Fido 562 * m_monnam: newt xan orc Fido 563 * y_monnam: your newt your xan your invisible orc Fido 564 */ 565 566/* Bug: if the monster is a priest or shopkeeper, not every one of these 567 * options works, since those are special cases. 568 */ 569char * 570x_monnam(mtmp, article, adjective, suppress, called) 571register struct monst *mtmp; 572int article; 573/* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious 574 * ARTICLE_YOUR: "your" on pets, "the" on everything else 575 * 576 * If the monster would be referred to as "it" or if the monster has a name 577 * _and_ there is no adjective, "invisible", "saddled", etc., override this 578 * and always use no article. 579 */ 580const char *adjective; 581int suppress; 582/* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE. 583 * EXACT_NAME: combination of all the above 584 */ 585boolean called; 586{ 587#ifdef LINT /* static char buf[BUFSZ]; */ 588 char buf[BUFSZ]; 589#else 590 static char buf[BUFSZ]; 591#endif 592 struct permonst *mdat = mtmp->data; 593 boolean do_hallu, do_invis, do_it, do_saddle; 594 boolean name_at_start, has_adjectives; 595 char *bp; 596 597 if (program_state.gameover) 598 suppress |= SUPPRESS_HALLUCINATION; 599 if (article == ARTICLE_YOUR && !mtmp->mtame) 600 article = ARTICLE_THE; 601 602 do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION); 603 do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE); 604 do_it = !canspotmon(mtmp) && 605 article != ARTICLE_YOUR && 606 !program_state.gameover && 607#ifdef STEED 608 mtmp != u.usteed && 609#endif 610 !(u.uswallow && mtmp == u.ustuck) && 611 !(suppress & SUPPRESS_IT); 612 do_saddle = !(suppress & SUPPRESS_SADDLE); 613 614 buf[0] = 0; 615 616 /* unseen monsters, etc. Use "it" */ 617 if (do_it) { 618 Strcpy(buf, "it"); 619 return buf; 620 } 621 622 /* priests and minions: don't even use this function */ 623 if (mtmp->ispriest || mtmp->isminion) { 624 char priestnambuf[BUFSZ]; 625 char *name; 626 long save_prop = EHalluc_resistance; 627 unsigned save_invis = mtmp->minvis; 628 629 /* when true name is wanted, explicitly block Hallucination */ 630 if (!do_hallu) EHalluc_resistance = 1L; 631 if (!do_invis) mtmp->minvis = 0; 632 name = priestname(mtmp, priestnambuf); 633 EHalluc_resistance = save_prop; 634 mtmp->minvis = save_invis; 635 if (article == ARTICLE_NONE && !strncmp(name, "the ", 4)) 636 name += 4; 637 return strcpy(buf, name); 638 } 639 640 /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just 641 * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible 642 * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating, 643 * none of this applies. 644 */ 645 if (mtmp->isshk && !do_hallu) { 646 if (adjective && article == ARTICLE_THE) { 647 /* pathological case: "the angry Asidonhopo the blue dragon" 648 sounds silly */ 649 Strcpy(buf, "the "); 650 Strcat(strcat(buf, adjective), " "); 651 Strcat(buf, shkname(mtmp)); 652 return buf; 653 } 654 Strcat(buf, shkname(mtmp)); 655 if (mdat == &mons[PM_SHOPKEEPER] && !do_invis) 656 return buf; 657 Strcat(buf, " the "); 658 if (do_invis) 659 Strcat(buf, "invisible "); 660 Strcat(buf, mdat->mname); 661 return buf; 662 } 663 664 /* Put the adjectives in the buffer */ 665 if (adjective) 666 Strcat(strcat(buf, adjective), " "); 667 if (do_invis) 668 Strcat(buf, "invisible "); 669#ifdef STEED 670 if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && 671 !Blind && !Hallucination) 672 Strcat(buf, "saddled "); 673#endif 674 if (buf[0] != 0) 675 has_adjectives = TRUE; 676 else 677 has_adjectives = FALSE; 678 679 /* Put the actual monster name or type into the buffer now */ 680 /* Be sure to remember whether the buffer starts with a name */ 681 if (do_hallu) { 682 Strcat(buf, rndmonnam()); 683 name_at_start = FALSE; 684 } else if (mtmp->mnamelth) { 685 char *name = NAME(mtmp); 686 687 if (mdat == &mons[PM_GHOST]) { 688 Sprintf(eos(buf), "%s ghost", s_suffix(name)); 689 name_at_start = TRUE; 690 } else if (called) { 691 Sprintf(eos(buf), "%s called %s", mdat->mname, name); 692 name_at_start = (boolean)type_is_pname(mdat); 693 } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) { 694 /* <name> the <adjective> <invisible> <saddled> <rank> */ 695 char pbuf[BUFSZ]; 696 697 Strcpy(pbuf, name); 698 pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */ 699 if (has_adjectives) 700 Strcat(pbuf, buf); 701 Strcat(pbuf, bp + 5); /* append the rest of the name */ 702 Strcpy(buf, pbuf); 703 article = ARTICLE_NONE; 704 name_at_start = TRUE; 705 } else { 706 Strcat(buf, name); 707 name_at_start = TRUE; 708 } 709 } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) { 710 char pbuf[BUFSZ]; 711 Strcpy(pbuf, rank_of((int)mtmp->m_lev, 712 monsndx(mdat), 713 (boolean)mtmp->female)); 714 Strcat(buf, lcase(pbuf)); 715 name_at_start = FALSE; 716 } else { 717 Strcat(buf, mdat->mname); 718 name_at_start = (boolean)type_is_pname(mdat); 719 } 720 721 if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) { 722 if (mdat == &mons[PM_WIZARD_OF_YENDOR]) 723 article = ARTICLE_THE; 724 else 725 article = ARTICLE_NONE; 726 } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) { 727 article = ARTICLE_THE; 728 } 729 730 { 731 char buf2[BUFSZ]; 732 733 switch(article) { 734 case ARTICLE_YOUR: 735 Strcpy(buf2, "your "); 736 Strcat(buf2, buf); 737 Strcpy(buf, buf2); 738 return buf; 739 case ARTICLE_THE: 740 Strcpy(buf2, "the "); 741 Strcat(buf2, buf); 742 Strcpy(buf, buf2); 743 return buf; 744 case ARTICLE_A: 745 return(an(buf)); 746 case ARTICLE_NONE: 747 default: 748 return buf; 749 } 750 } 751} 752 753#endif /* OVL0 */ 754#ifdef OVLB 755 756char * 757l_monnam(mtmp) 758register struct monst *mtmp; 759{ 760 return(x_monnam(mtmp, ARTICLE_NONE, (char *)0, 761 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, TRUE)); 762} 763 764#endif /* OVLB */ 765#ifdef OVL0 766 767char * 768mon_nam(mtmp) 769register struct monst *mtmp; 770{ 771 return(x_monnam(mtmp, ARTICLE_THE, (char *)0, 772 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE)); 773} 774 775/* print the name as if mon_nam() was called, but assume that the player 776 * can always see the monster--used for probing and for monsters aggravating 777 * the player with a cursed potion of invisibility 778 */ 779char * 780noit_mon_nam(mtmp) 781register struct monst *mtmp; 782{ 783 return(x_monnam(mtmp, ARTICLE_THE, (char *)0, 784 mtmp->mnamelth ? (SUPPRESS_SADDLE|SUPPRESS_IT) : 785 SUPPRESS_IT, FALSE)); 786} 787 788char * 789Monnam(mtmp) 790register struct monst *mtmp; 791{ 792 register char *bp = mon_nam(mtmp); 793 794 *bp = highc(*bp); 795 return(bp); 796} 797 798char * 799noit_Monnam(mtmp) 800register struct monst *mtmp; 801{ 802 register char *bp = noit_mon_nam(mtmp); 803 804 *bp = highc(*bp); 805 return(bp); 806} 807 808/* monster's own name */ 809char * 810m_monnam(mtmp) 811struct monst *mtmp; 812{ 813 return x_monnam(mtmp, ARTICLE_NONE, (char *)0, EXACT_NAME, FALSE); 814} 815 816/* pet name: "your little dog" */ 817char * 818y_monnam(mtmp) 819struct monst *mtmp; 820{ 821 int prefix, suppression_flag; 822 823 prefix = mtmp->mtame ? ARTICLE_YOUR : ARTICLE_THE; 824 suppression_flag = (mtmp->mnamelth 825#ifdef STEED 826 /* "saddled" is redundant when mounted */ 827 || mtmp == u.usteed 828#endif 829 ) ? SUPPRESS_SADDLE : 0; 830 831 return x_monnam(mtmp, prefix, (char *)0, suppression_flag, FALSE); 832} 833 834#endif /* OVL0 */ 835#ifdef OVLB 836 837char * 838Adjmonnam(mtmp, adj) 839register struct monst *mtmp; 840register const char *adj; 841{ 842 register char *bp = x_monnam(mtmp, ARTICLE_THE, adj, 843 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE); 844 845 *bp = highc(*bp); 846 return(bp); 847} 848 849char * 850a_monnam(mtmp) 851register struct monst *mtmp; 852{ 853 return x_monnam(mtmp, ARTICLE_A, (char *)0, 854 mtmp->mnamelth ? SUPPRESS_SADDLE : 0, FALSE); 855} 856 857char * 858Amonnam(mtmp) 859register struct monst *mtmp; 860{ 861 register char *bp = a_monnam(mtmp); 862 863 *bp = highc(*bp); 864 return(bp); 865} 866 867/* used for monster ID by the '/', ';', and 'C' commands to block remote 868 identification of the endgame altars via their attending priests */ 869char * 870distant_monnam(mon, article, outbuf) 871struct monst *mon; 872int article; /* only ARTICLE_NONE and ARTICLE_THE are handled here */ 873char *outbuf; 874{ 875 /* high priest(ess)'s identity is concealed on the Astral Plane, 876 unless you're adjacent (overridden for hallucination which does 877 its own obfuscation) */ 878 if (mon->data == &mons[PM_HIGH_PRIEST] && !Hallucination && 879 Is_astralevel(&u.uz) && distu(mon->mx, mon->my) > 2) { 880 Strcpy(outbuf, article == ARTICLE_THE ? "the " : ""); 881 Strcat(outbuf, mon->female ? "high priestess" : "high priest"); 882 } else { 883 Strcpy(outbuf, x_monnam(mon, article, (char *)0, 0, TRUE)); 884 } 885 return outbuf; 886} 887 888static const char * const bogusmons[] = { 889 "jumbo shrimp", "giant pigmy", "gnu", "killer penguin", 890 "giant cockroach", "giant slug", "maggot", "pterodactyl", 891 "tyrannosaurus rex", "basilisk", "beholder", "nightmare", 892 "efreeti", "marid", "rot grub", "bookworm", "master lichen", 893 "shadow", "hologram", "jester", "attorney", "sleazoid", 894 "killer tomato", "amazon", "robot", "battlemech", 895 "rhinovirus", "harpy", "lion-dog", "rat-ant", "Y2K bug", 896 /* misc. */ 897 "grue", "Christmas-tree monster", "luck sucker", "paskald", 898 "brogmoid", "dornbeast", /* Quendor (Zork, &c.) */ 899 "Ancient Multi-Hued Dragon", "Evil Iggy", 900 /* Moria */ 901 "emu", "kestrel", "xeroc", "venus flytrap", 902 /* Rogue */ 903 "creeping coins", /* Wizardry */ 904 "hydra", "siren", /* Greek legend */ 905 "killer bunny", /* Monty Python */ 906 "rodent of unusual size", /* The Princess Bride */ 907 "Smokey the bear", /* "Only you can prevent forest fires!" */ 908 "Luggage", /* Discworld */ 909 "Ent", /* Lord of the Rings */ 910 "tangle tree", "nickelpede", "wiggle", /* Xanth */ 911 "white rabbit", "snark", /* Lewis Carroll */ 912 "pushmi-pullyu", /* Dr. Doolittle */ 913 "smurf", /* The Smurfs */ 914 "tribble", "Klingon", "Borg", /* Star Trek */ 915 "Ewok", /* Star Wars */ 916 "Totoro", /* Tonari no Totoro */ 917 "ohmu", /* Nausicaa */ 918 "youma", /* Sailor Moon */ 919 "nyaasu", /* Pokemon (Meowth) */ 920 "Godzilla", "King Kong", /* monster movies */ 921 "earthquake beast", /* old L of SH */ 922 "Invid", /* Robotech */ 923 "Terminator", /* The Terminator */ 924 "boomer", /* Bubblegum Crisis */ 925 "Dalek", /* Dr. Who ("Exterminate!") */ 926 "microscopic space fleet", "Ravenous Bugblatter Beast of Traal", 927 /* HGttG */ 928 "teenage mutant ninja turtle", /* TMNT */ 929 "samurai rabbit", /* Usagi Yojimbo */ 930 "aardvark", /* Cerebus */ 931 "Audrey II", /* Little Shop of Horrors */ 932 "witch doctor", "one-eyed one-horned flying purple people eater", 933 /* 50's rock 'n' roll */ 934 "Barney the dinosaur", /* saccharine kiddy TV */ 935 "Morgoth", /* Angband */ 936 "Vorlon", /* Babylon 5 */ 937 "questing beast", /* King Arthur */ 938 "Predator", /* Movie */ 939 "mother-in-law" /* common pest */ 940}; 941 942 943/* Return a random monster name, for hallucination. 944 * KNOWN BUG: May be a proper name (Godzilla, Barney), may not 945 * (the Terminator, a Dalek). There's no elegant way to deal 946 * with this without radically modifying the calling functions. 947 */ 948const char * 949rndmonnam() 950{ 951 int name; 952 953 do { 954 name = rn1(SPECIAL_PM + SIZE(bogusmons) - LOW_PM, LOW_PM); 955 } while (name < SPECIAL_PM && 956 (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN))); 957 958 if (name >= SPECIAL_PM) return bogusmons[name - SPECIAL_PM]; 959 return mons[name].mname; 960} 961 962#ifdef REINCARNATION 963const char * 964roguename() /* Name of a Rogue player */ 965{ 966 char *i, *opts; 967 968 if ((opts = nh_getenv("ROGUEOPTS")) != 0) { 969 for (i = opts; *i; i++) 970 if (!strncmp("name=",i,5)) { 971 char *j; 972 if ((j = index(i+5,',')) != 0) 973 *j = (char)0; 974 return i+5; 975 } 976 } 977 return rn2(3) ? (rn2(2) ? "Michael Toy" : "Kenneth Arnold") 978 : "Glenn Wichman"; 979} 980#endif /* REINCARNATION */ 981#endif /* OVLB */ 982 983#ifdef OVL2 984 985static NEARDATA const char * const hcolors[] = { 986 "ultraviolet", "infrared", "bluish-orange", 987 "reddish-green", "dark white", "light black", "sky blue-pink", 988 "salty", "sweet", "sour", "bitter", 989 "striped", "spiral", "swirly", "plaid", "checkered", "argyle", 990 "paisley", "blotchy", "guernsey-spotted", "polka-dotted", 991 "square", "round", "triangular", 992 "cabernet", "sangria", "fuchsia", "wisteria", 993 "lemon-lime", "strawberry-banana", "peppermint", 994 "romantic", "incandescent" 995}; 996 997const char * 998hcolor(colorpref) 999const char *colorpref; 1000{ 1001 return (Hallucination || !colorpref) ? 1002 hcolors[rn2(SIZE(hcolors))] : colorpref; 1003} 1004 1005/* return a random real color unless hallucinating */ 1006const char * 1007rndcolor() 1008{ 1009 int k = rn2(CLR_MAX); 1010 return Hallucination ? hcolor((char *)0) : (k == NO_COLOR) ? 1011 "colorless" : c_obj_colors[k]; 1012} 1013 1014/* Aliases for road-runner nemesis 1015 */ 1016static const char * const coynames[] = { 1017 "Carnivorous Vulgaris","Road-Runnerus Digestus", 1018 "Eatibus Anythingus" ,"Famishus-Famishus", 1019 "Eatibus Almost Anythingus","Eatius Birdius", 1020 "Famishius Fantasticus","Eternalii Famishiis", 1021 "Famishus Vulgarus","Famishius Vulgaris Ingeniusi", 1022 "Eatius-Slobbius","Hardheadipus Oedipus", 1023 "Carnivorous Slobbius","Hard-Headipus Ravenus", 1024 "Evereadii Eatibus","Apetitius Giganticus", 1025 "Hungrii Flea-Bagius","Overconfidentii Vulgaris", 1026 "Caninus Nervous Rex","Grotesques Appetitus", 1027 "Nemesis Riduclii","Canis latrans" 1028}; 1029 1030char * 1031coyotename(mtmp, buf) 1032struct monst *mtmp; 1033char *buf; 1034{ 1035 if (mtmp && buf) { 1036 Sprintf(buf, "%s - %s", 1037 x_monnam(mtmp, ARTICLE_NONE, (char *)0, 0, TRUE), 1038 mtmp->mcan ? coynames[SIZE(coynames)-1] : coynames[rn2(SIZE(coynames)-1)]); 1039 } 1040 return buf; 1041} 1042#endif /* OVL2 */ 1043 1044/*do_name.c*/ 1045