Allow toggling menu for any travel target list

This commit is contained in:
Pasi Kallinen
2016-10-13 20:16:21 +03:00
parent 4af4fc1143
commit abb4f0fab2
7 changed files with 150 additions and 65 deletions
+15 -3
View File
@@ -2910,6 +2910,14 @@ The
option is also used with option is also used with
the `/m', `/M', `/o', and `/O' sub-commands of `/', the `/m', `/M', `/o', and `/O' sub-commands of `/',
where the `none' setting is overridden with `map'. where the `none' setting is overridden with `map'.
.lp whatis_inview
When getting a location on the map, and using the keys to cycle through
next and previous targets, limit the possible targets to those in view.
(default off)
.lp whatis_menu
When getting a location on the map, and using a key to cycle through
next and previous targets, use a menu instead to pick a target.
(default off)
.lp windowtype .lp windowtype
Select which windowing system to use, such as ``tty'' or ``X11'' Select which windowing system to use, such as ``tty'' or ``X11''
(default depends on version). (default depends on version).
@@ -3201,6 +3209,10 @@ When asked for a direction, the key to target yourself. Default is '.'.
When asked for a direction, the key to target yourself. Default is 's'. When asked for a direction, the key to target yourself. Default is 's'.
.lp getpos.autodescribe .lp getpos.autodescribe
When asked for a location, the key to toggle autodescribe. Default is '#'. When asked for a location, the key to toggle autodescribe. Default is '#'.
.lp getpos.all.next
When asked for a location, the key to go to next closest interesting thing. Default is 'a'.
.lp getpos.all.prev
When asked for a location, the key to go to previous closest interesting thing. Default is 'A'.
.lp getpos.door.next .lp getpos.door.next
When asked for a location, the key to go to next closest door or doorway. Default is 'd'. When asked for a location, the key to go to next closest door or doorway. Default is 'd'.
.lp getpos.door.prev .lp getpos.door.prev
@@ -3216,9 +3228,9 @@ When asked for a location, the key to go to next closest object. Default is 'o'.
.lp getpos.obj.prev .lp getpos.obj.prev
When asked for a location, the key to go to previous closest object. Default is 'O'. When asked for a location, the key to go to previous closest object. Default is 'O'.
.lp getpos.menu .lp getpos.menu
When asked for a location, show a menu of all interesting targets. Default is 'A'. When asked for a location, and using one of the next or previous keys to cycle through targets, toggle showing a menu instead. Default is '!'.
.lp getpos.menu.cansee .lp getpos.inview
When asked for a location, show a menu of interesting targets in view. Default is 'a'. When asked for a location, and using one of the next or previous keys to cycle through targets, toggle limiting possible targets to those in view only. Default is '"'.
.lp getpos.pick .lp getpos.pick
When asked for a location, the key to choose the location, and possibly ask for more info. Default is '.'. When asked for a location, the key to choose the location, and possibly ask for more info. Default is '.'.
.lp getpos.pick.once .lp getpos.pick.once
+18 -3
View File
@@ -3543,6 +3543,15 @@ the `{\tt /m}', `{\tt /M}', `{\tt /o}', and `{\tt /O}' sub-commands
of `{\tt /}', of `{\tt /}',
where the `{\it none\/}' setting is overridden with `{\it map}'. where the `{\it none\/}' setting is overridden with `{\it map}'.
%.lp %.lp
\item[\ib{whatis\verb+_+inview}]
When getting a location on the map, and using the keys to cycle through
next and previous targets, limit the possible targets to those in view.
(default off)
\item[\ib{whatis\verb+_+menu}]
When getting a location on the map, and using a key to cycle through
next and previous targets, use a menu instead to pick a target.
(default off)
%.lp
\item[\ib{windowtype}] \item[\ib{windowtype}]
Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}'' Select which windowing system to use, such as ``{\tt tty}'' or ``{\tt X11}''
(default depends on version). (default depends on version).
@@ -3917,6 +3926,12 @@ When asked for a direction, the key to target yourself. Default is ``{\tt s}''.
\item{\bb{getpos.autodescribe}} \item{\bb{getpos.autodescribe}}
When asked for a location, the key to toggle {\it autodescribe\/}. Default is ``{\tt \#}''. When asked for a location, the key to toggle {\it autodescribe\/}. Default is ``{\tt \#}''.
%.lp %.lp
\item{\bb{getpos.all.next}}
When asked for a location, the key to go to next closest interesting thing. Default is ``{\tt a}''.
%.lp
\item{\bb{getpos.all.prev}}
When asked for a location, the key to go to previous closest interesting thing. Default is ``{\tt A}''.
%.lp
\item{\bb{getpos.door.next}} \item{\bb{getpos.door.next}}
When asked for a location, the key to go to next closest door or doorway. Default is ``{\tt d}''. When asked for a location, the key to go to next closest door or doorway. Default is ``{\tt d}''.
%.lp %.lp
@@ -3939,10 +3954,10 @@ When asked for a location, the key to go to next closest object. Default is ``{\
When asked for a location, the key to go to previous closest object. Default is ``{\tt O}''. When asked for a location, the key to go to previous closest object. Default is ``{\tt O}''.
%.lp %.lp
\item{\bb{getpos.menu}} \item{\bb{getpos.menu}}
When asked for a location, show a menu of all interesting targets. Default is '{\tt A}'. When asked for a location, and using one of the next or previous keys to cycle through targets, toggle showing a menu instead. Default is '{\tt !}'.
%.lp %.lp
\item{\bb{getpos.menu.cansee}} \item{\bb{getpos.inview}}
When asked for a location, show a menu of interesting targets in view. Default is '{\tt a}'. When asked for a location, and using one of the next or previous keys to cycle through targets, toggle limiting possible targets to those in view only. Default is '{\tt "}'.
%.lp %.lp
\item{\bb{getpos.pick}} \item{\bb{getpos.pick}}
When asked for a location, the key to choose the location, and possibly ask for more info. Default is ``{\tt .}''. When asked for a location, the key to choose the location, and possibly ask for more info. Default is ``{\tt .}''.
+1 -1
View File
@@ -379,7 +379,7 @@ E void NDECL(heal_legs);
/* ### do_name.c ### */ /* ### do_name.c ### */
E char *FDECL(coord_desc, (int, int, char *, CHAR_P)); E char *FDECL(coord_desc, (int, int, char *, CHAR_P));
E boolean FDECL(getpos_menu, (coord *, BOOLEAN_P)); E boolean FDECL(getpos_menu, (coord *, BOOLEAN_P, int));
E int FDECL(getpos, (coord *, BOOLEAN_P, const char *)); E int FDECL(getpos, (coord *, BOOLEAN_P, const char *));
E void FDECL(getpos_sethilite, (void (*f)(int))); E void FDECL(getpos_sethilite, (void (*f)(int)));
E void FDECL(new_mname, (struct monst *, int)); E void FDECL(new_mname, (struct monst *, int));
+15 -1
View File
@@ -194,6 +194,8 @@ struct instance_flags {
#define TER_MON 0x08 #define TER_MON 0x08
#define TER_DETECT 0x10 /* detect_foo magic rather than #terrain */ #define TER_DETECT 0x10 /* detect_foo magic rather than #terrain */
boolean getloc_travelmode; boolean getloc_travelmode;
boolean getloc_limitview;
boolean getloc_usemenu;
coord travelcc; /* coordinates for travel_cache */ coord travelcc; /* coordinates for travel_cache */
boolean window_inited; /* true if init_nhwindows() completed */ boolean window_inited; /* true if init_nhwindows() completed */
boolean vision_inited; /* true if vision is ready */ boolean vision_inited; /* true if vision is ready */
@@ -471,13 +473,25 @@ enum nh_keyfunc {
NHKF_GETPOS_DOOR_PREV, NHKF_GETPOS_DOOR_PREV,
NHKF_GETPOS_UNEX_NEXT, NHKF_GETPOS_UNEX_NEXT,
NHKF_GETPOS_UNEX_PREV, NHKF_GETPOS_UNEX_PREV,
NHKF_GETPOS_INTERESTING_NEXT,
NHKF_GETPOS_INTERESTING_PREV,
NHKF_GETPOS_HELP, NHKF_GETPOS_HELP,
NHKF_GETPOS_MENU, NHKF_GETPOS_MENU,
NHKF_GETPOS_MENU_FOV, NHKF_GETPOS_LIMITVIEW,
NUM_NHKF NUM_NHKF
}; };
enum gloctypes {
GLOC_MONS = 0,
GLOC_OBJS,
GLOC_DOOR,
GLOC_EXPLORE,
GLOC_INTERESTING,
NUM_GLOCS
};
/* commands[] is used to directly access cmdlist[] instead of looping /* commands[] is used to directly access cmdlist[] instead of looping
through it to find the entry for a given input character; through it to find the entry for a given input character;
move_X is the character used for moving one step in direction X; move_X is the character used for moving one step in direction X;
+5 -3
View File
@@ -3544,9 +3544,11 @@ struct {
{ NHKF_GETPOS_DOOR_PREV, 'D', "getpos.door.prev" }, { NHKF_GETPOS_DOOR_PREV, 'D', "getpos.door.prev" },
{ NHKF_GETPOS_UNEX_NEXT, 'x', "getpos.unexplored.next" }, { NHKF_GETPOS_UNEX_NEXT, 'x', "getpos.unexplored.next" },
{ NHKF_GETPOS_UNEX_PREV, 'X', "getpos.unexplored.prev" }, { NHKF_GETPOS_UNEX_PREV, 'X', "getpos.unexplored.prev" },
{ NHKF_GETPOS_INTERESTING_NEXT, 'a', "getpos.all.next" },
{ NHKF_GETPOS_INTERESTING_PREV, 'A', "getpos.all.prev" },
{ NHKF_GETPOS_HELP, '?', "getpos.help" }, { NHKF_GETPOS_HELP, '?', "getpos.help" },
{ NHKF_GETPOS_MENU, 'A', "getpos.menu" }, { NHKF_GETPOS_LIMITVIEW, '"', "getpos.inview" },
{ NHKF_GETPOS_MENU_FOV, 'a', "getpos.menu.cansee" } { NHKF_GETPOS_MENU, '!', "getpos.menu" }
}; };
boolean boolean
@@ -4727,7 +4729,7 @@ dotravel(VOID_ARGS)
} }
iflags.getloc_travelmode = TRUE; iflags.getloc_travelmode = TRUE;
if (iflags.menu_requested) { if (iflags.menu_requested) {
if (!getpos_menu(&cc, TRUE)) { if (!getpos_menu(&cc, TRUE, GLOC_INTERESTING)) {
iflags.getloc_travelmode = FALSE; iflags.getloc_travelmode = FALSE;
return 0; return 0;
} }
+90 -50
View File
@@ -44,6 +44,32 @@ void FDECL((*f), (int));
getpos_hilitefunc = f; getpos_hilitefunc = f;
} }
const char *const gloc_descr[NUM_GLOCS][4] = {
{ "any monsters", "monster", "next monster", "monsters" },
{ "any items", "item", "next object", "objects" },
{ "any doors", "door", "next door or doorway", "doors or doorways" },
{ "any unexplored areas", "unexplored area", "unexplored location", "unexplored locations" },
{ "anything interesting", "interesting thing", "anything interesting", "anything interesting" }
};
void
getpos_help_keyxhelp(tmpwin, k1,k2,gloc)
winid tmpwin;
const char *k1;
const char *k2;
int gloc;
{
char sbuf[BUFSZ];
Sprintf(sbuf, "Use '%s' or '%s' to %s%s%s.",
k1, k2,
iflags.getloc_usemenu ? "get a menu of "
: "move the cursor to ",
gloc_descr[gloc][2 + iflags.getloc_usemenu],
iflags.getloc_limitview ? " in view" : "");
putstr(tmpwin, 0, sbuf);
}
/* the response for '?' help request in getpos() */ /* the response for '?' help request in getpos() */
STATIC_OVL void STATIC_OVL void
getpos_help(force, goal) getpos_help(force, goal)
@@ -63,37 +89,39 @@ const char *goal;
visctrl(Cmd.spkeys[NHKF_GETPOS_SELF])); visctrl(Cmd.spkeys[NHKF_GETPOS_SELF]));
putstr(tmpwin, 0, sbuf); putstr(tmpwin, 0, sbuf);
if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) { if (!iflags.terrainmode || (iflags.terrainmode & TER_MON) != 0) {
Sprintf(sbuf, "Use '%s' or '%s' to move the cursor to next monster.", getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]), visctrl(Cmd.spkeys[NHKF_GETPOS_MON_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV])); visctrl(Cmd.spkeys[NHKF_GETPOS_MON_PREV]),
putstr(tmpwin, 0, sbuf); GLOC_MONS);
} }
if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) { if (!iflags.terrainmode || (iflags.terrainmode & TER_OBJ) != 0) {
Sprintf(sbuf, "Use '%s' or '%s' to move the cursor to next object.", getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]), visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV])); visctrl(Cmd.spkeys[NHKF_GETPOS_OBJ_PREV]),
putstr(tmpwin, 0, sbuf); GLOC_OBJS);
} }
if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) { if (!iflags.terrainmode || (iflags.terrainmode & TER_MAP) != 0) {
/* both of these are primarily useful when choosing a travel /* these are primarily useful when choosing a travel
destination for the '_' command */ destination for the '_' command */
Sprintf(sbuf, getpos_help_keyxhelp(tmpwin,
"Use '%s' or '%s' to move the cursor to next door or doorway.",
visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]), visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV])); visctrl(Cmd.spkeys[NHKF_GETPOS_DOOR_PREV]),
putstr(tmpwin, 0, sbuf); GLOC_DOOR);
Sprintf(sbuf, getpos_help_keyxhelp(tmpwin,
"Use '%s' or '%s' to move the cursor to unexplored location.",
visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]), visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV])); visctrl(Cmd.spkeys[NHKF_GETPOS_UNEX_PREV]),
putstr(tmpwin, 0, sbuf); GLOC_EXPLORE);
getpos_help_keyxhelp(tmpwin,
visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_NEXT]),
visctrl(Cmd.spkeys[NHKF_GETPOS_INTERESTING_PREV]),
GLOC_INTERESTING);
} }
Sprintf(sbuf, "Use '%s' for a menu of interesting targets in view.", Sprintf(sbuf, "Use '%s' to toggle menu listing for possible targets.",
visctrl(Cmd.spkeys[NHKF_GETPOS_MENU_FOV]));
putstr(tmpwin, 0, sbuf);
Sprintf(sbuf, "Use '%s' for a menu of all interesting targets.",
visctrl(Cmd.spkeys[NHKF_GETPOS_MENU])); visctrl(Cmd.spkeys[NHKF_GETPOS_MENU]));
putstr(tmpwin, 0, sbuf); putstr(tmpwin, 0, sbuf);
Sprintf(sbuf, "Use '%s' to toggle limiting possible targets to in view only.",
visctrl(Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]));
putstr(tmpwin, 0, sbuf);
if (!iflags.terrainmode) { if (!iflags.terrainmode) {
char kbuf[BUFSZ]; char kbuf[BUFSZ];
if (getpos_hilitefunc) { if (getpos_hilitefunc) {
@@ -174,19 +202,6 @@ const void *b;
return dist_1 - dist_2; return dist_1 - dist_2;
} }
enum gloctypes {
GLOC_MONS = 0,
GLOC_OBJS,
GLOC_DOOR,
GLOC_EXPLORE,
NUM_GLOCS,
GLOC_INTERESTING,
GLOC_INTERESTING_FOV
};
#define IS_UNEXPLORED_LOC(x,y) \ #define IS_UNEXPLORED_LOC(x,y) \
(isok((x), (y)) \ (isok((x), (y)) \
&& glyph_is_cmap(levl[(x)][(y)].glyph) \ && glyph_is_cmap(levl[(x)][(y)].glyph) \
@@ -202,6 +217,9 @@ int x,y, gloc;
*/ */
int glyph = glyph_at(x, y); int glyph = glyph_at(x, y);
if (iflags.getloc_limitview && !cansee(x,y))
return FALSE;
switch (gloc) { switch (gloc) {
default: default:
case GLOC_MONS: case GLOC_MONS:
@@ -231,9 +249,6 @@ int x,y, gloc;
|| IS_UNEXPLORED_LOC(x - 1, y) || IS_UNEXPLORED_LOC(x - 1, y)
|| IS_UNEXPLORED_LOC(x, y + 1) || IS_UNEXPLORED_LOC(x, y + 1)
|| IS_UNEXPLORED_LOC(x, y - 1))); || IS_UNEXPLORED_LOC(x, y - 1)));
case GLOC_INTERESTING_FOV:
if (!cansee(x,y))
return FALSE;
case GLOC_INTERESTING: case GLOC_INTERESTING:
return gather_locs_interesting(x,y, GLOC_DOOR) return gather_locs_interesting(x,y, GLOC_DOOR)
|| !(glyph_is_cmap(glyph) || !(glyph_is_cmap(glyph)
@@ -400,9 +415,10 @@ int cx, cy;
} }
boolean boolean
getpos_menu(ccp, fovonly) getpos_menu(ccp, fovonly, gloc)
coord *ccp; coord *ccp;
boolean fovonly; boolean fovonly;
int gloc;
{ {
coord *garr = DUMMY; coord *garr = DUMMY;
int gcount = 0; int gcount = 0;
@@ -412,11 +428,12 @@ boolean fovonly;
menu_item *picks = (menu_item *) 0; menu_item *picks = (menu_item *) 0;
char tmpbuf[BUFSZ]; char tmpbuf[BUFSZ];
gather_locs(&garr, &gcount, gather_locs(&garr, &gcount, gloc);
fovonly ? GLOC_INTERESTING_FOV : GLOC_INTERESTING);
if (gcount < 2) { /* gcount always includes the hero */ if (gcount < 2) { /* gcount always includes the hero */
free((genericptr_t) garr); free((genericptr_t) garr);
You("cannot %s anything interesting.", fovonly ? "see" : "detect"); You("cannot %s %s.",
fovonly ? "see" : "detect", gloc_descr[gloc][0]);
return FALSE; return FALSE;
} }
@@ -424,7 +441,8 @@ boolean fovonly;
start_menu(tmpwin); start_menu(tmpwin);
any = zeroany; any = zeroany;
for (i = 0; i < gcount; i++) { /* gather_locs returns array[0] == you. skip it. */
for (i = 1; i < gcount; i++) {
char fullbuf[BUFSZ]; char fullbuf[BUFSZ];
coord tmpcc; coord tmpcc;
const char *firstmatch = "unknown"; const char *firstmatch = "unknown";
@@ -440,8 +458,8 @@ boolean fovonly;
} }
} }
Sprintf(tmpbuf, "Pick a target%s%s", Sprintf(tmpbuf, "Pick a target %s%s%s",
fovonly ? " in view" : "", gloc_descr[gloc][1], fovonly ? " in view" : "",
iflags.getloc_travelmode ? " for travel" : ""); iflags.getloc_travelmode ? " for travel" : "");
end_menu(tmpwin, tmpbuf); end_menu(tmpwin, tmpbuf);
pick_cnt = select_menu(tmpwin, PICK_ONE, &picks); pick_cnt = select_menu(tmpwin, PICK_ONE, &picks);
@@ -478,10 +496,12 @@ const char *goal;
NHKF_GETPOS_DOOR_NEXT, NHKF_GETPOS_DOOR_NEXT,
NHKF_GETPOS_DOOR_PREV, NHKF_GETPOS_DOOR_PREV,
NHKF_GETPOS_UNEX_NEXT, NHKF_GETPOS_UNEX_NEXT,
NHKF_GETPOS_UNEX_PREV NHKF_GETPOS_UNEX_PREV,
NHKF_GETPOS_INTERESTING_NEXT,
NHKF_GETPOS_INTERESTING_PREV
}; };
char pick_chars[6]; char pick_chars[6];
char mMoOdDxX[9]; char mMoOdDxX[11];
int result = 0; int result = 0;
int cx, cy, i, c; int cx, cy, i, c;
int sidx, tx, ty; int sidx, tx, ty;
@@ -618,13 +638,24 @@ const char *goal;
show_goal_msg = TRUE; show_goal_msg = TRUE;
msg_given = TRUE; msg_given = TRUE;
goto nxtc; goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_MENU] } else if (c == Cmd.spkeys[NHKF_GETPOS_LIMITVIEW]) {
|| c == Cmd.spkeys[NHKF_GETPOS_MENU_FOV]) { iflags.getloc_limitview = !iflags.getloc_limitview;
coord tmpcrd; for (i = 0; i < NUM_GLOCS; i++) {
if (getpos_menu(&tmpcrd, (c == Cmd.spkeys[NHKF_GETPOS_MENU_FOV]))) { if (garr[i]) {
cx = tmpcrd.x; free((genericptr_t) garr[i]);
cy = tmpcrd.y; garr[i] = NULL;
} }
gidx[i] = gcount[i] = 0;
}
pline("%s possible targets to those in sight only.",
iflags.getloc_limitview ? "Limiting" : "Not limiting");
msg_given = TRUE;
goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_MENU]) {
iflags.getloc_usemenu = !iflags.getloc_usemenu;
pline("%s a menu to show possible targets.",
iflags.getloc_usemenu ? "Using" : "Not using");
msg_given = TRUE;
goto nxtc; goto nxtc;
} else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) { } else if (c == Cmd.spkeys[NHKF_GETPOS_SELF]) {
/* reset 'm&M', 'o&O', &c; otherwise, there's no way for player /* reset 'm&M', 'o&O', &c; otherwise, there's no way for player
@@ -639,6 +670,15 @@ const char *goal;
int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */ int gtmp = (int) (cp - mMoOdDxX), /* 0..7 */
gloc = gtmp >> 1; /* 0..3 */ gloc = gtmp >> 1; /* 0..3 */
if (iflags.getloc_usemenu) {
coord tmpcrd;
if (getpos_menu(&tmpcrd, iflags.getloc_limitview, gloc)) {
cx = tmpcrd.x;
cy = tmpcrd.y;
}
goto nxtc;
}
if (!garr[gloc]) { if (!garr[gloc]) {
gather_locs(&garr[gloc], &gcount[gloc], gloc); gather_locs(&garr[gloc], &gcount[gloc], gloc);
gidx[gloc] = 0; /* garr[][0] is hero's spot */ gidx[gloc] = 0; /* garr[][0] is hero's spot */
+2
View File
@@ -230,6 +230,8 @@ static struct Bool_Opt {
#else #else
{ "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE }, { "vt_tiledata", (boolean *) 0, FALSE, SET_IN_FILE },
#endif #endif
{ "whatis_menu", &iflags.getloc_usemenu, FALSE, SET_IN_GAME },
{ "whatis_inview", &iflags.getloc_limitview, FALSE, SET_IN_GAME },
{ "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME }, { "wizweight", &iflags.wizweight, FALSE, SET_IN_WIZGAME },
{ "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME }, { "wraptext", &iflags.wc2_wraptext, FALSE, SET_IN_GAME },
#ifdef ZEROCOMP #ifdef ZEROCOMP