/** * Find a default user name from the system. */ static void user_name(char *buf, size_t len, int id) { struct passwd *pw = getpwuid(id); /* Default to PLAYER */ if (!pw || !pw->pw_name || !pw->pw_name[0] ) { my_strcpy(buf, "PLAYER", len); return; } /* Copy and capitalise */ my_strcpy(buf, pw->pw_name, len); my_strcap(buf); }
/** * Build the object list. */ static void build_obj_list(int last, struct object **list, item_tester tester, olist_detail_t mode) { int i; struct object *obj; char buf[80]; bool gold_ok = (mode & OLIST_GOLD) ? TRUE : FALSE; bool in_term = (mode & OLIST_WINDOW) ? TRUE : FALSE; bool show_empty = (mode & OLIST_SEMPTY) ? TRUE : FALSE; bool equip = list ? FALSE : TRUE; /* Build the object list */ for (i = 0; i <= last; i++) { obj = equip ? slot_object(player, i) : list[i]; /* Acceptable items get a label */ if (object_test(tester, obj) || (obj && tval_is_money(obj) && gold_ok)) strnfmt(items[num_obj].label, sizeof(items[num_obj].label), "%c) ", I2A(i)); /* Unacceptable items are still sometimes shown */ else if ((!obj && show_empty) || in_term) my_strcpy(items[num_obj].label, " ", sizeof(items[num_obj].label)); /* Unacceptable items are skipped in the main window */ else continue; /* Show full slot labels for equipment (or quiver in subwindow) */ if (equip) { strnfmt(buf, sizeof(buf), "%-14s: ", equip_mention(player, i)); my_strcap(buf); my_strcpy(items[num_obj].equip_label, buf, sizeof(items[num_obj].equip_label)); } else if (in_term && (list == player->upkeep->quiver)) { strnfmt(buf, sizeof(buf), "Slot %-9d: ", i); my_strcpy(items[num_obj].equip_label, buf, sizeof(items[num_obj].equip_label)); } else { strnfmt(items[num_obj].equip_label, sizeof(items[num_obj].equip_label), ""); } /* Save the object */ items[num_obj].object = obj; items[num_obj].key = (items[num_obj].label)[0]; num_obj++; } }
int main(int argc, char *argv[]) { int i; char name[256]; Rand_value = time(NULL); for (i = 0; i < 20; i++) { randname_make(RANDNAME_TOLKIEN, 5, 9, name, 256, name_sections); my_strcap(name); printf("%s\n", name); } return 0; }
/** * Get a spell from the player. */ int textui_get_spell(const char *verb, item_tester book_filter, cmd_code cmd, const char *error, bool (*spell_filter)(int spell_index)) { char prompt[1024]; struct object *book; /* Create prompt */ strnfmt(prompt, sizeof prompt, "%s which book?", verb); my_strcap(prompt); if (!get_item(&book, prompt, error, cmd, book_filter, (USE_INVEN | USE_FLOOR))) return -1; return textui_get_spell_from_book(verb, book, error, spell_filter); }
/** * Run the spell menu to select a spell. */ static int spell_menu_select(struct menu *m, const char *noun, const char *verb) { struct spell_menu_data *d = menu_priv(m); char buf[80]; screen_save(); region_erase_bordered(&m->active); /* Format, capitalise and display */ strnfmt(buf, sizeof buf, "%s which %s? ('?' to toggle description)", verb, noun); my_strcap(buf); prt(buf, 0, 0); menu_select(m, 0, TRUE); screen_load(); return d->selected_spell; }
/** * Show spell long description when browsing */ static void curse_menu_browser(int oid, void *data, const region *loc) { struct curse_menu_data *choice = data; char buf[80]; /* Redirect output to the screen */ text_out_hook = text_out_to_screen; text_out_wrap = 0; text_out_indent = loc->col - 1; text_out_pad = 1; Term_gotoxy(loc->col, loc->row + loc->page_rows); my_strcpy(buf, curses[choice[oid].index].desc, sizeof(buf)); my_strcap(buf); text_out(" %s.\n", buf); /* XXX */ text_out_pad = 0; text_out_indent = 0; }
/* * A "keypress" handling function for askfor_aux, that handles the special * case of '*' for a new random "name" and passes any other "keypress" * through to the default "editing" handler. */ static bool get_name_keypress(char *buf, size_t buflen, size_t *curs, size_t *len, struct keypress keypress, bool firsttime) { bool result; switch (keypress.code) { case '*': { *len = randname_make(RANDNAME_TOLKIEN, 4, 8, buf, buflen, name_sections); my_strcap(buf); *curs = 0; result = FALSE; break; } default: { result = askfor_aux_keypress(buf, buflen, curs, len, keypress, firsttime); break; } } return result; }
/** * Decreases a monster's hit points by `dam` and handle monster death. * * Hack -- we "delay" fear messages by passing around a "fear" flag. * * We announce monster death (using an optional "death message" (`note`) * if given, and a otherwise a generic killed/destroyed message). * * Returns TRUE if the monster has been killed (and deleted). * * TODO: Consider decreasing monster experience over time, say, by using * "(m_exp * m_lev * (m_lev)) / (p_lev * (m_lev + n_killed))" instead * of simply "(m_exp * m_lev) / (p_lev)", to make the first monster * worth more than subsequent monsters. This would also need to * induce changes in the monster recall code. XXX XXX XXX **/ bool mon_take_hit(struct monster *m_ptr, int dam, bool *fear, const char *note) { s32b div, new_exp, new_exp_frac; monster_lore *l_ptr = get_lore(m_ptr->race); /* Redraw (later) if needed */ if (p_ptr->health_who == m_ptr) p_ptr->redraw |= (PR_HEALTH); /* Wake it up */ mon_clear_timed(m_ptr, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE, FALSE); /* Become aware of its presence */ if (m_ptr->unaware) become_aware(m_ptr); /* Hurt it */ m_ptr->hp -= dam; /* It is dead now */ if (m_ptr->hp < 0) { char m_name[80]; char buf[80]; /* Assume normal death sound */ int soundfx = MSG_KILL; /* Play a special sound if the monster was unique */ if (rf_has(m_ptr->race->flags, RF_UNIQUE)) { if (m_ptr->race->base == lookup_monster_base("Morgoth")) soundfx = MSG_KILL_KING; else soundfx = MSG_KILL_UNIQUE; } /* Extract monster name */ monster_desc(m_name, sizeof(m_name), m_ptr, 0); /* Death by Missile/Spell attack */ if (note) { /* Hack -- allow message suppression */ if (strlen(note) <= 1) { /* Be silent */ } else { char *str = format("%s%s", m_name, note); my_strcap(str); msgt(soundfx, "%s", str); } } /* Death by physical attack -- invisible monster */ else if (!m_ptr->ml) msgt(soundfx, "You have killed %s.", m_name); /* Death by Physical attack -- non-living monster */ else if (monster_is_unusual(m_ptr->race)) msgt(soundfx, "You have destroyed %s.", m_name); /* Death by Physical attack -- living monster */ else msgt(soundfx, "You have slain %s.", m_name); /* Player level */ div = p_ptr->lev; /* Give some experience for the kill */ new_exp = ((long)m_ptr->race->mexp * m_ptr->race->level) / div; /* Handle fractional experience */ new_exp_frac = ((((long)m_ptr->race->mexp * m_ptr->race->level) % div) * 0x10000L / div) + p_ptr->exp_frac; /* Keep track of experience */ if (new_exp_frac >= 0x10000L) { new_exp++; p_ptr->exp_frac = (u16b)(new_exp_frac - 0x10000L); } else p_ptr->exp_frac = (u16b)new_exp_frac; /* When the player kills a Unique, it stays dead */ if (rf_has(m_ptr->race->flags, RF_UNIQUE)) { char unique_name[80]; m_ptr->race->max_num = 0; /* * This gets the correct name if we slay an invisible * unique and don't have See Invisible. */ monster_desc(unique_name, sizeof(unique_name), m_ptr, MDESC_SHOW | MDESC_IND2); /* Log the slaying of a unique */ strnfmt(buf, sizeof(buf), "Killed %s", unique_name); history_add(buf, HISTORY_SLAY_UNIQUE, 0); } /* Gain experience */ player_exp_gain(p_ptr, new_exp); /* Generate treasure */ monster_death(m_ptr, FALSE); /* Recall even invisible uniques or winners */ if (m_ptr->ml || rf_has(m_ptr->race->flags, RF_UNIQUE)) { /* Count kills this life */ if (l_ptr->pkills < MAX_SHORT) l_ptr->pkills++; /* Count kills in all lives */ if (l_ptr->tkills < MAX_SHORT) l_ptr->tkills++; /* Hack -- Auto-recall */ monster_race_track(m_ptr->race); } /* Delete the monster */ delete_monster_idx(m_ptr->midx); /* Not afraid */ (*fear) = FALSE; /* Monster is dead */ return (TRUE); } /* Mega-Hack -- Pain cancels fear */ if (!(*fear) && m_ptr->m_timed[MON_TMD_FEAR] && (dam > 0)) { int tmp = randint1(dam); /* Cure a little fear */ if (tmp < m_ptr->m_timed[MON_TMD_FEAR]) { /* Reduce fear */ mon_dec_timed(m_ptr, MON_TMD_FEAR, tmp, MON_TMD_FLG_NOMESSAGE, FALSE); } /* Cure all the fear */ else { /* Cure fear */ mon_clear_timed(m_ptr, MON_TMD_FEAR, MON_TMD_FLG_NOMESSAGE, FALSE); /* No more fear */ (*fear) = FALSE; } } /* Sometimes a monster gets scared by damage */ if (!m_ptr->m_timed[MON_TMD_FEAR] && !rf_has(m_ptr->race->flags, RF_NO_FEAR) && dam > 0) { int percentage; /* Percentage of fully healthy */ percentage = (100L * m_ptr->hp) / m_ptr->maxhp; /* * Run (sometimes) if at 10% or less of max hit points, * or (usually) when hit for half its current hit points */ if ((randint1(10) >= percentage) || ((dam >= m_ptr->hp) && (randint0(100) < 80))) { int timer = randint1(10) + (((dam >= m_ptr->hp) && (percentage > 7)) ? 20 : ((11 - percentage) * 5)); /* Hack -- note fear */ (*fear) = TRUE; mon_inc_timed(m_ptr, MON_TMD_FEAR, timer, MON_TMD_FLG_NOMESSAGE | MON_TMD_FLG_NOFAIL, FALSE); } } /* Not dead yet */ return (FALSE); }
/** * Builds a string describing a monster in some way. * * We can correctly describe monsters based on their visibility. * We can force all monsters to be treated as visible or invisible. * We can build nominatives, objectives, possessives, or reflexives. * We can selectively pronominalize hidden, visible, or all monsters. * We can use definite or indefinite descriptions for hidden monsters. * We can use definite or indefinite descriptions for visible monsters. * * Pronominalization involves the gender whenever possible and allowed, * so that by cleverly requesting pronominalization / visibility, you * can get messages like "You hit someone. She screams in agony!". * * Reflexives are acquired by requesting Objective plus Possessive. * * I am assuming that no monster name is more than 65 characters long, * so that "char desc[80];" is sufficiently large for any result, even * when the "offscreen" notation is added. * * Note that the "possessive" for certain unique monsters will look * really silly, as in "Morgoth, King of Darkness's". We should * perhaps add a flag to "remove" any "descriptives" in the name. * * Note that "offscreen" monsters will get a special "(offscreen)" * notation in their name if they are visible but offscreen. This * may look silly with possessives, as in "the rat's (offscreen)". * Perhaps the "offscreen" descriptor should be abbreviated. * * Mode Flags: * 0x01 --> Objective (or Reflexive) * 0x02 --> Possessive (or Reflexive) * 0x04 --> Use indefinites for hidden monsters ("something") * 0x08 --> Use indefinites for visible monsters ("a kobold") * 0x10 --> Pronominalize hidden monsters * 0x20 --> Pronominalize visible monsters * 0x40 --> Assume the monster is hidden * 0x80 --> Assume the monster is visible * 0x100 --> Capitalise monster name * * Useful Modes: * 0x00 --> Full nominative name ("the kobold") or "it" * 0x04 --> Full nominative name ("the kobold") or "something" * 0x80 --> Banishment resistance name ("the kobold") * 0x88 --> Killing name ("a kobold") * 0x22 --> Possessive, genderized if visable ("his") or "its" * 0x23 --> Reflexive, genderized if visable ("himself") or "itself" */ void monster_desc(char *desc, size_t max, const struct monster *mon, int mode) { const char *choice; bool seen, use_pronoun; assert(mon); /* Can we "see" it (forced, or not hidden + visible) */ seen = ((mode & (MDESC_SHOW)) || (!(mode & (MDESC_HIDE)) && mflag_has(mon->mflag, MFLAG_VISIBLE))); /* Sexed Pronouns (seen and forced, or unseen and allowed) */ use_pronoun = ((seen && (mode & (MDESC_PRO_VIS))) || (!seen && (mode & (MDESC_PRO_HID)))); /* First, try using pronouns, or describing hidden monsters */ if (!seen || use_pronoun) { /* an encoding of the monster "sex" */ int msex = 0x00; /* Extract the gender (if applicable) */ if (rf_has(mon->race->flags, RF_FEMALE)) msex = 0x20; else if (rf_has(mon->race->flags, RF_MALE)) msex = 0x10; /* Ignore the gender (if desired) */ if (!mon || !use_pronoun) msex = 0x00; /* Assume simple result */ choice = "it"; /* Brute force: split on the possibilities */ switch (msex + (mode & 0x07)) { /* Neuter, or unknown */ case 0x00: choice = "it"; break; case 0x01: choice = "it"; break; case 0x02: choice = "its"; break; case 0x03: choice = "itself"; break; case 0x04: choice = "something"; break; case 0x05: choice = "something"; break; case 0x06: choice = "something's"; break; case 0x07: choice = "itself"; break; /* Male (assume human if vague) */ case 0x10: choice = "he"; break; case 0x11: choice = "him"; break; case 0x12: choice = "his"; break; case 0x13: choice = "himself"; break; case 0x14: choice = "someone"; break; case 0x15: choice = "someone"; break; case 0x16: choice = "someone's"; break; case 0x17: choice = "himself"; break; /* Female (assume human if vague) */ case 0x20: choice = "she"; break; case 0x21: choice = "her"; break; case 0x22: choice = "her"; break; case 0x23: choice = "herself"; break; case 0x24: choice = "someone"; break; case 0x25: choice = "someone"; break; case 0x26: choice = "someone's"; break; case 0x27: choice = "herself"; break; } /* Copy the result */ my_strcpy(desc, choice, max); } else if ((mode & MDESC_POSS) && (mode & MDESC_OBJE)) { /* The monster is visible, so use its gender */ if (rf_has(mon->race->flags, RF_FEMALE)) my_strcpy(desc, "herself", max); else if (rf_has(mon->race->flags, RF_MALE)) my_strcpy(desc, "himself", max); else my_strcpy(desc, "itself", max); } else { /* Unique, indefinite or definite */ if (rf_has(mon->race->flags, RF_UNIQUE)) { /* Start with the name (thus nominative and objective) */ my_strcpy(desc, mon->race->name, max); } else if (mode & MDESC_IND_VIS) { /* XXX Check plurality for "some" */ /* Indefinite monsters need an indefinite article */ my_strcpy(desc, is_a_vowel(mon->race->name[0]) ? "an " : "a ", max); my_strcat(desc, mon->race->name, max); } else { /* Definite monsters need a definite article */ my_strcpy(desc, "the ", max); my_strcat(desc, mon->race->name, max); } /* Handle the Possessive as a special afterthought */ if (mode & MDESC_POSS) { /* XXX Check for trailing "s" */ /* Simply append "apostrophe" and "s" */ my_strcat(desc, "'s", max); } /* Mention "offscreen" monsters XXX XXX */ if (!panel_contains(mon->fy, mon->fx)) { /* Append special notation */ my_strcat(desc, " (offscreen)", max); } } if (mode & MDESC_CAPITAL) my_strcap(desc); }