/** * Ask for a "user pref file" and process it. * * This function should only be used by standard interaction commands, * in which a standard "Command:" prompt is present on the given row. * * Allow absolute file names? XXX XXX XXX */ static void do_cmd_pref_file_hack(long row) { char ftmp[80]; screen_save(); /* Prompt */ prt("Command: Load a user pref file", row, 0); /* Prompt */ prt("File: ", row + 2, 0); /* Default filename */ strnfmt(ftmp, sizeof ftmp, "%s.prf", player_safe_name(player, true)); /* Ask for a file (or cancel) */ if (askfor_aux(ftmp, sizeof ftmp, NULL)) { /* Process the given filename */ if (process_pref_file(ftmp, false, true) == false) { /* Mention failure */ prt("", 0, 0); msg("Failed to load '%s'!", ftmp); } else { /* Mention success */ prt("", 0, 0); msg("Loaded '%s'.", ftmp); } } screen_load(); }
/** * Menu command: dump character dump to file. */ static void death_file(const char *title, int row) { char buf[1024]; char ftmp[80]; strnfmt(ftmp, sizeof(ftmp), "%s.txt", player_safe_name(player, false)); if (get_file(ftmp, buf, sizeof buf)) { bool success; /* Dump a character file */ screen_save(); success = dump_save(buf); screen_load(); /* Check result */ if (success) msg("Character dump successful."); else msg("Character dump failed!"); /* Flush messages */ event_signal(EVENT_MESSAGE_FLUSH); } }
/** * Menu command: dump character dump to file. */ static void death_file(const char *title, int row) { char buf[1024]; char ftmp[80]; /* Get the filesystem-safe name and append .txt */ player_safe_name(ftmp, sizeof(ftmp), player->full_name, false); my_strcat(ftmp, ".txt", sizeof(ftmp)); if (get_file(ftmp, buf, sizeof buf)) { bool success; /* Dump a character file */ screen_save(); success = dump_save(buf); screen_load(); /* Check result */ if (success) msg("Character dump successful."); else msg("Character dump failed!"); /* Flush messages */ event_signal(EVENT_MESSAGE_FLUSH); } }
/** * Ask for a "user pref file" and process it. * * This function should only be used by standard interaction commands, * in which a standard "Command:" prompt is present on the given row. * * Allow absolute file names? XXX XXX XXX */ static void do_cmd_pref_file_hack(long row) { char ftmp[80]; screen_save(); /* Prompt */ prt("Command: Load a user pref file", row, 0); /* Prompt */ prt("File: ", row + 2, 0); /* Get the filesystem-safe name and append .prf */ player_safe_name(ftmp, sizeof(ftmp), player->full_name, true); my_strcat(ftmp, ".prf", sizeof(ftmp)); /* Ask for a file (or cancel) */ if (askfor_aux(ftmp, sizeof ftmp, NULL)) { /* Process the given filename */ if (process_pref_file(ftmp, false, true) == false) { /* Mention failure */ prt("", 0, 0); msg("Failed to load '%s'!", ftmp); } else { /* Mention success */ prt("", 0, 0); msg("Loaded '%s'.", ftmp); } } screen_load(); }
/** * Prompt the user for a filename to save the pref file to. */ static bool get_pref_path(const char *what, int row, char *buf, size_t max) { char ftmp[80]; bool ok; screen_save(); /* Prompt */ prt(format("%s to a pref file", what), row, 0); prt("File: ", row + 2, 0); /* Get the filesystem-safe name and append .prf */ player_safe_name(ftmp, sizeof(ftmp), player->full_name, true); my_strcat(ftmp, ".prf", sizeof(ftmp)); /* Get a filename */ ok = askfor_aux(ftmp, sizeof ftmp, NULL); screen_load(); /* Build the filename */ if (ok) path_build(buf, max, ANGBAND_DIR_USER, ftmp); return ok; }
static void ui_leave_birthscreen(game_event_type type, game_event_data *data, void *user) { /* Set the savefile name if it's not already set */ if (!savefile[0]) savefile_set_name(player_safe_name(player, TRUE)); free_birth_menus(); }
/** * Save the game */ void save_game(void) { char name[80]; char path[1024]; /* Disturb the player */ disturb(player, 1); /* Clear messages */ event_signal(EVENT_MESSAGE_FLUSH); /* Handle stuff */ handle_stuff(player); /* Message */ prt("Saving game...", 0, 0); /* Refresh */ Term_fresh(); /* The player is not dead */ my_strcpy(player->died_from, "(saved)", sizeof(player->died_from)); /* Forbid suspend */ signals_ignore_tstp(); /* Save the player */ if (savefile_save(savefile)) prt("Saving game... done.", 0, 0); else prt("Saving game... failed!", 0, 0); /* Refresh */ Term_fresh(); /* Save the window prefs */ strnfmt(name, sizeof(name), "%s.prf", player_safe_name(player, TRUE)); path_build(path, sizeof(path), ANGBAND_DIR_USER, name); if (!prefs_save(path, option_dump, "Dump window settings")) prt("Failed to save subwindow preferences", 0, 0); /* Allow suspend again */ signals_handle_tstp(); /* Refresh */ Term_fresh(); /* Note that the player is not dead */ my_strcpy(player->died_from, "(alive and well)", sizeof(player->died_from)); }
/** * Prompt the user for a filename to save the pref file to. */ static bool get_pref_path(const char *what, int row, char *buf, size_t max) { char ftmp[80]; bool ok; screen_save(); /* Prompt */ prt(format("%s to a pref file", what), row, 0); prt("File: ", row + 2, 0); /* Default filename */ strnfmt(ftmp, sizeof ftmp, "%s.prf", player_safe_name(player, true)); /* Get a filename */ ok = askfor_aux(ftmp, sizeof ftmp, NULL); screen_load(); /* Build the filename */ if (ok) path_build(buf, max, ANGBAND_DIR_USER, ftmp); return ok; }
/** * Hack -- change name */ void do_cmd_change_name(void) { ui_event ke; int mode = 0; const char *p; bool more = true; /* Prompt */ p = "['c' to change name, 'f' to file, 'h' to change mode, or ESC]"; /* Save screen */ screen_save(); /* Forever */ while (more) { /* Display the player */ display_player(mode); /* Prompt */ Term_putstr(2, 23, -1, COLOUR_WHITE, p); /* Query */ ke = inkey_ex(); if ((ke.type == EVT_KBRD)||(ke.type == EVT_BUTTON)) { switch (ke.key.code) { case ESCAPE: more = false; break; case 'c': { if(arg_force_name) msg("You are not allowed to change your name!"); else { char namebuf[32] = ""; /* Set player name */ if (get_character_name(namebuf, sizeof namebuf)) my_strcpy(player->full_name, namebuf, sizeof(player->full_name)); } break; } case 'f': { char buf[1024]; char fname[80]; /* Get the filesystem-safe name and append .txt */ player_safe_name(fname, sizeof(fname), player->full_name, false); my_strcat(fname, ".txt", sizeof(fname)); if (get_file(fname, buf, sizeof buf)) { if (dump_save(buf)) msg("Character dump successful."); else msg("Character dump failed!"); } break; } case 'h': case ARROW_LEFT: case ' ': mode = (mode + 1) % INFO_SCREENS; break; case 'l': case ARROW_RIGHT: mode = (mode - 1) % INFO_SCREENS; break; } } else if (ke.type == EVT_MOUSE) { if (ke.mouse.button == 1) { /* Flip through the screens */ mode = (mode + 1) % INFO_SCREENS; } else if (ke.mouse.button == 2) { /* exit the screen */ more = false; } else { /* Flip backwards through the screens */ mode = (mode - 1) % INFO_SCREENS; } } /* Flush messages */ event_signal(EVENT_MESSAGE_FLUSH); } /* Load screen */ screen_load(); }
/* * Helper function for "process_pref_file()" * * Input: * v: output buffer array * f: final character * * Output: * result */ static const char *process_pref_file_expr(char **sp, char *fp) { const char *v; char *b; char *s; char f = ' '; /* Initial */ s = (*sp); /* Skip spaces */ while (isspace((unsigned char) *s)) s++; /* Save start */ b = s; /* Default */ v = "?o?o?"; /* Analyze */ if (*s == '[') { const char *p; const char *t; /* Skip [ */ s++; /* First */ t = process_pref_file_expr(&s, &f); /* Oops */ if (!*t) { /* Nothing */ } /* Function: IOR */ else if (streq(t, "IOR")) { v = "0"; while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); if (*t && !streq(t, "0")) v = "1"; } } /* Function: AND */ else if (streq(t, "AND")) { v = "1"; while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); if (*t && streq(t, "0")) v = "0"; } } /* Function: NOT */ else if (streq(t, "NOT")) { v = "1"; while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); if (*t && !streq(t, "0")) v = "0"; } } /* Function: EQU */ else if (streq(t, "EQU")) { v = "1"; if (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } while (*s && (f != ']')) { p = t; t = process_pref_file_expr(&s, &f); if (*t && !streq(p, t)) v = "0"; } } /* Function: LEQ */ else if (streq(t, "LEQ")) { v = "1"; if (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } while (*s && (f != ']')) { p = t; t = process_pref_file_expr(&s, &f); if (*t && (strcmp(p, t) >= 0)) v = "0"; } } /* Function: GEQ */ else if (streq(t, "GEQ")) { v = "1"; if (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } while (*s && (f != ']')) { p = t; t = process_pref_file_expr(&s, &f); if (*t && (strcmp(p, t) <= 0)) v = "0"; } } /* Oops */ else { while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } } /* Verify ending */ if (f != ']') v = "?x?x?"; /* Extract final and Terminate */ if ((f = *s) != '\0') *s++ = '\0'; } /* Other */ else { /* Accept all printables except spaces and brackets */ while (isprint((unsigned char) *s) && !strchr(" []", *s)) ++s; /* Extract final and Terminate */ if ((f = *s) != '\0') *s++ = '\0'; /* Variable */ if (*b == '$') { if (streq(b + 1, "SYS")) v = ANGBAND_SYS; else if (streq(b + 1, "GRAF")) v = ANGBAND_GRAF; else if (streq(b + 1, "RACE")) v = rp_ptr->name; else if (streq(b + 1, "CLASS")) v = cp_ptr->name; else if (streq(b + 1, "PLAYER")) v = player_safe_name(p_ptr, TRUE); else if (streq(b + 1, "GENDER")) v = sp_ptr->title; } /* Constant */ else { v = b; } } /* Save */ (*fp) = f; (*sp) = s; return v; }
/** * Simple "main" function for multiple platforms. * * Note the special "--" option which terminates the processing of * standard options. All non-standard options (if any) are passed * directly to the "init_xxx()" function. */ int main(int argc, char *argv[]) { int i; bool done = FALSE; const char *mstr = NULL; const char *soundstr = NULL; bool args = TRUE; /* Save the "program name" XXX XXX XXX */ argv0 = argv[0]; #ifdef UNIX /* Default permissions on files */ (void)umask(022); /* Get the user id */ player_uid = getuid(); #endif /* UNIX */ #ifdef SETGID /* Save the effective GID for later recall */ player_egid = getegid(); #endif /* UNIX */ /* Drop permissions */ safe_setuid_drop(); /* Get the file paths * Paths may be overriden by -d options, so this has to occur *before* * processing command line args */ init_stuff(); /* Process the command line arguments */ for (i = 1; args && (i < argc); i++) { const char *arg = argv[i]; /* Require proper options */ if (*arg++ != '-') goto usage; /* Analyze option */ switch (*arg++) { case 'l': list_saves(); exit(0); case 'n': new_game = TRUE; break; case 'w': arg_wizard = TRUE; break; case 'p': arg_power = TRUE; break; case 'r': arg_rebalance = TRUE; break; case 'g': /* Default graphics tile */ /* in graphics.txt, 2 corresponds to adam bolt's tiles */ arg_graphics = 2; if (*arg) arg_graphics = atoi(arg); break; case 'u': { if (!*arg) goto usage; my_strcpy(op_ptr->full_name, arg, sizeof op_ptr->full_name); /* The difference here is because on setgid we have to be * careful to only let the player have savefiles stored in * the central save directory. Sanitising input using * player_safe_name() removes anything like that. * * But if the player is running with per-user saves, they * can do whatever the hell they want. */ #ifdef SETGID savefile_set_name(player_safe_name(player, FALSE)); #else savefile_set_name(arg); #endif /* SETGID */ continue; } case 'm': if (!*arg) goto usage; mstr = arg; continue; case 's': if (!*arg) goto usage; soundstr = arg; continue; case 'd': change_path(arg); continue; case 'x': debug_opt(arg); continue; case '-': argv[i] = argv[0]; argc = argc - i; argv = argv + i; args = FALSE; break; default: usage: puts("Usage: angband [options] [-- subopts]"); puts(" -n Start a new character (WARNING: overwrites default savefile without -u)"); puts(" -l Lists all savefiles you can play"); puts(" -w Resurrect dead character (marks savefile)"); puts(" -r Rebalance monsters"); puts(" -g Request graphics mode"); puts(" -x<opt> Debug options; see -xhelp"); puts(" -u<who> Use your <who> savefile"); puts(" -d<dir>=<path> Override a specific directory with <path>. <path> can be:"); for (i = 0; i < (int)N_ELEMENTS(change_path_values); i++) { #ifdef SETGID if (!change_path_values[i].setgid_ok) continue; #endif printf(" %s (default is %s)\n", change_path_values[i].name, *change_path_values[i].path); } puts(" Multiple -d options are allowed."); puts(" -s<mod> Use sound module <sys>:"); for (i = 0; i < (int)N_ELEMENTS(sound_modules); i++) printf(" %s %s\n", sound_modules[i].name, sound_modules[i].help); puts(" -m<sys> Use module <sys>, where <sys> can be:"); /* Print the name and help for each available module */ for (i = 0; i < (int)N_ELEMENTS(modules); i++) printf(" %s %s\n", modules[i].name, modules[i].help); /* Actually abort the process */ quit(NULL); } if (*arg) goto usage; } /* Hack -- Forget standard args */ if (args) { argc = 1; argv[1] = NULL; } /* Install "quit" hook */ quit_aux = quit_hook; /* If we were told which mode to use, then use it */ if (mstr) ANGBAND_SYS = mstr; if (setlocale(LC_CTYPE, "")) { /* Require UTF-8 */ if (strcmp(nl_langinfo(CODESET), "UTF-8") != 0) quit("Angband requires UTF-8 support"); } /* Try the modules in the order specified by modules[] */ for (i = 0; i < (int)N_ELEMENTS(modules); i++) { /* User requested a specific module? */ if (!mstr || (streq(mstr, modules[i].name))) { ANGBAND_SYS = modules[i].name; if (0 == modules[i].init(argc, argv)) { done = TRUE; break; } } } /* Make sure we have a display! */ if (!done) quit("Unable to prepare any 'display module'!"); #ifdef UNIX /* Get the "user name" as default player name, unless set with -u switch */ if (!op_ptr->full_name[0]) { user_name(op_ptr->full_name, sizeof(op_ptr->full_name), player_uid); /* Set the savefile to load */ savefile_set_name(player_safe_name(player, FALSE)); } /* Create any missing directories */ create_needed_dirs(); #endif /* UNIX */ /* Try the modules in the order specified by sound_modules[] */ for (i = 0; i < (int)N_ELEMENTS(sound_modules); i++) if (!soundstr || streq(soundstr, sound_modules[i].name)) if (0 == sound_modules[i].init(argc, argv)) break; /* Catch nasty signals */ signals_init(); /* Set up the command hook */ cmd_get_hook = textui_get_cmd; /* Set up the display handlers and things. */ init_display(); init_angband(); textui_init(); /* Wait for response */ pause_line(Term); /* Play the game */ play_game(new_game); /* Free resources */ textui_cleanup(); cleanup_angband(); /* Quit */ quit(NULL); /* Exit */ return (0); }
/** * Helper function for "process_pref_file()" * * Input: * v: output buffer array * f: final character * * Output: * result */ static const char *process_pref_file_expr(char **sp, char *fp) { const char *v; char *b; char *s; char f = ' '; /* Initial */ s = (*sp); /* Skip spaces */ while (isspace((unsigned char)*s)) s++; /* Save start */ b = s; /* Default */ v = "?o?o?"; /* Either the string starts with a [ or it doesn't */ if (*s == '[') { const char *p; const char *t; /* Skip [ */ s++; /* First */ t = process_pref_file_expr(&s, &f); /* Check all the different types of connective */ if (!*t) { /* Nothing */ } else if (streq(t, "IOR")) { v = "0"; while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); if (*t && !streq(t, "0")) v = "1"; } } else if (streq(t, "AND")) { v = "1"; while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); if (*t && streq(t, "0")) v = "0"; } } else if (streq(t, "NOT")) { v = "1"; while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); if (*t && !streq(t, "0")) v = "0"; } } else if (streq(t, "EQU")) { v = "1"; if (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } while (*s && (f != ']')) { p = t; t = process_pref_file_expr(&s, &f); if (*t && !streq(p, t)) v = "0"; } } else if (streq(t, "LEQ")) { v = "1"; if (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } while (*s && (f != ']')) { p = t; t = process_pref_file_expr(&s, &f); if (*t && (strcmp(p, t) >= 0)) v = "0"; } } else if (streq(t, "GEQ")) { v = "1"; if (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } while (*s && (f != ']')) { p = t; t = process_pref_file_expr(&s, &f); if (*t && (strcmp(p, t) <= 0)) v = "0"; } } else { while (*s && (f != ']')) { t = process_pref_file_expr(&s, &f); } } /* Verify ending */ if (f != ']') v = "?x?x?"; /* Extract final and Terminate */ if ((f = *s) != '\0') *s++ = '\0'; } else { /* Accept all printables except spaces and brackets */ while (isprint((unsigned char)*s) && !strchr(" []", *s)) ++s; /* Extract final and Terminate */ if ((f = *s) != '\0') *s++ = '\0'; /* Variables start with $, otherwise it's a constant */ if (*b == '$') { if (streq(b+1, "SYS")) v = ANGBAND_SYS; else if (streq(b+1, "RACE")) v = player->race->name; else if (streq(b+1, "CLASS")) v = player->class->name; else if (streq(b+1, "PLAYER")) v = player_safe_name(player, true); } else {