/* ------------------------------------------------------------------------ * Quickstart? screen. * ------------------------------------------------------------------------ */ static enum birth_stage get_quickstart_command(void) { const char *prompt = "['Y' to use this character, 'N' to start afresh, 'C' to change name]"; enum birth_stage next = BIRTH_QUICKSTART; /* Prompt for it */ prt("New character based on previous one:", 0, 0); prt(prompt, Term->hgt - 1, Term->wid / 2 - strlen(prompt) / 2); /* Buttons */ button_kill_all(); button_add("[Y]", 'y'); button_add("[N]", 'n'); button_add("[C]", 'c'); redraw_stuff(p_ptr); do { /* Get a key */ struct keypress ke = inkey(); if (ke.code == 'N' || ke.code == 'n') { cmd_insert(CMD_BIRTH_RESET); next = BIRTH_SEX_CHOICE; } else if (ke.code == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (ke.code == 'C' || ke.code == 'c') { next = BIRTH_NAME_CHOICE; } else if (ke.code == 'Y' || ke.code == 'y') { cmd_insert(CMD_ACCEPT_CHARACTER); next = BIRTH_COMPLETE; } } while (next == BIRTH_QUICKSTART); /* Buttons */ button_kill_all(); redraw_stuff(p_ptr); /* Clear prompt */ clear_from(23); return next; }
/** * Handle a textui mouseclick. */ static void textui_process_click(ui_event_data e) { int x, y; if (!OPT(mouse_movement)) return; y = KEY_GRID_Y(e); x = KEY_GRID_X(e); /* Check for a valid location */ if (!in_bounds_fully(y, x)) return; /* XXX show context menu here */ if ((p_ptr->py == y) && (p_ptr->px == x)) textui_cmd_rest(); else /* if (e.mousebutton == 1) */ { if (p_ptr->timed[TMD_CONFUSED]) { cmd_insert(CMD_WALK); } else { cmd_insert(CMD_PATHFIND); cmd_set_arg_point(cmd_get_top(), 0, y, x); } } #if 0 else if (e.mousebutton == 2)
/** * Study a book to gain a new spell */ void textui_obj_study(void) { int item; char q[80]; char s[80]; if (mp_ptr->spell_realm == REALM_NONE) { msg("You cannot read books!"); return; } strnfmt(q, sizeof(q), "Study which %s?", magic_desc[mp_ptr->spell_realm][BOOK_NOUN]); strnfmt(s, sizeof(s), " You have no %ss that you can study.", magic_desc[mp_ptr->spell_realm][BOOK_LACK]); item_tester_hook = obj_can_study; if (!get_item(&item, q, s, CMD_STUDY_BOOK, (USE_INVEN | USE_FLOOR))) return; track_object(item); handle_stuff(p_ptr); if (mp_ptr->spell_book != TV_PRAYER_BOOK) { int spell = get_spell(object_from_item_idx(item), "study", spell_okay_to_study); if (spell >= 0) { cmd_insert(CMD_STUDY_SPELL); cmd_set_arg_choice(cmd_get_top(), 0, spell); } } else { cmd_insert(CMD_STUDY_BOOK); cmd_set_arg_item(cmd_get_top(), 0, item); } }
/* ------------------------------------------------------------------------ * Quickstart? screen. * ------------------------------------------------------------------------ */ static enum birth_stage get_quickstart_command(void) { const char *prompt = "['Y' to use this character, 'N' to start afresh, 'C' to change name]"; ui_event_data ke; enum birth_stage next = BIRTH_QUICKSTART; /* Prompt for it */ prt("New character based on previous one:", 0, 0); prt(prompt, Term->hgt - (mouse_buttons ? 2 : 1), Term->wid / 2 - strlen(prompt) / 2); /* Buttons */ button_kill_all(); button_add("[YES]", 'y'); button_add("[START_OVER]", 'n'); button_add("[CHANGE_NAME]", 'c'); redraw_stuff(); event_signal(EVENT_MOUSEBUTTONS); do { /* Get a key */ ke = inkey_ex(); if (ke.key == 'N' || ke.key == 'n') { cmd_insert(CMD_BIRTH_RESET, TRUE); next = BIRTH_SEX_CHOICE; } else if (ke.key == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (ke.key == 'C' || ke.key == 'c') { next = BIRTH_NAME_CHOICE; } else if (ke.key == 'Y' || ke.key == 'y') { cmd_insert(CMD_ACCEPT_CHARACTER); next = BIRTH_COMPLETE; } } while (next == BIRTH_QUICKSTART); /* Buttons */ button_kill_all(); handle_stuff(); event_signal(EVENT_MOUSEBUTTONS); /* Clear prompt */ clear_from(23); return next; }
/* ------------------------------------------------------------------------ * Final confirmation of character. * ------------------------------------------------------------------------ */ static enum birth_stage get_confirm_command(void) { const char *prompt = "['ESC' to step back, 'S' to start over, or any other key to continue]"; ui_event_data ke; enum birth_stage next; /* Prompt for it */ prt(prompt, Term->hgt - (mouse_buttons ? 2 : 1), Term->wid / 2 - strlen(prompt) / 2); /* Buttons */ button_kill_all(); button_add("[CONTINUE]", 'q'); button_add("[BACK]", ESCAPE); button_add("[START OVER]", 'S'); handle_stuff(); event_signal(EVENT_MOUSEBUTTONS); /* Get a key */ ke = inkey_ex(); /* Start over */ if (ke.key == 'S' || ke.key == 's') { next = BIRTH_RESET; } else if (ke.key == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (ke.key == ESCAPE) { next = BIRTH_BACK; } else { cmd_insert(CMD_ACCEPT_CHARACTER); next = BIRTH_COMPLETE; } /* Buttons */ button_kill_all(); handle_stuff(); event_signal(EVENT_MOUSEBUTTONS); /* Clear prompt */ clear_from(23); return next; }
/* * Pass the appropriate "Initialisation screen" command to the game, * getting user input if needed. */ static errr get_init_cmd(void) { /* Wait for response */ pause_line(Term); if (new_game) cmd_insert(CMD_NEWGAME); else /* This might be modified to supply the filename in future. */ cmd_insert(CMD_LOADFILE); /* Everything's OK. */ return 0; }
/* ------------------------------------------------------------------------ * Final confirmation of character. * ------------------------------------------------------------------------ */ static enum birth_stage get_confirm_command(void) { const char *prompt = "['ESC' to step back, 'S' to start over, or any other key to continue]"; struct keypress ke; enum birth_stage next; /* Prompt for it */ prt(prompt, Term->hgt - 1, Term->wid / 2 - strlen(prompt) / 2); /* Buttons */ button_kill_all(); button_add("[Continue]", 'q'); button_add("[ESC]", ESCAPE); button_add("[S]", 'S'); redraw_stuff(p_ptr); /* Get a key */ ke = inkey(); /* Start over */ if (ke.code == 'S' || ke.code == 's') { next = BIRTH_RESET; } else if (ke.code == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } else if (ke.code == ESCAPE) { next = BIRTH_BACK; } else { cmd_insert(CMD_ACCEPT_CHARACTER); next = BIRTH_COMPLETE; } /* Buttons */ button_kill_all(); redraw_stuff(p_ptr); /* Clear prompt */ clear_from(23); return next; }
void textui_obj_wield(object_type *o_ptr, int item) { int slot = wield_slot(o_ptr); /* Usually if the slot is taken we'll just replace the item in the slot, * but in some cases we need to ask the user which slot they actually * want to replace */ if (p_ptr->inventory[slot].k_idx) { if (o_ptr->tval == TV_RING) { cptr q = "Replace which ring? "; cptr s = "Error in obj_wield, please report"; item_tester_hook = obj_is_ring; if (!get_item(&slot, q, s, CMD_WIELD, USE_EQUIP)) return; } if (obj_is_ammo(o_ptr) && !object_similar(&p_ptr->inventory[slot], o_ptr, OSTACK_QUIVER)) { cptr q = "Replace which ammunition? "; cptr s = "Error in obj_wield, please report"; item_tester_hook = obj_is_ammo; if (!get_item(&slot, q, s, CMD_WIELD, USE_EQUIP)) return; } } cmd_insert(CMD_WIELD); cmd_set_arg_item(cmd_get_top(), 0, item); cmd_set_arg_number(cmd_get_top(), 1, slot); }
/* * Stay still. Search. Enter stores. * Pick up treasure if "pickup" is true. */ void do_cmd_hold(cmd_code code, cmd_arg args[]) { /* Take a turn */ p_ptr->energy_use = 100; /* Spontaneous Searching */ if ((p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] >= 50) || one_in_(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) { search(FALSE); } /* Continuous Searching */ if (p_ptr->searching) { search(FALSE); } /* Pick things up, not using extra energy */ (void)py_pickup(0); /* Hack -- enter a store if we are on one */ if ((cave_feat[p_ptr->py][p_ptr->px] >= FEAT_SHOP_HEAD) && (cave_feat[p_ptr->py][p_ptr->px] <= FEAT_SHOP_TAIL)) { /* Disturb */ disturb(0, 0); cmd_insert(CMD_ENTER_STORE); /* Free turn XXX XXX XXX */ p_ptr->energy_use = 0; } }
void textui_cmd_suicide(void) { /* Flush input */ flush(); /* Verify Retirement */ if (p_ptr->total_winner) { /* Verify */ if (!get_check("Do you want to retire? ")) return; } /* Verify Suicide */ else { char ch; /* Verify */ if (!get_check("Do you really want to commit suicide? ")) return; /* Special Verification for suicide */ prt("Please verify SUICIDE by typing the '@' sign: ", 0, 0); flush(); ch = inkey(); prt("", 0, 0); if (ch != '@') return; } cmd_insert(CMD_SUICIDE); }
/** * Front-end command which fires at the nearest target with default ammo. */ void textui_cmd_fire_at_nearest(void) { /* the direction '5' means 'use the target' */ int i, dir = 5, item = -1; /* Require a usable launcher */ if (!p_ptr->inventory[INVEN_BOW].tval || !p_ptr->state.ammo_tval) { msg("You have nothing to fire with."); return; } /* Find first eligible ammo in the quiver */ for (i = QUIVER_START; i < QUIVER_END; i++) { if (p_ptr->inventory[i].tval != p_ptr->state.ammo_tval) continue; item = i; break; } /* Require usable ammo */ if (item < 0) { msg("You have no ammunition in the quiver to fire"); return; } /* Require foe */ if (!target_set_closest(TARGET_KILL | TARGET_QUIET)) return; /* Fire! */ cmd_insert(CMD_FIRE); cmd_set_arg_item(cmd_get_top(), 0, item); cmd_set_arg_target(cmd_get_top(), 1, dir); }
/** * Cast a spell from a book. */ void textui_obj_cast(void) { int item; int spell; const char *verb = magic_desc[mp_ptr->spell_realm][SPELL_VERB]; char q[80]; char s[80]; if (mp_ptr->spell_realm == REALM_NONE) { msg("You cannot read books!"); return; } strnfmt(q, sizeof(q), "Use which %s?", magic_desc[mp_ptr->spell_realm][BOOK_NOUN]); strnfmt(s, sizeof(s), " You have no %ss that you can use.", magic_desc[mp_ptr->spell_realm][BOOK_LACK]); item_tester_hook = obj_can_cast_from; if (!get_item(&item, q, s, CMD_CAST, (USE_INVEN | USE_FLOOR))) return; /* Track the object kind */ track_object(item); /* Ask for a spell */ spell = get_spell(object_from_item_idx(item), verb, spell_okay_to_cast); if (spell >= 0) { cmd_insert(CMD_CAST); cmd_set_arg_choice(cmd_get_top(), 0, spell); } }
void textui_cmd_rest(void) { /* Prompt for time if needed */ if (p_ptr->command_arg <= 0) { cptr p = "Rest (0-9999, '!' for HP or SP, '*' for HP and SP, '&' as needed): "; char out_val[5] = "& "; /* Ask for duration */ if (!get_string(p, out_val, sizeof(out_val))) return; /* Rest until done */ if (out_val[0] == '&') { cmd_insert(CMD_REST); cmd_set_arg_choice(cmd_get_top(), 0, REST_COMPLETE); } /* Rest a lot */ else if (out_val[0] == '*') { cmd_insert(CMD_REST); cmd_set_arg_choice(cmd_get_top(), 0, REST_ALL_POINTS); } /* Rest until HP or SP filled */ else if (out_val[0] == '!') { cmd_insert(CMD_REST); cmd_set_arg_choice(cmd_get_top(), 0, REST_SOME_POINTS); } /* Rest some */ else { int turns = atoi(out_val); if (turns <= 0) return; if (turns > 9999) turns = 9999; cmd_insert(CMD_REST); cmd_set_arg_choice(cmd_get_top(), 0, turns); } } }
/** * Handle user input from a command menu */ static bool show_action(menu_type * menu, const ui_event_data * e, int oid) { /* Handle enter and mouse */ if (e->type == EVT_SELECT) { cmd_insert(comm_code[oid]); if (comm_code[oid] == CMD_NULL) Term_keypress(comm[oid]); } return TRUE; }
/** * Handle user input from a command menu */ static bool show_action(menu_type * menu, const ui_event * e, int oid) { /* Handle enter and mouse */ if (e->type == EVT_SELECT) { cmd_insert(comm_code[oid]); if (comm_code[oid] == CMD_NULL) Term_keypress(comm[oid],0); cmd_set_arg_item(cmd_get_top(), 0, item); } return FALSE; }
void inter_instr() { char opt; idx_cmd = 0; if (cmd == NULL || cmd[idx_cmd] == '\0') notif_error("No option"); opt = cmd[idx_cmd++]; if (opt == 'E') return cmd_exit(); next_arg(); if (opt == 'D') return cmd_delete(); if (opt == 'I') return cmd_insert(); if (opt == 'R') return cmd_replace(); notif_error("Invalid option"); }
/* ------------------------------------------------------------------------ * Asking for the player's chosen name. * ------------------------------------------------------------------------ */ static enum birth_stage get_name_command(void) { enum birth_stage next; char name[32]; if (get_name(name, sizeof(name))) { cmd_insert(CMD_NAME_CHOICE, name); next = BIRTH_FINAL_CONFIRM; } else { next = BIRTH_BACK; } return next; }
/** * Front-end 'throw' command. */ void textui_cmd_throw(void) { int item, dir; const char *q, *s; /* Get an item */ q = "Throw which item? "; s = "You have nothing to throw."; if (!get_item(&item, q, s, CMD_THROW, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; if (item >= INVEN_WIELD && item < QUIVER_START) { msg("You cannot throw wielded items."); return; } /* Get a direction (or cancel) */ if (!get_aim_dir(&dir)) return; cmd_insert(CMD_THROW); cmd_set_arg_item(cmd_get_top(), 0, item); cmd_set_arg_target(cmd_get_top(), 1, dir); }
void textui_obj_inscribe(object_type *o_ptr, int item) { char o_name[80]; char tmp[80] = ""; object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); msg_format("Inscribing %s.", o_name); message_flush(); /* Use old inscription */ if (o_ptr->note) strnfmt(tmp, sizeof(tmp), "%s", quark_str(o_ptr->note)); /* Get a new inscription (possibly empty) */ if (get_string("Inscription: ", tmp, sizeof(tmp))) { cmd_insert(CMD_INSCRIBE); cmd_set_arg_item(cmd_get_top(), 0, item); cmd_set_arg_string(cmd_get_top(), 1, tmp); } }
/* * Stay still. Search. Enter stores. * Pick up treasure if "pickup" is true. */ void do_cmd_hold(cmd_code code, cmd_arg args[]) { /* Take a turn */ p_ptr->energy_use = 100; /* Spontaneous Searching */ if ((p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] >= 50) || one_in_(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) { search(FALSE); } /* Continuous Searching */ if (p_ptr->searching) { search(FALSE); } /* Pick things up, not using extra energy */ do_autopickup(); /* Hack -- enter a store if we are on one */ if (cave_isshop(cave, p_ptr->py, p_ptr->px)) { /* Disturb */ disturb(p_ptr, 0, 0); cmd_insert(CMD_ENTER_STORE); /* Free turn XXX XXX XXX */ p_ptr->energy_use = 0; } else { event_signal(EVENT_SEEFLOOR); } }
int main(int argc, char **argv) { struct arguments args; int rc; rc = -1; memset(&args, 0, sizeof(args)); argp_parse(&argp, argc, argv, 0, 0, &args); switch (args.cmd) { case CMD_INIT: rc = cmd_init(&args); break; case CMD_LIST: rc = cmd_list(&args); break; case CMD_INSERT: rc = cmd_insert(&args); break; case CMD_RETRIEVE: rc = cmd_retrieve(&args); break; case CMD_KILL: rc = cmd_kill(&args); break; case CMD_INTERACTIVE: rc = cmd_interactive(&args); break; default: fprintf(stderr, "invalid command\n"); goto out; } out: return rc; }
/* pick the context menu options appropiate for an item available in a store */ int context_menu_store_item(struct store *store, const int oid, int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; object_type *o_ptr; char header[120]; /* Get the actual object */ o_ptr = &store->stock[oid]; m = menu_dynamic_new(); if (!m || !store) { return 0; } object_desc(header, sizeof(header), o_ptr, ODESC_PREFIX | ODESC_BASE); labels = string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Examine", 'x', 4, labels); if (store->sidx == STORE_HOME) { menu_dynamic_add_label(m, "Take", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Take One", 'o', 5, labels); } } else { menu_dynamic_add_label(m, "Buy", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Buy One", 'o', 5, labels); } } /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); menu_layout(m, &r); region_erase_bordered(&r); prt(format("(Enter to select, ESC) Command for %s:", header), 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 4) { Term_keypress('x', 0); } else if (selected == 5) { if (store->sidx == STORE_HOME) { cmd_insert(CMD_RETRIEVE); } else { cmd_insert(CMD_BUY); } cmd_set_arg_choice(cmd_get_top(), 0, oid); cmd_set_arg_number(cmd_get_top(), 1, 1); } else if (selected == 6) { Term_keypress('p', 0); } return 1; }
/* pick the context menu options appropiate for a store */ int context_menu_store(struct store *store, const int oid, int mx, int my) { menu_type *m; rect_region r; int selected; char *labels; object_type *o_ptr; m = menu_dynamic_new(); if (!m || !store) { return 0; } /* Get the actual object */ o_ptr = &store->stock[oid]; labels = string_make(lower_case); m->selections = labels; menu_dynamic_add_label(m, "Inspect Inventory", 'I', 1, labels); if (store->sidx == STORE_HOME) { /*menu_dynamic_add(m, "Stash One", 2);*/ menu_dynamic_add_label(m, "Stash", 'd', 3, labels); menu_dynamic_add_label(m, "Examine", 'x', 4, labels); menu_dynamic_add_label(m, "Take", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Take One", 'o', 5, labels); } } else { /*menu_dynamic_add(m, "Sell One", 2);*/ menu_dynamic_add_label(m, "Sell", 'd', 3, labels); menu_dynamic_add_label(m, "Examine", 'x', 4, labels); menu_dynamic_add_label(m, "Buy", 'p', 6, labels); if (o_ptr->number > 1) { menu_dynamic_add_label(m, "Buy One", 'o', 5, labels); } } menu_dynamic_add_label(m, "Exit", '`', 7, labels); /* work out display region */ r.width = menu_dynamic_longest_entry(m) + 3 + 2; /* +3 for tag, 2 for pad */ if (mx > Term->wid - r.width - 1) { r.col = Term->wid - r.width - 1; } else { r.col = mx + 1; } r.page_rows = m->count; if (my > Term->hgt - r.page_rows - 1) { if (my - r.page_rows - 1 <= 0) { /* menu has too many items, so put in upper right corner */ r.row = 1; r.col = Term->wid - r.width - 1; } else { r.row = Term->hgt - r.page_rows - 1; } } else { r.row = my + 1; } /* Hack -- no flush needed */ msg_flag = FALSE; screen_save(); button_backup_all(TRUE); menu_layout(m, &r); region_erase_bordered(&r); prt("(Enter to select, ESC) Command:", 0, 0); selected = menu_dynamic_select(m); menu_dynamic_free(m); string_free(labels); button_restore(); screen_load(); if (selected == 1) { Term_keypress('I', 0); } else if (selected == 2) { Term_keypress('s', 0); /* oid is store item we do not know item we want to sell here */ /*if (store->sidx == STORE_HOME) { cmd_insert(CMD_STASH); } else { cmd_insert(CMD_SELL); } cmd_set_arg_item(cmd_get_top(), 0, oid); cmd_set_arg_number(cmd_get_top(), 1, 1);*/ } else if (selected == 3) { Term_keypress('s', 0); } else if (selected == 4) { Term_keypress('x', 0); } else if (selected == 5) { if (store->sidx == STORE_HOME) { cmd_insert(CMD_RETRIEVE); } else { cmd_insert(CMD_BUY); } cmd_set_arg_choice(cmd_get_top(), 0, oid); cmd_set_arg_number(cmd_get_top(), 1, 1); } else if (selected == 6) { Term_keypress('p', 0); } else if (selected == 7) { Term_keypress(ESCAPE, 0); } return 1; }
/* * 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); }
static enum birth_stage point_based_command(void) { static int stat = 0; struct keypress ch; enum birth_stage next = BIRTH_POINTBASED; /* point_based_display();*/ /* Place cursor just after cost of current stat */ Term_gotoxy(COSTS_COL + 4, COSTS_ROW + stat); /* Get key */ ch = inkey(); if (ch.code == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } /* Go back a step, or back to the start of this step */ else if (ch.code == ESCAPE) { next = BIRTH_BACK; } else if (ch.code == 'r' || ch.code == 'R') { cmd_insert(CMD_RESET_STATS); cmd_set_arg_choice(cmd_get_top(), 0, FALSE); } /* Done */ else if ((ch.code == '\r') || (ch.code == '\n')) { next = BIRTH_NAME_CHOICE; } else { int dir = target_dir(ch); /* Prev stat, looping round to the bottom when going off the top */ if (dir == 8) stat = (stat + A_MAX - 1) % A_MAX; /* Next stat, looping round to the top when going off the bottom */ if (dir == 2) stat = (stat + 1) % A_MAX; /* Decrease stat (if possible) */ if (dir == 4) { cmd_insert(CMD_SELL_STAT); cmd_set_arg_choice(cmd_get_top(), 0, stat); } /* Increase stat (if possible) */ if (dir == 6) { cmd_insert(CMD_BUY_STAT); cmd_set_arg_choice(cmd_get_top(), 0, stat); } } return next; }
/* * Move player in the given direction. * * This routine should only be called when energy has been expended. * * Note that this routine handles monsters in the destination grid, * and also handles attempting to move into walls/doors/rubble/etc. */ void move_player(int dir, bool disarm) { int py = p_ptr->py; int px = p_ptr->px; int y = py + ddy[dir]; int x = px + ddx[dir]; int m_idx = cave->m_idx[y][x]; /* Attack monsters */ if (m_idx > 0) { /* Mimics surprise the player */ if (is_mimicking(m_idx)) { become_aware(m_idx); /* Mimic wakes up */ mon_clear_timed(m_idx, MON_TMD_SLEEP, MON_TMD_FLG_NOMESSAGE); } else { py_attack(y, x); } } /* Optionally alter traps/doors on movement */ else if (disarm && (cave->info[y][x] & CAVE_MARK) && (cave_isknowntrap(cave, y, x) || cave_iscloseddoor(cave, y, x))) { /* Auto-repeat if not already repeating */ if (cmd_get_nrepeats() == 0) cmd_set_repeat(99); do_cmd_alter_aux(dir); } /* Cannot walk through walls */ else if (!cave_floor_bold(y, x)) { /* Disturb the player */ disturb(p_ptr, 0, 0); /* Notice unknown obstacles */ if (!(cave->info[y][x] & CAVE_MARK)) { /* Rubble */ if (cave->feat[y][x] == FEAT_RUBBLE) { msgt(MSG_HITWALL, "You feel a pile of rubble blocking your way."); cave->info[y][x] |= (CAVE_MARK); cave_light_spot(cave, y, x); } /* Closed door */ else if (cave->feat[y][x] < FEAT_SECRET) { msgt(MSG_HITWALL, "You feel a door blocking your way."); cave->info[y][x] |= (CAVE_MARK); cave_light_spot(cave, y, x); } /* Wall (or secret door) */ else { msgt(MSG_HITWALL, "You feel a wall blocking your way."); cave->info[y][x] |= (CAVE_MARK); cave_light_spot(cave, y, x); } } /* Mention known obstacles */ else { if (cave->feat[y][x] == FEAT_RUBBLE) msgt(MSG_HITWALL, "There is a pile of rubble blocking your way."); else if (cave->feat[y][x] < FEAT_SECRET) msgt(MSG_HITWALL, "There is a door blocking your way."); else msgt(MSG_HITWALL, "There is a wall blocking your way."); } } /* Normal movement */ else { /* See if trap detection status will change */ bool old_dtrap = ((cave->info2[py][px] & (CAVE2_DTRAP)) != 0); bool new_dtrap = ((cave->info2[y][x] & (CAVE2_DTRAP)) != 0); /* Note the change in the detect status */ if (old_dtrap != new_dtrap) p_ptr->redraw |= (PR_DTRAP); /* Disturb player if the player is about to leave the area */ if (OPT(disturb_detect) && p_ptr->running && !p_ptr->running_firststep && old_dtrap && !new_dtrap) { disturb(p_ptr, 0, 0); return; } /* Move player */ monster_swap(py, px, y, x); /* New location */ y = py = p_ptr->py; x = px = p_ptr->px; /* Searching */ if (p_ptr->searching || (p_ptr->state.skills[SKILL_SEARCH_FREQUENCY] >= 50) || one_in_(50 - p_ptr->state.skills[SKILL_SEARCH_FREQUENCY])) search(FALSE); /* Handle "store doors" */ if ((cave->feat[p_ptr->py][p_ptr->px] >= FEAT_SHOP_HEAD) && (cave->feat[p_ptr->py][p_ptr->px] <= FEAT_SHOP_TAIL)) { /* Disturb */ disturb(p_ptr, 0, 0); cmd_insert(CMD_ENTER_STORE); } /* All other grids (including traps) */ else { /* Handle objects (later) */ p_ptr->notice |= (PN_PICKUP); } /* Discover invisible traps */ if (cave->feat[y][x] == FEAT_INVIS) { /* Disturb */ disturb(p_ptr, 0, 0); /* Message */ msg("You found a trap!"); /* Pick a trap */ pick_trap(y, x); /* Hit the trap */ hit_trap(y, x); } /* Set off an visible trap */ else if (cave_isknowntrap(cave, y, x)) { /* Disturb */ disturb(p_ptr, 0, 0); /* Hit the trap */ hit_trap(y, x); } } p_ptr->running_firststep = FALSE; }
/* * 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); }
/* * This is called when we receive a request for a command in the birth * process. * The birth process continues until we send a final character confirmation * command (or quit), so this is effectively called in a loop by the main * game. * * We're imposing a step-based system onto the main game here, so we need * to keep track of where we're up to, where each step moves on to, etc. */ errr get_birth_command(bool wait) { static enum birth_stage current_stage = BIRTH_RESET; static enum birth_stage prev; static enum birth_stage roller = BIRTH_RESET; enum birth_stage next = current_stage; switch (current_stage) { case BIRTH_RESET: { cmd_insert(CMD_BIRTH_RESET); roller = BIRTH_RESET; if (quickstart_allowed) next = BIRTH_QUICKSTART; else next = BIRTH_SEX_CHOICE; break; } case BIRTH_QUICKSTART: { display_player(0); next = get_quickstart_command(); break; } case BIRTH_SEX_CHOICE: case BIRTH_CLASS_CHOICE: case BIRTH_RACE_CHOICE: case BIRTH_ROLLER_CHOICE: { menu_type *menu = &sex_menu; cmd_code command = CMD_CHOOSE_SEX; Term_clear(); print_menu_instructions(); if (current_stage > BIRTH_SEX_CHOICE) { menu_refresh(&sex_menu, FALSE); menu = &race_menu; command = CMD_CHOOSE_RACE; } if (current_stage > BIRTH_RACE_CHOICE) { menu_refresh(&race_menu, FALSE); menu = &class_menu; command = CMD_CHOOSE_CLASS; } if (current_stage > BIRTH_CLASS_CHOICE) { menu_refresh(&class_menu, FALSE); menu = &roller_menu; command = CMD_NULL; } next = menu_question(current_stage, menu, command); if (next == BIRTH_BACK) next = current_stage - 1; /* Make sure that the character gets reset before quickstarting */ if (next == BIRTH_QUICKSTART) next = BIRTH_RESET; break; } case BIRTH_POINTBASED: { roller = BIRTH_POINTBASED; if (prev > BIRTH_POINTBASED) point_based_start(); next = point_based_command(); if (next == BIRTH_BACK) next = BIRTH_ROLLER_CHOICE; if (next != BIRTH_POINTBASED) point_based_stop(); break; } case BIRTH_ROLLER: { roller = BIRTH_ROLLER; next = roller_command(prev < BIRTH_ROLLER); if (next == BIRTH_BACK) next = BIRTH_ROLLER_CHOICE; break; } case BIRTH_NAME_CHOICE: { if (prev < BIRTH_NAME_CHOICE) display_player(0); next = get_name_command(); if (next == BIRTH_BACK) next = roller; break; } case BIRTH_FINAL_CONFIRM: { if (prev < BIRTH_FINAL_CONFIRM) display_player(0); next = get_confirm_command(); if (next == BIRTH_BACK) next = BIRTH_NAME_CHOICE; break; } default: { /* Remove dodgy compiler warning, */ } } prev = current_stage; current_stage = next; return 0; }
/* * 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); }
static enum birth_stage roller_command(bool first_call) { char prompt[80] = ""; size_t promptlen = 0; struct keypress ch; enum birth_stage next = BIRTH_ROLLER; /* Used to keep track of whether we've rolled a character before or not. */ static bool prev_roll = FALSE; /* Display the player - a bit cheaty, but never mind. */ display_player(0); if (first_call) prev_roll = FALSE; /* Add buttons */ button_add("[ESC]", ESCAPE); button_add("[Enter]", '\r'); button_add("[r]", 'r'); if (prev_roll) button_add("[p]", 'p'); clear_from(Term->hgt - 2); redraw_stuff(p_ptr); /* Prepare a prompt (must squeeze everything in) */ strnfcat(prompt, sizeof (prompt), &promptlen, "['r' to reroll"); if (prev_roll) strnfcat(prompt, sizeof(prompt), &promptlen, ", 'p' for prev"); strnfcat(prompt, sizeof (prompt), &promptlen, " or 'Enter' to accept]"); /* Prompt for it */ prt(prompt, Term->hgt - 1, Term->wid / 2 - promptlen / 2); /* Prompt and get a command */ ch = inkey(); if (ch.code == ESCAPE) { button_kill('r'); button_kill('p'); next = BIRTH_BACK; } /* 'Enter' accepts the roll */ if ((ch.code == '\r') || (ch.code == '\n')) { next = BIRTH_NAME_CHOICE; } /* Reroll this character */ else if ((ch.code == ' ') || (ch.code == 'r')) { cmd_insert(CMD_ROLL_STATS); prev_roll = TRUE; } /* Previous character */ else if (prev_roll && (ch.code == 'p')) { cmd_insert(CMD_PREV_STATS); } /* Quit */ else if (ch.code == KTRL('X')) { cmd_insert(CMD_QUIT); next = BIRTH_COMPLETE; } /* Help XXX */ else if (ch.code == '?') { do_cmd_help(); } /* Nothing handled directly here */ else { bell("Illegal roller command!"); } /* Kill buttons */ button_kill(ESCAPE); button_kill('\r'); button_kill('r'); button_kill('p'); redraw_stuff(p_ptr); return next; }