/* * Present a sorted list to the player, and get a selection */ int get_player_sort_choice(cptr *choices, int num, int col, int wid, cptr helpfile, void (*hook) (cptr)) { int i; int choice; cptr *strings; C_MAKE(strings, num, cptr); /* Initialise the sorted string array */ for (i = 0; i < num; i++) { strings[i] = choices[i]; } /* Sort the strings */ ang_sort_comp = ang_sort_comp_hook_string; ang_sort_swap = ang_sort_swap_hook_string; /* Sort the (unique) slopes */ ang_sort((void *)strings, NULL, num); /* Get the choice */ choice = get_player_choice(strings, num, col, wid, helpfile, hook); /* Invert the choice */ for (i = 0; i < num; i++) { /* Does the string match the one we selected? */ if (choices[i] == strings[choice]) { /* Save the choice + exit */ choice = i; break; } } /* Free the strings */ FREE((void *)strings); /* Return the value from the list */ return (choice); }
/* * Prepare the "temp" array for "target_interactive_set" * * Return the number of target_able monsters in the set. */ static void target_set_interactive_prepare(int mode) { int y, x; /* Reset "temp" array */ temp_n = 0; /* Scan the current panel */ for (y = Term->offset_y; y < Term->offset_y + SCREEN_HGT; y++) { for (x = Term->offset_x; x < Term->offset_x + SCREEN_WID; x++) { /* Check bounds */ if (!in_bounds_fully(y, x)) continue; /* Require "interesting" contents */ if (!target_set_interactive_accept(y, x)) continue; /* Special mode */ if (mode & (TARGET_KILL)) { /* Must contain a monster */ if (!(cave_m_idx[y][x] > 0)) continue; /* Must be a targettable monster */ if (!target_able(cave_m_idx[y][x])) continue; } /* Save the location */ temp_x[temp_n] = x; temp_y[temp_n] = y; temp_n++; } } /* Set the sort hooks */ ang_sort_comp = ang_sort_comp_distance; ang_sort_swap = ang_sort_swap_distance; /* Sort the positions */ ang_sort(temp_x, temp_y, temp_n); }
/* * Prepare the "temp" array for "target_interactive_set" * * Return the number of target_able monsters in the set. */ static void target_set_interactive_prepare(int mode) { int y, x; bool expand_look = (mode & (TARGET_LOOK)) ? TRUE : FALSE; /* Reset "temp" array */ clear_temp_array(); /* Scan the current panel */ for (y = Term->offset_y; y < Term->offset_y + SCREEN_HGT; y++) { for (x = Term->offset_x; x < Term->offset_x + SCREEN_WID; x++) { bool do_continue = FALSE; /* Check overflow */ if (temp_n >= TEMP_MAX) continue; /* Check bounds */ if (!in_bounds_fully(y, x)) continue; /* Require line of sight, unless "look" is "expanded" */ if (!player_has_los_bold(y, x) && (!expand_look)) continue; /* Require "interesting" contents */ if (!target_set_interactive_accept(y, x)) continue; /* Special mode */ if (mode & (TARGET_KILL)) { /* Must contain a monster */ if (!(cave_m_idx[y][x] > 0)) do_continue = TRUE; /* Must be a targettable monster */ if (!target_able(cave_m_idx[y][x])) do_continue = TRUE; } /* Don't continue on the trap exception, or if probing. */ if ((mode & (TARGET_TRAP)) && target_able_trap(y, x)) do_continue = FALSE; else if (mode & (TARGET_PROBE)) do_continue = FALSE; if (do_continue) continue; /* * Hack - don't go over redundant elemental terrain \ * (since we have large lakes and pools of the same terrain) */ if ((p_ptr->target_row > 0) || (p_ptr->target_col > 0)) { if (cave_feat[p_ptr->target_row][p_ptr->target_col] == cave_feat[y][x]) { if (cave_ff3_match(y, x, TERRAIN_MASK)) continue; } } /* Save the location */ temp_x[temp_n] = x; temp_y[temp_n] = y; temp_n++; } } /* Set the sort hooks */ ang_sort_comp = ang_sort_comp_distance; ang_sort_swap = ang_sort_swap_distance; /* Sort the positions */ ang_sort(temp_x, temp_y, temp_n); }
/* * Identify a character, allow recall of monsters * * Several "special" responses recall "mulitple" monsters: * ^A (all monsters) * ^U (all unique monsters) * ^N (all non-unique monsters) * * The responses may be sorted in several ways, see below. * * Note that the player ghosts are ignored, since they do not exist. */ void do_cmd_query_symbol(void) { int i, n, r_idx; char sym, query; char buf[128]; bool all = FALSE; bool uniq = FALSE; bool norm = FALSE; bool kill = TRUE; bool recall = FALSE; u16b why = 0; u16b *who; /* Get a character, or abort */ if (!get_com("Enter character to be identified: ", &sym)) return; /* Find that character info, and describe it */ for (i = 0; ident_info[i]; ++i) { if (sym == ident_info[i][0]) break; } /* Describe */ if (sym == KTRL('A')) { all = TRUE; strcpy(buf, "Full monster list."); } else if (sym == KTRL('U')) { all = uniq = TRUE; strcpy(buf, "Unique monster list."); } else if (sym == KTRL('N')) { all = norm = TRUE; strcpy(buf, "Non-unique monster list."); } else if (sym == KTRL('K')) { all = kill = TRUE; strcpy(buf, "Killed monster list."); } else if (ident_info[i]) { sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); } else { sprintf(buf, "%c - %s.", sym, "Unknown Symbol"); } /* Display the result */ prt(buf, 0, 0); /* Allocate the "who" array */ C_MAKE(who, z_info->r_max, u16b); /* Collect matching monsters */ for (n = 0, i = 1; i < z_info->r_max - 1; i++) { monster_race *r_ptr = &r_info[i]; monster_lore *l_ptr = &l_list[i]; /* Nothing to recall */ if (!cheat_know && !l_ptr->sights) continue; /* Skip unused monsters */ if (!(r_ptr->hdice)) continue; /* Require non-unique monsters if needed */ if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; /* Require unique monsters if needed */ if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; /* Require killed if needed */ if (kill && !(l_ptr->pkills)) continue; /* Collect "appropriate" monsters */ if (all || (r_ptr->d_char == sym)) who[n++] = i; } /* Nothing to recall */ if (!n) { /* XXX XXX Free the "who" array */ FREE(who); return; } /* Prompt */ put_str("Recall details? (k/K/p/P/a/A/y/n): ", 0, 40); /* Query */ query = inkey(); /* Restore */ prt(buf, 0, 0); /* Sort by kills (and level) */ if (query == 'k') { why = 4; query = 'y'; } if (query == 'K') { why = 4+16; query = 'y'; } /* Sort by total kills (and level) */ if (query == 'a') { why = 3; query = 'y'; } if (query == 'A') { why = 3+16; query = 'y'; } /* Sort by level (and experience) */ if (query == 'p') { why = 2; query = 'y'; } if (query == 'P') { why = 2+16; query = 'y'; } /* Catch "escape" */ if (query != 'y') { /* XXX XXX Free the "who" array */ FREE(who); return; } /* Sort if needed */ if (why) { /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array */ ang_sort(who, &why, n); } /* Start at the end */ i = n - 1; /* Scan the monster memory */ while (1) { /* Extract a race */ r_idx = who[i]; /* Hack -- Auto-recall */ monster_race_track(r_idx); /* Hack -- Handle stuff */ handle_stuff(); /* Hack -- Begin the prompt */ roff_top(r_idx); /* Hack -- Complete the prompt */ Term_addstr(-1, TERM_WHITE, " [(r)ecall, ESC]"); /* Interact */ while (1) { /* Recall */ if (recall) { /* Save screen */ screen_save(); /* Recall on screen */ screen_roff(who[i]); /* Hack -- Complete the prompt (again) */ Term_addstr(-1, TERM_WHITE, " [(r)ecall, ESC]"); } /* Command */ query = inkey(); /* Unrecall */ if (recall) { /* Load screen */ screen_load(); } /* Normal commands */ if (query != 'r') break; /* Toggle recall */ recall = !recall; } /* Stop scanning */ if (query == ESCAPE) break; /* Move to "prev" monster */ if (query == '-') { if (++i == n) { i = 0; if (!expand_list) break; } } /* Move to "next" monster */ else { if (i-- == 0) { i = n - 1; if (!expand_list) break; } } } /* Re-display the identity */ prt(buf, 0, 0); /* Free the "who" array */ FREE(who); }
void do_cmd_list_objects(void) { int list[_MAX_OBJ_LIST]; int i, ct = 0; int cx, cy, row = 1, col; for (i = 0; i < max_o_idx; i++) { object_type *o_ptr = &o_list[i]; int auto_pick_idx; if (!o_ptr->k_idx) continue; if (!(o_ptr->marked & OM_FOUND)) continue; if (o_ptr->tval == TV_GOLD) continue; if (ct >= _MAX_OBJ_LIST) break; auto_pick_idx = is_autopick(o_ptr); if (!p_ptr->wizard) { if (auto_pick_idx < 0) continue; if (!(autopick_list[auto_pick_idx].action & DO_DISPLAY)) continue; if (!(autopick_list[auto_pick_idx].action & (DO_AUTOPICK | DO_QUERY_AUTOPICK | DONT_AUTOPICK))) continue; } list[ct++] = i; } if (!ct) { msg_print("No objects match your pickup preferences."); return; } ang_sort_comp = _compare_obj_list_info; ang_sort_swap = _swap_int; ang_sort(list, NULL, ct); Term_get_size(&cx, &cy); col = cx - 52; screen_save(); c_prt(TERM_WHITE, format("%d object%s match your pickup preferences", ct, ct != 1 ? "s" : ""), 0, col); for (i = 0; i < ct; i++) { char o_name[MAX_NLEN]; object_type *o_ptr = &o_list[list[i]]; byte a = object_attr(o_ptr); char c = object_char(o_ptr); byte attr = TERM_WHITE; Term_erase(col - 1, row, 53); if (row >= cy - 2) { c_prt(TERM_YELLOW, "...", row++, col+2); break; } object_desc(o_name, o_ptr, 0); attr = tval_to_attr[o_ptr->tval % 128]; Term_queue_bigchar(col, row, a, c, 0, 0); c_put_str(attr, format(" %-50.50s", o_name), row++, col+1); } Term_erase(col - 1, row, 53); c_prt(TERM_YELLOW, "Hit any key.", row, col+2); inkey(); prt("", 0, 0); screen_load(); }
/* Idea borrowed from Vanilla 3.5, but recoded from scratch ... */ void do_cmd_list_monsters(void) { int i, ct_types, ct_total = 0; int_map_ptr info = int_map_alloc(free); /* Collect */ for (i = 0; i < max_m_idx; i++) { const monster_type *m_ptr = &m_list[i]; _mon_list_info_ptr info_ptr; if (!m_ptr->ap_r_idx) continue; if (!m_ptr->ml) continue; info_ptr = int_map_find(info, m_ptr->ap_r_idx); if (!info_ptr) { info_ptr = malloc(sizeof(_mon_list_info_t)); info_ptr->r_idx = m_ptr->ap_r_idx; info_ptr->ct_total = 0; info_ptr->ct_awake = 0; info_ptr->ct_los = 0; int_map_add(info, m_ptr->ap_r_idx, info_ptr); } assert(info_ptr); info_ptr->ct_total++; ct_total++; if (!MON_CSLEEP(m_ptr)) info_ptr->ct_awake++; if (projectable(py, px, m_ptr->fy, m_ptr->fx)) info_ptr->ct_los++; } ct_types = int_map_count(info); if (ct_types) { int_map_iter_ptr iter; int *order; int cx, cy, row = 1, col; /* Sort */ C_MAKE(order, ct_types, int); i = 0; for (iter = int_map_iter_alloc(info); int_map_iter_is_valid(iter); int_map_iter_next(iter)) { _mon_list_info_ptr info_ptr = int_map_iter_current(iter); order[i++] = info_ptr->r_idx; } int_map_iter_free(iter); ang_sort_comp = _compare_r_level; ang_sort_swap = _swap_int; ang_sort(order, NULL, ct_types); /* Display */ Term_get_size(&cx, &cy); col = cx - 52; screen_save(); c_prt(TERM_WHITE, format("You see %d monster%s", ct_total, ct_total != 1 ? "s" : ""), 0, col); for (i = 0; i < ct_types; i++) { int r_idx = order[i]; const monster_race *r_ptr = &r_info[r_idx]; byte attr = TERM_WHITE; _mon_list_info_ptr info_ptr = int_map_find(info, r_idx); char buf[100]; assert(info_ptr); Term_erase(col - 1, row, 53); if (row >= cy - 2) { c_prt(TERM_YELLOW, "...", row++, col+2); break; } if (r_ptr->flags1 & RF1_UNIQUE) attr = TERM_VIOLET; else if (r_ptr->level > base_level) attr = TERM_RED; else if (!info_ptr->ct_awake) attr = TERM_L_UMBER; if (info_ptr->ct_total == 1) sprintf(buf, "%s", r_name + r_ptr->name); else if (!info_ptr->ct_awake) sprintf(buf, "%s (%d sleeping)", r_name + r_ptr->name, info_ptr->ct_total); else if (info_ptr->ct_awake == info_ptr->ct_total) sprintf(buf, "%s (%d awake)", r_name + r_ptr->name, info_ptr->ct_total); else sprintf(buf, "%s (%d awake, %d sleeping)", r_name + r_ptr->name, info_ptr->ct_awake, info_ptr->ct_total - info_ptr->ct_awake); Term_queue_bigchar(col, row, r_ptr->x_attr, r_ptr->x_char, 0, 0); c_put_str(attr, format(" %-50.50s", buf), row++, col+1); } Term_erase(col - 1, row, 53); c_prt(TERM_YELLOW, "Hit any key.", row, col+2); inkey(); prt("", 0, 0); screen_load(); C_KILL(order, ct_types, int); } else msg_print("You see no visible monsters."); int_map_free(info); }
/* * Identify a character, allow recall of monsters * * Several "special" responses recall "multiple" monsters: * ^A (all monsters) * ^U (all unique monsters) * ^N (all non-unique monsters) * * The responses may be sorted in several ways, see below. * * Note that the player ghosts are ignored. XXX XXX XXX */ void do_cmd_query_symbol(void) { int i, n, r_idx; char sym, query; char buf[128]; bool all = FALSE; bool uniq = FALSE; bool norm = FALSE; bool ride = FALSE; char temp[80] = ""; bool recall = FALSE; u16b why = 0; u16b *who; /* Get a character, or abort */ if (!get_com("Enter character to be identified(^A:All,^U:Uniqs,^N:Non uniqs,^M:Name): ", &sym, FALSE)) return; /* Find that character info, and describe it */ for (i = 0; ident_info[i]; ++i) { if (sym == ident_info[i][0]) break; } /* Describe */ if (sym == KTRL('A')) { all = TRUE; strcpy(buf, "Full monster list."); } else if (sym == KTRL('U')) { all = uniq = TRUE; strcpy(buf, "Unique monster list."); } else if (sym == KTRL('N')) { all = norm = TRUE; strcpy(buf, "Non-unique monster list."); } else if (sym == KTRL('R')) { all = ride = TRUE; strcpy(buf, "Ridable monster list."); } /* XTRA HACK WHATSEARCH */ else if (sym == KTRL('M')) { all = TRUE; if (!get_string("Enter name:",temp, 70)) { temp[0]=0; return; } sprintf(buf, "Monsters with a name \"%s\"",temp); } else if (ident_info[i]) { sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); } else { sprintf(buf, "%c - %s.", sym, "Unknown Symbol"); } /* Display the result */ prt(buf, 0, 0); /* Allocate the "who" array */ C_MAKE(who, max_r_idx, u16b); /* Collect matching monsters */ for (n = 0, i = 1; i < max_r_idx; i++) { monster_race *r_ptr = &r_info[i]; /* Nothing to recall */ if (!(cheat_know || p_ptr->wizard) && !r_ptr->r_sights) continue; /* Require non-unique monsters if needed */ if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; /* Require unique monsters if needed */ if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; /* Require ridable monsters if needed */ if (ride && !(r_ptr->flags7 & (RF7_RIDING))) continue; /* XTRA HACK WHATSEARCH */ if (temp[0]) { int xx; char temp2[80]; for (xx=0; temp[xx] && xx<80; xx++) { if (isupper(temp[xx])) temp[xx]=tolower(temp[xx]); } strcpy(temp2, r_name+r_ptr->name); for (xx=0; temp2[xx] && xx<80; xx++) if (isupper(temp2[xx])) temp2[xx]=tolower(temp2[xx]); if (my_strstr(temp2, temp)) who[n++]=i; } /* Collect "appropriate" monsters */ else if (all || (r_ptr->d_char == sym)) who[n++] = i; } /* Nothing to recall */ if (!n) { /* Free the "who" array */ C_KILL(who, max_r_idx, u16b); return; } /* Prompt XXX XXX XXX */ put_str("Recall details? (k/y/n): ", 0, 40); /* Query */ query = inkey(); /* Restore */ prt(buf, 0, 0); why = 2; /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array */ ang_sort(who, &why, n); /* Sort by kills (and level) */ if (query == 'k') { why = 4; query = 'y'; } /* Catch "escape" */ if (query != 'y') { /* Free the "who" array */ C_KILL(who, max_r_idx, u16b); return; } /* Sort if needed */ if (why == 4) { /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array */ ang_sort(who, &why, n); } /* Start at the end */ i = n - 1; /* Scan the monster memory */ while (1) { /* Extract a race */ r_idx = who[i]; /* Hack -- Auto-recall */ monster_race_track(r_idx); /* Hack -- Handle stuff */ handle_stuff(); /* Interact */ while (1) { /* Recall */ if (recall) { /* Save the screen */ screen_save(); /* Recall on screen */ screen_roff(who[i], 0); } /* Hack -- Begin the prompt */ roff_top(r_idx); /* Hack -- Complete the prompt */ Term_addstr(-1, TERM_WHITE, " [(r)ecall, ESC]"); /* Command */ query = inkey(); /* Unrecall */ if (recall) { /* Restore */ screen_load(); } /* Normal commands */ if (query != 'r') break; /* Toggle recall */ recall = !recall; } /* Stop scanning */ if (query == ESCAPE) break; /* Move to "prev" monster */ if (query == '-') { if (++i == n) { i = 0; if (!expand_list) break; } } /* Move to "next" monster */ else { if (i-- == 0) { i = n - 1; if (!expand_list) break; } } } /* Free the "who" array */ C_KILL(who, max_r_idx, u16b); /* Re-display the identity */ prt(buf, 0, 0); }
/*! * @brief 保存フロアの書き込み / Actually write a saved floor data using effectively compressed format. * @param sf_ptr 保存したいフロアの参照ポインタ * @return なし */ static void wr_saved_floor(saved_floor_type *sf_ptr) { cave_template_type *templates; u16b max_num_temp; u16b num_temp = 0; int dummy_why; int i, y, x; u16b tmp16u; byte count; u16b prev_u16b; /*** Basic info ***/ /* Dungeon floor specific info follows */ if (!sf_ptr) { /*** Not a saved floor ***/ wr_s16b(dun_level); } else { /*** The saved floor ***/ wr_s16b(sf_ptr->floor_id); wr_byte(sf_ptr->savefile_id); wr_s16b(sf_ptr->dun_level); wr_s32b(sf_ptr->last_visit); wr_u32b(sf_ptr->visit_mark); wr_s16b(sf_ptr->upper_floor_id); wr_s16b(sf_ptr->lower_floor_id); } wr_u16b(base_level); wr_u16b(num_repro); wr_u16b((u16b)py); wr_u16b((u16b)px); wr_u16b(cur_hgt); wr_u16b(cur_wid); wr_byte(p_ptr->feeling); /*********** Make template for cave_type **********/ /* * Usually number of templates are fewer than 255. Even if * more than 254 are exist, the occurrence of each template * with larger ID is very small when we sort templates by * occurrence. So we will use two (or more) bytes for * templete ID larger than 254. * * Ex: 256 will be "0xff" "0x01". * 515 will be "0xff" "0xff" "0x03" */ /* Fake max number */ max_num_temp = 255; /* Allocate the "template" array */ C_MAKE(templates, max_num_temp, cave_template_type); /* Extract template array */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { cave_type *c_ptr = &cave[y][x]; for (i = 0; i < num_temp; i++) { if (templates[i].info == c_ptr->info && templates[i].feat == c_ptr->feat && templates[i].mimic == c_ptr->mimic && templates[i].special == c_ptr->special) { /* Same terrain is exist */ templates[i].occurrence++; break; } } /* Are there same one? */ if (i < num_temp) continue; /* If the max_num_temp is too small, increase it. */ if (num_temp >= max_num_temp) { cave_template_type *old_template = templates; /* Re-allocate the "template" array */ C_MAKE(templates, max_num_temp + 255, cave_template_type); (void)C_COPY(templates, old_template, max_num_temp, cave_template_type); C_KILL(old_template, max_num_temp, cave_template_type); max_num_temp += 255; } /* Add new template */ templates[num_temp].info = c_ptr->info; templates[num_temp].feat = c_ptr->feat; templates[num_temp].mimic = c_ptr->mimic; templates[num_temp].special = c_ptr->special; templates[num_temp].occurrence = 1; /* Increase number of template */ num_temp++; } } /* Select the sort method */ ang_sort_comp = ang_sort_comp_cave_temp; ang_sort_swap = ang_sort_swap_cave_temp; /* Sort by occurrence */ ang_sort(templates, &dummy_why, num_temp); /*** Dump templates ***/ /* Total templates */ wr_u16b(num_temp); /* Dump the templates */ for (i = 0; i < num_temp; i++) { cave_template_type *ct_ptr = &templates[i]; /* Dump it */ wr_u16b(ct_ptr->info); wr_s16b(ct_ptr->feat); wr_s16b(ct_ptr->mimic); wr_s16b(ct_ptr->special); } /*** "Run-Length-Encoding" of cave ***/ /* Note that this will induce two wasted bytes */ count = 0; prev_u16b = 0; /* Dump the cave */ for (y = 0; y < cur_hgt; y++) { for (x = 0; x < cur_wid; x++) { cave_type *c_ptr = &cave[y][x]; for (i = 0; i < num_temp; i++) { if (templates[i].info == c_ptr->info && templates[i].feat == c_ptr->feat && templates[i].mimic == c_ptr->mimic && templates[i].special == c_ptr->special) break; } /* Extract an ID */ tmp16u = i; /* If the run is broken, or too full, flush it */ if ((tmp16u != prev_u16b) || (count == MAX_UCHAR)) { wr_byte((byte)count); while (prev_u16b >= MAX_UCHAR) { /* Mark as actual data is larger than 254 */ wr_byte(MAX_UCHAR); prev_u16b -= MAX_UCHAR; } wr_byte((byte)prev_u16b); prev_u16b = tmp16u; count = 1; } /* Continue the run */ else { count++; } } } /* Flush the data (if any) */ if (count) { wr_byte((byte)count); while (prev_u16b >= MAX_UCHAR) { /* Mark as actual data is larger than 254 */ wr_byte(MAX_UCHAR); prev_u16b -= MAX_UCHAR; } wr_byte((byte)prev_u16b); } /* Free the "template" array */ C_KILL(templates, max_num_temp, cave_template_type); /*** Dump objects ***/ /* Total objects */ wr_u16b(o_max); /* Dump the objects */ for (i = 1; i < o_max; i++) { object_type *o_ptr = &o_list[i]; /* Dump it */ wr_item(o_ptr); } /*** Dump the monsters ***/ /* Total monsters */ wr_u16b(m_max); /* Dump the monsters */ for (i = 1; i < m_max; i++) { monster_type *m_ptr = &m_list[i]; /* Dump it */ wr_monster(m_ptr); } }
/* * Create a spoiler file for monsters */ static void spoil_mon_desc(cptr fname) { int i, n = 0; char buf[1024]; /* We use either ascii or system-specific encoding */ int encoding = (xchars_to_file) ? SYSTEM_SPECIFIC : ASCII; char nam[DESC_LEN]; char lev[32]; char rar[32]; char spd[32]; char ac[32]; char hp[32]; char exp[32]; u16b *who; u16b why = 2; /* Build the filename */ (void)path_build(buf, sizeof(buf), ANGBAND_DIR_INFO, fname); /* File type is "TEXT" */ FILE_TYPE(FILE_TYPE_TEXT); /* Open the file */ fff = my_fopen(buf, "w"); /* Oops */ if (!fff) { msg_print("Cannot create spoiler file."); return; } /* Dump to the spoiler file */ text_out_hook = text_out_to_file; text_out_file = fff; /* Print header */ print_header("Brief Monster"); /* Dump the header */ fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n", "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info"); fprintf(fff, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n", "----", "---", "---", "---", "--", "--", "-----------"); /* Allocate the "who" array */ C_MAKE(who, z_info->r_max, u16b); /* Scan the monsters */ for (i = 1; i < z_info->r_max; i++) { monster_race *r_ptr = &r_info[i]; /* Use that monster */ if (r_ptr->name) who[n++] = (u16b)i; } /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array by dungeon depth of monsters */ ang_sort(who, &why, n); /* Scan again */ for (i = 0; i < n; i++) { monster_race *r_ptr = &r_info[who[i]]; cptr name = (r_name + r_ptr->name); /* Get the "name" */ if (r_ptr->flags1 & (RF1_QUESTOR)) { (void)strnfmt(nam, sizeof(nam), "[Q] %s", name); } else if (r_ptr->flags1 & (RF1_UNIQUE)) { (void)strnfmt(nam, sizeof(nam), "[U] %s", name); } else { (void)strnfmt(nam, sizeof(nam), "The %s", name); } /* Level */ (void)strnfmt(lev, sizeof(lev), "%d", r_ptr->level); /* Rarity */ (void)strnfmt(rar, sizeof(rar), "%d", r_ptr->rarity); /* Speed */ (void)strnfmt(spd, sizeof(spd), "%+d", (r_ptr->speed - 110)); /* Armor Class */ (void)strnfmt(ac, sizeof(ac), "%d", r_ptr->ac); /* Hitpoints */ if (r_ptr->flags1 & (RF1_FIXED_HPS)) { (void)strnfmt(hp, sizeof(hp), "%d", (int)r_ptr->hitpoints); } else { (void)strnfmt(hp, sizeof(hp), "~%d", (int)r_ptr->hitpoints); } /* Experience */ (void)strnfmt(exp, sizeof(exp), "%ld", (long)(r_ptr->mexp)); /* Hack -- use visual instead */ (void)strnfmt(exp, sizeof(exp), "%s '%c'", attr_to_text(r_ptr->d_attr), r_ptr->d_char); /* Dump the info */ x_fprintf(fff, encoding, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n", nam, lev, rar, spd, hp, ac, exp); } /* End it */ fprintf(fff, "\n"); /* Free the "who" array */ FREE(who); /* Check for errors */ if (ferror(fff) || my_fclose(fff)) { msg_print("Cannot close spoiler file."); return; } /* Worked */ msg_print("Successfully created a spoiler file."); }
/* * Create a spoiler file for monsters * [email protected] (Shawn McHorse) */ static void spoil_mon_info(cptr fname) { char buf[1024]; int i, n; u16b why = 2; u16b *who; int count = 0; /* Build the filename */ (void)path_build(buf, sizeof(buf), ANGBAND_DIR_INFO, fname); /* File type is "TEXT" */ FILE_TYPE(FILE_TYPE_TEXT); /* Open the file */ fff = my_fopen(buf, "w"); /* Oops */ if (!fff) { msg_print("Cannot create spoiler file."); return; } /* Dump to the spoiler file */ text_out_hook = text_out_to_file; text_out_file = fff; /* Print header */ print_header("Full Monster"); /* Allocate the "who" array */ C_MAKE(who, z_info->r_max, u16b); /* Scan the monsters */ for (i = 1; i < z_info->r_max; i++) { monster_race *r_ptr = &r_info[i]; /* Use that monster */ if (r_ptr->name) who[count++] = (u16b)i; } /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array by dungeon depth of monsters */ ang_sort(who, &why, count); /* * List all monsters in order. */ for (n = 0; n < count; n++) { int r_idx = who[n]; monster_race *r_ptr = &r_info[r_idx]; /* Prefix */ if (r_ptr->flags1 & RF1_QUESTOR) { text_out("[Q] "); } else if (r_ptr->flags1 & RF1_UNIQUE) { text_out("[U] "); } else { text_out("The "); } /* Name */ (void)strnfmt(buf, sizeof(buf), "%s (", (r_name + r_ptr->name)); /* ---)--- */ text_out(buf); /* Color */ text_out(attr_to_text(r_ptr->d_attr)); /* Symbol --(-- */ (void)strnfmt(buf, sizeof(buf), " '%c')\n", r_ptr->d_char); text_out(buf); /* Indent */ (void)strnfmt(buf, sizeof(buf), "=== "); text_out(buf); /* Number */ (void)strnfmt(buf, sizeof(buf), "Num:%d ", r_idx); text_out(buf); /* Level */ (void)strnfmt(buf, sizeof(buf), "Lev:%d ", r_ptr->level); text_out(buf); /* Rarity */ (void)strnfmt(buf, sizeof(buf), "Rar:%d ", r_ptr->rarity); text_out(buf); /* Speed */ if (r_ptr->speed >= 110) { (void)strnfmt(buf, sizeof(buf), "Spd:+%d ", (r_ptr->speed - 110)); } else { (void)strnfmt(buf, sizeof(buf), "Spd:-%d ", (110 - r_ptr->speed)); } text_out(buf); /* Hitpoints */ if (r_ptr->flags1 & (RF1_FIXED_HPS)) { (void)strnfmt(buf, sizeof(buf), "%d", r_ptr->hitpoints); } else { (void)strnfmt(buf, sizeof(buf), "~%d", r_ptr->hitpoints); } text_out(buf); /* Armor Class */ (void)strnfmt(buf, sizeof(buf), "Ac:%d ", r_ptr->ac); text_out(buf); /* Experience */ (void)strnfmt(buf, sizeof(buf), "Exp:%ld\n", (long)(r_ptr->mexp)); text_out(buf); /* Describe */ describe_monster(r_idx, TRUE); /* Terminate the entry */ text_out("\n"); } /* Free the "who" array */ FREE(who); /* Check for errors */ if (ferror(fff) || my_fclose(fff)) { msg_print("Cannot close spoiler file."); return; } msg_print("Successfully created a spoiler file."); }
/* * Create a spoiler file for monsters -BEN- */ static void spoil_mon_desc(cptr fname) { int i, n = 0; u16b why = 2; s16b *who; char buf[1024]; char nam[80]; char lev[80]; char rar[80]; char spd[80]; char ac[80]; char hp[80]; char exp[80]; /* Build the filename */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); /* File type is "TEXT" */ FILE_TYPE(FILE_TYPE_TEXT); /* Open the file */ fff = my_fopen(buf, "w"); /* Oops */ if (!fff) { msg_print("Cannot create spoiler file."); return; } /* Allocate the "who" array */ C_MAKE(who, max_r_idx, s16b); /* Dump the header */ fprintf(fff, "Spoiler File -- Monsters (PosChengband %d.%d.%d)\n\n\n", VER_MAJOR, VER_MINOR, VER_PATCH); fprintf(fff, "------------------------------------------\n\n"); /* Dump the header */ fprintf(fff, " %-38.38s%4s%4s%4s%7s%5s %11.11s\n", "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info"); fprintf(fff, "%-42.42s%4s%4s%4s%7s%5s %11.11s\n", "--------", "---", "---", "---", "--", "--", "-----------"); /* Scan the monsters */ for (i = 1; i < max_r_idx; i++) { monster_race *r_ptr = &r_info[i]; /* Use that monster */ if (r_ptr->name) who[n++] = i; } /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array by dungeon depth of monsters */ ang_sort(who, &why, n); /* Scan again */ for (i = 0; i < n; i++) { monster_race *r_ptr = &r_info[who[i]]; cptr name = (r_name + r_ptr->name); if (r_ptr->flags7 & (RF7_KAGE)) continue; /* Get the "name" */ /* else if (r_ptr->flags1 & (RF1_QUESTOR)) { sprintf(nam, "[Q] %s", name); } */ else if (r_ptr->flags1 & (RF1_UNIQUE)) { sprintf(nam, "[U] %s", name); } else { sprintf(nam, "The %s", name); } /* Level */ sprintf(lev, "%d", r_ptr->level); /* Rarity */ sprintf(rar, "%d", r_ptr->rarity); /* Speed */ if (r_ptr->speed >= 110) { sprintf(spd, "+%d", (r_ptr->speed - 110)); } else { sprintf(spd, "-%d", (110 - r_ptr->speed)); } /* Armor Class */ sprintf(ac, "%d", r_ptr->ac); /* Hitpoints */ if ((r_ptr->flags1 & (RF1_FORCE_MAXHP)) || (r_ptr->hside == 1)) { sprintf(hp, "%d", r_ptr->hdice * r_ptr->hside); } else { sprintf(hp, "%dd%d", r_ptr->hdice, r_ptr->hside); } /* Experience */ sprintf(exp, "%d", r_ptr->mexp); /* Hack -- use visual instead */ sprintf(exp, "%s '%c'", attr_to_text(r_ptr), r_ptr->d_char); /* Dump the info */ fprintf(fff, "%-42.42s%4s%4s%4s%7s%5s %11.11s\n", nam, lev, rar, spd, hp, ac, exp); } /* End it */ fprintf(fff, "\n"); /* Free the "who" array */ C_KILL(who, max_r_idx, s16b); /* Check for errors */ if (ferror(fff) || my_fclose(fff)) { msg_print("Cannot close spoiler file."); return; } /* Worked */ msg_print("Successfully created a spoiler file."); }
/* * Print monsters' evolution information to file */ static void spoil_mon_evol(cptr fname) { char buf[1024]; monster_race *r_ptr; int **evol_tree, i, j, n, r_idx; int *evol_tree_zero; /* For C_KILL() */ /* Build the filename */ path_build(buf, sizeof buf, ANGBAND_DIR_USER, fname); /* File type is "TEXT" */ FILE_TYPE(FILE_TYPE_TEXT); /* Open the file */ fff = my_fopen(buf, "w"); /* Oops */ if (!fff) { msg_print("Cannot create spoiler file."); return; } /* Dump the header */ sprintf(buf, "Monster Spoilers for PosChengband Version %d.%d.%d\n", VER_MAJOR, VER_MINOR, VER_PATCH); spoil_out(buf); spoil_out("------------------------------------------\n\n"); /* Allocate the "evol_tree" array (2-dimension) */ C_MAKE(evol_tree, max_r_idx, int *); C_MAKE(*evol_tree, max_r_idx * (MAX_EVOL_DEPTH + 1), int); for (i = 1; i < max_r_idx; i++) evol_tree[i] = *evol_tree + i * (MAX_EVOL_DEPTH + 1); evol_tree_zero = *evol_tree; /* Step 1: Build the evolution tree */ for (i = 1; i < max_r_idx; i++) { r_ptr = &r_info[i]; /* No evolution */ if (!r_ptr->next_exp) continue; /* Trace evolution */ n = 0; evol_tree[i][n++] = i; do { evol_tree[i][n++] = r_ptr->next_r_idx; r_ptr = &r_info[r_ptr->next_r_idx]; } while (r_ptr->next_exp && (n < MAX_EVOL_DEPTH)); } /* Step 2: Scan the evolution trees and remove "partial tree" */ for (i = 1; i < max_r_idx; i++) { /* Not evolution tree */ if (!evol_tree[i][0]) continue; for (j = 1; j < max_r_idx; j++) { /* Same tree */ if (i == j) continue; /* Not evolution tree */ if (!evol_tree[j][0]) continue; /* Is evolution tree[i] is part of [j]? */ if (is_partial_tree(evol_tree[j], evol_tree[i])) { /* Remove this evolution tree */ evol_tree[i][0] = 0; break; } } } /* Step 3: Sort the evolution trees */ /* Select the sort method */ ang_sort_comp = ang_sort_comp_evol_tree; ang_sort_swap = ang_sort_swap_evol_tree; /* Sort the array */ ang_sort(evol_tree, NULL, max_r_idx); /* Step 4: Print the evolution trees */ for (i = 0; i < max_r_idx; i++) { r_idx = evol_tree[i][0]; /* No evolution or removed evolution tree */ if (!r_idx) continue; /* Trace the evolution tree */ r_ptr = &r_info[r_idx]; fprintf(fff, "[%d]: %s (Level %d, '%c')\n", r_idx, r_name + r_ptr->name, r_ptr->level, r_ptr->d_char); for (n = 1; r_ptr->next_exp; n++) { fprintf(fff, "%*s-(%d)-> ", n * 2, "", r_ptr->next_exp); fprintf(fff, "[%d]: ", r_ptr->next_r_idx); r_ptr = &r_info[r_ptr->next_r_idx]; fprintf(fff, "%s (Level %d, '%c')\n", r_name + r_ptr->name, r_ptr->level, r_ptr->d_char); } /* End of evolution tree */ fputc('\n', fff); } /* Free the "evol_tree" array (2-dimension) */ C_KILL(evol_tree_zero, max_r_idx * (MAX_EVOL_DEPTH + 1), int); C_KILL(evol_tree, max_r_idx, int *); /* Check for errors */ if (ferror(fff) || my_fclose(fff)) { msg_print("Cannot close spoiler file."); return; } /* Message */ msg_print("Successfully created a spoiler file."); }
/* * Display list of svals to be squelched. */ static bool sval_menu(int tval, const char *desc) { menu_type menu; menu_iter menu_f = { NULL, NULL, sval_display, sval_action }; region area = { 1, 5, -1, -1 }; int num = 0; size_t i; squelch_choice *choice; /* Create the array, with entries both for aware and unaware squelch */ choice = C_ZNEW(2 * z_info->k_max, squelch_choice); /* Iterate over all possible object kinds, finding ones which can be squelched */ for (i = 1; i < z_info->k_max; i++) { object_kind *k_ptr = &k_info[i]; /* Skip empty objects, unseen objects, and incorrect tvals */ if (!k_ptr->name) continue; if (k_ptr->tval != tval) continue; if (!k_ptr->aware) { /* can unaware squelch anything */ /* XXX Eddie should it be required that unaware squelched flavors have been seen this game, if so, how to save that info? */ choice[num].idx = i; choice[num].aware = FALSE; num++; } if (k_ptr->everseen || k_ptr->tval == TV_GOLD) { /* aware squelch requires everseen */ /* do not require awareness for aware squelch, so people can set at game start */ choice[num].idx = i; choice[num].aware = TRUE; num++; } } /* Return here if there are no objects */ if (!num) { FREE(choice); return FALSE; } /* sort by name in squelch menus except for categories of items that are aware from the start */ switch(tval) { case TV_LIGHT: case TV_MAGIC_BOOK: case TV_PRAYER_BOOK: case TV_DRAG_ARMOR: case TV_GOLD: /* leave sorted by sval */ break; default: /* sort by name */ ang_sort_comp = ang_sort_comp_hook_squelch_choices; ang_sort_swap = ang_sort_swap_hook_squelch_choices; ang_sort((void*)choice, NULL, num); } /* Save the screen and clear it */ screen_save(); clear_from(0); /* Help text */ /* Output to the screen */ text_out_hook = text_out_to_screen; /* Indent output */ text_out_indent = 1; text_out_wrap = 79; Term_gotoxy(1, 0); /* Display some helpful information */ text_out("Use the "); text_out_c(TERM_L_GREEN, "movement keys"); text_out(" to scroll the list or "); text_out_c(TERM_L_GREEN, "ESC"); text_out(" to return to the previous menu. "); text_out_c(TERM_L_BLUE, "Enter"); text_out(" toggles the current setting."); text_out_indent = 0; /* Run menu */ menu_init(&menu, MN_SKIN_SCROLL, &menu_f); menu_setpriv(&menu, num, choice); menu_layout(&menu, &area); menu_select(&menu, 0); /* Free memory */ FREE(choice); /* Load screen */ screen_load(); return TRUE; }
/* * research_mon * -KMW- */ bool research_mon(void) { int i, n, r_idx; char sym, query; char buf[128]; s16b oldkills; byte oldwake; bool oldcheat; bool notpicked; bool recall = FALSE; u16b why = 0; monster_race *r2_ptr; u16b *who; #ifdef JP /* XTRA HACK WHATSEARCH */ bool all = FALSE; bool uniq = FALSE; bool norm = FALSE; char temp[80] = ""; /* XTRA HACK REMEMBER_IDX */ static int old_sym = '\0'; static int old_i = 0; #endif oldcheat = cheat_know; /* Save the screen */ screen_save(); /* Get a character, or abort */ #ifdef JP if (!get_com("モンスターの文字を入力して下さい(記号 or ^A全,^Uユ,^N非ユ,^M名前):", &sym)) #else if (!get_com("Enter character of monster: ", &sym)) #endif { /* Restore */ screen_load(); return (FALSE); } /* Allocate the "who" array */ C_MAKE(who, max_r_idx, u16b); /* Find that character info, and describe it */ for (i = 0; ident_info[i]; ++i) { if (sym == ident_info[i][0]) break; } #ifdef JP /* XTRA HACK WHATSEARCH */ if (sym == KTRL('A')) { all = TRUE; strcpy(buf, "全モンスターのリスト"); } else if (sym == KTRL('U')) { all = uniq = TRUE; strcpy(buf, "ユニーク・モンスターのリスト"); } else if (sym == KTRL('N')) { all = norm = TRUE; strcpy(buf, "ユニーク外モンスターのリスト"); } else if (sym == KTRL('M')) { all = TRUE; if (!get_string("名前(英語の場合小文字で可)", temp, 70)) { all = FALSE; temp[0] = 0; } sprintf(buf, "名前:%sにマッチ",temp); } else if (ident_info[i]) { sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); } #else if (ident_info[i]) { sprintf(buf, "%c - %s.", sym, ident_info[i] + 2); } #endif else { #ifdef JP sprintf(buf, "%c - %s", sym, "無効な文字"); #else sprintf(buf, "%c - %s.", sym, "Unknown Symbol"); #endif } /* Display the result */ prt(buf, 16, 10); /* Collect matching monsters */ for (n = 0, i = 1; i < max_r_idx; i++) { monster_race *r_ptr = &r_info[i]; cheat_know = TRUE; #ifdef JP /* XTRA HACK WHATSEARCH */ /* Require non-unique monsters if needed */ if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; /* Require unique monsters if needed */ if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; /* 名前検索 */ if (temp[0]){ char temp2[80]; int xx; for (xx=0; temp[xx] && xx<80; xx++){ if (iskanji(temp[xx])) { xx++; continue; } if (isupper(temp[xx])) temp[xx]=tolower(temp[xx]); } strcpy(temp2, r_name+r_ptr->E_name); for (xx=0; temp2[xx] && xx<80; xx++) if (isupper(temp2[xx])) temp2[xx]=tolower(temp2[xx]); if (my_strstr(temp2, temp) || my_strstr(r_name + r_ptr->name, temp) ) who[n++]=i; } else if (all || (r_ptr->d_char == sym)) who[n++] = i; #else /* Collect "appropriate" monsters */ if (r_ptr->d_char == sym) who[n++] = i; #endif } /* Nothing to recall */ if (!n) { cheat_know = oldcheat; /* Free the "who" array */ C_KILL(who, max_r_idx, u16b); /* Restore */ screen_load(); return (FALSE); } /* Sort by level */ why = 2; query = 'y'; /* Sort if needed */ if (why) { /* Select the sort method */ ang_sort_comp = ang_sort_comp_hook; ang_sort_swap = ang_sort_swap_hook; /* Sort the array */ ang_sort(who, &why, n); } /* Start at the end */ #ifdef JP /* XTRA HACK REMEMBER_IDX */ if (old_sym == sym && old_i < n) i = old_i; else i = n - 1; #else i = n - 1; #endif notpicked = TRUE; /* Scan the monster memory */ while (notpicked) { /* Extract a race */ r_idx = who[i]; /* Save this monster ID */ p_ptr->monster_race_idx = r_idx; /* Hack -- Handle stuff */ handle_stuff(); /* Hack -- Begin the prompt */ roff_top(r_idx); /* Hack -- Complete the prompt */ #ifdef JP Term_addstr(-1, TERM_WHITE, " ['r'思い出, ' 'で続行, ESC]"); #else Term_addstr(-1, TERM_WHITE, " [(r)ecall, ESC, space to continue]"); #endif /* Interact */ while (1) { /* Recall */ if (recall) { /* Recall on screen */ r2_ptr = &r_info[r_idx]; oldkills = r2_ptr->r_tkills; oldwake = r2_ptr->r_wake; screen_roff(who[i], 1); r2_ptr->r_tkills = oldkills; r2_ptr->r_wake = oldwake; cheat_know = oldcheat; notpicked = FALSE; #ifdef JP /* XTRA HACK REMEMBER_IDX */ old_sym = sym; old_i = i; #endif } /* Command */ query = inkey(); /* Normal commands */ if (query != 'r') break; /* Toggle recall */ recall = !recall; } /* Stop scanning */ if (query == ESCAPE) break; /* Move to "prev" monster */ if (query == '-') { if (++i == n) { i = 0; if (!expand_list) break; } } /* Move to "next" monster */ else { if (i-- == 0) { i = n - 1; if (!expand_list) break; } } } /* Re-display the identity */ /* prt(buf, 5, 5);*/ cheat_know = oldcheat; /* Free the "who" array */ C_KILL(who, max_r_idx, u16b); /* Restore */ screen_load(); return (!notpicked); }