/* * Examine a grid, return a keypress. * * The "mode" argument contains the "TARGET_LOOK" bit flag, which * indicates that the "space" key should scan through the contents * of the grid, instead of simply returning immediately. This lets * the "look" command get complete information, without making the * "target" command annoying. * * The "info" argument contains the "commands" which should be shown * inside the "[xxx]" text. This string must never be empty, or grids * containing monsters will be displayed with an extra comma. * * Note that if a monster is in the grid, we update both the monster * recall info and the health bar info to track that monster. * * This function correctly handles multiple objects per grid, and objects * and terrain features in the same grid, though the latter never happens. * * This function must handle blindness/hallucination. */ static ui_event_data target_set_interactive_aux(int y, int x, int mode, cptr info, bool list_floor_objects) { s16b this_o_idx, next_o_idx = 0; s16b this_x_idx, next_x_idx = 0; cptr s1, s2, s3; bool floored; u16b feat; ui_event_data query; char out_val[256]; char coords[20]; /* Describe the square location */ coords_desc(coords, sizeof(coords), y, x); /* Repeat forever */ while (1) { int i; char feat_name[80]; /* Terrain suffix for monsters and objects */ char terrain_suffix[200]; /* Temporary array of visible effects */ s16b x_seen[50]; u16b size_x_seen = 0; /* Paranoia */ query.key = ' '; /* Default */ s1 = "You see "; s2 = ""; s3 = "on "; /* The player */ if (cave_m_idx[y][x] < 0) { /* Description */ s1 = "You are "; /* Preposition */ s2 = "on "; } /* Feature (apply "mimic") */ feat = f_info[cave_feat[y][x]].f_mimic; /* Require knowledge about grid, or ability to see grid */ if (!(cave_info[y][x] & (CAVE_MARK)) && !player_can_see_bold(y,x)) { /* Forget feature */ feat = FEAT_NONE; } else { /* Hack -- track the current feature */ feature_kind_track(feat); /* Window stuff */ p_ptr->redraw |= (PR_FEATURE); } /* Pick a prefix */ if (*s2 && (!feat_ff1_match(feat, FF1_MOVE) || !feat_ff1_match(feat, FF1_LOS) || feat_ff1_match(feat, FF1_SHOP | FF1_DOOR) || feat_ff2_match(feat, FF2_SHALLOW | FF2_DEEP) || feat_ff3_match(feat, FF3_NEED_TREE))) { s3 = "in "; } /* Get a default name */ if (feat <= FEAT_NONE) { my_strcpy(feat_name, "an unknown grid", sizeof(feat_name)); } /* Get the real name */ else { feature_desc(feat_name, sizeof (feat_name), feat, TRUE, FALSE); } /* List all effects in the grid */ for (this_x_idx = cave_x_idx[y][x]; this_x_idx; this_x_idx = next_x_idx) { effect_type *x_ptr; /* Get the effect */ x_ptr = &x_list[this_x_idx]; /* Get the next effect */ next_x_idx = x_ptr->next_x_idx; /* Describe it, if not hidden */ if (!(x_ptr->x_flags & (EF1_HIDDEN)) && x_ptr->x_f_idx) { /* Check for available space */ if (size_x_seen < N_ELEMENTS(x_seen)) { x_seen[size_x_seen++] = x_ptr->x_f_idx; } } } /* Prepare the terrain suffix for monsters and objects */ my_strcpy(terrain_suffix, format(" %s%s", s3, feat_name), sizeof(terrain_suffix)); /* Concat the collected effect names */ for (i = 0; i < size_x_seen; i++) { char x_name[80]; /* Obtain an object description */ feature_desc(x_name, sizeof(x_name), x_seen[i], TRUE, TRUE); /* First effect */ if (i == 0) { if ((feat == FEAT_NONE) || !feat_ff1_match(feat, FF1_MOVE) || cave_any_trap_bold(y, x)) { /* Basic info */ my_strcat(terrain_suffix, format(" with %s", x_name), sizeof(terrain_suffix)); } else { /* Basic info */ my_strcat(terrain_suffix, format(" beneath %s", x_name), sizeof(terrain_suffix)); } } /* Basic info */ else if (i < (size_x_seen - 1)) { my_strcat(terrain_suffix, format(", %s", x_name), sizeof(terrain_suffix)); } /* Basic info */ else { my_strcat(terrain_suffix, format(" and %s", x_name), sizeof(terrain_suffix)); } } /* Ignore the terrain suffix if certain things happen */ if ((size_x_seen == 0) && (feat <= FEAT_FLOOR)) { terrain_suffix[0] = '\0'; } /* Hack -- hallucination */ if (p_ptr->timed[TMD_IMAGE]) { cptr name = "something strange"; /* Display a message */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s, [%s] %s (%d:%d).", s1, s2, name, info, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s [%s], %s.", s1, s2, name, info, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Stop on everything but "return" */ if ((query.key != '\n') && (query.key != '\r')) break; /* Repeat forever */ continue; } /* Actual monsters */ if (cave_m_idx[y][x] > 0) { monster_type *m_ptr = &mon_list[cave_m_idx[y][x]]; monster_race *r_ptr = &r_info[m_ptr->r_idx]; /* Visible */ if (m_ptr->ml) { bool recall = FALSE; char m_name[80]; if (m_ptr->mimic_k_idx) { /*get the description*/ mimic_desc_object(m_name, sizeof(m_name), m_ptr->mimic_k_idx); } else { /* Get the monster name ("a kobold") */ monster_desc(m_name, sizeof(m_name), m_ptr, 0x08); /* Hack -- track this monster race */ monster_race_track(m_ptr->r_idx); /* Hack -- health bar for this monster */ health_track(cave_m_idx[y][x]); /*Track the feature*/ feature_kind_track(cave_feat[y][x]); /* Window stuff */ p_ptr->redraw |= (PR_FEATURE); /* Hack -- handle stuff */ handle_stuff(); } /* Interact */ while (1) { if (recall) button_add("[CLEAR_RECALL]", 'r'); else button_add("[RECALL]", 'r'); if (cave_o_idx[y][x] > 0)button_add("[VIEW_FLOOR]", 'f'); event_signal(EVENT_MOUSEBUTTONS); /* Recall, but not mimics */ if ((recall) && (!(m_ptr->mimic_k_idx))) { /* Save screen */ screen_save(); /* Recall on screen */ screen_roff(m_ptr->r_idx); /* Hack -- Complete the prompt (again) */ Term_addstr(-1, TERM_WHITE, format(" [r,%s]", info)); /* Command */ query = inkey_ex(); /* Load screen */ screen_load(); } /* Normal */ else { /* Basic info */ strnfmt(out_val, sizeof(out_val), "%s%s%s", s1, s2, m_name); /* Describe the monster, unless a mimic */ if (!(m_ptr->mimic_k_idx)) { char buf[80]; look_mon_desc(buf, sizeof(buf), cave_m_idx[y][x]); /* Monster state, terrain suffix, options */ my_strcat(out_val, format(" (%s)%s [r,%s]", buf, terrain_suffix, info), sizeof(out_val)); } /* Mimics */ else { /* Terrain suffix, options */ my_strcat(out_val, format("%s [I,%s]", terrain_suffix, info), sizeof(out_val)); } /* Wizards want coordinates */ if (p_ptr->wizard) { my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val)); } prt(out_val, 0, 0); /* Place cursor */ move_cursor_relative(y, x); /* Command */ query = inkey_ex(); } button_kill('r'); button_kill('f'); event_signal(EVENT_MOUSEBUTTONS); /* Handle fake object recall */ if (m_ptr->mimic_k_idx) { object_type body; object_type *o_ptr = &body; /* Validate input first */ if (query.key != 'I') break; /* Paranoia */ object_wipe(o_ptr); /* Prepare */ object_prep(o_ptr, m_ptr->mimic_k_idx); /* Fake history */ object_history(o_ptr, ORIGIN_FLOOR, 0); /* Clear prompt. Place cursor */ prt("", 0, 0); /* Show the fake info - EXPERIMENTAL */ object_info_screen(o_ptr); } /* Regular monsters */ else { /* Normal commands */ if (query.key != 'r') break; /* Toggle recall */ recall = !recall; } } /* Stop on everything but "return"/"space", or floor */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ') && (query.key != 'f')) break; /* continue with 'f' only if there are floor items....*/ if ((query.key == 'f') && (!cave_o_idx[y][x])) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s1 = "It is "; /* Hack -- take account of gender */ if (r_ptr->flags1 & (RF1_FEMALE)) s1 = "She is "; else if (r_ptr->flags1 & (RF1_MALE)) s1 = "He is "; /* Use a preposition */ s2 = "carrying "; /* Scan all objects being carried */ for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) { char o_name[80]; object_type *o_ptr; /* Get the object */ o_ptr = &o_list[this_o_idx]; /* Get the next object */ next_o_idx = o_ptr->next_o_idx; /*Don't let the player see certain objects (used for vault treasure)*/ if ((o_ptr->ident & (IDENT_HIDE_CARRY)) && (!p_ptr->wizard) && (!cheat_peek)) continue; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Describe the object */ strnfmt(out_val, sizeof(out_val), "%s%s%s [%s]", s1, s2, o_name, info); /* Wizards want coordinates */ if (p_ptr->wizard) { my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val)); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s2 = "also carrying "; } /* Double break */ if (this_o_idx) break; /* Use a preposition */ s2 = "on "; } } /* Assume not floored */ floored = FALSE; /* Scan all objects in the grid */ if (TRUE) { int floor_list[MAX_FLOOR_STACK]; int floor_num; track_object(-floor_list[0]); handle_stuff(); /* Scan for floor objects */ floor_num = scan_floor(floor_list, MAX_FLOOR_STACK, y, x, 0x02); /* Actual pile */ if (floor_num > 1) { /* Floored */ floored = TRUE; /* Describe */ while (1) { /* Basic info */ strnfmt(out_val, sizeof(out_val), "%s%sa pile of %d objects%s [r,%s]", s1, s2, floor_num, terrain_suffix, info); /* Wizards want coordinates */ if (p_ptr->wizard) { my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val)); } prt(out_val, 0, 0); if (list_floor_objects) { /* Save screen */ screen_save(); /* Display */ show_floor(floor_list, floor_num, (OLIST_WEIGHT | OLIST_GOLD)); } move_cursor_relative(y, x); query = inkey_ex(); if (list_floor_objects) { screen_load(); } /* Display objects */ if (query.key == 'r') { int pos; pos = query.key - 'a'; if (0 <= pos && pos < floor_num) { track_object(-floor_list[pos]); handle_stuff(); } } /* Done */ break; } /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s1 = "It is "; /* Preposition */ s2 = "on "; } } /* Scan all objects in the grid */ for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx) { object_type *o_ptr; /* Get the object */ o_ptr = &o_list[this_o_idx]; /* Get the next object */ next_o_idx = o_ptr->next_o_idx; /* Skip objects if floored */ if (floored) continue; /* Describe it */ if (o_ptr->marked) { char o_name[80]; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Basic info */ strnfmt(out_val, sizeof(out_val), "%s%s%s%s [I,%s]", s1, s2, o_name, terrain_suffix, info); /* Wizards want coordinates */ if (p_ptr->wizard) { my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val)); } /* Show object. Handle object recall */ while (TRUE) { /* Print the prompt */ prt(out_val, 0, 0); /* Move cursor to that location */ move_cursor_relative(y, x); /* Read input key */ query = inkey_ex(); /* No object recall */ if (query.key != 'I') break; /* Object recall. Clear the first line */ prt("", 0, 0); /* Do it */ object_info_screen(o_ptr); } /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s1 = "It is "; /* Plurals */ if (o_ptr->number != 1) s1 = "They are "; /* Preposition */ s2 = "on "; } } /* Double break */ if (this_o_idx) break; /* Display terrain */ if (TRUE) { u16b temp_feat; bool enable_recall; bool show_recall = FALSE; char temp_name[80]; /* * Display terrain and effects */ for (i = 0; i <= size_x_seen; i++) { /* Hack - This is the mark for the feature stored in cave_feat */ if (i == size_x_seen) { temp_feat = feat; /* Just copy the feature name */ my_strcpy(temp_name, feat_name, sizeof(temp_name)); } /* Any other value is an effect stored x_list */ else { temp_feat = x_seen[i]; /* Get the effect's name */ feature_desc(temp_name, sizeof(temp_name), temp_feat, TRUE, TRUE); } /* Don't display feature recall if the grid is unknown */ enable_recall = (temp_feat != FEAT_NONE); /* Handle recall */ while (TRUE) { /* Handle recall mode */ if (show_recall && enable_recall) { /* Save screen */ screen_save(); /* Recall feature on screen */ screen_feature_roff(temp_feat); } /* Display a message */ strnfmt(out_val, sizeof(out_val), "%s%s%s [%s%s]%s", s1, s2, temp_name, (enable_recall ? "r,": ""), info, (i < size_x_seen) ? " (more)": ""); /* Wizards want coordinates */ if (p_ptr->wizard) { my_strcat(out_val, format(" (%d:%d)", y, x), sizeof(out_val)); } /*Track this feature*/ feature_kind_track(temp_feat); /* Hack -- handle stuff */ handle_stuff(); prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Load screen if necessary */ if (show_recall && enable_recall) { screen_load(); } /* Stop on everything but the recall command, if enabled */ if (!enable_recall || (query.key != 'r')) break; /* Toggle recall */ show_recall = !show_recall; } /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; } } /* Hack -- handle stuff */ handle_stuff(); /* Stop on everything but "return" */ if ((query.key != '\n') && (query.key != '\r')) break; } /* Keep going */ return (query); }
//static struct keypress target_set_interactive_aux(int y, int x, int mode) static ui_event target_set_interactive_aux(int y, int x, int mode) { s16b this_o_idx = 0, next_o_idx = 0; const char *s1, *s2, *s3; bool boring; int floor_list[MAX_FLOOR_STACK]; int floor_num; //struct keypress query; ui_event press; char out_val[256]; char coords[20]; const char *name; /* Describe the square location */ coords_desc(coords, sizeof(coords), y, x); /* Repeat forever */ while (1) { /* Paranoia */ press.type = EVT_KBRD; press.key.code = ' '; press.key.mods = 0; /* Assume boring */ boring = TRUE; /* Default */ s1 = "You see "; s2 = ""; s3 = ""; /* The player */ if (cave->m_idx[y][x] < 0) { /* Description */ s1 = "You are "; /* Preposition */ s2 = "on "; } /* Hallucination messes things up */ if (p_ptr->timed[TMD_IMAGE]) { const char *name = "something strange"; /* Display a message */ if (p_ptr->wizard) strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, name, coords, y, x); else strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, name, coords); prt(out_val, 0, 0); move_cursor_relative(y, x); //input = inkey_m(); //if ( press.key = inkey(); /* Stop on everything but "return" */ if (press.key.code == KC_ENTER) continue; return press; } /* Actual monsters */ if (cave->m_idx[y][x] > 0) { monster_type *m_ptr = cave_monster_at(cave, y, x); const monster_lore *l_ptr = get_lore(m_ptr->race); /* Visible */ if (m_ptr->ml && !m_ptr->unaware) { bool recall = FALSE; char m_name[80]; /* Not boring */ boring = FALSE; /* Get the monster name ("a kobold") */ monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND2); /* Hack -- track this monster race */ monster_race_track(m_ptr->race); /* Hack -- health bar for this monster */ health_track(p_ptr, m_ptr); /* Hack -- handle stuff */ handle_stuff(p_ptr); /* Interact */ while (1) { /* Recall */ if (recall) { /* Save screen */ screen_save(); /* Recall on screen */ screen_roff(m_ptr->race, l_ptr); /* Command */ press = inkey_m(); /* Load screen */ screen_load(); } /* Normal */ else { char buf[80]; /* Describe the monster */ look_mon_desc(buf, sizeof(buf), cave->m_idx[y][x]); /* Describe, and prompt for recall */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s (%s), %s (%d:%d).", s1, s2, s3, m_name, buf, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s (%s), %s.", s1, s2, s3, m_name, buf, coords); } prt(out_val, 0, 0); /* Place cursor */ move_cursor_relative(y, x); /* Command */ press = inkey_m(); } /* Normal commands */ if ((press.type == EVT_MOUSE) && (press.mouse.button == 1) && (KEY_GRID_X(press) == x) && (KEY_GRID_Y(press) == y)) recall = !recall; else if ((press.type == EVT_KBRD) && (press.key.code == 'r')) recall = !recall; else break; } if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button == 2) break; /* Sometimes stop at "space" key */ if (press.mouse.button && !(mode & (TARGET_LOOK))) break; } else { /* Stop on everything but "return"/"space" */ if (press.key.code != KC_ENTER && press.key.code != ' ') break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; } /* Take account of gender */ if (rf_has(m_ptr->race->flags, RF_FEMALE)) s1 = "She is "; else if (rf_has(m_ptr->race->flags, RF_MALE)) s1 = "He is "; else s1 = "It is "; /* Use a verb */ s2 = "carrying "; /* Scan all objects being carried */ for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) { char o_name[80]; object_type *o_ptr; /* Get the object */ o_ptr = object_byid(this_o_idx); /* Get the next object */ next_o_idx = o_ptr->next_o_idx; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Describe the object */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, o_name, coords, y, x); } /* Disabled since monsters now carry their drops else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, o_name, coords); } */ prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button == 2) break; /* Sometimes stop at "space" key */ if (press.mouse.button && !(mode & (TARGET_LOOK))) break; } else { /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; } /* Change the intro */ s2 = "also carrying "; } /* Double break */ if (this_o_idx) break; /* Use a preposition */ s2 = "on "; } } /* Assume not floored */ floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x0A); /* Scan all marked objects in the grid */ if ((floor_num > 0) && (!(p_ptr->timed[TMD_BLIND]) || (y == p_ptr->py && x == p_ptr->px))) { /* Not boring */ boring = FALSE; track_object(-floor_list[0]); handle_stuff(p_ptr); /* If there is more than one item... */ if (floor_num > 1) while (1) { /* Describe the pile */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%sa pile of %d objects, %s (%d:%d).", s1, s2, s3, floor_num, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%sa pile of %d objects, %s.", s1, s2, s3, floor_num, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); /* Display objects */ if (((press.type == EVT_MOUSE) && (press.mouse.button == 1) && (KEY_GRID_X(press) == x) && (KEY_GRID_Y(press) == y)) || ((press.type == EVT_KBRD) && (press.key.code == 'r'))) { int rdone = 0; int pos; while (!rdone) { /* Save screen */ screen_save(); /* Display */ show_floor(floor_list, floor_num, (OLIST_WEIGHT | OLIST_GOLD)); /* Describe the pile */ prt(out_val, 0, 0); press = inkey_m(); /* Load screen */ screen_load(); if (press.type == EVT_MOUSE) { pos = press.mouse.y-1; } else { pos = press.key.code - 'a'; } if (0 <= pos && pos < floor_num) { track_object(-floor_list[pos]); handle_stuff(p_ptr); continue; } rdone = 1; } /* Now that the user's done with the display loop, let's */ /* the outer loop over again */ continue; } /* Done */ break; } /* Only one object to display */ else { char o_name[80]; /* Get the single object in the list */ object_type *o_ptr = object_byid(floor_list[0]); /* Not boring */ boring = FALSE; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Describe the object */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, o_name, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, o_name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s1 = "It is "; /* Plurals */ if (o_ptr->number != 1) s1 = "They are "; /* Preposition */ s2 = "on "; } } /* Double break */ if (this_o_idx) break; name = cave_apparent_name(cave, p_ptr, y, x); /* Terrain feature if needed */ if (boring || cave_isinteresting(cave, y, x)) { /* Hack -- handle unknown grids */ /* Pick a prefix */ if (*s2 && cave_isdoor(cave, y, x)) s2 = "in "; /* Pick proper indefinite article */ s3 = (is_a_vowel(name[0])) ? "an " : "a "; /* Hack -- special introduction for store doors */ if (cave_isshop(cave, y, x)) { s3 = "the entrance to the "; } /* Display a message */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, name, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button == 2) break; } else { /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; } } /* Stop on everything but "return" */ if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button != 2) break; } else { if (press.key.code != KC_ENTER) break; } } /* Keep going */ return (press); }
/* * Examine a grid, return a keypress. * * The "mode" argument contains the "TARGET_LOOK" bit flag, which * indicates that the "space" key should scan through the contents * of the grid, instead of simply returning immediately. This lets * the "look" command get complete information, without making the * "target" command annoying. * * The "info" argument contains the "commands" which should be shown * inside the "[xxx]" text. This string must never be empty, or grids * containing monsters will be displayed with an extra comma. * * Note that if a monster is in the grid, we update both the monster * recall info and the health bar info to track that monster. * * This function correctly handles multiple objects per grid, and objects * and terrain features in the same grid, though the latter never happens. * * This function must handle blindness/hallucination. */ static ui_event_data target_set_interactive_aux(int y, int x, int mode) { s16b this_o_idx = 0, next_o_idx = 0; cptr s1, s2, s3; bool boring; bool floored; int feat; int floor_list[MAX_FLOOR_STACK]; int floor_num; ui_event_data query; char out_val[256]; char coords[20]; /* Describe the square location */ coords_desc(coords, sizeof(coords), y, x); /* Repeat forever */ while (1) { /* Paranoia */ query.key = ' '; /* Assume boring */ boring = TRUE; /* Default */ s1 = "You see "; s2 = ""; s3 = ""; /* The player */ if (cave_m_idx[y][x] < 0) { /* Description */ s1 = "You are "; /* Preposition */ s2 = "on "; } /* Hack -- hallucination */ if (p_ptr->timed[TMD_IMAGE]) { cptr name = "something strange"; /* Display a message */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, name, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Stop on everything but "return" */ if ((query.key != '\n') && (query.key != '\r')) break; /* Repeat forever */ continue; } /* Actual monsters */ if (cave_m_idx[y][x] > 0) { monster_type *m_ptr = &mon_list[cave_m_idx[y][x]]; monster_race *r_ptr = &r_info[m_ptr->r_idx]; /* Visible */ if (m_ptr->ml) { bool recall = FALSE; char m_name[80]; /* Not boring */ boring = FALSE; /* Get the monster name ("a kobold") */ monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND2); /* Hack -- track this monster race */ monster_race_track(m_ptr->r_idx); /* Hack -- health bar for this monster */ health_track(cave_m_idx[y][x]); /* Hack -- handle stuff */ handle_stuff(); /* Interact */ while (1) { /* Recall */ if (recall) { /* Save screen */ screen_save(); /* Recall on screen */ screen_roff(m_ptr->r_idx); /* Command */ query = inkey_ex(); /* Load screen */ screen_load(); } /* Normal */ else { char buf[80]; /* Describe the monster */ look_mon_desc(buf, sizeof(buf), cave_m_idx[y][x]); /* Describe, and prompt for recall */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s (%s), %s (%d:%d).", s1, s2, s3, m_name, buf, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s (%s), %s.", s1, s2, s3, m_name, buf, coords); } prt(out_val, 0, 0); /* Place cursor */ move_cursor_relative(y, x); /* Command */ query = inkey_ex(); } /* Normal commands */ if (query.key != 'r') break; /* Toggle recall */ recall = !recall; } /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s1 = "It is "; /* Hack -- take account of gender */ if (rf_has(r_ptr->flags, RF_FEMALE)) s1 = "She is "; else if (rf_has(r_ptr->flags, RF_MALE)) s1 = "He is "; /* Use a preposition */ s2 = "carrying "; /* Scan all objects being carried */ for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) { char o_name[80]; object_type *o_ptr; /* Get the object */ o_ptr = &o_list[this_o_idx]; /* Get the next object */ next_o_idx = o_ptr->next_o_idx; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Describe the object */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, o_name, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, o_name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s2 = "also carrying "; } /* Double break */ if (this_o_idx) break; /* Use a preposition */ s2 = "on "; } } /* Assume not floored */ floored = FALSE; floor_num = scan_floor(floor_list, N_ELEMENTS(floor_list), y, x, 0x02); /* Scan all marked objects in the grid */ if ((floor_num > 0) && (!(p_ptr->timed[TMD_BLIND]) || (y == p_ptr->py && x == p_ptr->px))) { /* Not boring */ boring = FALSE; track_object(-floor_list[0]); handle_stuff(); /* If there is more than one item... */ if (floor_num > 1) while (1) { floored = TRUE; /* Describe the pile */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%sa pile of %d objects, %s (%d:%d).", s1, s2, s3, floor_num, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%sa pile of %d objects, %s.", s1, s2, s3, floor_num, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Display objects */ if (query.key == 'r') { int rdone = 0; int pos; while (!rdone) { /* Save screen */ screen_save(); /* Display */ show_floor(floor_list, floor_num, (OLIST_WEIGHT | OLIST_GOLD)); /* Describe the pile */ prt(out_val, 0, 0); query = inkey_ex(); /* Load screen */ screen_load(); pos = query.key - 'a'; if (0 <= pos && pos < floor_num) { track_object(-floor_list[pos]); handle_stuff(); continue; } rdone = 1; } /* Now that the user's done with the display loop, let's */ /* the outer loop over again */ continue; } /* Done */ break; } /* Only one object to display */ else { char o_name[80]; /* Get the single object in the list */ object_type *o_ptr = &o_list[floor_list[0]]; /* Not boring */ boring = FALSE; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), o_ptr, ODESC_PREFIX | ODESC_FULL); /* Describe the object */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, o_name, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, o_name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; /* Sometimes stop at "space" key */ if ((query.key == ' ') && !(mode & (TARGET_LOOK))) break; /* Change the intro */ s1 = "It is "; /* Plurals */ if (o_ptr->number != 1) s1 = "They are "; /* Preposition */ s2 = "on "; } } /* Double break */ if (this_o_idx) break; /* Feature (apply "mimic") */ feat = f_info[cave_feat[y][x]].mimic; /* Require knowledge about grid, or ability to see grid */ if (!(cave_info[y][x] & (CAVE_MARK)) && !player_can_see_bold(y,x)) { /* Forget feature */ feat = FEAT_NONE; } /* Terrain feature if needed */ if (boring || (feat > FEAT_INVIS)) { cptr name = f_info[feat].name; /* Hack -- handle unknown grids */ if (feat == FEAT_NONE) name = "unknown grid"; /* Pick a prefix */ if (*s2 && (feat >= FEAT_DOOR_HEAD)) s2 = "in "; /* Pick proper indefinite article */ s3 = (is_a_vowel(name[0])) ? "an " : "a "; /* Hack -- special introduction for store doors */ if ((feat >= FEAT_SHOP_HEAD) && (feat <= FEAT_SHOP_TAIL)) { s3 = "the entrance to the "; } /* Display a message */ if (p_ptr->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d).", s1, s2, s3, name, coords, y, x); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); query = inkey_ex(); /* Stop on everything but "return"/"space" */ if ((query.key != '\n') && (query.key != '\r') && (query.key != ' ')) break; } /* Stop on everything but "return" */ if ((query.key != '\n') && (query.key != '\r')) break; } /* Keep going */ return (query); }
/** * Examine a grid, return a keypress. * * The "mode" argument contains the "TARGET_LOOK" bit flag, which * indicates that the "space" key should scan through the contents * of the grid, instead of simply returning immediately. This lets * the "look" command get complete information, without making the * "target" command annoying. * * The "info" argument contains the "commands" which should be shown * inside the "[xxx]" text. This string must never be empty, or grids * containing monsters will be displayed with an extra comma. * * Note that if a monster is in the grid, we update both the monster * recall info and the health bar info to track that monster. * * This function correctly handles multiple objects per grid, and objects * and terrain features in the same grid, though the latter never happens. * * This function must handle blindness/hallucination. */ static ui_event target_set_interactive_aux(int y, int x, int mode) { struct object *obj = NULL; const char *s1, *s2, *s3; bool boring; int floor_max = z_info->floor_size; struct object **floor_list = mem_zalloc(floor_max * sizeof(*floor_list)); int floor_num; ui_event press; char out_val[TARGET_OUT_VAL_SIZE]; char coords[20]; const char *name; /* Describe the square location */ coords_desc(coords, sizeof(coords), y, x); /* Repeat forever */ while (1) { /* Paranoia */ press.type = EVT_KBRD; press.key.code = ' '; press.key.mods = 0; /* Assume boring */ boring = TRUE; /* Default */ s1 = "You see "; s2 = ""; s3 = ""; /* The player */ if (cave->squares[y][x].mon < 0) { /* Description */ s1 = "You are "; /* Preposition */ s2 = "on "; } /* Hallucination messes things up */ if (player->timed[TMD_IMAGE]) { const char *name = "something strange"; /* Display a message */ if (player->wizard) strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3, name, coords, y, x, (int)cave->squares[y][x].cost, (int)cave->squares[y][x].when); else strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, name, coords); prt(out_val, 0, 0); move_cursor_relative(y, x); press.key = inkey(); /* Stop on everything but "return" */ if (press.key.code == KC_ENTER) continue; mem_free(floor_list); return press; } /* Actual monsters */ if (cave->squares[y][x].mon > 0) { monster_type *m_ptr = square_monster(cave, y, x); const monster_lore *l_ptr = get_lore(m_ptr->race); /* Visible */ if (mflag_has(m_ptr->mflag, MFLAG_VISIBLE) && !mflag_has(m_ptr->mflag, MFLAG_UNAWARE)) { bool recall = FALSE; char m_name[80]; /* Not boring */ boring = FALSE; /* Get the monster name ("a kobold") */ monster_desc(m_name, sizeof(m_name), m_ptr, MDESC_IND_VIS); /* Hack -- track this monster race */ monster_race_track(player->upkeep, m_ptr->race); /* Hack -- health bar for this monster */ health_track(player->upkeep, m_ptr); /* Hack -- handle stuff */ handle_stuff(player); /* Interact */ while (1) { /* Recall or target */ if (recall) { lore_show_interactive(m_ptr->race, l_ptr); press = inkey_m(); } else { char buf[80]; /* Describe the monster */ look_mon_desc(buf, sizeof(buf), cave->squares[y][x].mon); /* Describe, and prompt for recall */ if (player->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s (%s), %s (%d:%d, cost=%d, when=%d).", s1, s2, s3, m_name, buf, coords, y, x, (int)cave->squares[y][x].cost, (int)cave->squares[y][x].when); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s (%s), %s.", s1, s2, s3, m_name, buf, coords); } prt(out_val, 0, 0); /* Place cursor */ move_cursor_relative(y, x); /* Command */ press = inkey_m(); } /* Normal commands */ if ((press.type == EVT_MOUSE) && (press.mouse.button == 1) && (KEY_GRID_X(press) == x) && (KEY_GRID_Y(press) == y)) recall = !recall; else if ((press.type == EVT_KBRD) && (press.key.code == 'r')) recall = !recall; else break; } if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button == 2) break; /* Sometimes stop at "space" key */ if (press.mouse.button && !(mode & (TARGET_LOOK))) break; } else { /* Stop on everything but "return"/"space" */ if (press.key.code != KC_ENTER && press.key.code != ' ') break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; } /* Take account of gender */ if (rf_has(m_ptr->race->flags, RF_FEMALE)) s1 = "She is "; else if (rf_has(m_ptr->race->flags, RF_MALE)) s1 = "He is "; else s1 = "It is "; /* Use a verb */ s2 = "carrying "; /* Scan all objects being carried */ for (obj = m_ptr->held_obj; obj; obj = obj->next) { char o_name[80]; /* Obtain an object description */ object_desc(o_name, sizeof(o_name), obj, ODESC_PREFIX | ODESC_FULL); /* Describe the object */ if (player->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3, o_name, coords, y, x, (int)cave->squares[y][x].cost, (int)cave->squares[y][x].when); } prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button == 2) break; /* Sometimes stop at "space" key */ if (press.mouse.button && !(mode & (TARGET_LOOK))) break; } else { /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; } /* Change the intro */ s2 = "also carrying "; } /* Double break */ if (obj) break; /* Use a preposition */ s2 = "on "; } } /* A trap */ if (square_isvisibletrap(cave, y, x)) { struct trap *trap = cave->squares[y][x].trap; /* Not boring */ boring = FALSE; /* Interact */ while (1) { /* Change the intro */ if (cave->squares[y][x].mon < 0) { s1 = "You are "; s2 = "on "; } else { s1 = "You see "; s2 = ""; } /* Pick proper indefinite article */ s3 = (is_a_vowel(trap->kind->desc[0])) ? "an " : "a "; /* Describe, and prompt for recall */ if (player->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3, trap->kind->name, coords, y, x, (int)cave->squares[y][x].cost, (int)cave->squares[y][x].when); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, trap->kind->desc, coords); } prt(out_val, 0, 0); /* Place cursor */ move_cursor_relative(y, x); /* Command */ press = inkey_m(); /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; } } /* Double break */ if (square_isvisibletrap(cave, y, x)) break; /* Assume not floored */ floor_num = scan_floor(floor_list, floor_max, y, x, 0x0A, NULL); /* Scan all marked objects in the grid */ if ((floor_num > 0) && (!(player->timed[TMD_BLIND]) || (y == player->py && x == player->px))) { /* Not boring */ boring = FALSE; track_object(player->upkeep, floor_list[0]); handle_stuff(player); /* If there is more than one item... */ if (floor_num > 1) while (1) { /* Describe the pile */ if (player->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%sa pile of %d objects, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3, floor_num, coords, y, x, (int)cave->squares[y][x].cost, (int)cave->squares[y][x].when); } else { strnfmt(out_val, sizeof(out_val), "%s%s%sa pile of %d objects, %s.", s1, s2, s3, floor_num, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); /* Display objects */ if (((press.type == EVT_MOUSE) && (press.mouse.button == 1) && (KEY_GRID_X(press) == x) && (KEY_GRID_Y(press) == y)) || ((press.type == EVT_KBRD) && (press.key.code == 'r'))) { int rdone = 0; int pos; while (!rdone) { /* Save screen */ screen_save(); /* Display */ show_floor(floor_list, floor_num, (OLIST_WEIGHT | OLIST_GOLD), NULL); /* Describe the pile */ prt(out_val, 0, 0); press = inkey_m(); /* Load screen */ screen_load(); if (press.type == EVT_MOUSE) { pos = press.mouse.y-1; } else { pos = press.key.code - 'a'; } if (0 <= pos && pos < floor_num) { track_object(player->upkeep, floor_list[pos]); handle_stuff(player); continue; } rdone = 1; } /* Now that the user's done with the display loop, * let's do the outer loop over again */ continue; } /* Done */ break; } /* Only one object to display */ else { /* Get the single object in the list */ struct object *obj = floor_list[0]; /* Allow user to recall an object */ press = target_recall_loop_object(obj, y, x, out_val, s1, s2, s3, coords); /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; /* Sometimes stop at "space" key */ if ((press.key.code == ' ') && !(mode & (TARGET_LOOK))) break; /* Plurals */ s1 = VERB_AGREEMENT(obj->number, "It is ", "They are "); /* Preposition */ s2 = "on "; } } /* Double break */ if (obj) break; name = square_apparent_name(cave, player, y, x); /* Terrain feature if needed */ if (boring || square_isinteresting(cave, y, x)) { /* Hack -- handle unknown grids */ /* Pick a prefix */ if (*s2 && square_isdoor(cave, y, x)) s2 = "in "; /* Pick proper indefinite article */ s3 = (is_a_vowel(name[0])) ? "an " : "a "; /* Hack -- special introduction for store doors */ if (square_isshop(cave, y, x)) s3 = "the entrance to the "; /* Display a message */ if (player->wizard) { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s (%d:%d, cost=%d, when=%d).", s1, s2, s3, name, coords, y, x, (int)cave->squares[y][x].cost, (int)cave->squares[y][x].when); } else { strnfmt(out_val, sizeof(out_val), "%s%s%s%s, %s.", s1, s2, s3, name, coords); } prt(out_val, 0, 0); move_cursor_relative(y, x); press = inkey_m(); if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button == 2) break; } else { /* Stop on everything but "return"/"space" */ if ((press.key.code != KC_ENTER) && (press.key.code != ' ')) break; } } /* Stop on everything but "return" */ if (press.type == EVT_MOUSE) { /* Stop on right click */ if (press.mouse.button != 2) break; } else { if (press.key.code != KC_ENTER) break; } } mem_free(floor_list); /* Keep going */ return (press); }