boolean set_option(const char *name, union nh_optvalue value, struct newgame_options *ngo) { struct nh_option_desc *option = NULL, *options = new_opt_struct(); boolean ret = FALSE; /* can't change options for other players */ if (program_state.followmode != FM_PLAY) goto free; if (options) option = nhlib_find_option(options, name); if (!option || (option->birth_option && program_state.game_running)) goto free; if (!nhlib_option_value_ok(option, value)) goto free; nhlib_copy_option_value(option, value); if (option->type == OPTTYPE_BOOL) { boolean *bvar = nhlib_find_boolopt(boolopt_map, option->name); if (!bvar) { impossible("no boolean for option '%s'", option->name); goto free; } *bvar = option->value.b; ret = TRUE; goto free; } else if (!strcmp("disclose", option->name)) { flags.end_disclose = option->value.e; } else if (!strcmp("fruit", option->name)) { strncpy(gamestate.fruits.curname, option->value.s, PL_FSIZ-1); gamestate.fruits.curname[PL_FSIZ - 1] = '\0'; if (objects) /* don't do fruitadd before the game is running */ fruitadd(gamestate.fruits.curname); } else if (!strcmp("menustyle", option->name)) { flags.menu_style = option->value.e; } else if (!strcmp("movecommand", option->name)) { flags.interaction_mode = option->value.e; } else if (!strcmp("packorder", option->name)) { if (!change_inv_order(option->value.s)) goto free; } else if (!strcmp("pickup_burden", option->name)) { flags.pickup_burden = option->value.e; } else if (!strcmp("autopickup_rules", option->name)) { if (flags.ap_rules) { free(flags.ap_rules->rules); free(flags.ap_rules); flags.ap_rules = NULL; } flags.ap_rules = nhlib_copy_autopickup_rules(option->value.ar); } /* birth options */ else if (!strcmp("mode", option->name)) { flags.debug = (option->value.e == MODE_WIZARD); flags.explore = (option->value.e == MODE_EXPLORE); flags.challenge = (option->value.e == MODE_CHALLENGE); } else if (!strcmp("align", option->name)) { u.initalign = option->value.e; } else if (!strcmp("gender", option->name)) { u.initgend = option->value.e; } else if (!strcmp("race", option->name)) { u.initrace = option->value.e; } else if (!strcmp("role", option->name)) { u.initrole = option->value.e; } else if (!strcmp("name", option->name)) { strncpy(u.uplname, option->value.s, PL_NSIZ-1); (u.uplname)[PL_NSIZ - 1] = '\0'; } else if (!strcmp("seed", option->name)) { /* note: does not NUL-terminate a max-length string, this is intentional */ strncpy(flags.setseed, option->value.s, RNG_SEED_SIZE_BASE64); } else if (!strcmp("catname", option->name)) { if (!ngo) panic("catname set outside newgame sequence"); strncpy(ngo->catname, option->value.s, PL_PSIZ-1); ngo->catname[PL_PSIZ - 1] = '\0'; } else if (!strcmp("dogname", option->name)) { if (!ngo) panic("dogname set outside newgame sequence"); strncpy(ngo->dogname, option->value.s, PL_PSIZ-1); ngo->dogname[PL_PSIZ - 1] = '\0'; } else if (!strcmp("horsename", option->name)) { if (!ngo) panic("horsename set outside newgame sequence"); strncpy(ngo->horsename, option->value.s, PL_PSIZ-1); ngo->horsename[PL_PSIZ - 1] = '\0'; } else if (!strcmp("pettype", option->name)) { if (!ngo) panic("preferred_pet set outside newgame sequence"); ngo->preferred_pet = (char)option->value.e; } else if (!strcmp("timezone", option->name)) { flags.timezone = option->value.e; } else if (!strcmp("polyinit", option->name)) { flags.polyinit_mnum = option->value.e; } else /* unrecognized option */ goto free; /* assume that any recognized option has been handled. */ ret = TRUE; free: nhlib_free_optlist(options); return ret; }
static boolean set_option(const char *name, union nh_optvalue value, boolean isstring) { boolean is_ui = FALSE; struct nh_option_desc *option = NULL; if (options) option = find_option(options, name); if (!option && !program_state.game_running && birth_options) option = find_option(birth_options, name); if (!option && ui_options) { option = find_option(ui_options, name); is_ui = TRUE; } if (!option) return FALSE; /* if this option change affects game options (!is_ui) and happens during a replay (program_state.viewing) and the change isn't triggered by the replay (!program_state.restoring) */ if (!is_ui && program_state.viewing && !program_state.restoring) return FALSE; /* Nope, sorry. That would mess up the replay */ if (isstring) value = string_to_optvalue(option, value.s); if (!option_value_ok(option, value)) return FALSE; if (copy_option_value(option, value) && !is_ui) log_option(option); /* prev value != new value */ if (option->type == OPTTYPE_BOOL) { int i; boolean *bvar = NULL; const struct nh_boolopt_map *boolmap = boolopt_map; if (is_ui) boolmap = ui_boolopt_map; for (i = 0; boolmap[i].optname && !bvar; i++) if (!strcmp(option->name, boolmap[i].optname)) bvar = boolmap[i].addr; if (!bvar) /* shouldn't happen */ return FALSE; *bvar = option->value.b; if (is_ui && ui_option_callback) /* allow the ui to "see" changes to booleans, but the return value doesn't mattter as the option was set here. */ ui_option_callback(option); return TRUE; } else if (is_ui) return ui_option_callback(option); /* regular non-boolean options */ else if (!strcmp("comment", option->name)) { /* do nothing */ } else if (!strcmp("disclose", option->name)) { flags.end_disclose = option->value.e; } else if (!strcmp("fruit", option->name)) { strncpy(pl_fruit, option->value.s, PL_FSIZ); if (objects) /* don't do fruitadd before the game is running */ fruitadd(pl_fruit); } else if (!strcmp("menustyle", option->name)) { flags.menu_style = option->value.e; } else if (!strcmp("packorder", option->name)) { if (!change_inv_order(option->value.s)) return FALSE; } else if (!strcmp("pickup_burden", option->name)) { flags.pickup_burden = option->value.e; } else if (!strcmp("runmode", option->name)) { iflags.runmode = option->value.e; } else if (!strcmp("autopickup_rules", option->name)) { if (iflags.ap_rules) { free(iflags.ap_rules->rules); free(iflags.ap_rules); iflags.ap_rules = NULL; } iflags.ap_rules = copy_autopickup_rules(option->value.ar); } /* birth options */ else if (!strcmp("align", option->name)) { flags.init_align = option->value.e; } else if (!strcmp("gender", option->name)) { flags.init_gend = option->value.e; } else if (!strcmp("race", option->name)) { flags.init_race = option->value.e; } else if (!strcmp("role", option->name)) { flags.init_role = option->value.e; } else if (!strcmp("catname", option->name)) { strncpy(catname, option->value.s, PL_PSIZ); } else if (!strcmp("dogname", option->name)) { strncpy(dogname, option->value.s, PL_PSIZ); } else if (!strcmp("horsename", option->name)) { strncpy(horsename, option->value.s, PL_PSIZ); } else if (!strcmp("pettype", option->name)) { preferred_pet = (char)option->value.e; } else /* unrecognized option */ return FALSE; /* assume that any recognized option has been handled. */ return TRUE; }