Example #1
0
void initoptions(void)
{
	int i;
	
	iflags.travelcc.x = iflags.travelcc.y = -1;
	flags.warnlevel = 1;
	flags.warntype = 0L;
	
	/* init flags.inv_order this way, as setting it via the option
	 * requires a preexisting order */
	memcpy(flags.inv_order, def_inv_order, sizeof flags.inv_order);

	/* since this is done before init_objects(), do partial init here */
	objects[SLIME_MOLD].oc_name_idx = SLIME_MOLD;
	strncpy(pl_fruit, OBJ_NAME(objects[SLIME_MOLD]), PL_FSIZ);
	fruitadd(pl_fruit);
	
	/* init from option definitions */
	for (i = 0; birth_options[i].name; i++)
		nh_set_option(birth_options[i].name, birth_options[i].value, FALSE);
	
	for (i = 0; options[i].name; i++)
		nh_set_option(options[i].name, options[i].value, FALSE);
	
	/* at this point the user may no longer change their birth options.
	 * active_birth_options will recieve birth option changes made during
	 * log replay, so that we can show the user what birth options the
	 * loaded game was started with */
	active_birth_options = clone_optlist(birth_options);
}
Example #2
0
void init_options(void)
{
    int i;

    find_option("name")->s.maxlen = PL_NSIZ;
    find_option("dungeon_name")->e = dungeon_name_spec;
    find_option("menu_headings")->e = menu_headings_spec;
    find_option("msgheight")->i.min = 0;
    find_option("msgheight")->i.max = MAX_MSGLINES;
    find_option("msghistory")->i.min = 20;   /* arbitrary min/max values */
    find_option("msghistory")->i.max = 20000;
    find_option("graphics")->e = graphics_spec;
    find_option("optstyle")->e = optstyle_spec;
    find_option("scores_top")->i.max = 10000;
    find_option("scores_around")->i.max = 100;
#if defined(PDCURSES) && defined(WIN32)
    find_option("win_width")->i.min = COLNO; /* can never be narrower than COLNO */
    find_option("win_width")->i.max = 100 + COLNO; /* 100 chars wide sidebar already looks pretty silly */
    find_option("win_height")->i.min = ROWNO + 3;
    find_option("win_height")->i.max = 70; /* ROWNO + max msgheight + extra for status and frame */
#endif
    nh_setup_ui_options(curses_options, boolopt_map, option_change_callback);
    
    /* set up option defaults; this is necessary for options that are not
     * specified in the config file */
    for (i = 0; curses_options[i].name; i++)
	nh_set_option(curses_options[i].name, curses_options[i].value, FALSE);
    
    read_ui_config();
}
Example #3
0
nh_bool
nhnet_set_option(const char *name, union nh_optvalue value, nh_bool isstr)
{
    int ret, i;
    json_t *jmsg, *joval, *jobj;
    struct nh_option_desc *gameopts, *birthopts, *opt;
    struct nh_autopickup_rule *r;

    ret = nh_set_option(name, value, isstr);
    if (!nhnet_active())
        return ret;

    if (!api_entry())
        return FALSE;

    gameopts = nhnet_get_options(GAME_OPTIONS);
    birthopts = nhnet_get_options(CURRENT_BIRTH_OPTIONS);
    opt = NULL;
    for (i = 0; gameopts[i].name && !opt; i++)
        if (!strcmp(name, gameopts[i].name))
            opt = &gameopts[i];
    for (i = 0; birthopts[i].name && !opt; i++)
        if (!strcmp(name, birthopts[i].name))
            opt = &birthopts[i];

    if (opt) {
        if (isstr || opt->type == OPTTYPE_STRING)
            joval = json_string(value.s);
        else if (opt->type == OPTTYPE_INT || opt->type == OPTTYPE_ENUM ||
                 opt->type == OPTTYPE_BOOL) {
            joval = json_integer(value.i);
        } else if (opt->type == OPTTYPE_AUTOPICKUP_RULES) {
            joval = json_array();
            for (i = 0; value.ar && i < value.ar->num_rules; i++) {
                r = &value.ar->rules[i];
                jobj =
                    json_pack("{ss,si,si,si}", "pattern", r->pattern, "oclass",
                              r->oclass, "buc", r->buc, "action", r->action);
                json_array_append_new(joval, jobj);
            }
        }

        jmsg =
            json_pack("{ss,so,si}", "name", name, "value", joval, "isstr",
                      isstr);
        jmsg = send_receive_msg("set_option", jmsg);
        if (json_unpack(jmsg, "{si,so!}", "return", &ret, "option", &jobj) ==
            -1) {
            print_error("Bad response in nhnet_set_option");
        } else {
            free_option_data(opt);
            read_json_option(jobj, opt);
        }
        json_decref(jmsg);
    }
    api_exit();
    return ret;
}
Example #4
0
void initoptions(void)
{
	int i;
	
	iflags.travelcc.x = iflags.travelcc.y = -1;
	flags.warnlevel = 1;
	flags.warntype = 0L;
	
	/* init flags.inv_order this way, as setting it via the option
	 * requires a preexisting order */
	memcpy(flags.inv_order, def_inv_order, sizeof flags.inv_order);

	fruitadd(obj_descr[SLIME_MOLD].oc_name);
	strncpy(pl_fruit, obj_descr[SLIME_MOLD].oc_name, PL_FSIZ);

	/* init from option definitions */
	for (i = 0; birth_options[i].name; i++)
	    nh_set_option(birth_options[i].name, birth_options[i].value, FALSE);

	for (i = 0; options[i].name; i++)
	    nh_set_option(options[i].name, options[i].value, FALSE);

	if (!active_birth_options) {
	    /* at this point the user may no longer change their birth options.
	     * active_birth_options will recieve birth option changes made during
	     * log replay, so that we can show the user what birth options the
	     * loaded game was started with */
	    active_birth_options = clone_optlist(birth_options);
	} else {
	    /* the switch to alternate birth options has already happened,
	     * so make sure those settings are active instead. */
	    for (i = 0; active_birth_options[i].name; i++) {
		nh_set_option(active_birth_options[i].name,
			      active_birth_options[i].value, FALSE);
	    }
	}
}
Example #5
0
/* parse a single line from the config file and set the option */
static void read_config_line(char* line)
{
    char *comment, *delim, *name, *value;
    union nh_optvalue optval;

    comment = strchr(line, '#');
    if (comment)
	comment = '\0';
    delim = strchr(line, '=');
    if (!delim)
	return; /* could whine about junk chars in the config, but why bother */
    
    name = line;
    value = delim + 1;
    *delim-- = '\0';
    
    /* remove space around name */
    while (isspace((unsigned char)*name))
	name++;
    while (isspace((unsigned char)*delim))
	*delim-- = '\0';
    
    /* remove spaces around value */
    delim = value;
    while (*delim)
	delim++;
    delim--;
    
    while (isspace((unsigned char)*value))
	value++;
    while (isspace((unsigned char)*delim))
	*delim-- = '\0';
    
    /* value may be enclosed with double quotes (") */
    if (*value == '"' && *delim == '"') {
	value++;
	*delim ='\0';
    }
    
    optval.s = value;
    nh_set_option(name, optval, TRUE);
}
Example #6
0
static void
ccmd_set_option(json_t * params)
{
    const char *optname, *optstr, *pattern;
    json_t *jmsg, *joval, *jopt;
    int isstr, i, ret;
    const struct nh_option_desc *gameopt, *birthopt, *option;
    union nh_optvalue value;
    struct nh_autopickup_rules ar = { NULL, 0 };
    struct nh_autopickup_rule *r;

    if (json_unpack
        (params, "{ss,so,si*}", "name", &optname, "value", &joval, "isstr",
         &isstr) == -1)
        exit_client("Bad parameters for set_option");

    /* find the option_desc for the options that should be set; the option type
       is required in order to decode the option value. */
    gameopt = nh_get_options(GAME_OPTIONS);
    birthopt =
        nh_get_options(gameid ? ACTIVE_BIRTH_OPTIONS : CURRENT_BIRTH_OPTIONS);
    option = find_option(optname, gameopt, birthopt);
    if (!option) {
        jmsg = json_pack("{si,so}", "return", FALSE, "option", json_object());
        client_msg("set_option", jmsg);
        return;
    }

    /* decode the option value depending on the option type */
    if (isstr || option->type == OPTTYPE_STRING) {
        if (!json_is_string(joval))
            exit_client("could not decode option string");
        value.s = (char *)json_string_value(joval);

    } else if (option->type == OPTTYPE_INT || option->type == OPTTYPE_ENUM ||
               option->type == OPTTYPE_BOOL) {
        if (!json_is_integer(joval))
            exit_client("could not decode option value");
        value.i = json_integer_value(joval);

    } else if (option->type == OPTTYPE_AUTOPICKUP_RULES) {
        if (!json_is_array(joval))
            exit_client("could not decode option");

        ar.num_rules = json_array_size(joval);
        ar.rules = malloc(sizeof (struct nh_autopickup_rule) * ar.num_rules);
        if (ar.num_rules) {
            value.ar = &ar;
            for (i = 0; i < ar.num_rules; i++) {
                r = &ar.rules[i];
                if (json_unpack
                    (json_array_get(joval, i), "{ss,si,si,si}", "pattern",
                     &pattern, "oclass", &r->oclass, "buc", &r->buc, "action",
                     &r->action) == -1)
                    exit_client("Error unpacking autopickup rule");
                strncpy(r->pattern, pattern, sizeof (r->pattern) - 1);
            }
        } else
            value.ar = NULL;
    }

    ret = nh_set_option(optname, value, isstr);

    if (option->type == OPTTYPE_AUTOPICKUP_RULES)
        free(ar.rules);

    gameopt = nh_get_options(GAME_OPTIONS);
    birthopt =
        nh_get_options(gameid ? ACTIVE_BIRTH_OPTIONS : CURRENT_BIRTH_OPTIONS);
    option = find_option(optname, gameopt, birthopt);

    jopt = json_option(option);
    optstr = nh_get_option_string(option);

    if (ret == TRUE)
        db_set_option(user_info.uid, optname, option->type, optstr);
    /* return the altered option struct and the string representation to the
       client. The intent is to save some network round trips and make a
       separate get_option_string message unneccessary */
    jmsg = json_pack("{si,so}", "return", ret, "option", jopt);
    client_msg("set_option", jmsg);
}
Example #7
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);
}
Example #8
0
/* get a new value of the appropriate type for the given option */
static nh_bool get_option_value(struct win_menu *mdat, int idx)
{
    char buf[BUFSZ], query[BUFSZ];
    union nh_optvalue value;
    struct nh_option_desc *option, *optlist;
    int listid = mdat->items[idx].id >> 10;
    int id = mdat->items[idx].id & 0x1ff;
    char strbuf[BUFSZ];
    int prev_optstyle = settings.optstyle;
    
    switch (listid) {
	case ACT_BIRTH_OPTS:
	    optlist = nh_get_options(ACTIVE_BIRTH_OPTIONS); break;
	case CUR_BIRTH_OPTS:
	    optlist = nh_get_options(CURRENT_BIRTH_OPTIONS); break;
	case GAME_OPTS:
	    optlist = nh_get_options(GAME_OPTIONS); break;
	case UI_OPTS:
	    optlist = curses_options; break;
	    
	default:
	    return FALSE;
    }
    
    option = &optlist[id];
    value.s = strbuf;
    
    switch ((int)option->type) {
	case OPTTYPE_BOOL:
	    select_boolean_value(&value, option);
	    break;
	    
	case OPTTYPE_INT:
	    sprintf(query, "New value for %s (number from %d to %d)",
		    option->name, option->i.min, option->i.max);
	    sprintf(buf, "%d", value.i);
	    curses_getline(query, buf);
	    if (buf[0] == '\033')
		return FALSE;
	    sscanf(buf, "%d", &value.i);
	    break;
	    
	case OPTTYPE_ENUM:
	    select_enum_value(&value, option);
	    break;
	    
	case OPTTYPE_STRING:
	    sprintf(query, "New value for %s (text)", option->name);
	    curses_getline(query, value.s);
	    if (value.s[0] == '\033')
		return FALSE;
	    break;
	    
	case OPTTYPE_AUTOPICKUP_RULES:
	    show_autopickup_menu(option);
	    return FALSE;
	    
	case OPTTYPE_MSGTYPE:
	    show_msgtype_menu(option);
	    return FALSE;
	    
	case OPTTYPE_KEYMAP:
	    show_keymap_menu(FALSE);
	    return FALSE;
	    
	default:
	    return FALSE;
    }
    
    if (!nh_set_option(option->name, value, FALSE)) {
	sprintf(strbuf, "new value for %s rejected", option->name);
	curses_msgwin(strbuf);
    } else
	print_option_string(option, mdat->items[idx].caption);
    
    /* special case: directly redo option menu appearance */
    if (settings.optstyle != prev_optstyle)
	return TRUE;
    
    return FALSE;
}
Example #9
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);
}
Example #10
0
nh_bool
curses_set_option(const char *name, union nh_optvalue value)
{
    nh_bool game_option = FALSE;
    struct nh_option_desc *option = nhlib_find_option(curses_options, name);

    if (!option) {
        if (game_is_running)
            return nh_set_option(name, value);

        /* If the game is not running, update our local copy of options. */
        if (!nh_options || !(option = nhlib_find_option(nh_options, name))) {
            return FALSE;
        }
        game_option = TRUE;
    }

    if ((int)option->type == OPTTYPE_KEYMAP) {
        return FALSE;
    }

    if (!nhlib_option_value_ok(option, value))
        return FALSE;

    nhlib_copy_option_value(option, value);

    if (game_option)
        return TRUE;

    /* In case the option affects graphics; this is pretty cheap if we don't do
       it every turn */
    mark_mapwin_for_full_refresh();

    if (option->type == OPTTYPE_BOOL) {
        nh_bool *var = nhlib_find_boolopt(boolopt_map, option->name);
        if (!var) {
            curses_impossible("missing boolean option");
            return FALSE;
        }

        *var = value.b;

        if (!strcmp(option->name, "status3")) {
            rebuild_ui();
        } else if (!strcmp(option->name, "darkgray")) {
            set_darkgray();
            draw_map(player.x, player.y);
        } else if (!strcmp(option->name, "mouse")) {
            uncursed_enable_mouse(option->value.b);
        }
    } else if (!strcmp(option->name, "comment")) {
        /* do nothing */
    } else if (!strcmp(option->name, "tileset")) {
        if (settings.tileset)
            free(settings.tileset);
        settings.tileset = malloc(strlen(option->value.s) + 1);
        strcpy(settings.tileset, option->value.s);
        rebuild_ui();
    } else if (!strcmp(option->name, "border")) {
        settings.whichframes = option->value.e;
        rebuild_ui();
    } else if (!strcmp(option->name, "menu_headings")) {
        settings.menu_headings = option->value.e;
    } else if (!strcmp(option->name, "palette")) {
        settings.palette = option->value.e;
        setup_palette();

        if (ui_flags.initialized) {
            /*
             * - We don't want to install a palette as a result of the default
             *   setting of "palette", because some terminals cannot handle a
             *   palette reset, and thus we need to ensure that we've loaded
             *   the user's palette setting before palette initialization.
             *
             * - Besides, clear() will crash with an uninitialized libuncursed.
             *   So we have to delay this anyway.
             */
            clear();
            refresh();
            rebuild_ui();
        }
    } else if (!strcmp(option->name, "animation")) {
        settings.animation = option->value.e;
    } else if (!strcmp(option->name, "sidebar")) {
        settings.sidebar = option->value.e;
        rebuild_ui();
    } else if (!strcmp(option->name, "scores_top")) {
        settings.end_top = option->value.i;
    } else if (!strcmp(option->name, "scores_around")) {
        settings.end_around = option->value.i;
    } else if (!strcmp(option->name, "networkmotd")) {
        settings.show_motd = option->value.e;
    } else if (!strcmp(option->name, "menupaging")) {
        settings.menupaging = option->value.e;
    } else if (!strcmp(option->name, "optstyle")) {
        settings.optstyle = option->value.e;
    } else if (!strcmp(option->name, "msgheight")) {
        settings.msgheight = option->value.i;
        rebuild_ui();
    } else if (!strcmp(option->name, "msghistory")) {
        settings.msghistory = option->value.i;
        alloc_hist_array();
    }
    else
        return FALSE;

    return TRUE;
}