示例#1
0
/* display a selection menu for tilesets */
static void
select_tileset_value(union nh_optvalue *value, struct nh_option_desc *option)
{
    struct nh_menulist menu;
    int i;

    int tc;
    struct tileset_description *tilesets = get_tileset_descriptions(&tc);
    struct tileset_description tilesets_copy[tc];
    memcpy(tilesets_copy, tilesets, sizeof tilesets_copy);
    free(tilesets);

    init_menulist(&menu);

    add_menu_txt(&menu, option->helptxt, MI_TEXT);
    add_menu_txt(&menu, "", MI_TEXT);

    for (i = 0; i < tc; i++)
        add_menu_item(&menu, i + 1, tilesets_copy[i].desc, 0, 0);

    int pick_list[1];
    curses_display_menu(&menu, option->name, PICK_ONE, PLHINT_RIGHT, pick_list,
                        curses_menu_callback);

    const char *newname = option->value.s;
    if (pick_list[0] != CURSES_MENU_CANCELLED)
        newname = tilesets_copy[pick_list[0] - 1].basename;

    value->s = malloc(strlen(newname) + 1);
    strcpy(value->s, newname);
}
示例#2
0
/* display a selection menu for enum options */
static void
select_enum_value(union nh_optvalue *value, struct nh_option_desc *option)
{
    struct nh_menulist menu;
    int i, selectidx;

    init_menulist(&menu);

    add_menu_txt(&menu, option->helptxt, MI_TEXT);
    add_menu_txt(&menu, "", MI_TEXT);

    for (i = 0; i < option->e.numchoices; i++) {
        char capbuf[QBUFSZ];
        const char *cap;

        if (option->value.e == option->e.choices[i].id) {
            snprintf(capbuf, QBUFSZ, "%s (set)", option->e.choices[i].caption);
            cap = capbuf;
        } else {
            cap = option->e.choices[i].caption;
        }
        /* don't use the choice ids directly, 0 is a valid value for those */
        add_menu_item(&menu, i + 1, cap, 0, 0);
    }

    int pick_list[1];
    curses_display_menu(&menu, option->name, PICK_ONE, PLHINT_RIGHT, pick_list,
                        curses_menu_callback);

    value->e = option->value.e; /* in case of ESC */
    if (pick_list[0] != CURSES_MENU_CANCELLED) {
        selectidx = pick_list[0] - 1;
        value->e = option->e.choices[selectidx].id;
    }
}
示例#3
0
/* add a list of options to the given selection menu */
static int
menu_add_options(struct nh_menulist *menu, int listid,
                 struct nh_option_desc *options, enum nh_optbirth birth,
                 nh_bool read_only)
{
    int i, id;
    char optbuf[256];

    for (i = 0; options[i].name; i++) {
        id = (listid << 10) | i;
        if (options[i].birth_option != birth)
            continue;

        print_option_string(&options[i], optbuf);
        if (read_only)
            add_menu_txt(menu, optbuf, MI_TEXT);
        else
            add_menu_item(menu, id, optbuf, 0, 0);
    }

    /* add an empty line */
    add_menu_txt(menu, "", MI_TEXT);

    return i;
}
示例#4
0
void
doprev_message(void)
{
    struct nh_menuitem *items;
    char buf[MSGLEN + 1];
    int icount, size, i;

    icount = 0;
    size = 10;
    items = malloc(size * sizeof (struct nh_menuitem));

    for (i = 0; i < histsize; i++) {
        int pos = histpos + i + 1;

        if (pos >= histsize)    /* wrap around eventually */
            pos -= histsize;

        if (!msghistory[pos].turn)
            continue;

        snprintf(buf, MSGLEN + 1, "T:%d\t%s", msghistory[pos].turn,
                 msghistory[pos].msg);
        add_menu_txt(items, size, icount, buf, MI_TEXT);
    }

    curses_display_menu(items, icount, "Message history:", PICK_NONE,
                        PLHINT_ANYWHERE, NULL);
    free(items);
}
示例#5
0
/* display the option dialog */
void display_options(nh_bool change_birth_opt)
{
    struct nh_menuitem *items;
    int icount, size;
    struct nh_option_desc *nhoptions = nh_get_options(GAME_OPTIONS);
    struct nh_option_desc *birthoptions = NULL;
    int n;
    
    size = 10;
    items = malloc(sizeof(struct nh_menuitem) * size);
    
    do {
	icount = 0;
	if (!change_birth_opt) {
	    birthoptions = nh_get_options(ACTIVE_BIRTH_OPTIONS);
	    /* add general game options */
	    add_menu_txt(items, size, icount, "游戏设置:", MI_HEADING);
	    menu_add_options(&items, &size, &icount, GAME_OPTS, nhoptions,
				FALSE);
	    
	    /* add or display birth options */
	    add_menu_txt(items, size, icount, "本次游戏人物设置:",
			    MI_HEADING);
	    menu_add_options(&items, &size, &icount, ACT_BIRTH_OPTS,
				birthoptions, TRUE);
	} else {
	    birthoptions = nh_get_options(CURRENT_BIRTH_OPTIONS);
	    /* add or display birth options */
	    add_menu_txt(items, size, icount, "创建人物设置:", MI_HEADING);
	    menu_add_options(&items, &size, &icount, CUR_BIRTH_OPTS,
				birthoptions, FALSE);
	    
	    add_menu_txt(items, size, icount, "游戏设置:", MI_HEADING);
	    menu_add_options(&items, &size, &icount, GAME_OPTS, nhoptions, FALSE);
	}
	
	/* add UI specific options */
	add_menu_txt(items, size, icount, "界面设置:", MI_HEADING);
	menu_add_options(&items, &size, &icount, UI_OPTS, curses_options, FALSE);
	
	n = curses_display_menu_core(items, icount, "选择哪个设置?", PICK_ONE,
				     NULL, 0, 0, -1, -1, get_option_value, FALSE);
    } while (n > 0);
    free(items);
    
    write_config();
}
示例#6
0
/* add a list of options to the given selection menu */
static int menu_add_options(struct nh_menuitem **items, int *size, int *icount,
	    int listid, struct nh_option_desc *options, nh_bool read_only)
{
    int i, id;
    char optbuf[256];
    
    for (i = 0; options[i].name; i++) {
	id = (listid << 10) | i;
	print_option_string(&options[i], optbuf);
	if (read_only)
	    add_menu_txt(*items, *size, *icount, optbuf, MI_TEXT);
	else
	    add_menu_item(*items, *size, *icount, id, optbuf, 0, 0);
    }
    
    /* add an empty line */
    add_menu_txt(*items, *size, *icount, "", MI_TEXT);
    
    return i;
}
示例#7
0
/* display a selecton menu for boolean options */
static void
select_boolean_value(union nh_optvalue *value, struct nh_option_desc *option)
{
    struct nh_menulist menu;
    int pick_list[1];

    init_menulist(&menu);

    add_menu_txt(&menu, option->helptxt, MI_TEXT);
    add_menu_txt(&menu, "", MI_TEXT);
    add_menu_item(&menu, 1, option->value.b ? "true (set)" : "true", 't', 0);
    add_menu_item(&menu, 2, option->value.b ? "false" : "false (set)", 'f', 0);

    curses_display_menu(&menu, option->name, PICK_ONE, PLHINT_RIGHT,
                        pick_list, curses_menu_callback);

    value->b = option->value.b; /* in case of ESC */
    if (pick_list[0] != CURSES_MENU_CANCELLED)
        value->b = pick_list[0] == 1;
}
示例#8
0
/* display a selecton menu for boolean options */
static void select_boolean_value(union nh_optvalue *value, struct nh_option_desc *option)
{
    struct nh_menuitem *items;
    int icount, size;
    int n, pick_list[2];

    icount = 0; size = 4;
    items = malloc(sizeof(struct nh_menuitem) * size);

    add_menu_txt(items, size, icount, option->helptxt, MI_TEXT);
    add_menu_txt(items, size, icount, "", MI_TEXT);
    add_menu_item(items, size, icount, 1,
		  option->value.b ? "是(已设)" : "是", 't', 0);
    add_menu_item(items, size, icount, 2,
		  option->value.b ? "否" : "否(已设)", 'f', 0);

    n = curses_display_menu(items, icount, option->name, PICK_ONE, pick_list);
    free(items);

    value->b = option->value.b; /* in case of ESC */
    if (n == 1)
	value->b = pick_list[0] == 1;
}
示例#9
0
/* display a selection menu for enum options */
static void select_enum_value(union nh_optvalue *value, struct nh_option_desc *option)
{
    struct nh_menuitem *items;
    int icount, size;
    int i, n, selectidx, *pick_list;

    icount = 0; size = 10;
    items = malloc(sizeof(struct nh_menuitem) * size);

    add_menu_txt(items, size, icount, option->helptxt, MI_TEXT);
    add_menu_txt(items, size, icount, "", MI_TEXT);

    for (i = 0; i < option->e.numchoices; i++) {
	char capbuf[QBUFSZ];
	char *cap;
	if (option->value.e == option->e.choices[i].id) {
	    snprintf(capbuf, QBUFSZ, "%s(已设)", option->e.choices[i].caption);
	    cap = capbuf;
	} else {
	    cap = option->e.choices[i].caption;
	}
	/* don't use the choice ids directly, 0 is a valid value for those */
	add_menu_item(items, size, icount, i+1, cap, 0, 0);
    }

    pick_list = malloc(sizeof(int) * icount);
    n = curses_display_menu(items, icount, option->name, PICK_ONE, pick_list);
    free(items);

    value->e = option->value.e; /* in case of ESC */
    if (n == 1) {
	selectidx = pick_list[0] - 1;
	value->e = option->e.choices[selectidx].id;
    }
    free(pick_list);
}
示例#10
0
/* display the option dialog */
void
display_options(nh_bool change_birth_opt)
{
    struct nh_menulist menu;
    struct nh_option_desc *options;
    int selected[1];

    do {
        init_menulist(&menu);
        options = curses_get_nh_opts();

        if (!change_birth_opt) {
            /* add general game options */
            add_menu_txt(&menu, "Game options:", MI_HEADING);
            menu_add_options(&menu, GAME_OPTS, options, nh_birth_ingame, FALSE);

            /* add or display birth options */
            add_menu_txt(&menu, "Birth options for this game:", MI_HEADING);
            menu_add_options(&menu, BIRTH_OPTS, options,
                             nh_birth_lasting, TRUE);
        } else {
            /* add or display birth options */
            add_menu_txt(&menu, "Birth options:", MI_HEADING);
            menu_add_options(&menu, BIRTH_OPTS, options,
                             nh_birth_lasting, FALSE);

            add_menu_txt(&menu, "Game creation options:", MI_HEADING);
            menu_add_options(&menu, CREATION_OPTS, options,
                             nh_birth_creation, FALSE);

            add_menu_txt(&menu, "Game options:", MI_HEADING);
            menu_add_options(&menu, GAME_OPTS, options, nh_birth_ingame, FALSE);
        }

        /* add UI specific options */
        add_menu_txt(&menu, "Interface options:", MI_HEADING);
        menu_add_options(&menu, UI_OPTS, curses_options, FALSE, FALSE);

        curses_display_menu_core(
            &menu, "Set what options?", PICK_ONE, selected,
            curses_menu_callback, 0, 0, -1, -1, FALSE, query_new_value, TRUE);

        curses_free_nh_opts(options);
    } while (*selected != CURSES_MENU_CANCELLED);

    write_ui_config();
    if (!game_is_running)
        write_nh_config();
}
示例#11
0
void print_options(void)
{
    struct nh_menuitem *items;
    int i, icount, size;
    char buf[BUFSZ];
    struct nh_option_desc *options;

    icount = 0; size = 10;
    items = malloc(sizeof(struct nh_menuitem) * size);
    
    add_menu_txt(items, size, icount, "创建人物设置:", MI_HEADING);
    options = nh_get_options(CURRENT_BIRTH_OPTIONS);
    for (i = 0; options[i].name; i++) {
	snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt);
	add_menu_txt(items, size, icount, buf, MI_TEXT);
    }
    add_menu_txt(items, size, icount, "", MI_TEXT);
    
    add_menu_txt(items, size, icount, "游戏设置:", MI_HEADING);
    options = nh_get_options(GAME_OPTIONS);
    for (i = 0; options[i].name; i++) {
	snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt);
	add_menu_txt(items, size, icount, buf, MI_TEXT);
    }
    add_menu_txt(items, size, icount, "", MI_TEXT);

    /* add UI specific options */
    add_menu_txt(items, size, icount, "界面设置:", MI_HEADING);
    for (i = 0; curses_options[i].name; i++) {
	snprintf(buf, BUFSZ, "%s\t%s", curses_options[i].name, curses_options[i].helptxt);
	add_menu_txt(items, size, icount, buf, MI_TEXT);
    }

    curses_display_menu(items, icount, "可用选项:", PICK_NONE, NULL);
    free(items);
}
示例#12
0
static void
show_autopickup_menu(struct nh_option_desc *opt)
{
    struct nh_menulist menu;
    int i, j, parts, selected[1], id;
    struct nh_autopickup_rule *r;
    char buf[BUFSZ];
    struct nh_autopickup_rule *rule;
    union nh_optvalue value;

    /* clone autopickup rules */
    value.ar = malloc(sizeof (struct nh_autopickup_rules));
    value.ar->num_rules = 0;
    value.ar->rules = NULL;
    if (opt->value.ar) {
        int size;
        value.ar->num_rules = opt->value.ar->num_rules;
        size = value.ar->num_rules * sizeof (struct nh_autopickup_rule);
        value.ar->rules = malloc(size);
        memcpy(value.ar->rules, opt->value.ar->rules, size);
    }

    do {
        init_menulist(&menu);

        add_menu_txt(&menu, "Pos\tRule\tAction", MI_HEADING);

        /* list the rules in human-readable form */
        for (i = 0; i < value.ar->num_rules; i++) {
            r = &value.ar->rules[i];
            parts = 0;
            snprintf(buf, ARRAY_SIZE(buf), "%2d.\tIF ", i + 1);

            if (strlen(r->pattern)) {
                parts++;
                sprintf(buf + strlen(buf), "name matches \"%s\"", r->pattern);
            }

            if (r->oclass != OCLASS_ANY) {
                const char *classname = NULL;

                for (j = 0; j < opt->a.numclasses && !classname; j++)
                    if (opt->a.classes[j].id == r->oclass)
                        classname = opt->a.classes[j].caption;

                if (parts++)
                    strcat(buf, " AND ");
                sprintf(buf + strlen(buf), "type is \"%s\"", classname);
            }

            if (r->buc != B_DONT_CARE) {
                if (parts++)
                    strcat(buf, " AND ");
                sprintf(buf + strlen(buf), "beatitude is %s", bucnames[r->buc]);
            }

            if (!parts)
                snprintf(buf, ARRAY_SIZE(buf), "%2d.\teverything", i + 1);

            if (r->action == AP_GRAB)
                sprintf(buf + strlen(buf), ":\t< GRAB");
            else
                sprintf(buf + strlen(buf), ":\t  LEAVE >");

            add_menu_item(&menu, i + 1, buf, 0, 0);
        }

        add_menu_txt(&menu, "", MI_TEXT);
        add_menu_item(&menu, -1, "add a new rule", '!', 0);
        add_menu_item(&menu, -2, "help", '?', 0);

        /* TODO */
        curses_display_menu(&menu, "Autopickup rules:", PICK_ONE,
                            PLHINT_RIGHT, selected, curses_menu_callback);
        if (*selected == CURSES_MENU_CANCELLED)
            break;

        /* add or edit a rule */
        id = selected[0];
        if (id == -1) {
            int size;

            /* create a new rule */
            id = value.ar->num_rules;
            value.ar->num_rules++;
            size = value.ar->num_rules * sizeof (struct nh_autopickup_rule);
            value.ar->rules = realloc(value.ar->rules, size);

            rule = &value.ar->rules[id];
            memset(rule->pattern, 0, sizeof(rule->pattern));
            rule->oclass = OCLASS_ANY;
            rule->buc = B_DONT_CARE;
            rule->action = AP_GRAB;
        } else if (id == -2) {
            autopickup_rules_help();
            continue;
        } else
            id--;

        edit_ap_rule(&opt->a, value.ar, id);
    } while (1);

    curses_set_option(opt->name, value);

    free(value.ar->rules);
    free(value.ar);
}
示例#13
0
int
network_motd(void)
{
    char errmsg[256];
    char motdmsg[4096];
    int fd = -1;

    if (settings.show_motd == MOTD_TRUE) {

        fd = connect_server(MOTD_SERVER, MOTD_PORT, FALSE,
                            errmsg, sizeof errmsg);
        if (fd == -1)
            fd = connect_server(MOTD_SERVER, MOTD_PORT, TRUE,
                                errmsg, sizeof errmsg);
        
        errmsg[sizeof errmsg - 1] = '\0';

        if (fd == -1) {
            strcpy(motdmsg, "Could not connect to <" MOTD_SERVER "> to "
                   "receive a Message of the Day: ");
            strcat(motdmsg, errmsg);
        } else {
            /* We want to receive until the connection closes (which causes
               either EPIPE on abnormal shutdown, or 0 on normal shutdown). So
               continue until we get an error message other than EINTR or the
               buffer fills (indicating a malicious connection; I'm not planning
               on sending malicious packets from motd.nethack4.org, especially
               as I wrote this code and so know it wouldn't work, but it's worth
               allowing for the possibility that someone else intercepts the
               connection). */
            int recvlen = 0;
            int rv;
            while (recvlen < sizeof motdmsg &&
                   (((rv = recv(fd, motdmsg + recvlen,
                                (sizeof motdmsg) - recvlen, 0))) > 0 ||
                    errno == EINTR))
                recvlen += rv < 0 ? 0 : rv;
            if (recvlen >= sizeof motdmsg)
                recvlen = -1 + sizeof motdmsg;

            motdmsg[recvlen] = '\0';
        }

        close(fd);
    } else if (settings.show_motd == MOTD_FALSE) {
        return 1;
    } else {
        /* It's a bad idea to do network connections without asking the user for
           permission first. (Arguably we could make an exception for
           connection-only mode, but that connects to localhost, which is not
           quite the same thing as connecting to the Internet, so I'd rather
           make absolutely sure we aren't doing connections unsolicited.)

           Note that nothing is sent (other than the fact that the connection
           exists); the nethack4 binary just creates the connection, then reads
           from it. */
        strcpy(motdmsg, "The Message of the Day system connects to the "
               "Internet to receive gameplay tips and announcements (such "
               "as tournament information or release announcements). Do you "
               "want to turn it on? (You can change this later with the "
               "\x0enetwork_motd\x0f option.)");
    }

    /* SI/SO in the output indicate bold text. This isn't implemented yet.  Also
       strip out all other unprintable characters for security reasons. We just
       use the ASCII space-to-tilde range for printables; we're not expecting
       any control characters but SI/SO, not even newlines. */
    char *f, *t;
    f = t = motdmsg;
    while (*f) {
        if (*f >= ' ' && *f <= '~')
            *(t++) = *f;
        f++;
    }
    *t = '\0';

    int outcount;
    char **outlines;
    wrap_text(COLNO-6, motdmsg, &outcount, &outlines);

    struct nh_menulist menu;
    int i;

    init_menulist(&menu);

    for (i = 0; i < outcount; i++)
        add_menu_txt(&menu, outlines[i], MI_TEXT);

    free_wrap(outlines);

    if (settings.show_motd == MOTD_ASK) {
        add_menu_txt(&menu, "", MI_TEXT);
        add_menu_item(&menu, 1,
                      "Yes, I'd like announcements and gameplay tips",
                      'y', FALSE);
        add_menu_item(&menu, 2,
                      "No, please don't connect to the MotD server",
                      'n', FALSE);

        curses_display_menu(&menu, "Message of the Day", PICK_ONE,
                            PLHINT_ANYWHERE, &i, curses_menu_callback);

        if (i == 1) {
            curses_set_option("networkmotd",
                              (union nh_optvalue){.e = MOTD_TRUE});
示例#14
0
static void show_autopickup_menu(struct nh_option_desc *opt)
{
    struct nh_menuitem *items;
    int i, j, n, icount, size, menusize, parts, selected[1], id;
    struct nh_autopickup_rule *r;
    char buf[BUFSZ];
    struct nh_autopickup_rule *rule;
    union nh_optvalue value;
    
    /* clone autopickup rules */
    value.ar = malloc(sizeof(struct nh_autopickup_rules));
    value.ar->num_rules = 0;
    value.ar->rules = NULL;
    if (opt->value.ar){
	value.ar->num_rules = opt->value.ar->num_rules;
	size = value.ar->num_rules * sizeof(struct nh_autopickup_rule);
	value.ar->rules = malloc(size);
	memcpy(value.ar->rules, opt->value.ar->rules, size);
    }
    
    menusize = value.ar->num_rules + 4;
    items = malloc(sizeof(struct nh_menuitem) * menusize);

    selected[0] = 0;
    do {
	icount = 0;
	
	add_menu_txt(items, menusize, icount, "Pos\tRule\tAction", MI_HEADING);
	
	/* list the rules in human-readable form */
	for (i = 0; i < value.ar->num_rules; i++) {
	    r = &value.ar->rules[i];
	    parts = 0;
	    sprintf(buf, "%2d.\tIF ", i+1);
	    
	    if (strlen(r->pattern)) {
		parts++;
		sprintf(buf + strlen(buf), "name matches \"%s\"", r->pattern);
	    }
	    
	    if (r->oclass != OCLASS_ANY) {
		char *classname = NULL;
		for (j = 0; j < opt->a.numclasses && !classname; j++)
		    if (opt->a.classes[j].id == r->oclass)
			classname = opt->a.classes[j].caption;
		
		if (parts++)
		    strcat(buf, " AND ");
		sprintf(buf + strlen(buf), "type is \"%s\"", classname);
	    }
	    
	    if (r->buc != B_DONT_CARE) {
		if (parts++)
		    strcat(buf, " AND ");
		sprintf(buf + strlen(buf), "beatitude is %s", bucnames[r->buc]);
	    }
	    
	    if (!parts)
		sprintf(buf, "%2d.\teverything", i+1);
	    
	    if (r->action == AP_GRAB)
		sprintf(buf + strlen(buf), ":\t< GRAB");
	    else
		sprintf(buf + strlen(buf), ":\t  LEAVE >");
	    
	    add_menu_item(items, menusize, icount, i+1, buf, 0, 0);
	}
	
	add_menu_txt(items, menusize, icount, "", MI_TEXT);
	add_menu_item(items, menusize, icount, -1, "add a new rule", '!', 0);
	add_menu_item(items, menusize, icount, -2, "help", '?', 0);
	
	/* If the previous selection was to add a rule, scroll to the bottom now
	 * so that the player can see it. */
	if (selected[0] == -1) {
	    n = curses_display_menu_bottom(items, icount, "Autopickup rules:",
					   PICK_ONE, selected);
	} else {
	    n = curses_display_menu(items, icount, "Autopickup rules:",
				    PICK_ONE, selected);
	}
	if (n <= 0)
	    break;
	
	/* add or edit a rule */
	id = selected[0];
	if (id == -1) {
	    /* create a new rule */
	    id = value.ar->num_rules;
	    value.ar->num_rules++;
	    size = value.ar->num_rules * sizeof(struct nh_autopickup_rule);
	    value.ar->rules = realloc(value.ar->rules, size);
	    
	    rule = &value.ar->rules[id];
	    rule->pattern[0] = '\0';
	    rule->oclass = OCLASS_ANY;
	    rule->buc = B_DONT_CARE;
	    rule->action = AP_GRAB;
	} else if (id == -2) {
	    autopickup_rules_help();
	    continue;
	} else
	    id--;
	
	edit_ap_rule(&opt->a, value.ar, id);
    } while (n > 0);
    
    nh_set_option(opt->name, value, FALSE);
    
    free(value.ar->rules);
    free(value.ar);
    free(items);
}
示例#15
0
void
print_options(void)
{
    struct nh_menulist menu;
    int i;
    char buf[BUFSZ];
    struct nh_option_desc *options = curses_get_nh_opts();

    init_menulist(&menu);

    add_menu_txt(&menu, "Birth options:", MI_HEADING);
    for (i = 0; options[i].name; i++) {
        if (options[i].birth_option != nh_birth_lasting)
            continue;
        snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt);
        add_menu_txt(&menu, buf, MI_TEXT);
    }
    add_menu_txt(&menu, "", MI_TEXT);

    add_menu_txt(&menu, "Game creation options:", MI_HEADING);
    for (i = 0; options[i].name; i++) {
        if (options[i].birth_option != nh_birth_creation)
            continue;
        snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt);
        add_menu_txt(&menu, buf, MI_TEXT);
    }
    add_menu_txt(&menu, "", MI_TEXT);

    add_menu_txt(&menu, "Game options:", MI_HEADING);
    for (i = 0; options[i].name; i++) {
        if (options[i].birth_option != nh_birth_ingame)
            continue;
        snprintf(buf, BUFSZ, "%s\t%s", options[i].name, options[i].helptxt);
        add_menu_txt(&menu, buf, MI_TEXT);
    }
    add_menu_txt(&menu, "", MI_TEXT);

    /* add UI specific options */
    add_menu_txt(&menu, "Interface options:", MI_HEADING);
    for (i = 0; curses_options[i].name; i++) {
        snprintf(buf, BUFSZ, "%s\t%s", curses_options[i].name,
                 curses_options[i].helptxt);
        add_menu_txt(&menu, buf, MI_TEXT);
    }

    curses_display_menu(&menu, "Available options:", PICK_NONE,
                        PLHINT_ANYWHERE, NULL, null_menu_callback);

    curses_free_nh_opts(options);
}
示例#16
0
static void edit_ap_rule(struct nh_autopick_option *desc,
			 struct nh_autopickup_rules *ar, int ruleno)
{
    struct nh_autopickup_rule *r = &ar->rules[ruleno];
    struct nh_autopickup_rule tmprule;
    struct nh_menuitem *items;
    int i, icount, size = 7, n, selected[1], newpos;
    char query[BUFSZ], buf[BUFSZ], *classname;
    
    items = malloc(sizeof(struct nh_menuitem) * size);
    
    do {
	icount = 0;
	sprintf(buf, "rule position:\t[%d]", ruleno + 1);
	add_menu_item(items, size, icount, 1, buf, 0, 0);
	
	sprintf(buf, "name pattern:\t[%s]", r->pattern);
	add_menu_item(items, size, icount, 2, buf, 0, 0);
	
	classname = NULL;
	for (i = 0; i < desc->numclasses && !classname; i++)
	    if (desc->classes[i].id == r->oclass)
		classname = desc->classes[i].caption;
	sprintf(buf, "object type:\t[%s]", classname);
	add_menu_item(items, size, icount, 3, buf, 0, 0);
	
	sprintf(buf, "beatitude:\t[%s]", bucnames[r->buc]);
	add_menu_item(items, size, icount, 4, buf, 0, 0);
	
	sprintf(buf, "action:\t[%s]", r->action == AP_GRAB ? "GRAB" : "LEAVE");
	add_menu_item(items, size, icount, 5, buf, 0, 0);
	add_menu_txt(items, size, icount, "", MI_TEXT);
	add_menu_item(items, size, icount, 6, "delete this rule", 'x', 0);
	
	n = curses_display_menu(items, icount, "Edit rule:", PICK_ONE, selected);
	if (n <= 0)
	    break;
	
	switch (selected[0]) {
	    /* move this rule */
	    case 1:
		sprintf(query, "New rule position: (1 - %d), currently: %d",
			ar->num_rules, ruleno + 1);
		buf[0] = '\0';
		curses_getline(query, buf);
		if (!*buf || *buf == '\033')
		    break;
		newpos = atoi(buf);
		if (newpos <= 0 || newpos > ar->num_rules) {
		    curses_msgwin("Invalid rule position.");
		    break;
		}
		newpos--;
		if (newpos == ruleno)
		    break;
		
		tmprule = ar->rules[ruleno];
		/* shift the rules around */
		if (newpos > ruleno) {
		    for (i = ruleno; i < newpos; i++)
			ar->rules[i] = ar->rules[i+1];
		} else {
		    for (i = ruleno; i > newpos; i--)
			ar->rules[i] = ar->rules[i-1];
		}
		ar->rules[newpos] = tmprule;
		goto out;
		
	    /* edit the pattern */
	    case 2:
		sprintf(query, "New name pattern (empty matches everything):");
		buf[0] = '\0';
		curses_getline(query, buf);
		if (*buf != '\033')
		    strncpy(r->pattern, buf, sizeof(r->pattern));
		r->pattern[sizeof(r->pattern)-1] = '\0';
		break;
	    
	    /* edit object class match */
	    case 3:
		r->oclass = get_autopickup_oclass(desc, r->oclass);
		break;
	    
	    /* edit beatitude match */
	    case 4:
		r->buc = get_autopickup_buc(r->buc);
		break;
		
	    /* toggle action */
	    case 5:
		if (r->action == AP_GRAB)
		    r->action = AP_LEAVE;
		else
		    r->action = AP_GRAB;
		break;
		
	    /* delete */
	    case 6:
		for (i = ruleno; i < ar->num_rules - 1; i++)
		    ar->rules[i] = ar->rules[i+1];
		ar->num_rules--;
		ar->rules = realloc(ar->rules, ar->num_rules * sizeof(struct nh_autopickup_rule));
		goto out; /* break just beaks the switch .. doh */
	}
	
    } while (n > 0);
out:
    free(items);
}
示例#17
0
static void
edit_ap_rule(struct nh_autopick_option *desc, struct nh_autopickup_rules *ar,
             int ruleno)
{
    struct nh_autopickup_rule *r = &ar->rules[ruleno];
    struct nh_autopickup_rule tmprule;
    struct nh_menulist menu;
    int i, selected[1], newpos, allocsize;
    char query[BUFSZ], buf[BUFSZ];
    const char *classname;

    do {
        init_menulist(&menu);

        snprintf(buf, ARRAY_SIZE(buf), "rule position:\t[%d]", ruleno + 1);
        add_menu_item(&menu, 1, buf, 0, 0);

        snprintf(buf, ARRAY_SIZE(buf), "name pattern:\t[%s]", r->pattern);
        add_menu_item(&menu, 2, buf, 0, 0);

        classname = NULL;
        for (i = 0; i < desc->numclasses && !classname; i++)
            if (desc->classes[i].id == r->oclass)
                classname = desc->classes[i].caption;
        snprintf(buf, ARRAY_SIZE(buf), "object type:\t[%s]", classname);
        add_menu_item(&menu, 3, buf, 0, 0);

        snprintf(buf, ARRAY_SIZE(buf), "beatitude:\t[%s]", bucnames[r->buc]);
        add_menu_item(&menu, 4, buf, 0, 0);

        snprintf(buf, ARRAY_SIZE(buf), "action:\t[%s]", r->action == AP_GRAB ? "GRAB" : "LEAVE");
        add_menu_item(&menu, 5, buf, 0, 0);
        add_menu_txt(&menu, "", MI_TEXT);
        add_menu_item(&menu, 6, "delete this rule", 'x', 0);

        curses_display_menu(&menu, "Edit rule:", PICK_ONE, PLHINT_RIGHT,
                            selected, curses_menu_callback);
        if (*selected == CURSES_MENU_CANCELLED)
            return;

        switch (selected[0]) {
            /* move this rule */
        case 1:
            snprintf(query, ARRAY_SIZE(query), "New rule position: (1 - %d), currently: %d",
                    ar->num_rules, ruleno + 1);
            newpos = ar->num_rules;
            curses_getline(query, &newpos, rule_position_callback);
            newpos--;
            if (newpos == ruleno || newpos < 0)
                break;

            tmprule = ar->rules[ruleno];
            /* shift the rules around */
            if (newpos > ruleno) {
                for (i = ruleno; i < newpos; i++)
                    ar->rules[i] = ar->rules[i + 1];
            } else {
                for (i = ruleno; i > newpos; i--)
                    ar->rules[i] = ar->rules[i - 1];
            }
            ar->rules[newpos] = tmprule;
            return;

            /* edit the pattern */
        case 2:
            snprintf(query, ARRAY_SIZE(query), "New name pattern (empty matches everything):");
            curses_getline(query, r->pattern, rule_pattern_callback);
            break;

            /* edit object class match */
        case 3:
            r->oclass = get_autopickup_oclass(desc, r->oclass);
            break;

            /* edit beatitude match */
        case 4:
            r->buc = get_autopickup_buc(r->buc);
            break;

            /* toggle action */
        case 5:
            if (r->action == AP_GRAB)
                r->action = AP_LEAVE;
            else
                r->action = AP_GRAB;
            break;

            /* delete */
        case 6:
            for (i = ruleno; i < ar->num_rules - 1; i++)
                ar->rules[i] = ar->rules[i + 1];
            ar->num_rules--;
            allocsize = ar->num_rules;
            if (allocsize < 1)
                allocsize = 1;
            ar->rules =
                realloc(ar->rules,
                        allocsize * sizeof (struct nh_autopickup_rule));
            return;
        }

    } while (1);
}
示例#18
0
static void msgtype_edit_rule(struct nh_msgtype_rules *mt_rules, int ruleno)
{
    struct nh_msgtype_rule *rule;
    /* Menu variables. */
    struct nh_menuitem *items;
    int icount, menusize, selected[1], n;

    rule = &mt_rules->rules[ruleno];

    menusize = 5;
    items = malloc(sizeof(struct nh_menuitem) * menusize);

    do {
	char buf[BUFSZ], query[BUFSZ];
	int i;
	icount = 0;

	sprintf(buf, "Position:\t[%d]", ruleno + 1);
	add_menu_item(items, menusize, icount, 1, buf, 0, 0);

	sprintf(buf, "Action:\t[%s]", msgtype_action_string(rule->action));
	add_menu_item(items, menusize, icount, 2, buf, 0, 0);

	sprintf(buf, "Pattern:\t[%s]", rule->pattern);
	add_menu_item(items, menusize, icount, 3, buf, 0, 0);

	add_menu_txt(items, menusize, icount, "", MI_TEXT);
	add_menu_item(items, menusize, icount, 4, "Delete this match", '!', 0);

	n = curses_display_menu(items, icount, "Edit match:", PICK_ONE, selected);
	if (n > 0) {
	    switch (selected[0]) {
	    case 1:	/* change position */
		{
		    int newpos;
		    struct nh_msgtype_rule tmprule;

		    sprintf(query, "New match position: (1 - %d, currently %d)",
			    mt_rules->num_rules, ruleno + 1);
		    buf[0] = '\0';
		    curses_getline(query, buf);
		    if (!*buf || *buf == '\033')
			break;

		    newpos = atoi(buf);
		    if (newpos <= 0 || newpos > mt_rules->num_rules) {
			curses_msgwin("Invalid match position.");
			break;
		    }

		    newpos--;
		    if (newpos == ruleno)
			break;

		    tmprule = mt_rules->rules[ruleno];
		    /* Shuffle rules in-between. */
		    if (newpos > ruleno) {
			for (i = ruleno; i < newpos; i++)
			    mt_rules->rules[i] = mt_rules->rules[i + 1];
		    } else {
			for (i = ruleno; i > newpos; i--)
			    mt_rules->rules[i] = mt_rules->rules[i - 1];
		    }
		    mt_rules->rules[newpos] = tmprule;

		    /* Exit menu do-while (n > 0) */
		    n = 0;
		}
		break;

	    case 2:	/* change action */
		rule->action = get_msgtype_action(rule->action);
		break;

	    case 3:	/* change pattern */
		snprintf(query, BUFSZ, "New match pattern: (currently \"%s\")",
			 rule->pattern);
		buf[0] = '\0';
		curses_getline(query, buf);
		if (*buf != '\033') {
		    /* Replace the same chars as msgtype_to_string to reduce
		     * player surprise when loading a game and viewing msgtypes. */
		    for (i = 0; i < sizeof(buf); i++) {
			if (buf[i] == '"' || buf[i] == '|' || buf[i] == ';')
			    buf[i] = '?';
		    }
		    strncpy(rule->pattern, buf, sizeof(rule->pattern));
		}
		rule->pattern[sizeof(rule->pattern) - 1] = '\0';
		break;

	    case 4:	/* delete match */
		/* Shuffle rules down. */
		for (i = ruleno; i < mt_rules->num_rules - 1; i++)
		    mt_rules->rules[i] = mt_rules->rules[i + 1];
		mt_rules->num_rules--;
		mt_rules->rules = realloc(mt_rules->rules, mt_rules->num_rules *
					  sizeof(struct nh_msgtype_rule));
		/* Exit menu do-while (n > 0) */
		n = 0;
		break;

	    default:
		curses_msgwin("无效的消息类型匹配目录选择。");
	    }
	}
    } while (n > 0);

    free(items);
}
示例#19
0
void
net_replay(void)
{
    char buf[BUFSZ];
    struct nhnet_game *gamelist;
    struct nh_menulist menu;
    int pick[1];
    int i, gamecount, gameid, want_done, show_all;

    want_done = FALSE;
    show_all = TRUE;
    while (1) {
        gamelist = nhnet_list_games(want_done, show_all, &gamecount);

        init_menulist(&menu);

        if (!gamecount)
            add_menu_txt(&menu, "(No games in this list)",
                         MI_NORMAL);

        /* add all the files to the menu */
        for (i = 0; i < gamecount; i++) {
            describe_game(buf, gamelist[i].status, &gamelist[i].i);
            add_menu_item(&menu, gamelist[i].gameid, buf, 0,
                          FALSE);
        }

        add_menu_txt(&menu, "", MI_NORMAL);
        if (want_done)
            add_menu_item(&menu, -1, show_all ? "Watch current games" :
                          "Replay your unfinished games", '!', FALSE);
        else
            add_menu_item(&menu, -1,
                          "Replay a completed game", '!', FALSE);

        if (show_all)
            add_menu_item(&menu, -2, want_done ? "View your completed games" :
                          "View your saved games", '#', FALSE);
        else
            add_menu_item(&menu, -2, "View games from other players",
                          '#', FALSE);

        curses_display_menu(&menu, want_done ? show_all ?
                            "Completed games by other players" :
                            "Your completed games" : show_all ?
                            "Pick a current game to watch" :
                            "Replay your saved games", PICK_ONE,
                            PLHINT_ANYWHERE, pick, curses_menu_callback);
        if (pick[0] == CURSES_MENU_CANCELLED)
            return;

        if (pick[0] == -1) {
            want_done = !want_done;
            if (want_done)
                show_all = FALSE; /* will normally be intended */
            continue;
        } else if (pick[0] == -2) {
            show_all = !show_all;
            continue;
        } else
            gameid = pick[0];

        break;
    }

    create_game_windows();

    /* If the game is over, we want to replay (nothing to watch). If it's our
       game, we want to replay (not much point in watching yourself). Otherwise,
       we start in watch mode; the player can change to replay mode from the
       watch menu. */
    int ret = playgame(gameid, show_all && !want_done ? FM_WATCH : FM_REPLAY);

    destroy_game_windows();
    cleanup_messages();

    game_ended(ret, NULL, TRUE);
}
示例#20
0
void
replay(void)
{
    char buf[BUFSZ];
    fnchar logdir[BUFSZ], savedir[BUFSZ], filename[1024], *dir, **files;
    struct nh_menuitem *items;
    int i, n, fd, icount, size, filecount, pick[1];
    enum nh_log_status status;
    struct nh_game_info gi;

    if (!get_gamedir(LOG_DIR, logdir))
        logdir[0] = '\0';
    if (!get_gamedir(SAVE_DIR, savedir))
        savedir[0] = '\0';

    if (*logdir)
        dir = logdir;
    else if (*savedir)
        dir = savedir;
    else {
        curses_msgwin("There are no games to replay.");
        return;
    }

    while (1) {
        filename[0] = '\0';
        files = list_gamefiles(dir, &filecount);
        /* make sure there are some files to show */
        if (!filecount) {
            if (dir == savedir) {
                curses_msgwin("There are no saved games to replay.");
                savedir[0] = '\0';
            } else {
                curses_msgwin("There are no completed games to replay.");
                logdir[0] = '\0';
            }

            dir = (dir == savedir) ? logdir : savedir;
            if (!*dir)
                return;
            continue;
        }

        icount = 0;
        size = filecount + 2;
        items = malloc(size * sizeof (struct nh_menuitem));

        /* add all the files to the menu */
        for (i = 0; i < filecount; i++) {
            fd = sys_open(files[i], O_RDWR, 0660);
            status = nh_get_savegame_status(fd, &gi);
            close(fd);

            describe_game(buf, status, &gi);
            add_menu_item(items, size, icount,
                          (status == LS_IN_PROGRESS) ? 0 : icount + 1, buf, 0,
                          FALSE);
        }

        if (dir == logdir && *savedir) {
            add_menu_txt(items, size, icount, "", MI_NORMAL);
            add_menu_item(items, size, icount, -1, "View saved games instead",
                          '!', FALSE);
        } else if (dir == savedir && *logdir) {
            add_menu_txt(items, size, icount, "", MI_NORMAL);
            add_menu_item(items, size, icount, -1, "View saved games instead",
                          '!', FALSE);
        }

        n = curses_display_menu(items, icount, "Pick a game to view", PICK_ONE,
                                PLHINT_ANYWHERE, pick);
        free(items);
        filename[0] = '\0';
        if (n > 0 && pick[0] != -1)
            fnncat(filename, files[pick[0] - 1],
                   sizeof (filename) / sizeof (fnchar) - 1);

        for (i = 0; i < filecount; i++)
            free(files[i]);
        free(files);

        if (n <= 0)
            return;

        if (pick[0] == -1) {
            dir = (dir == savedir) ? logdir : savedir;
            continue;
        }

        /* we have a valid filename */
        break;
    }

    fd = sys_open(filename, O_RDWR, 0660);
    replay_commandloop(fd);
    close(fd);
}
示例#21
0
static void show_msgtype_menu(struct nh_option_desc *opt)
{
    /* msgtype option variables. */
    union nh_optvalue value;
    unsigned int size;
    /* Menu variables. */
    struct nh_menuitem *items;
    int icount, menusize, selected[1], n;

    /* Clone msgtype rules. */
    value.mt = malloc(sizeof(struct nh_msgtype_rules));
    if (opt->value.mt) {
	value.mt->num_rules = opt->value.mt->num_rules;
	size = value.mt->num_rules * sizeof(struct nh_msgtype_rule);
	value.mt->rules = malloc(size);
	memcpy(value.mt->rules, opt->value.mt->rules, size);
    } else {
	value.mt->num_rules = 0;
	value.mt->rules = NULL;
    }

    menusize = value.mt->num_rules + 4;
    items = malloc(sizeof(struct nh_menuitem) * menusize);

    selected[0] = 0;
    do {
	int i, id;
	icount = 0;

	add_menu_txt(items, menusize, icount, "Pos\tAction\tPattern", MI_HEADING);

	for (i = 0; i < value.mt->num_rules; i++) {
	    /* position (3) + '.' (1) + '\t' (1) + pattern (119) + '\t' (1) +
	     * "NO REPEAT" (9) + null (1) */
	    char buf[134];
	    struct nh_msgtype_rule *r = &value.mt->rules[i];
	    sprintf(buf, "%2d.\t%s\t%s", i + 1, msgtype_action_string(r->action),
		    r->pattern);
	    add_menu_item(items, menusize, icount, i + 1, buf, 0, 0);
	}

	add_menu_txt(items, menusize, icount, "", MI_TEXT);
	add_menu_item(items, menusize, icount, -1, "add new match", '+', 0);
	add_menu_item(items, menusize, icount, -2, "help", '?', 0);

	/* If the previous selection was to add a rule, scroll to the bottom now
	 * so that the player can see it. */
	if (selected[0] == -1) {
	    n = curses_display_menu_bottom(items, icount, "Message types:",
					   PICK_ONE, selected);
	} else {
	    n = curses_display_menu(items, icount, "Message types:",
				    PICK_ONE, selected);
	}
	if (n > 0) {
	    id = selected[0];
	    if (id == -2) {
		msgtype_help();
	    } else if (id == -1) {
		/* add new match */
		if (value.mt->num_rules >= MSGTYPE_MAX_RULES) {
		    curses_msgwin("Maximum number of rules reached.");
		} else {
		    struct nh_msgtype_rule *r;
		    id = value.mt->num_rules;

		    value.mt->num_rules++;
		    size = value.mt->num_rules * sizeof(struct nh_msgtype_rule);
		    value.mt->rules = realloc(value.mt->rules, size);

		    r = &value.mt->rules[id];
		    r->pattern[0] = '\0';
		    r->action = MSGTYPE_DEFAULT;
		}
	    } else {
		/* edit existing match */
		msgtype_edit_rule(value.mt, id - 1);
	    }
	}
    } while (n > 0);

    nh_set_option(opt->name, value, FALSE);

    if (value.mt->rules)
	free(value.mt->rules);
    free(value.mt);
    free(items);
}