/* This is the one we want to use when printing messages. */ int pronoun_gender(struct monst *mtmp) { if (is_neuter(mtmp->data) || !canclassifymon(mtmp)) return 2; return (humanoid(mtmp->data) || (mtmp->data->geno & G_UNIQ) || type_is_pname(mtmp->data)) ? (int)mtmp->female : 2; }
static const char * convert_arg(char c) { switch (c) { case 'p': return msg_from_string(u.uplname); case 'c': return (u.ufemale && urole.name.f) ? urole.name.f : urole.name.m; case 'r': return rank_of(u.ulevel, Role_switch, u.ufemale); case 'R': return rank_of(MIN_QUEST_LEVEL, Role_switch, u.ufemale); case 's': return (u.ufemale) ? "sister" : "brother"; case 'S': return (u.ufemale) ? "daughter" : "son"; case 'l': case 'n': { int i = c == 'l' ? urole.ldrnum : urole.neminum;; return msgcat(type_is_pname(&mons[i]) ? "" : "the ", mons[i].mname); } case 'i': return urole.intermed; case 'o': return the(artiname(urole.questarti)); case 'g': return mons[urole.guardnum].mname; case 'G': return align_gtitle(u.ualignbase[A_ORIGINAL]); case 'H': return urole.homebase; case 'a': return align_str(u.ualignbase[A_ORIGINAL]); case 'A': return align_str(u.ualign.type); case 'd': return align_gname(u.ualignbase[A_ORIGINAL]); case 'D': return align_gname(A_LAWFUL); case 'C': return "chaotic"; case 'N': return "neutral"; case 'L': return "lawful"; case 'x': return Blind ? "sense" : "see"; case 'Z': return msg_from_string(gamestate.dungeons[0].dname); case '%': return "%"; default: return ""; } }
static const char * neminame (void) /* return your role nemesis' name */ { int i = urole.neminum; sprintf(nambuf, "%s%s", type_is_pname(&mons[i]) ? "" : "the ", mons[i].mname); return nambuf; }
const char * ldrname (void) /* return your role leader's name */ { int i = urole.ldrnum; sprintf(nambuf, "%s%s", type_is_pname(&mons[i]) ? "" : "the ", mons[i].mname); return nambuf; }
/* Return a random monster name, for hallucination. * KNOWN BUG: May be a proper name (Godzilla, Barney), may not * (the Terminator, a Dalek). There's no elegant way to deal * with this without radically modifying the calling functions. */ const char *rndmonnam(void) { int name; do { name = display_rng(SPECIAL_PM + SIZE(bogusmons) - LOW_PM) + LOW_PM; } while (name < SPECIAL_PM && (type_is_pname(&mons[name]) || (mons[name].geno & G_NOGEN))); if (name >= SPECIAL_PM) return bogusmons[name - SPECIAL_PM]; return mons[name].mname; }
void nh_timeout() { register struct prop *upp; int sleeptime; int m_idx; int baseluck = (flags.moonphase == FULL_MOON) ? 1 : 0; if (flags.friday13) baseluck -= 1; if (u.uluck != baseluck && moves % (u.uhave.amulet || u.ugangr ? 300 : 600) == 0) { /* Cursed luckstones stop bad luck from timing out; blessed luckstones * stop good luck from timing out; normal luckstones stop both; * neither is stopped if you don't have a luckstone. * Luck is based at 0 usually, +1 if a full moon and -1 on Friday 13th */ register int time_luck = stone_luck(FALSE); boolean nostone = !carrying(LUCKSTONE) && !stone_luck(TRUE); if(u.uluck > baseluck && (nostone || time_luck < 0)) u.uluck--; else if(u.uluck < baseluck && (nostone || time_luck > 0)) u.uluck++; } if(u.uinvulnerable) return; /* things past this point could kill you */ if(Stoned) stoned_dialogue(); if(Slimed) slime_dialogue(); if(Vomiting) vomiting_dialogue(); if(Strangled) choke_dialogue(); if(u.mtimedone && !--u.mtimedone) { if (Unchanging) u.mtimedone = rnd(100*youmonst.data->mlevel + 1); else rehumanize(); } if(u.ucreamed) u.ucreamed--; /* Dissipate spell-based protection. */ if (u.usptime) { if (--u.usptime == 0 && u.uspellprot) { u.usptime = u.uspmtime; u.uspellprot--; find_ac(); if (!Blind) Norep("The %s haze around you %s.", hcolor(NH_GOLDEN), u.uspellprot ? "becomes less dense" : "disappears"); } } #ifdef STEED if (u.ugallop) { if (--u.ugallop == 0L && u.usteed) pline("%s stops galloping.", Monnam(u.usteed)); } #endif for(upp = u.uprops; upp < u.uprops+SIZE(u.uprops); upp++) if((upp->intrinsic & TIMEOUT) && !(--upp->intrinsic & TIMEOUT)) { switch(upp - u.uprops){ case STONED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { /* leaving killer_format would make it "petrified by petrification" */ killer_format = NO_KILLER_PREFIX; killer = "killed by petrification"; } done(STONING); break; case SLIMED: if (delayed_killer && !killer) { killer = delayed_killer; delayed_killer = 0; } if (!killer) { killer_format = NO_KILLER_PREFIX; killer = "turned into green slime"; } done(TURNED_SLIME); break; case VOMITING: make_vomiting(0L, TRUE); break; case SICK: You("die from your illness."); killer_format = KILLED_BY_AN; killer = u.usick_cause; if ((m_idx = name_to_mon(killer)) >= LOW_PM) { if (type_is_pname(&mons[m_idx])) { killer_format = KILLED_BY; } else if (mons[m_idx].geno & G_UNIQ) { killer = the(killer); Strcpy(u.usick_cause, killer); killer_format = KILLED_BY; } } u.usick_type = 0; done(POISONING); break; case FAST: if (!Very_fast) You_feel("yourself slowing down%s.", Fast ? " a bit" : ""); break; case CONFUSION: HConfusion = 1; /* So make_confused works properly */ make_confused(0L, TRUE); stop_occupation(); break; case STUNNED: HStun = 1; make_stunned(0L, TRUE); stop_occupation(); break; case BLINDED: Blinded = 1; make_blinded(0L, TRUE); stop_occupation(); break; case INVIS: newsym(u.ux,u.uy); if (!Invis && !BInvis && !Blind) { You(!See_invisible ? "are no longer invisible." : "can no longer see through yourself."); stop_occupation(); } break; case SEE_INVIS: set_mimic_blocking(); /* do special mimic handling */ see_monsters(); /* make invis mons appear */ newsym(u.ux,u.uy); /* make self appear */ stop_occupation(); break; case WOUNDED_LEGS: heal_legs(); stop_occupation(); break; case HALLUC: HHallucination = 1; (void) make_hallucinated(0L, TRUE, 0L); stop_occupation(); break; case SLEEPING: if (unconscious() || Sleep_resistance) HSleeping += rnd(100); else if (Sleeping) { You("fall asleep."); sleeptime = rnd(20); fall_asleep(-sleeptime, TRUE); HSleeping += sleeptime + rnd(100); } break; case LEVITATION: (void) float_down(I_SPECIAL|TIMEOUT, 0L); break; case STRANGLED: killer_format = KILLED_BY; killer = (u.uburied) ? "suffocation" : "strangulation"; done(DIED); break; case FUMBLING: /* call this only when a move took place. */ /* otherwise handle fumbling msgs locally. */ if (u.umoved && !Levitation) { slip_or_trip(); nomul(-2, "fumbling"); nomovemsg = ""; /* The more you are carrying the more likely you * are to make noise when you fumble. Adjustments * to this number must be thoroughly play tested. */ if ((inv_weight() > -500)) { You("make a lot of noise!"); wake_nearby(); } } /* from outside means slippery ice; don't reset counter if that's the only fumble reason */ HFumbling &= ~FROMOUTSIDE; if (Fumbling) HFumbling += rnd(20); break; case DETECT_MONSTERS: see_monsters(); break; case PREGNANT: { char buf[BUFSZ]; if (!flags.female) { strcpy(buf, body_part(STOMACH)); if (!strcmp(buf, "stomach")) strcpy(buf, "belly"); pline("Something bursts out of your %s!"); killer_format = KILLED_BY; killer = "male childbirth"; done(DIED); } mksobj_at(PLACENTA, u.ux, u.uy, FALSE, FALSE); pline("BABIES!"); /* TODO */ stop_occupation(); break; } } } run_timers(); }
/* Bug: if the monster is a priest or shopkeeper, not every one of these * options works, since those are special cases. */ char *x_monnam(const struct monst *mtmp, int article, /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious * ARTICLE_YOUR: "your" on pets, "the" on everything * else * If the monster would be referred to as "it" or if the monster has a name * _and_ there is no adjective, "invisible", "saddled", etc., override this * and always use no article. */ const char *adjective, int suppress, /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE. * EXACT_NAME: combination of all the above */ boolean called) { static char buf[BUFSZ]; const struct permonst *mdat = mtmp->data; boolean do_hallu, do_invis, do_it, do_saddle; boolean name_at_start, has_adjectives; char *bp; if (program_state.gameover) suppress |= SUPPRESS_HALLUCINATION; if (article == ARTICLE_YOUR && !mtmp->mtame) article = ARTICLE_THE; do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION); do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE); do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR && !program_state.gameover && mtmp != u.usteed && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT); do_saddle = !(suppress & SUPPRESS_SADDLE); buf[0] = 0; /* unseen monsters, etc. Use "it" */ if (do_it) { strcpy(buf, "it"); return buf; } /* priests and minions: don't even use this function */ if (mtmp->ispriest || mtmp->isminion) { struct monst *priestmon = newmonst(mtmp->mxtyp, mtmp->mnamelth); char priestnambuf[BUFSZ]; char *name; long save_prop = EHalluc_resistance; memcpy(priestmon, mtmp, sizeof(struct monst) + mtmp->mxlth + mtmp->mnamelth); /* when true name is wanted, explicitly block Hallucination */ if (!do_hallu) EHalluc_resistance = 1L; if (!do_invis) priestmon->minvis = 0; name = priestname(priestmon, priestnambuf); EHalluc_resistance = save_prop; if (article == ARTICLE_NONE && !strncmp(name, "the ", 4)) name += 4; strcpy(buf, name); free(priestmon); return buf; } /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating, * none of this applies. */ if (mtmp->isshk && !do_hallu) { if (adjective && article == ARTICLE_THE) { /* pathological case: "the angry Asidonhopo the blue dragon" sounds silly */ strcpy(buf, "the "); strcat(strcat(buf, adjective), " "); strcat(buf, shkname(mtmp)); return buf; } strcat(buf, shkname(mtmp)); if (mdat == &mons[PM_SHOPKEEPER] && !do_invis) return buf; strcat(buf, " the "); if (do_invis) strcat(buf, "invisible "); strcat(buf, mdat->mname); return buf; } /* Put the adjectives in the buffer */ if (adjective) strcat(strcat(buf, adjective), " "); if (do_invis) strcat(buf, "invisible "); if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind && !Hallucination) strcat(buf, "saddled "); if (buf[0] != 0) has_adjectives = TRUE; else has_adjectives = FALSE; /* Put the actual monster name or type into the buffer now */ /* Be sure to remember whether the buffer starts with a name */ if (do_hallu) { strcat(buf, rndmonnam()); name_at_start = FALSE; } else if (mtmp->mnamelth) { char *name = NAME(mtmp); if (mdat == &mons[PM_GHOST]) { sprintf(eos(buf), "%s ghost", s_suffix(name)); name_at_start = TRUE; } else if (called) { sprintf(eos(buf), "%s called %s", mdat->mname, name); name_at_start = (boolean)type_is_pname(mdat); } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) { /* <name> the <adjective> <invisible> <saddled> <rank> */ char pbuf[BUFSZ]; strcpy(pbuf, name); pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */ if (has_adjectives) strcat(pbuf, buf); strcat(pbuf, bp + 5); /* append the rest of the name */ strcpy(buf, pbuf); article = ARTICLE_NONE; name_at_start = TRUE; } else { strcat(buf, name); name_at_start = TRUE; } } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) { char pbuf[BUFSZ]; strcpy(pbuf, rank_of((int)mtmp->m_lev, monsndx(mdat), (boolean)mtmp->female)); strcat(buf, lcase(pbuf)); name_at_start = FALSE; } else { strcat(buf, mdat->mname); name_at_start = (boolean)type_is_pname(mdat); } if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) { if (mdat == &mons[PM_WIZARD_OF_YENDOR]) article = ARTICLE_THE; else article = ARTICLE_NONE; } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) { article = ARTICLE_THE; } { char buf2[BUFSZ]; switch(article) { case ARTICLE_YOUR: strcpy(buf2, "your "); strcat(buf2, buf); strcpy(buf, buf2); return buf; case ARTICLE_THE: strcpy(buf2, "the "); strcat(buf2, buf); strcpy(buf, buf2); return buf; case ARTICLE_A: return an(buf); case ARTICLE_NONE: default: return buf; } } }