getpos improvements: automatic description

Pressing '@' will move the cursor on top of the hero.
Pressing '#' will toggle automatic description mode, where
the feature under the cursor is automatically described
when the cursor is moved.
This commit is contained in:
Pasi Kallinen
2015-03-11 17:16:05 +02:00
parent 64b3c6460a
commit 3243b332a3
3 changed files with 271 additions and 202 deletions
+3
View File
@@ -1080,6 +1080,9 @@ Add database entry for shuriken and make it match throwing star
Add database entry for fedora Add database entry for fedora
Add database entry for land mine Add database entry for land mine
change command X to twoweapon toggle change command X to twoweapon toggle
pressing @ when cursor positioning moves cursor on top of hero
pressing # when cursor positioning toggles automatic description of features
under the cursor
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
+42 -1
View File
@@ -40,6 +40,8 @@ const char *goal;
putstr(tmpwin, 0, sbuf); putstr(tmpwin, 0, sbuf);
putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time."); putstr(tmpwin, 0, "Use [HJKL] to move the cursor 8 units at a time.");
putstr(tmpwin, 0, "Or enter a background symbol (ex. <)."); putstr(tmpwin, 0, "Or enter a background symbol (ex. <).");
putstr(tmpwin, 0, "Use @ to move the cursor on yourself.");
putstr(tmpwin, 0, "Use # to toggle automatic description.");
/* disgusting hack; the alternate selection characters work for any /* disgusting hack; the alternate selection characters work for any
getpos call, but they only matter for dowhatis (and doquickwhatis) */ getpos call, but they only matter for dowhatis (and doquickwhatis) */
doing_what_is = (goal == what_is_an_unknown_object); doing_what_is = (goal == what_is_an_unknown_object);
@@ -63,6 +65,8 @@ const char *goal;
int cx, cy, i, c; int cx, cy, i, c;
int sidx, tx, ty; int sidx, tx, ty;
boolean msg_given = TRUE; /* clear message window by default */ boolean msg_given = TRUE; /* clear message window by default */
boolean auto_msg = FALSE;
boolean show_goal_msg = FALSE;
static const char pick_chars[] = ".,;:"; static const char pick_chars[] = ".,;:";
const char *cp; const char *cp;
@@ -82,7 +86,32 @@ const char *goal;
lock_mouse_cursor(TRUE); lock_mouse_cursor(TRUE);
#endif #endif
for (;;) { for (;;) {
if (show_goal_msg) {
pline("Move cursor to %s:", goal);
curs(WIN_MAP, cx, cy);
flush_screen(0);
show_goal_msg = FALSE;
} else if (auto_msg && !msg_given) {
coord cc;
int sym = 0;
char tmpbuf[BUFSZ];
char *firstmatch = NULL;
cc.x = cx;
cc.y = cy;
if (do_screen_description(cc, TRUE, sym, tmpbuf, &firstmatch)) {
/* there may be an encoded glyph */
putmixed(WIN_MESSAGE, 0, tmpbuf);
curs(WIN_MAP, cx, cy);
flush_screen(0);
}
}
c = nh_poskey(&tx, &ty, &sidx); c = nh_poskey(&tx, &ty, &sidx);
if (auto_msg)
msg_given = FALSE;
if (c == '\033') { if (c == '\033') {
cx = cy = -10; cx = cy = -10;
msg_given = TRUE; /* force clear */ msg_given = TRUE; /* force clear */
@@ -142,8 +171,20 @@ const char *goal;
else /* ^R */ else /* ^R */
docrt(); /* redraw */ docrt(); /* redraw */
/* update message window to reflect that we're still targetting */ /* update message window to reflect that we're still targetting */
pline("Move cursor to %s:", goal); show_goal_msg = TRUE;
msg_given = TRUE; msg_given = TRUE;
} else if (c == '#') {
auto_msg = !auto_msg;
pline("Automatic description %sis %s.",
flags.verbose ? "of features under cursor " : "",
auto_msg ? "on" : "off");
if (!auto_msg) show_goal_msg = TRUE;
msg_given = TRUE;
goto nxtc;
} else if (c == '@') {
cx = u.ux;
cy = u.uy;
goto nxtc;
} else { } else {
if (!index(quitchars, c)) { if (!index(quitchars, c)) {
char matching[MAXPCHARS]; char matching[MAXPCHARS];
+226 -201
View File
@@ -437,6 +437,229 @@ bad_data_file: impossible("'data' file in wrong format");
(void) dlb_fclose(fp); (void) dlb_fclose(fp);
} }
int
do_screen_description(cc, looked, sym, out_str, firstmatch)
coord cc;
boolean looked;
int sym;
char *out_str;
const char **firstmatch;
{
boolean need_to_look = FALSE;
int glyph;
char look_buf[BUFSZ], prefix[BUFSZ];
int found = 0; /* count of matching syms found */
int i;
int skipped_venom = 0;
boolean hit_trap;
const char *x_str;
static const char *mon_interior = "the interior of a monster";
struct permonst *pm = NULL;
if (looked) {
int oc, so;
unsigned os;
glyph = glyph_at(cc.x,cc.y);
/* Convert the glyph at the selected position to a symbol. */
so = mapglyph(glyph, &sym, &oc, &os, cc.x, cc.y);
}
if (looked)
Sprintf(prefix, "%s ", encglyph(glyph));
else
Sprintf(prefix, "%c ", sym);
/*
* Check all the possibilities, saving all explanations in a buffer.
* When all have been checked then the string is printed.
*/
/* Check for monsters */
for (i = 0; i < MAXMCLASSES; i++) {
if (sym == ((looked) ?
showsyms[i + SYM_OFF_M] : def_monsyms[i].sym) &&
def_monsyms[i].explain) {
need_to_look = TRUE;
if (!found) {
Sprintf(out_str, "%s%s",
prefix, an(def_monsyms[i].explain));
*firstmatch = def_monsyms[i].explain;
found++;
} else {
found += append_str(out_str, an(def_monsyms[i].explain));
}
}
}
/* handle '@' as a special case if it refers to you and you're
playing a character which isn't normally displayed by that
symbol; firstmatch is assumed to already be set for '@' */
if (((looked) ?
(sym == showsyms[S_HUMAN + SYM_OFF_M] && cc.x == u.ux && cc.y == u.uy) :
(sym == def_monsyms[S_HUMAN].sym && !flags.showrace)) &&
!(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
found += append_str(out_str, "you"); /* tack on "or you" */
/*
* Special case: if identifying from the screen, and we're swallowed,
* and looking at something other than our own symbol, then just say
* "the interior of a monster".
*/
if (u.uswallow && (looked) && is_swallow_sym(sym)) {
if (!found) {
Sprintf(out_str, "%s%s",
prefix, mon_interior);
*firstmatch = mon_interior;
} else {
found += append_str(out_str, mon_interior);
}
need_to_look = TRUE;
}
/* Now check for objects */
for (i = 1; i < MAXOCLASSES; i++) {
if (sym == ((looked) ?
showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
need_to_look = TRUE;
if ((looked) && i == VENOM_CLASS) {
skipped_venom++;
continue;
}
if (!found) {
Sprintf(out_str, "%s%s",
prefix, an(def_oc_syms[i].explain));
*firstmatch = def_oc_syms[i].explain;
found++;
} else {
found += append_str(out_str, an(def_oc_syms[i].explain));
}
}
}
if (sym == DEF_INVISIBLE) {
if (!found) {
Sprintf(out_str, "%s%s",
prefix,
an(invisexplain));
*firstmatch = invisexplain;
found++;
} else {
found += append_str(out_str, an(invisexplain));
}
}
#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
/* Now check for graphics symbols */
for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
x_str = defsyms[i].explanation;
if (sym == ((looked) ?
showsyms[i] : defsyms[i].sym) && *x_str) {
/* avoid "an air", "a water", or "a floor of a room" */
int article = (i == S_room) ? 2 : /* 2=>"the" */
!(strcmp(x_str, "air") == 0 || /* 1=>"an" */
strcmp(x_str, "water") == 0); /* 0=>(none)*/
if (!found) {
if (is_cmap_trap(i)) {
Sprintf(out_str, "%sa trap", prefix);
hit_trap = TRUE;
} else {
Sprintf(out_str, "%s%s",
prefix,
article == 2 ? the(x_str) :
article == 1 ? an(x_str) : x_str);
}
*firstmatch = x_str;
found++;
} else if (!u.uswallow && !(hit_trap && is_cmap_trap(i)) &&
!(found >= 3 && is_cmap_drawbridge(i))) {
found += append_str(out_str,
article == 2 ? the(x_str) :
article == 1 ? an(x_str) : x_str);
if (is_cmap_trap(i)) hit_trap = TRUE;
}
if (i == S_altar || is_cmap_trap(i))
need_to_look = TRUE;
}
}
/* Now check for warning symbols */
for (i = 1; i < WARNCOUNT; i++) {
x_str = def_warnsyms[i].explanation;
if (sym == ((looked) ?
warnsyms[i] : def_warnsyms[i].sym)) {
if (!found) {
Sprintf(out_str, "%s%s",
prefix, def_warnsyms[i].explanation);
*firstmatch = def_warnsyms[i].explanation;
found++;
} else {
found += append_str(out_str, def_warnsyms[i].explanation);
}
/* Kludge: warning trumps boulders on the display.
Reveal the boulder too or player can get confused */
if ((looked) && sobj_at(BOULDER, cc.x, cc.y))
Strcat(out_str, " co-located with a boulder");
break; /* out of for loop*/
}
}
/* if we ignored venom and list turned out to be short, put it back */
if (skipped_venom && found < 2) {
x_str = def_oc_syms[VENOM_CLASS].explain;
if (!found) {
Sprintf(out_str, "%s%s",
prefix, an(x_str));
*firstmatch = x_str;
found++;
} else {
found += append_str(out_str, an(x_str));
}
}
/* handle optional boulder symbol as a special case */
if (iflags.bouldersym && sym == iflags.bouldersym) {
if (!found) {
*firstmatch = "boulder";
Sprintf(out_str, "%s%s",
prefix, an(*firstmatch));
found++;
} else {
found += append_str(out_str, "boulder");
}
}
/*
* If we are looking at the screen, follow multiple possibilities or
* an ambiguous explanation by something more detailed.
*/
if (looked) {
if (found > 1 || need_to_look) {
char monbuf[BUFSZ];
char temp_buf[BUFSZ];
pm = lookat(cc.x, cc.y, look_buf, monbuf);
*firstmatch = look_buf;
if (*(*firstmatch)) {
Sprintf(temp_buf, " (%s)", *firstmatch);
(void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
found = 1; /* we have something to look up */
}
if (monbuf[0]) {
Sprintf(temp_buf, " [seen: %s]", monbuf);
(void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
}
}
}
return found;
}
/* getpos() return values */ /* getpos() return values */
#define LOOK_TRADITIONAL 0 /* '.' -- ask about "more info?" */ #define LOOK_TRADITIONAL 0 /* '.' -- ask about "more info?" */
#define LOOK_QUICK 1 /* ',' -- skip "more info?" */ #define LOOK_QUICK 1 /* ',' -- skip "more info?" */
@@ -453,19 +676,15 @@ do_look(mode, click_cc)
{ {
boolean quick = (mode == 1); /* use cursor && don't search for "more info" */ boolean quick = (mode == 1); /* use cursor && don't search for "more info" */
boolean clicklook = (mode == 2); /* right mouse-click method */ boolean clicklook = (mode == 2); /* right mouse-click method */
char out_str[BUFSZ], look_buf[BUFSZ], prefix[BUFSZ]; char out_str[BUFSZ];
const char *x_str, *firstmatch = 0; const char *firstmatch = 0;
struct permonst *pm = 0; struct permonst *pm = 0;
int glyph; /* glyph at selected position */
int i, ans = 0; int i, ans = 0;
int sym; /* typed symbol or converted glyph */ int sym; /* typed symbol or converted glyph */
int found; /* count of matching syms found */ int found; /* count of matching syms found */
coord cc; /* screen pos of unknown glyph */ coord cc; /* screen pos of unknown glyph */
boolean save_verbose; /* saved value of flags.verbose */ boolean save_verbose; /* saved value of flags.verbose */
boolean from_screen; /* question from the screen */ boolean from_screen; /* question from the screen */
boolean need_to_look; /* need to get explan. from glyph */
boolean hit_trap; /* true if found trap explanation */
int skipped_venom; /* non-zero if we ignored "splash of venom" */
static const char *mon_interior = "the interior of a monster"; static const char *mon_interior = "the interior of a monster";
if (!clicklook) { if (!clicklook) {
@@ -506,9 +725,7 @@ do_look(mode, click_cc)
*/ */
do { do {
/* Reset some variables. */ /* Reset some variables. */
need_to_look = FALSE;
pm = (struct permonst *)0; pm = (struct permonst *)0;
skipped_venom = 0;
found = 0; found = 0;
out_str[0] = '\0'; out_str[0] = '\0';
@@ -529,201 +746,9 @@ do_look(mode, click_cc)
} }
flags.verbose = FALSE; /* only print long question once */ flags.verbose = FALSE; /* only print long question once */
} }
glyph = glyph_at(cc.x,cc.y);
/* Convert the glyph at the selected position to a symbol. */
so = mapglyph(glyph, &sym, &oc, &os, cc.x, cc.y);
} }
if (from_screen || clicklook) found = do_screen_description(cc, (from_screen||clicklook), sym, out_str, &firstmatch);
Sprintf(prefix, "%s ", encglyph(glyph));
else
Sprintf(prefix, "%c ", sym);
/*
* Check all the possibilities, saving all explanations in a buffer.
* When all have been checked then the string is printed.
*/
/* Check for monsters */
for (i = 0; i < MAXMCLASSES; i++) {
if (sym == ((from_screen || clicklook) ?
showsyms[i + SYM_OFF_M] : def_monsyms[i].sym) &&
def_monsyms[i].explain) {
need_to_look = TRUE;
if (!found) {
Sprintf(out_str, "%s%s",
prefix, an(def_monsyms[i].explain));
firstmatch = def_monsyms[i].explain;
found++;
} else {
found += append_str(out_str, an(def_monsyms[i].explain));
}
}
}
/* handle '@' as a special case if it refers to you and you're
playing a character which isn't normally displayed by that
symbol; firstmatch is assumed to already be set for '@' */
if (((from_screen || clicklook) ?
(sym == showsyms[S_HUMAN + SYM_OFF_M] && cc.x == u.ux && cc.y == u.uy) :
(sym == def_monsyms[S_HUMAN].sym && !flags.showrace)) &&
!(Race_if(PM_HUMAN) || Race_if(PM_ELF)) && !Upolyd)
found += append_str(out_str, "you"); /* tack on "or you" */
/*
* Special case: if identifying from the screen, and we're swallowed,
* and looking at something other than our own symbol, then just say
* "the interior of a monster".
*/
if (u.uswallow && (from_screen || clicklook) && is_swallow_sym(sym)) {
if (!found) {
Sprintf(out_str, "%s%s",
prefix, mon_interior);
firstmatch = mon_interior;
} else {
found += append_str(out_str, mon_interior);
}
need_to_look = TRUE;
}
/* Now check for objects */
for (i = 1; i < MAXOCLASSES; i++) {
if (sym == ((from_screen || clicklook) ?
showsyms[i + SYM_OFF_O] : def_oc_syms[i].sym)) {
need_to_look = TRUE;
if ((from_screen || clicklook) && i == VENOM_CLASS) {
skipped_venom++;
continue;
}
if (!found) {
Sprintf(out_str, "%s%s",
prefix, an(def_oc_syms[i].explain));
firstmatch = def_oc_syms[i].explain;
found++;
} else {
found += append_str(out_str, an(def_oc_syms[i].explain));
}
}
}
if (sym == DEF_INVISIBLE) {
if (!found) {
Sprintf(out_str, "%s%s",
prefix,
an(invisexplain));
firstmatch = invisexplain;
found++;
} else {
found += append_str(out_str, an(invisexplain));
}
}
#define is_cmap_trap(i) ((i) >= S_arrow_trap && (i) <= S_polymorph_trap)
#define is_cmap_drawbridge(i) ((i) >= S_vodbridge && (i) <= S_hcdbridge)
/* Now check for graphics symbols */
for (hit_trap = FALSE, i = 0; i < MAXPCHARS; i++) {
x_str = defsyms[i].explanation;
if (sym == ((from_screen || clicklook) ?
showsyms[i] : defsyms[i].sym) && *x_str) {
/* avoid "an air", "a water", or "a floor of a room" */
int article = (i == S_room) ? 2 : /* 2=>"the" */
!(strcmp(x_str, "air") == 0 || /* 1=>"an" */
strcmp(x_str, "water") == 0); /* 0=>(none)*/
if (!found) {
if (is_cmap_trap(i)) {
Sprintf(out_str, "%sa trap", prefix);
hit_trap = TRUE;
} else {
Sprintf(out_str, "%s%s",
prefix,
article == 2 ? the(x_str) :
article == 1 ? an(x_str) : x_str);
}
firstmatch = x_str;
found++;
} else if (!u.uswallow && !(hit_trap && is_cmap_trap(i)) &&
!(found >= 3 && is_cmap_drawbridge(i))) {
found += append_str(out_str,
article == 2 ? the(x_str) :
article == 1 ? an(x_str) : x_str);
if (is_cmap_trap(i)) hit_trap = TRUE;
}
if (i == S_altar || is_cmap_trap(i))
need_to_look = TRUE;
}
}
/* Now check for warning symbols */
for (i = 1; i < WARNCOUNT; i++) {
x_str = def_warnsyms[i].explanation;
if (sym == ((from_screen || clicklook) ?
warnsyms[i] : def_warnsyms[i].sym)) {
if (!found) {
Sprintf(out_str, "%s%s",
prefix, def_warnsyms[i].explanation);
firstmatch = def_warnsyms[i].explanation;
found++;
} else {
found += append_str(out_str, def_warnsyms[i].explanation);
}
/* Kludge: warning trumps boulders on the display.
Reveal the boulder too or player can get confused */
if ((from_screen || clicklook) && sobj_at(BOULDER, cc.x, cc.y))
Strcat(out_str, " co-located with a boulder");
break; /* out of for loop*/
}
}
/* if we ignored venom and list turned out to be short, put it back */
if (skipped_venom && found < 2) {
x_str = def_oc_syms[VENOM_CLASS].explain;
if (!found) {
Sprintf(out_str, "%s%s",
prefix, an(x_str));
firstmatch = x_str;
found++;
} else {
found += append_str(out_str, an(x_str));
}
}
/* handle optional boulder symbol as a special case */
if (iflags.bouldersym && sym == iflags.bouldersym) {
if (!found) {
firstmatch = "boulder";
Sprintf(out_str, "%s%s",
prefix, an(firstmatch));
found++;
} else {
found += append_str(out_str, "boulder");
}
}
/*
* If we are looking at the screen, follow multiple possibilities or
* an ambiguous explanation by something more detailed.
*/
if (from_screen || clicklook) {
if (found > 1 || need_to_look) {
char monbuf[BUFSZ];
char temp_buf[BUFSZ];
pm = lookat(cc.x, cc.y, look_buf, monbuf);
firstmatch = look_buf;
if (*firstmatch) {
Sprintf(temp_buf, " (%s)", firstmatch);
(void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
found = 1; /* we have something to look up */
}
if (monbuf[0]) {
Sprintf(temp_buf, " [seen: %s]", monbuf);
(void)strncat(out_str, temp_buf, BUFSZ-strlen(out_str)-1);
}
}
}
/* Finally, print out our explanation. */ /* Finally, print out our explanation. */
if (found) { if (found) {