/* * Advance the skill point of the skill specified by i and * modify related skills */ void increase_skill(int i, s16b *invest) { s32b max_skill_overage; /* No skill points to be allocated */ if (!p_ptr->skill_points) return; /* The skill cannot be increased */ if (!s_info[i].mod) return; /* The skill is already maxed */ if (s_info[i].value >= SKILL_MAX) return; /* Cannot allocate more than player level + max_skill_overage levels */ call_lua("get_module_info", "(s)", "d", "max_skill_overage", &max_skill_overage); if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1)) { int hgt, wid; Term_get_size(&wid, &hgt); msg_box(format("Cannot raise a skill value above %i + player level.", max_skill_overage), (int)(hgt / 2), (int)(wid / 2)); return; } /* Spend an unallocated skill point */ p_ptr->skill_points--; /* Increase the skill */ s_info[i].value += s_info[i].mod; invest[i]++; }
/** * Display the winner crown */ static void display_winner(void) { char buf[1024]; ang_file *fp; int wid, hgt; int i = 2; int width = 0; path_build(buf, sizeof(buf), ANGBAND_DIR_SCREENS, "crown.txt"); fp = file_open(buf, MODE_READ, FTYPE_TEXT); Term_clear(); Term_get_size(&wid, &hgt); if (fp) { /* Get us the first line of file, which tells us how long the */ /* longest line is */ file_getl(fp, buf, sizeof(buf)); sscanf(buf, "%d", &width); if (!width) width = 25; /* Dump the file to the screen */ while (file_getl(fp, buf, sizeof(buf))) put_str(buf, i++, (wid/2) - (width/2)); file_close(fp); } put_str_centred(i, 0, wid, "All Hail the Mighty Champion!"); event_signal(EVENT_INPUT_FLUSH); pause_line(Term); }
/* * Draw the skill tree */ void print_skills(s32b **table, s32b max, s32b sel, s32b start) { s32b i, j; s32b wid, hgt; cptr keys; Term_clear(); Term_get_size(&wid, &hgt); c_prt(TERM_WHITE, format("%s Skills Screen", game_module), 0, 28); keys = format("#BEnter#W to develop a branch, #Bup#W/#Bdown#W to move, #Bright#W/#Bleft#W to modify, #B?#W for help"); display_message(0, 1, strlen(keys), TERM_WHITE, keys); c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED, format("Skill points left: %d", p_ptr->skill_points), 2, 0); print_desc_aux(s_info[table[sel][0]].desc, 3, 0); for (j = start; j < start + (hgt - 7); j++) { byte color = TERM_WHITE; char deb = ' ', end = ' '; if (j >= max) break; i = table[j][0]; if (get_skill(i) == 0) { if (s_info[i].mod == 0) color = TERM_L_DARK; else color = TERM_ORANGE; } else if (get_skill_raw(i) == SKILL_MAX) color = TERM_L_BLUE; if (s_info[i].hidden) color = TERM_L_RED; if (j == sel) { color = TERM_L_GREEN; deb = '['; end = ']'; } if (!has_child(i)) { c_prt(color, format("%c.%c%s", deb, end, s_info[i].name), j + 7 - start, table[j][1] * 4); } else if (s_info[i].dev) { c_prt(color, format("%c-%c%s", deb, end, s_info[i].name), j + 7 - start, table[j][1] * 4); } else { c_prt(color, format("%c+%c%s", deb, end, s_info[i].name), j + 7 - start, table[j][1] * 4); } c_prt(color, format("%c%02ld.%03ld [%01d.%03d]", (get_skill_raw(i) < 0) ? '-' : ' ', abs(get_skill_raw(i)) / SKILL_STEP, abs(get_skill_raw(i)) % SKILL_STEP, s_info[i].mod / 1000, s_info[i].mod % 1000), j + 7 - start, 60); } }
void map_panel_size(void) { int wid, hgt; /* Only if the map exists */ if (!character_dungeon) return; /* Get size */ Term_get_size(&wid, &hgt); /* Offset */ wid -= COL_MAP + 1; /* reset panels */ if (p_ptr->depth) { /* Determine number of panels (dungeon) */ max_panel_rows = max_hgt - min_hgt; max_panel_cols = max_wid - min_wid; } else { /* Determine number of panels (wilderness) */ max_panel_rows = max_wild * 16; max_panel_cols = max_wild * 16; } /* Assume illegal panel */ panel_row_min = max_panel_rows; panel_col_min = max_panel_cols; /* Kill previous size of line */ #ifdef USE_TRANSPARENCY /* String of terrain characters along one row of the map */ if (mp_ta) C_KILL(mp_ta, map_wid_old, byte); if (mp_tc) C_KILL(mp_tc, map_wid_old, char); #endif /* USE_TRANSPARENCY */ /* String of characters along one row of the map */ if (mp_a) C_KILL(mp_a, map_wid_old, byte); if (mp_c) C_KILL(mp_c, map_wid_old, char); /* Save size */ map_wid_old = wid; /* Make the new lines */ #ifdef USE_TRANSPARENCY /* String of terrain characters along one row of the map */ C_MAKE(mp_ta, wid, byte); C_MAKE(mp_tc, wid, char); #endif /* USE_TRANSPARENCY */ /* String of characters along one row of the map */ C_MAKE(mp_a, wid, byte); C_MAKE(mp_c, wid, char); }
/* * Change the player into a King! -RAK- */ void kingly(void) { int wid, hgt; int cx, cy; bool seppuku = streq(p_ptr->died_from, "Seppuku"); /* Hack -- retire in town */ dun_level = 0; /* Fake death */ if (!seppuku) (void)strcpy(p_ptr->died_from, "Ripe Old Age"); /* Restore the experience */ p_ptr->exp = p_ptr->max_exp; /* Restore the level */ p_ptr->lev = p_ptr->max_plv; Term_get_size(&wid, &hgt); cy = hgt / 2; cx = wid / 2; /* Hack -- Instant Gold */ p_ptr->au += 10000000; stats_on_gold_winnings(10000000); /* Clear screen */ Term_clear(); /* Display a crown */ put_str("#", cy - 11, cx - 1); put_str("#####", cy - 10, cx - 3); put_str("#", cy - 9, cx - 1); put_str(",,, $$$ ,,,", cy - 8, cx - 7); put_str(",,=$ \"$$$$$\" $=,,", cy - 7, cx - 11); put_str(",$$ $$$ $$,", cy - 6, cx - 13); put_str("*> <*> <*", cy - 5, cx - 13); put_str("$$ $$$ $$", cy - 4, cx - 13); put_str("\"$$ $$$ $$\"", cy - 3, cx - 13); put_str("\"$$ $$$ $$\"", cy - 2, cx - 12); put_str("*#########*#########*", cy - 1, cx - 11); put_str("*#########*#########*", cy, cx - 11); /* Display a message */ put_str("Veni, Vidi, Vici!", cy + 3, cx - 9); put_str("I came, I saw, I conquered!", cy + 4, cx - 14); put_str(format("All Hail the Mighty %s!", sex_info[p_ptr->psex].winner), cy + 5, cx - 13); /* Flush input */ flush(); /* Wait for response */ pause_line(hgt - 1); }
/* * Advance the skill point of the skill specified by i and * modify related skills */ void increase_skill(s32b i, s16b *invest) { s32b max_skill_overage, max_level; cptr error = NULL; /* No skill points to be allocated */ if (!p_ptr->skill_points) return; /* The skill cannot be increased */ if (!s_info[i].mod) return; /* The skill is already maxed */ call_lua("get_module_info", "(s)", "d", "max_skill_level", &max_level); if (s_info[i].value >= max_level * SKILL_STEP) return; /* Cannot allocate more than player level + max_skill_overage levels */ call_lua("get_module_info", "(s)", "d", "max_skill_overage", &max_skill_overage); if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1)) { s32b hgt, wid; Term_get_size(&wid, &hgt); msg_box(format("Cannot raise a skill value to or above %d until you get more experienced.", p_ptr->lev + max_skill_overage), (s32b)(hgt / 2), (s32b)(wid / 2)); return; } /* More complex checking */ call_lua("get_module_info", "(s,d)", "s", "allow_skill_raise", i, &error); if (error) { s32b hgt, wid; Term_get_size(&wid, &hgt); msg_box(error, (s32b)(hgt / 2), (s32b)(wid / 2)); return; } /* Spend an unallocated skill point */ p_ptr->skill_points--; /* Increase the skill */ s_info[i].value += s_info[i].mod; invest[i]++; }
/* * Display targeting help at the bottom of the screen. */ static void target_display_help(bool monster, bool free) { /* Determine help location */ int wid, hgt, help_loc; Term_get_size(&wid, &hgt); help_loc = hgt - HELP_HEIGHT - (mouse_buttons ? 1 : 0); /* Clear */ clear_from(help_loc); /* Prepare help hooks */ text_out_hook = text_out_to_screen; text_out_indent = 1; Term_gotoxy(1, help_loc); /* Display help */ text_out_c(TERM_L_GREEN, "<dir>"); text_out(" and "); text_out_c(TERM_L_GREEN, "<click>"); text_out(" look around. '"); text_out_c(TERM_L_GREEN, "g"); text_out(" moves to the selection. '"); text_out_c(TERM_L_GREEN, "p"); text_out("' selects the player. '"); text_out_c(TERM_L_GREEN, "q"); text_out("' exits. '"); text_out_c(TERM_L_GREEN, "r"); text_out("' displays details. '"); if (free) { text_out_c(TERM_L_GREEN, "m"); text_out("' restricts to interesting places. "); } else { text_out_c(TERM_L_GREEN, "+"); text_out("' and '"); text_out_c(TERM_L_GREEN, "-"); text_out("' cycle through interesting places. '"); text_out_c(TERM_L_GREEN, "o"); text_out("' allows free selection. "); } if (monster || free) { text_out("'"); text_out_c(TERM_L_GREEN, "t"); text_out("' targets the current selection."); } /* Reset */ text_out_indent = 0; }
/* * Draw the abilities list */ void print_abilities(s32b table[], s32b max, s32b sel, s32b start) { s32b i, j; s32b wid, hgt; cptr keys; Term_clear(); Term_get_size(&wid, &hgt); c_prt(TERM_WHITE, format("%s Abilities Screen", game_module), 0, 28); keys = format("#Bup#W/#Bdown#W to move, #Bright#W to buy, #B?#W for help"); display_message(0, 1, strlen(keys), TERM_WHITE, keys); c_prt((p_ptr->skill_points) ? TERM_L_BLUE : TERM_L_RED, format("Skill points left: %d", p_ptr->skill_points), 2, 0); print_desc_aux(ab_info[table[sel]].desc, 3, 0); for (j = start; j < start + (hgt - 7); j++) { byte color = TERM_WHITE; char deb = ' ', end = ' '; if (j >= max) break; i = table[j]; if (ab_info[i].acquired) color = TERM_L_BLUE; else if (can_learn_ability(i)) color = TERM_WHITE; else color = TERM_L_DARK; if (j == sel) { color = TERM_L_GREEN; deb = '['; end = ']'; } c_prt(color, format("%c.%c%s", deb, end, ab_info[i].name), j + 7 - start, 0); if (!ab_info[i].acquired) { c_prt(color, format("%d", ab_info[i].cost), j + 7 - start, 60); } else { c_prt(color, "Known", j + 7 - start, 60); } } }
/* Yucky menu code modified from spells.c ... But I didn't want to create a new spell object for each racial form since all we really need is the level and the race's integer identifier. */ static int _col_height(int ct) { int w, h; int result = ct; Term_get_size(&w, &h); h -= 9; /* Room for browsing */ if (result > h) { result = (ct + 1)/2; } return result; }
/* プレイホストのマップが大きいときクライアントのマップもリサイズする */ static void update_term_size(int x, int y, int len) { int ox, oy; int nx, ny; Term_get_size(&ox, &oy); nx = ox; ny = oy; /* 横方向のチェック */ if (x + len > ox) nx = x + len; /* 縦方向のチェック */ if (y + 1 > oy) ny = y + 1; if (nx != ox || ny != oy) Term_resize(nx, ny); }
region region_calculate(region loc) { int w, h; Term_get_size(&w, &h); if (loc.col < 0) loc.col += w; if (loc.row < 0) loc.row += w; if (loc.width <= 0) loc.width += w - loc.col; if (loc.page_rows <= 0) loc.page_rows += h - loc.row; return loc; }
/* * Hack -- display recent messages in sub-windows * * XXX XXX XXX Adjust for width and split messages */ void fix_message(void) { s32b j, i; s32b w, h; s32b x, y; /* Scan windows */ for (j = 0; j < 8; j++) { term *old = Term; /* No window */ if (!angband_term[j]) continue; /* No relevant flags */ if (!flag_exists(&window_flag[j], FLAG_PW_MESSAGE)) continue; /* Activate */ Term_activate(angband_term[j]); /* Get size */ Term_get_size(&w, &h); /* Dump messages */ for (i = 0; i < h; i++) { /* Dump the message on the appropriate line */ display_message(0, (h - 1) - i, strlen(message_str((s16b)i)), message_color((s16b)i), message_str((s16b)i)); /* Cursor */ Term_locate(&x, &y); /* Clear to end of line */ Term_erase(x, y, 255); } /* Fresh */ Term_fresh(); /* Restore */ Term_activate(old); } }
/* * This prints the sidebar, using a clever method which means that it will only * print as much as can be displayed on <24-line screens. * * Each row is given a priority; the least important higher numbers and the most * important lower numbers. As the screen gets smaller, the rows start to * disappear in the order of lowest to highest importance. */ static void update_sidebar(game_event_type type, game_event_data *data, void *user) { int x, y, row; int max_priority; size_t i; Term_get_size(&x, &y); /* Keep the top and bottom lines clear. */ max_priority = y - 2; /* Display list entries */ for (i = 0, row = 1; i < N_ELEMENTS(side_handlers); i++) { const struct side_handler_t *hnd = &side_handlers[i]; int priority = hnd->priority; bool from_bottom = FALSE; /* Negative means print from bottom */ if (priority < 0) { priority = -priority; from_bottom = TRUE; } /* If this is high enough priority, display it */ if (priority <= max_priority) { if (hnd->type == type && hnd->hook) { if (from_bottom) hnd->hook(Term->hgt - (N_ELEMENTS(side_handlers) - i), 0); else hnd->hook(row, 0); } /* Increment for next time */ row++; } } }
/* Compare what you get from borg_what_text immediately */ bool borg_term_text_comp(int x, int y, cptr what) { byte t_a; int wid, hgt; int len = strlen(what); char buf[120]; /* Get size */ Term_get_size(&wid, &hgt); /* That's left or right of the term */ if (x < 0 || x + len > wid) return (FALSE); /* That's higher or lower of the term */ if (y < 0 || y >= hgt) return (FALSE); if (0 == borg_what_text(x, y, strlen(what), &t_a, buf) && streq(buf, what)) return (TRUE); /* No match */ return (FALSE); }
/* Learn an ability */ static void gain_ability(s32b ab) { s32b wid, hgt; Term_get_size(&wid, &hgt); if (!can_learn_ability(ab)) { msg_box("You cannot learn this ability.", (s32b)(hgt / 2), (s32b)(wid / 2)); return; } /* Flush input as we ask an important and irreversible question */ flush(); /* Ask we can commit the change */ /* if (msg_box("Learn this ability(this is permanent)? (y/n)", (s32b)(hgt / 2), (s32b)(wid / 2)) != 'y') { return; }*/ ab_info[ab].acquired = TRUE; p_ptr->skill_points -= ab_info[ab].cost; }
/* * Display the winner crown */ static void display_winner(void) { char buf[1024]; ang_file *fp; int wid, hgt; int i = 2; int width = 0; path_build(buf, sizeof(buf), ANGBAND_DIR_FILE, "crown.txt"); fp = file_open(buf, MODE_READ, -1); Term_clear(); Term_get_size(&wid, &hgt); if (fp) { /* Get us the first line of file, which tells us how long the */ /* longest line is */ file_getl(fp, buf, sizeof(buf)); sscanf(buf, "%d", &width); if (!width) width = 25; /* Dump the file to the screen */ while (file_getl(fp, buf, sizeof(buf))) put_str(buf, i++, (wid/2) - (width/2)); file_close(fp); } put_str_centred(i, 0, wid, "All Hail the Mighty %s!", p_ptr->sex->winner); flush(); pause_line(Term); }
static void display_columns(menu_type *menu, int cursor, int *top, rect_region *loc) { int c, r; int w, h; int n = menu->filter_list ? menu->filter_count : menu->count; int col = loc->col; int row = loc->row; int rows_per_page = loc->page_rows; int cols = (n + rows_per_page - 1) / rows_per_page; int colw = 23; Term_get_size(&w, &h); if (menu->column_width > 0) { colw = menu->column_width; } else if ((colw * cols) > (w - col)) colw = (w - col) / cols; for (c = 0; c < cols; c++) { for (r = 0; r < rows_per_page; r++) { int pos = c * rows_per_page + r; bool is_cursor = (pos == cursor); if (pos < n) display_menu_row(menu, pos, 0, is_cursor, row + r, col + c * colw, colw); } } if (menu->cursor >= 0) Term_gotoxy(col + (cursor / rows_per_page) * colw, row + (cursor % rows_per_page) - *top); }
/* 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); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; bool list_floor_objects = auto_display_lists; u16b path_n; u16b path_g[PATH_SIZE]; u16b path_gx[PATH_SIZE]; ui_event_data query; char info[80]; /* These are used for displaying the path to the target */ char path_char[MAX_RANGE]; byte path_attr[MAX_RANGE]; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targeting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* make some buttons */ button_backup_all(); button_kill_all(); button_add("[ESCAPE]", ESCAPE); button_add("[NEXT]", '+'); button_add("[PREV]", '-'); button_add("[PLAYER]", 'p'); button_add("[PATHFIND]", 'g'); button_add("[TARGET]", 't'); /* health_track(0); */ /* All grids are selectable */ if (mode & (TARGET_GRID)) { /* Disable other modes */ mode &= ~(TARGET_LOOK | TARGET_KILL | TARGET_TRAP); /* Disable interesting grids */ flag = FALSE; } /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - (mouse_buttons ? 2 : 1); /* Display the help prompt */ prt("'?' - help", help_prompt_loc, 0); /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { button_kill('l'); button_kill('?'); if (list_floor_objects) { button_add("[HIDE_OBJLIST]", 'l'); } else button_add("[SHOW_OBJLIST]", 'l'); if (help) { button_add("[HIDE_HELP]", '?'); } else button_add("[SHOW_HELP]",'?'); /* Interesting grids */ if (flag && temp_n) { bool path_drawn = FALSE; int yy, xx; y = temp_y[m]; x = temp_x[m]; button_add("[SCAN]",'o'); /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Dummy pointers to send to project_path */ yy = y; xx = x; /* Allow targets for monsters....or traps, if applicable */ if (((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])) || ((mode & (TARGET_TRAP)) && target_able_trap(y, x))) { strcpy(info, "q,t,r,l,p,o,+,-,<dir>"); } /* Dis-allow target */ else { strcpy(info, "q,p,l,o,+,-,<dir>"); } /* Adjust panel if needed */ if (adjust_panel(y, x)) { /* Handle stuff */ handle_stuff(); } /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (cave_info[y][x] & (CAVE_FIRE))) { path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px, y, x); } event_signal(EVENT_MOUSEBUTTONS); /* Describe and Prompt */ query = target_set_interactive_aux(y, x, mode, info, list_floor_objects); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no "direction" */ d = 0; /* Analyze */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == temp_n) m = 0; break; } case '-': { if (m-- == 0) m = temp_n - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = py; x = px; } case 'o': { flag = FALSE; break; } case 'm': { break; } /* If we click, move the target location to the click and switch to "free targetting" mode by unsetting 'flag'. This means we get some info about wherever we've picked. */ case DEFINED_XFF: { x = KEY_GRID_X(query); y = KEY_GRID_Y(query); flag = FALSE; break; } case 't': case '5': case '0': case '.': { int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); done = TRUE; } else if ((mode & (TARGET_TRAP)) && target_able_trap(y, x)) { target_set_location(y, x); done = TRUE; } else if (mode & (TARGET_PROBE)) { target_set_location(y, x); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND, y, x); done = TRUE; break; } case 'l': { list_floor_objects = (!list_floor_objects); } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("'?' - help", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = temp_y[m]; int old_x = temp_x[m]; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { bool path_drawn = FALSE; /* Dummy pointers to send to project_path */ int yy = y; int xx = x; /* Don't need this button any more */ button_kill('o'); /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Default prompt */ if (!(mode & (TARGET_GRID))) { strcpy(info, "q,t,l,p,m,+,-,<dir>"); } /* Disable monster selection */ else { strcpy(info, "q,t,l.p,+,-,<dir>"); } /* Find the path. */ path_n = project_path(path_g, path_gx, MAX_RANGE, py, px, &yy, &xx, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if ((mode & (TARGET_KILL)) && (cave_info[y][x] & (CAVE_FIRE))) { /* Save target info */ path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px, y, x); } event_signal(EVENT_MOUSEBUTTONS); /* Describe and Prompt (enable "TARGET_LOOK") */ query = target_set_interactive_aux(y, x, (mode | TARGET_LOOK), info, list_floor_objects); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; /* Analyze the keypress */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = py; x = px; } case 'o': { break; } case 'm': { /* Monster selection is disabled */ if (mode & (TARGET_GRID)) break; flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < temp_n; i++) { t = distance(y, x, temp_y[i], temp_x[i]); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case '\xff': { /* We only target if we click somewhere where the cursor is already (i.e. a double-click without a time limit) */ if (KEY_GRID_X(query) == x && KEY_GRID_Y(query) == y) { /* Make an attempt to target the monster on the given square rather than the square itself (it seems this is the more likely intention of clicking on a monster). */ int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); } else { /* There is no monster, or it isn't targettable, so target the location instead. */ target_set_location(y, x); } done = TRUE; } else { /* Just move the cursor for now - another click will target. */ x = KEY_GRID_X(query); y = KEY_GRID_Y(query); } break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND, y, x); done = TRUE; break; } case 'l': { list_floor_objects = (!list_floor_objects); } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("'?' - help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = p_ptr->cur_map_hgt; int dungeon_wid = p_ptr->cur_map_wid; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel(y, x)) { /* Handle stuff */ handle_stuff(); /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ temp_n = 0; /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Restore buttons */ button_restore(); /* Handle stuff */ handle_stuff(); /* Failure to set target */ if (!p_ptr->target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; ui_event_data query; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targetting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* Cancel tracking */ /* health_track(0); */ /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - 1; /* Display the help prompt */ prt("Press '?' for help.", help_prompt_loc, 0); /* Prepare the "temp" array */ target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { /* Interesting grids */ if (flag && temp_n) { y = temp_y[m]; x = temp_x[m]; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(); } /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Describe and Prompt */ query = target_set_interactive_aux(y, x, mode); /* Cancel tracking */ /* health_track(0); */ /* Assume no "direction" */ d = 0; /* If we click, move the target location to the click and switch to "free targetting" mode by unsetting 'flag'. This means we get some info about wherever we've picked. */ if (query.type == EVT_MOUSE) { x = KEY_GRID_X(query); y = KEY_GRID_Y(query); flag = FALSE; break; } else { /* Analyze */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == temp_n) m = 0; break; } case '-': { if (m-- == 0) m = temp_n - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = p_ptr->py; x = p_ptr->px; } case 'o': { flag = FALSE; break; } case 'm': { break; } case 't': case '5': case '0': case '.': { int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } } /* Hack -- move around */ if (d) { int old_y = temp_y[m]; int old_x = temp_x[m]; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d]); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { /* Update help */ if (help) { bool good_target = ((cave_m_idx[y][x] > 0) && target_able(cave_m_idx[y][x])); target_display_help(good_target, !(flag && temp_n)); } /* Describe and Prompt (enable "TARGET_LOOK") */ query = target_set_interactive_aux(y, x, mode | TARGET_LOOK); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; if (query.type == EVT_MOUSE) { /* We only target if we click somewhere where the cursor is already (i.e. a double-click without a time limit) */ if (KEY_GRID_X(query) == x && KEY_GRID_Y(query) == y) { /* Make an attempt to target the monster on the given square rather than the square itself (it seems this is the more likely intention of clicking on a monster). */ int m_idx = cave_m_idx[y][x]; if ((m_idx > 0) && target_able(m_idx)) { health_track(m_idx); target_set_monster(m_idx); } else { /* There is no monster, or it isn't targettable, so target the location instead. */ target_set_location(y, x); } done = TRUE; } else { /* Just move the cursor for now - another click will target. */ x = KEY_GRID_X(query); y = KEY_GRID_Y(query); } break; } else { /* Analyze the keypress */ switch (query.key) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); y = p_ptr->py; x = p_ptr->px; } case 'o': { break; } case 'm': { flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < temp_n; i++) { t = distance(y, x, temp_y[i], temp_x[i]); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(query.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } } /* Handle "direction" */ if (d) { int dungeon_hgt = (p_ptr->depth == 0) ? TOWN_HGT : DUNGEON_HGT; int dungeon_wid = (p_ptr->depth == 0) ? TOWN_WID : DUNGEON_WID; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(); /* Recalculate interesting grids */ target_set_interactive_prepare(mode); } } } } /* Forget */ temp_n = 0; /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(); /* Failure to set target */ if (!target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Print some (colored) text to the screen at the current cursor position, * automatically "wrapping" existing text (at spaces) when necessary to * avoid placing any text into the last column, and clearing every line * before placing any text in that line. Also, allow "newline" to force * a "wrap" to the next line. Advance the cursor as needed so sequential * calls to this function will work correctly. * * Once this function has been called, the cursor should not be moved * until all the related "text_out()" calls to the window are complete. * * This function will correctly handle any width up to the maximum legal * value of 256, though it works best for a standard 80 character width. */ void text_out_to_screen(byte a, const char *str) { int x, y; int wid, h; int wrap; const wchar_t *s; wchar_t buf[1024]; /* Obtain the size */ (void)Term_get_size(&wid, &h); /* Obtain the cursor */ (void)Term_locate(&x, &y); /* Copy to a rewriteable string */ Term_mbstowcs(buf, str, 1024); /* Use special wrapping boundary? */ if ((text_out_wrap > 0) && (text_out_wrap < wid)) wrap = text_out_wrap; else wrap = wid; /* Process the string */ for (s = buf; *s; s++) { wchar_t ch; /* Force wrap */ if (*s == L'\n') { /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); continue; } /* Clean up the char */ ch = (iswprint(*s) ? *s : L' '); /* Wrap words as needed */ if ((x >= wrap - 1) && (ch != L' ')) { int i, n = 0; byte av[256]; wchar_t cv[256]; /* Wrap word */ if (x < wrap) { /* Scan existing text */ for (i = wrap - 2; i >= 0; i--) { /* Grab existing attr/char */ Term_what(i, y, &av[i], &cv[i]); /* Break on space */ if (cv[i] == L' ') break; /* Track current word */ n = i; } } /* Special case */ if (n == 0) n = wrap; /* Clear line */ Term_erase(n, y, 255); /* Wrap */ x = text_out_indent; y++; /* Clear line, move cursor */ Term_erase(x, y, 255); x += text_out_pad; Term_gotoxy(x, y); /* Wrap the word (if any) */ for (i = n; i < wrap - 1; i++) { /* Dump */ Term_addch(av[i], cv[i]); /* Advance (no wrap) */ if (++x > wrap) x = wrap; } } /* Dump */ Term_addch(a, ch); /* Advance */ if (++x > wrap) x = wrap; } }
/* * Output a message to the top line of the screen. * * Break long messages into multiple pieces (40-72 chars). * * Allow multiple short messages to "share" the top line. * * Prompt the user to make sure he has a chance to read them. * * These messages are memorized for later reference (see above). * * We could do a "Term_fresh()" to provide "flicker" if needed. * * The global "msg_flag" variable can be cleared to tell us to "erase" any * "pending" messages still on the screen, instead of using "msg_flush()". * This should only be done when the user is known to have read the message. * * We must be very careful about using the "msg("%s", )" functions without * explicitly calling the special "msg("%s", NULL)" function, since this may * result in the loss of information if the screen is cleared, or if anything * is displayed on the top line. * * Hack -- Note that "msg("%s", NULL)" will clear the top line even if no * messages are pending. */ static void msg_print_aux(u16b type, const char *msg) { int n; char *t; char buf[1024]; byte color; int w, h; if (!Term) return; /* Obtain the size */ (void)Term_get_size(&w, &h); /* Hack -- Reset */ if (!msg_flag) message_column = 0; /* Message Length */ n = (msg ? strlen(msg) : 0); /* Hack -- flush when requested or needed */ if (message_column && (!msg || ((message_column + n) > (w - 8)))) { /* Flush */ msg_flush(message_column); /* Forget it */ msg_flag = FALSE; /* Reset */ message_column = 0; } /* No message */ if (!msg) return; /* Paranoia */ if (n > 1000) return; /* Memorize the message (if legal) */ if (character_generated && !(p_ptr->is_dead)) message_add(msg, type); /* Window stuff */ p_ptr->redraw |= (PR_MESSAGE); /* Copy it */ my_strcpy(buf, msg, sizeof(buf)); /* Analyze the buffer */ t = buf; /* Get the color of the message */ color = message_type_color(type); /* Split message */ while (n > w - 1) { char oops; int check, split; /* Default split */ split = w - 8; /* Find the rightmost split point */ for (check = (w / 2); check < w - 8; check++) if (t[check] == ' ') split = check; /* Save the split character */ oops = t[split]; /* Split the message */ t[split] = '\0'; /* Display part of the message */ Term_putstr(0, 0, split, color, t); /* Flush it */ msg_flush(split + 1); /* Restore the split character */ t[split] = oops; /* Insert a space */ t[--split] = ' '; /* Prepare to recurse on the rest of "buf" */ t += split; n -= split; } /* Display the tail of the message */ Term_putstr(message_column, 0, n, color, t); /* Remember the message */ msg_flag = TRUE; /* Remember the position */ message_column += n + 1; /* Send refresh event */ event_signal(EVENT_MESSAGE); }
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(); }
/* * Display inventory */ void do_cmd_inven(void) { char out_val[160]; /* Note that we are in "inventory" mode */ command_wrk = FALSE; #ifdef ALLOW_EASY_FLOOR /* Note that we are in "inventory" mode */ if (easy_floor) command_wrk = (USE_INVEN); #endif /* ALLOW_EASY_FLOOR */ /* Save screen */ screen_save(); /* Hack -- show empty slots */ item_tester_full = TRUE; /* Display the inventory */ (void)show_inven(0, 0); /* Hack -- hide empty slots */ item_tester_full = FALSE; sprintf(out_val, "Inventory: carrying %d.%d pounds (%d%% of capacity). Command: ", (int)(p_ptr->total_weight / 10), (int)(p_ptr->total_weight % 10), (p_ptr->total_weight * 100) / weight_limit()); /* Get a command */ prt(out_val, 0, 0); /* Get a new command */ command_new = inkey(); /* Load screen */ screen_load(); /* Process "Escape" */ if (command_new == ESCAPE) { int wid, hgt; /* Get size */ Term_get_size(&wid, &hgt); /* Reset stuff */ command_new = 0; command_gap = wid - 30; } /* Process normal keys */ else { /* Hack -- Use "display" mode */ command_see = TRUE; } }
/* * Interactive group by. * Recognises inscriptions, graphical symbols, lore */ static void display_knowledge(const char *title, int *obj_list, int o_count, group_funcs g_funcs, member_funcs o_funcs, const char *otherfields) { /* maximum number of groups to display */ int max_group = g_funcs.maxnum < o_count ? g_funcs.maxnum : o_count; /* This could (should?) be (void **) */ int *g_list, *g_offset; const char **g_names; int g_name_len = 8; /* group name length, minumum is 8 */ int grp_cnt = 0; /* total number groups */ int g_cur = 0, grp_old = -1; /* group list positions */ int o_cur = 0; /* object list positions */ int g_o_count = 0; /* object count for group */ int oid = -1; /* object identifiers */ region title_area = { 0, 0, 0, 4 }; region group_region = { 0, 6, MISSING, -2 }; region object_region = { MISSING, 6, 0, -2 }; /* display state variables */ bool tiles = (current_graphics_mode != NULL); bool tile_picker = FALSE; bool glyph_picker = FALSE; byte attr_top = 0; byte char_left = 0; int delay = 0; menu_type group_menu; menu_type object_menu; menu_iter object_iter = { NULL, NULL, display_group_member, NULL, NULL }; /* Panel state */ /* These are swapped in parallel whenever the actively browsing " */ /* changes */ int *active_cursor = &g_cur, *inactive_cursor = &o_cur; menu_type *active_menu = &group_menu, *inactive_menu = &object_menu; int panel = 0; void *swapspace; bool do_swap = FALSE; bool flag = FALSE; bool redraw = TRUE; int browser_rows; int wid, hgt; int i; int prev_g = -1; int omode = OPT(rogue_like_commands); ui_event ke; /* Get size */ Term_get_size(&wid, &hgt); browser_rows = hgt - 8; /* Disable the roguelike commands for the duration */ OPT(rogue_like_commands) = FALSE; /* Determine if using tiles or not */ if (tiles) tiles = (current_graphics_mode->grafID != 0); if (g_funcs.gcomp) sort(obj_list, o_count, sizeof(*obj_list), g_funcs.gcomp); /* Sort everything into group order */ g_list = C_ZNEW(max_group + 1, int); g_offset = C_ZNEW(max_group + 1, int); for (i = 0; i < o_count; i++) { if (prev_g != g_funcs.group(obj_list[i])) { prev_g = g_funcs.group(obj_list[i]); g_offset[grp_cnt] = i; g_list[grp_cnt++] = prev_g; } } g_offset[grp_cnt] = o_count; g_list[grp_cnt] = -1; /* The compact set of group names, in display order */ g_names = C_ZNEW(grp_cnt, const char *); for (i = 0; i < grp_cnt; i++) { int len; g_names[i] = g_funcs.name(g_list[i]); len = strlen(g_names[i]); if (len > g_name_len) g_name_len = len; } /* Reasonable max group name len */ if (g_name_len >= 20) g_name_len = 20; object_region.col = g_name_len + 3; group_region.width = g_name_len; /* Leave room for the group summary information */ if (g_funcs.summary) object_region.page_rows = -3; /* Set up the two menus */ menu_init(&group_menu, MN_SKIN_SCROLL, menu_find_iter(MN_ITER_STRINGS)); menu_setpriv(&group_menu, grp_cnt, g_names); menu_layout(&group_menu, &group_region); menu_init(&object_menu, MN_SKIN_SCROLL, &object_iter); menu_setpriv(&object_menu, 0, &o_funcs); menu_layout(&object_menu, &object_region); o_funcs.is_visual = FALSE; /* Save screen */ screen_save(); clear_from(0); /* This is the event loop for a multi-region panel */ /* Panels are -- text panels, two menus, and visual browser */ /* with "pop-up menu" for lore */ while ((!flag) && (grp_cnt)) { bool recall = FALSE; if (redraw) { /* Print the title bits */ region_erase(&title_area); prt(format("Knowledge - %s", title), 2, 0); prt("Group", 4, 0); prt("Name", 4, g_name_len + 3); if (otherfields) prt(otherfields, 4, 46); /* Print dividers: horizontal and vertical */ for (i = 0; i < 79; i++) Term_putch(i, 5, TERM_WHITE, '='); for (i = 0; i < browser_rows; i++) Term_putch(g_name_len + 1, 6 + i, TERM_WHITE, '|'); /* Reset redraw flag */ redraw = FALSE; } if (g_cur != grp_old) { grp_old = g_cur; o_cur = 0; g_o_count = g_offset[g_cur + 1] - g_offset[g_cur]; menu_set_filter(&object_menu, obj_list + g_offset[g_cur], g_o_count); group_menu.cursor = g_cur; object_menu.cursor = 0; } /* HACK ... */ if (!(tile_picker || glyph_picker)) { /* ... The object menu may be browsing the entire group... */ o_funcs.is_visual = FALSE; menu_set_filter(&object_menu, obj_list + g_offset[g_cur], g_o_count); object_menu.cursor = o_cur; } else { /* ... or just a single element in the group. */ o_funcs.is_visual = TRUE; menu_set_filter(&object_menu, obj_list + o_cur + g_offset[g_cur], 1); object_menu.cursor = 0; } oid = obj_list[g_offset[g_cur] + o_cur]; /* Print prompt */ { const char *pedit = (!o_funcs.xattr) ? "" : (!(attr_idx | char_idx) ? ", 'c' to copy" : ", 'c', 'p' to paste"); const char *xtra = o_funcs.xtra_prompt ? o_funcs.xtra_prompt(oid) : ""; const char *pvs = ""; if (tile_picker) pvs = ", ENTER to accept"; else if (glyph_picker) pvs = ", 'i' to insert, ENTER to accept"; else if (o_funcs.xattr) pvs = ", 'v' for visuals"; prt(format("<dir>%s%s%s, ESC", pvs, pedit, xtra), hgt - 1, 0); } if (do_swap) { do_swap = FALSE; swap(active_menu, inactive_menu); swap(active_cursor, inactive_cursor); panel = 1 - panel; } if (g_funcs.summary && !tile_picker && !glyph_picker) { g_funcs.summary(g_cur, obj_list, g_o_count, g_offset[g_cur], object_menu.active.row + object_menu.active.page_rows, object_region.col); } menu_refresh(inactive_menu, FALSE); menu_refresh(active_menu, FALSE); handle_stuff(p_ptr); if (tile_picker) { bigcurs = TRUE; display_tiles(g_name_len + 3, 7, browser_rows - 1, wid - (g_name_len + 3), attr_top, char_left); place_tile_cursor(g_name_len + 3, 7, *o_funcs.xattr(oid), (byte) * o_funcs.xchar(oid), attr_top, char_left); } if (glyph_picker) { display_glyphs(g_name_len + 3, 7, browser_rows - 1, wid - (g_name_len + 3), *o_funcs.xattr(oid), *o_funcs.xchar(oid)); } if (delay) { /* Force screen update */ Term_fresh(); /* Delay */ Term_xtra(TERM_XTRA_DELAY, delay); delay = 0; } ke = inkey_ex(); if (!tile_picker && !glyph_picker) { ui_event ke0 = EVENT_EMPTY; if (ke.type == EVT_MOUSE) menu_handle_mouse(active_menu, &ke, &ke0); else if (ke.type == EVT_KBRD) menu_handle_keypress(active_menu, &ke, &ke0); if (ke0.type != EVT_NONE) ke = ke0; } /* XXX Do visual mode command if needed */ if (o_funcs.xattr && o_funcs.xchar) { if (tiles) { if (tile_picker_command(ke, &tile_picker, browser_rows - 1, wid - (g_name_len + 3), &attr_top, &char_left, o_funcs.xattr(oid), (byte *) o_funcs.xchar(oid), g_name_len + 3, 7, &delay)) continue; } else { if (glyph_command(ke, &glyph_picker, browser_rows - 1, wid - (g_name_len + 3), o_funcs.xattr(oid), o_funcs.xchar(oid), g_name_len + 3, 7)) continue; } } switch (ke.type) { case EVT_KBRD: { if (ke.key.code == 'r' || ke.key.code == 'R') recall = TRUE; else if (o_funcs.xtra_act) o_funcs.xtra_act(ke.key, oid); break; } case EVT_MOUSE: { /* Change active panels */ if (region_inside(&inactive_menu->boundary, &ke)) { swap(active_menu, inactive_menu); swap(active_cursor, inactive_cursor); panel = 1 - panel; } continue; } case EVT_ESCAPE: { if (panel == 1) do_swap = TRUE; else flag = TRUE; break; } case EVT_SELECT: { if (panel == 0) do_swap = TRUE; else if (panel == 1 && oid >= 0 && o_cur == active_menu->cursor) recall = TRUE; break; } case EVT_MOVE: { *active_cursor = active_menu->cursor; break; } default: { break; } } /* Recall on screen */ if (recall) { if (oid >= 0) o_funcs.lore(oid); redraw = TRUE; } } /* Restore roguelike option */ OPT(rogue_like_commands) = omode; /* Prompt */ if (!grp_cnt) prt(format("No %s known.", title), 15, 0); FREE(g_names); FREE(g_offset); FREE(g_list); screen_load(); }
/* * Display equipment */ void do_cmd_equip(void) { char out_val[160]; /* Note that we are in "equipment" mode */ command_wrk = TRUE; #ifdef ALLOW_EASY_FLOOR /* Note that we are in "equipment" mode */ if (easy_floor) command_wrk = (USE_EQUIP); #endif /* ALLOW_EASY_FLOOR */ /* Save the screen */ screen_save(); /* Hack -- show empty slots */ item_tester_full = TRUE; /* Display the equipment */ (void)show_equip(0); /* Hack -- undo the hack above */ item_tester_full = FALSE; /* Build a prompt */ #ifdef JP sprintf(out_val, "装備: 合計 %3d.%1d kg (限界の%ld%%) コマンド: ", lbtokg1(p_ptr->total_weight) , lbtokg2(p_ptr->total_weight) , (p_ptr->total_weight * 100) / weight_limit()); #else sprintf(out_val, "Equipment: carrying %d.%d pounds (%ld%% of capacity). Command: ", (int)(p_ptr->total_weight / 10), (int)(p_ptr->total_weight % 10), (p_ptr->total_weight * 100) / weight_limit()); #endif /* Get a command */ prt(out_val, 0, 0); /* Get a new command */ command_new = inkey(); /* Restore the screen */ screen_load(); /* Process "Escape" */ if (command_new == ESCAPE) { int wid, hgt; /* Get size */ Term_get_size(&wid, &hgt); /* Reset stuff */ command_new = 0; command_gap = wid - 30; } /* Process normal keys */ else { /* Enter "display" mode */ command_see = TRUE; } }
/* * Make screen dump to buffer */ cptr make_screen_dump(void) { BUF *screen_buf; int y, x, i; cptr ret; byte a = 0, old_a = 0; char c = ' '; static cptr html_head[] = { "<html>\n<body text=\"#ffffff\" bgcolor=\"#000000\">\n", "<pre>", 0, }; static cptr html_foot[] = { "</pre>\n", "</body>\n</html>\n", 0, }; bool old_use_graphics = use_graphics; int wid, hgt; Term_get_size(&wid, &hgt); /* Alloc buffer */ screen_buf = buf_new(); if (screen_buf == NULL) return (NULL); if (old_use_graphics) { /* Clear -more- prompt first */ msg_print(NULL); use_graphics = FALSE; reset_visuals(); /* Redraw everything */ p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); /* Hack -- update */ handle_stuff(); } for (i = 0; html_head[i]; i++) buf_sprintf(screen_buf, html_head[i]); /* Dump the screen */ for (y = 0; y < hgt; y++) { /* Start the row */ if (y != 0) buf_sprintf(screen_buf, "\n"); /* Dump each row */ for (x = 0; x < wid - 1; x++) { int rv, gv, bv; cptr cc = NULL; /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); switch (c) { case '&': cc = "&"; break; case '<': cc = "<"; break; case '>': cc = ">"; break; #ifdef WINDOWS case 0x1f: c = '.'; break; case 0x7f: c = (a == 0x09) ? '%' : '#'; break; #endif } a = a & 0x0F; if ((y == 0 && x == 0) || a != old_a) { rv = angband_color_table[a][1]; gv = angband_color_table[a][2]; bv = angband_color_table[a][3]; buf_sprintf(screen_buf, "%s<font color=\"#%02x%02x%02x\">", ((y == 0 && x == 0) ? "" : "</font>"), rv, gv, bv); old_a = a; } if (cc) buf_sprintf(screen_buf, "%s", cc); else buf_sprintf(screen_buf, "%c", c); } } buf_sprintf(screen_buf, "</font>"); for (i = 0; html_foot[i]; i++) buf_sprintf(screen_buf, html_foot[i]); /* Screen dump size is too big ? */ if (screen_buf->size + 1> SCREEN_BUF_SIZE) { ret = NULL; } else { /* Terminate string */ buf_append(screen_buf, "", 1); ret = string_make(screen_buf->data); } /* Free buffer */ buf_delete(screen_buf); if (old_use_graphics) { use_graphics = TRUE; reset_visuals(); /* Redraw everything */ p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIPPY); /* Hack -- update */ handle_stuff(); } return ret; }
/** * Take an html screenshot */ void html_screenshot(const char *path, int mode) { int y, x; int wid, hgt; int a = COLOUR_WHITE; int oa = COLOUR_WHITE; int fg_colour = COLOUR_WHITE; int bg_colour = COLOUR_DARK; wchar_t c = L' '; const char *new_color_fmt = (mode == 0) ? "<font color=\"#%02X%02X%02X\" style=\"background-color: #%02X%02X%02X\">" : "[COLOR=\"#%02X%02X%02X\"]"; const char *change_color_fmt = (mode == 0) ? "</font><font color=\"#%02X%02X%02X\" style=\"background-color: #%02X%02X%02X\">" : "[/COLOR][COLOR=\"#%02X%02X%02X\"]"; const char *close_color_fmt = mode == 0 ? "</font>" : "[/COLOR]"; ang_file *fp; fp = file_open(path, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fp) { plog_fmt("Cannot write the '%s' file!", path); return; } /* Retrieve current screen size */ Term_get_size(&wid, &hgt); if (mode == 0) { file_putf(fp, "<!DOCTYPE html><html><head>\n"); file_putf(fp, " <meta='generator' content='%s'>\n", buildid); file_putf(fp, " <title>%s</title>\n", path); file_putf(fp, "</head>\n\n"); file_putf(fp, "<body style='color: #fff; background: #000;'>\n"); file_putf(fp, "<pre>\n"); } else { file_putf(fp, "[CODE][TT][BC=black][COLOR=white]\n"); } /* Dump the screen */ for (y = 0; y < hgt; y++) { for (x = 0; x < wid; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Set the foreground and background */ fg_colour = a % MAX_COLORS; switch (a / MAX_COLORS) { case BG_BLACK: bg_colour = COLOUR_DARK; break; case BG_SAME: bg_colour = fg_colour; break; case BG_DARK: bg_colour = COLOUR_SHADE; break; default: assert((a >= BG_BLACK) && (a < BG_MAX * MAX_COLORS)); } /* Color change */ if (oa != a) { if (oa == COLOUR_WHITE) { /* From the default white to another color */ file_putf(fp, new_color_fmt, angband_color_table[fg_colour][1], angband_color_table[fg_colour][2], angband_color_table[fg_colour][3], angband_color_table[bg_colour][1], angband_color_table[bg_colour][2], angband_color_table[bg_colour][3]); } else if (fg_colour == COLOUR_WHITE && bg_colour == COLOUR_DARK) { /* From another color to the default white */ file_putf(fp, close_color_fmt); } else { /* Change colors */ file_putf(fp, change_color_fmt, angband_color_table[fg_colour][1], angband_color_table[fg_colour][2], angband_color_table[fg_colour][3], angband_color_table[bg_colour][1], angband_color_table[bg_colour][2], angband_color_table[bg_colour][3]); } /* Remember the last color */ oa = a; } /* Write the character and escape special HTML characters */ if (mode == 0) write_html_escape_char(fp, c); else { char mbseq[MB_LEN_MAX+1] = {0}; wctomb(mbseq, c); file_putf(fp, "%s", mbseq); } } /* End the row */ file_putf(fp, "\n"); } /* Close the last font-color tag if necessary */ if (oa != COLOUR_WHITE) file_putf(fp, close_color_fmt); if (mode == 0) { file_putf(fp, "</pre>\n"); file_putf(fp, "</body>\n"); file_putf(fp, "</html>\n"); } else { file_putf(fp, "[/COLOR][/BC][/TT][/CODE]\n"); } /* Close it */ file_close(fp); }
/* * Handle "target" and "look". * * Note that this code can be called from "get_aim_dir()". * * Currently, when "flag" is true, that is, when * "interesting" grids are being used, and a directional key is used, we * only scroll by a single panel, in the direction requested, and check * for any interesting grids on that panel. The "correct" solution would * actually involve scanning a larger set of grids, including ones in * panels which are adjacent to the one currently scanned, but this is * overkill for this function. XXX XXX * * Hack -- targetting/observing an "outer border grid" may induce * problems, so this is not currently allowed. * * The player can use the direction keys to move among "interesting" * grids in a heuristic manner, or the "space", "+", and "-" keys to * move through the "interesting" grids in a sequential manner, or * can enter "location" mode, and use the direction keys to move one * grid at a time in any direction. The "t" (set target) command will * only target a monster (as opposed to a location) if the monster is * target_able and the "interesting" mode is being used. * * The current grid is described using the "look" method above, and * a new command may be entered at any time, but note that if the * "TARGET_LOOK" bit flag is set (or if we are in "location" mode, * where "space" has no obvious meaning) then "space" will scan * through the description of the current grid until done, instead * of immediately jumping to the next "interesting" grid. This * allows the "target" command to retain its old semantics. * * The "*", "+", and "-" keys may always be used to jump immediately * to the next (or previous) interesting grid, in the proper mode. * * The "return" key may always be used to scan through a complete * grid description (forever). * * This command will cancel any old target, even if used from * inside the "look" command. * * * 'mode' is one of TARGET_LOOK or TARGET_KILL. * 'x' and 'y' are the initial position of the target to be highlighted, * or -1 if no location is specified. * Returns TRUE if a target has been successfully set, FALSE otherwise. */ bool target_set_interactive(int mode, int x, int y) { int py = p_ptr->py; int px = p_ptr->px; int path_n; u16b path_g[256]; int i, d, m, t, bd; int wid, hgt, help_prompt_loc; bool done = FALSE; bool flag = TRUE; bool help = FALSE; //struct keypress query; ui_event press; /* These are used for displaying the path to the target */ wchar_t path_char[MAX_RANGE_LGE]; int path_attr[MAX_RANGE_LGE]; struct point_set *targets; /* If we haven't been given an initial location, start on the player. */ if (x == -1 || y == -1) { x = p_ptr->px; y = p_ptr->py; } /* If we /have/ been given an initial location, make sure we honour it by going into "free targetting" mode. */ else { flag = FALSE; } /* Cancel target */ target_set_monster(0); /* Cancel tracking */ /* health_track(NULL); */ /* Calculate the window location for the help prompt */ Term_get_size(&wid, &hgt); help_prompt_loc = hgt - 1; /* Display the help prompt */ prt("Press '?' for help.", help_prompt_loc, 0); /* Prepare the target set */ targets = target_set_interactive_prepare(mode); /* Start near the player */ m = 0; /* Interact */ while (!done) { bool path_drawn = FALSE; /* Interesting grids */ if (flag && point_set_size(targets)) { y = targets->pts[m].y; x = targets->pts[m].x; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) handle_stuff(p_ptr); /* Update help */ if (help) { bool good_target = target_able(cave_monster_at(cave, y, x)); target_display_help(good_target, !(flag && point_set_size(targets))); } /* Find the path. */ path_n = project_path(path_g, MAX_RANGE, py, px, y, x, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if (mode & (TARGET_KILL)) path_drawn = draw_path(path_n, path_g, path_char, path_attr, py, px); /* Describe and Prompt */ press = target_set_interactive_aux(y, x, mode); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(NULL); */ /* Assume no "direction" */ d = 0; /* Analyze */ if (press.type == EVT_MOUSE) { if (press.mouse.button == 3) { /* give the target selection command */ press.mouse.button = 2; press.mouse.mods = KC_MOD_CONTROL; } if (press.mouse.button == 2) { y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (press.mouse.mods & KC_MOD_CONTROL) { /* same as keyboard target selection command below */ struct monster *m = cave_monster_at(cave, y, x); if (target_able(m)) { /* Set up target information */ monster_race_track(m->race); health_track(p_ptr, m); target_set_monster(m); done = TRUE; } else { bell("Illegal target!"); } } else if (press.mouse.mods & KC_MOD_ALT) { /* go to spot - same as 'g' command below */ cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; } else { /* cancel look mode */ done = TRUE; } } else /*if (press.mouse.button == 3) { } else*/ { y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (cave->m_idx[y][x] || cave->o_idx[y][x]){// || cave->feat[y][x]&) { /* reset the flag, to make sure we stay in this mode if * something is actually there */ flag = FALSE; /* scan the interesting list and see if there in anything here */ for (i = 0; i < point_set_size(targets); i++) { if ((y == targets->pts[i].y) && (x == targets->pts[i].x)) { m = i; flag = TRUE; break; } } } else { flag = FALSE; } } } else switch (press.key.code) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': { if (++m == point_set_size(targets)) m = 0; break; } case '-': { if (m-- == 0) m = point_set_size(targets) - 1; break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(p_ptr); y = p_ptr->py; x = p_ptr->px; } case 'o': { flag = FALSE; break; } case 'm': { break; } case 't': case '5': case '0': case '.': { struct monster *m = cave_monster_at(cave, y, x); if (target_able(m)) { health_track(p_ptr, m); target_set_monster(m); done = TRUE; } else { bell("Illegal target!"); } break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(p_ptr); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract direction */ d = target_dir(press.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Hack -- move around */ if (d) { int old_y = targets->pts[m].y; int old_x = targets->pts[m].x; /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d], targets); /* Scroll to find interesting grid */ if (i < 0) { int old_wy = Term->offset_y; int old_wx = Term->offset_x; /* Change if legal */ if (change_panel(d)) { /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); /* Find a new monster */ i = target_pick(old_y, old_x, ddy[d], ddx[d], targets); /* Restore panel if needed */ if ((i < 0) && modify_panel(Term, old_wy, old_wx)) { /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); } /* Handle stuff */ handle_stuff(p_ptr); } } /* Use interesting grid if found */ if (i >= 0) m = i; } } /* Arbitrary grids */ else { /* Update help */ if (help) { bool good_target = target_able(cave_monster_at(cave, y, x)); target_display_help(good_target, !(flag && point_set_size(targets))); } /* Find the path. */ path_n = project_path(path_g, MAX_RANGE, py, px, y, x, PROJECT_THRU); /* Draw the path in "target" mode. If there is one */ if (mode & (TARGET_KILL)) path_drawn = draw_path (path_n, path_g, path_char, path_attr, py, px); /* Describe and Prompt (enable "TARGET_LOOK") */ press = target_set_interactive_aux(y, x, mode | TARGET_LOOK); /* Remove the path */ if (path_drawn) load_path(path_n, path_g, path_char, path_attr); /* Cancel tracking */ /* health_track(0); */ /* Assume no direction */ d = 0; /* Analyze the keypress */ if (press.type == EVT_MOUSE) { if (press.mouse.button == 3) { /* give the target selection command */ press.mouse.button = 2; press.mouse.mods = KC_MOD_CONTROL; } if (press.mouse.button == 2) { if (mode & (TARGET_KILL)) { if ((y == KEY_GRID_Y(press)) && (x == KEY_GRID_X(press))) { d = -1; } } y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (press.mouse.mods & KC_MOD_CONTROL) { /* same as keyboard target selection command below */ target_set_location(y, x); done = TRUE; } else if (press.mouse.mods & KC_MOD_ALT) { /* go to spot - same as 'g' command below */ cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; } else { /* cancel look mode */ done = TRUE; if (d == -1) { target_set_location(y, x); d = 0; } } } else /*if (press.mouse.button == 3) { } else*/ { int dungeon_hgt = cave->height; int dungeon_wid = cave->width; y = KEY_GRID_Y(press);//.mouse.y; x = KEY_GRID_X(press);//.mouse.x; if (Term) { if (press.mouse.y <= 1) { /* move the screen north */ y--; } else if (press.mouse.y >= (Term->hgt - 2)) { /* move the screen south */ y++; } else if (press.mouse.x <= COL_MAP) { /* move the screen in west */ x--; } else if (press.mouse.x >= (Term->wid - 2)) { /* move the screen east */ x++; } } if (y < 0) y = 0; if (x < 0) x = 0; if (y >= dungeon_hgt-1) y = dungeon_hgt-1; if (x >= dungeon_wid-1) x = dungeon_wid-1; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(p_ptr); /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); } if (cave->m_idx[y][x] || cave->o_idx[y][x]) { /* scan the interesting list and see if there in anything here */ for (i = 0; i < point_set_size(targets); i++) { if ((y == targets->pts[i].y) && (x == targets->pts[i].x)) { m = i; flag = TRUE; break; } } } else { flag = FALSE; } } } else switch (press.key.code) { case ESCAPE: case 'q': { done = TRUE; break; } case ' ': case '*': case '+': case '-': { break; } case 'p': { /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(p_ptr); y = p_ptr->py; x = p_ptr->px; } case 'o': { break; } case 'm': { flag = TRUE; m = 0; bd = 999; /* Pick a nearby monster */ for (i = 0; i < point_set_size(targets); i++) { t = distance(y, x, targets->pts[i].y, targets->pts[i].x); /* Pick closest */ if (t < bd) { m = i; bd = t; } } /* Nothing interesting */ if (bd == 999) flag = FALSE; break; } case 't': case '5': case '0': case '.': { target_set_location(y, x); done = TRUE; break; } case 'g': { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); done = TRUE; break; } case '?': { help = !help; /* Redraw main window */ p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); handle_stuff(p_ptr); if (!help) prt("Press '?' for help.", help_prompt_loc, 0); break; } default: { /* Extract a direction */ d = target_dir(press.key); /* Oops */ if (!d) bell("Illegal command for target mode!"); break; } } /* Handle "direction" */ if (d) { int dungeon_hgt = cave->height; int dungeon_wid = cave->width; /* Move */ x += ddx[d]; y += ddy[d]; /* Slide into legality */ if (x >= dungeon_wid - 1) x--; else if (x <= 0) x++; /* Slide into legality */ if (y >= dungeon_hgt - 1) y--; else if (y <= 0) y++; /* Adjust panel if needed */ if (adjust_panel_help(y, x, help)) { /* Handle stuff */ handle_stuff(p_ptr); /* Recalculate interesting grids */ point_set_dispose(targets); targets = target_set_interactive_prepare(mode); } } } } /* Forget */ point_set_dispose(targets); /* Redraw as necessary */ if (help) { p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP | PR_EQUIP); Term_clear(); } else { prt("", 0, 0); prt("", help_prompt_loc, 0); p_ptr->redraw |= (PR_DEPTH | PR_STATUS); } /* Recenter around player */ verify_panel(); /* Handle stuff */ handle_stuff(p_ptr); /* Failure to set target */ if (!target_set) return (FALSE); /* Success */ return (TRUE); }
/* * Memorize a message, Log it, Search it, and Display it in pieces */ static void borg_note_aux(cptr what) { int j, n, i, k; int w, h, x, y; term *old = Term; /* Memorize it */ message_add(what, MSG_GENERIC); /* Log the message */ if (borg_fff) froff(borg_fff, "%s\n", what); /* Mega-Hack -- Check against the search string */ if (borg_match[0] && strstr(what, borg_match)) { /* Tell the user why you quit */ borg_oops("Search string was matched"); } /* Scan windows */ for (j = 0; j < 8; j++) { if (!angband_term[j]) continue; /* Check flag */ if (!(window_flag[j] & PW_BORG_1)) continue; /* Activate */ Term_activate(angband_term[j]); /* Access size */ Term_get_size(&w, &h); /* Access cursor */ Term_locate(&x, &y); /* Erase current line */ clear_row(y); /* Total length */ n = strlen(what); /* Too long */ if (n > w - 2) { char buf[1024]; /* Split */ while (n > w - 2) { /* Default */ k = w - 2; /* Find a split point */ for (i = w / 2; i < w - 2; i++) { /* Pre-emptive split point */ if (isspace(what[i])) k = i; } /* Copy over the split message */ for (i = 0; i < k; i++) { /* Copy */ buf[i] = what[i]; } /* Indicate split */ buf[i++] = '\\'; /* Terminate */ buf[i] = '\0'; /* Show message */ roff(buf); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ clear_row(y); /* Advance */ what += k; /* Reduce */ n -= k; } /* Show message tail */ roff(what); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ clear_row(y); } /* Normal */ else { /* Show message */ roff(what); /* Advance (wrap) */ if (++y >= h) y = 0; /* Erase next line */ clear_row(y); } /* Flush output */ Term_fresh(); /* Use correct window */ Term_activate(old); } }