/* * Hack -- main Angband initialization entry point * * Verify some files, display the "news.txt" file, create * the high score file, initialize all internal arrays, and * load the basic "user pref files". * * Be very careful to keep track of the order in which things * are initialized, in particular, the only thing *known* to * be available when this function is called is the "z-term.c" * package, and that may not be fully initialized until the * end of this function, when the default "user pref files" * are loaded and "Term_xtra(TERM_XTRA_REACT,0)" is called. * * Note that this function attempts to verify the "news" file, * and the game aborts (cleanly) on failure, since without the * "news" file, it is likely that the "lib" folder has not been * correctly located. Otherwise, the news file is displayed for * the user. * * Note that this function attempts to verify (or create) the * "high score" file, and the game aborts (cleanly) on failure, * since one of the most common "extraction" failures involves * failing to extract all sub-directories (even empty ones), such * as by failing to use the "-d" option of "pkunzip", or failing * to use the "save empty directories" option with "Compact Pro". * This error will often be caught by the "high score" creation * code below, since the "lib/apex" directory, being empty in the * standard distributions, is most likely to be "lost", making it * impossible to create the high score file. * * Note that various things are initialized by this function, * including everything that was once done by "init_some_arrays". * * This initialization involves the parsing of special files * in the "lib/edit" directories. * * Note that the "template" files are initialized first, since they * often contain errors. This means that macros and message recall * and things like that are not available until after they are done. * * We load the default "user pref files" here in case any "color" * changes are needed before character creation. * * Note that the "graf-xxx.prf" file must be loaded separately, * if needed, in the first (?) pass through "TERM_XTRA_REACT". */ public static bool init_angband() { Game_Event.signal(Game_Event.Event_Type.ENTER_INIT); /*** Initialize some arrays ***/ Init.arrays(); /*** Load default user pref files ***/ /* Initialize feature info */ Game_Event.signal_string(Game_Event.Event_Type.INITSTATUS, "Loading basic user pref file..."); /* Process that file */ Prefs.process_pref_file("pref.prf", false, false); /* Done */ Game_Event.signal_string(Game_Event.Event_Type.INITSTATUS, "Initialization complete"); /* Sneakily init command list */ Command.Init(); //#ifdef ALLOW_BORG /* apw */ // /* Allow the screensaver to do its work */ // if (screensaver) // { // event_signal(EVENT_LEAVE_INIT); // return !file_exists(savefile); // } //#endif /* ALLOW_BORG */ /* Ask for a "command" until we get one we like. */ while (true) { Game_Command command_req = new Game_Command(); if (Game_Command.get(cmd_context.CMD_INIT, ref command_req, true) == null) { continue; } else if (command_req.command == Command_Code.QUAFF) { Utilities.quit(); } else if (command_req.command == Command_Code.NEWGAME) { Game_Event.signal(Game_Event.Event_Type.LEAVE_INIT); return(true); } else if (command_req.command == Command_Code.LOADFILE) { Game_Event.signal(Game_Event.Event_Type.LEAVE_INIT); return(false); } } }
const int MAX_BIRTH_POINTS = 24; /* 3 * (1+1+1+1+1+1+2) */ static void recalculate_stats(short[] stats, int points_left) { /* Process stats */ for (int i = 0; i < (int)Stat.Max; i++) { /* Variable stat maxes */ if (Option.birth_maximize.value) { /* Reset stats */ Player.Player.instance.stat_cur[i] = Player.Player.instance.stat_max[i] = Player.Player.instance.stat_birth[i] = stats[i]; } /* Fixed stat maxes */ else { int bonus = 0; /* Obtain a "bonus" for "race" and "class" */ if (Player.Player.instance.Race != null || Player.Player.instance.Class != null) { bonus = Player.Player.instance.Race.r_adj[i] + Player.Player.instance.Class.c_adj[i]; } /* Apply the racial/class bonuses */ Player.Player.instance.stat_cur[i] = Player.Player.instance.stat_max[i] = Player.Player.instance.stat_birth[i] = modify_stat_value(stats[i], bonus); } } /* Gold is inversely proportional to cost */ Player.Player.instance.au_birth = STARTING_GOLD + (50 * points_left); /* Update bonuses, hp, etc. */ get_bonuses(); /* Tell the UI about all this stuff that's changed. */ Game_Event.signal(Game_Event.Event_Type.GOLD); Game_Event.signal(Game_Event.Event_Type.AC); Game_Event.signal(Game_Event.Event_Type.HP); Game_Event.signal(Game_Event.Event_Type.STATS); }
/* * Create a new character. * * Note that we may be called with "junk" leftover in the various * fields, so we must be sure to clear them first. */ public static void player_birth(bool quickstart_allowed) { Game_Command blank = new Game_Command(Command_Code.NULL, null, null, false, 0); Game_Command cmd = blank; short[] stats = new short[(int)Stat.Max]; int[] points_spent = new int[(int)Stat.Max]; int points_left = 0; string buf; int success; bool rolled_stats = false; /* * The last character displayed, to allow the user to flick between two. * We rely on prev.age being zero to determine whether there is a stored * character or not, so initialise it here. */ Birther prev = new Birther(); /* * If quickstart is allowed, we store the old character in this, * to allow for it to be reloaded if we step back that far in the * birth process. */ Birther quickstart_prev = new Birther(); /* * If there's a quickstart character, store it for later use. * If not, default to whatever the first of the choices is. */ if (quickstart_allowed) { quickstart_prev.save_roller_data(); } else { Player.Player.instance.psex = 0; /* XXX default race/class */ Player.Player.instance.Class = Misc.classes; Player.Player.instance.Race = Misc.races; Player.Player.instance.generate(null, null, null); } /* Handle incrementing name suffix */ buf = Utilities.find_roman_suffix_start(Player_Other.instance.full_name); if (buf != null) { /* Try to increment the roman suffix */ success = Utilities.int_to_roman((Utilities.roman_to_int(buf) + 1), buf); if (success == 0) { Utilities.msg("Sorry, could not deal with suffix"); } } /* We're ready to start the interactive birth process. */ Game_Event.signal_flag(Game_Event.Event_Type.ENTER_BIRTH, quickstart_allowed); /* * Loop around until the UI tells us we have an acceptable character. * Note that it is possible to quit from inside this loop. */ while (cmd.command != Command_Code.ACCEPT_CHARACTER) { /* Grab a command from the queue - we're happy to wait for it. */ if (Game_Command.get(cmd_context.CMD_BIRTH, ref cmd, true) == null) { continue; } if (cmd.command == Command_Code.BIRTH_RESET) { Player.Player.instance.generate(null, null, null); reset_stats(stats, points_spent, ref points_left); do_birth_reset(quickstart_allowed, quickstart_prev); rolled_stats = false; } else if (cmd.command == Command_Code.CHOOSE_SEX) { Player.Player.instance.psex = (byte)cmd.arg[0].value; Player.Player.instance.generate(null, null, null); } else if (cmd.command == Command_Code.CHOOSE_RACE) { Player.Player.instance.generate(null, Player_Race.player_id2race(cmd.arg[0].value), null); reset_stats(stats, points_spent, ref points_left); generate_stats(stats, points_spent, ref points_left); rolled_stats = false; } else if (cmd.command == Command_Code.CHOOSE_CLASS) { Player.Player.instance.generate(null, null, Player_Class.player_id2class(cmd.arg[0].value)); reset_stats(stats, points_spent, ref points_left); generate_stats(stats, points_spent, ref points_left); rolled_stats = false; } else if (cmd.command == Command_Code.FINALIZE_OPTIONS) { /* Reset score options from cheat options */ for (int i = Option.CHEAT; i < Option.CHEAT + Option.N_OPTS_CHEAT; i++) { Player_Other.instance.opt[Option.SCORE + (i - Option.CHEAT)] = Player_Other.instance.opt[i]; } } else if (cmd.command == Command_Code.BUY_STAT) { /* .choice is the stat to buy */ if (!rolled_stats) { buy_stat((Stat)cmd.arg[0].value, stats, points_spent, ref points_left); } } else if (cmd.command == Command_Code.SELL_STAT) { /* .choice is the stat to sell */ if (!rolled_stats) { sell_stat((Stat)cmd.arg[0].value, stats, points_spent, ref points_left); } } else if (cmd.command == Command_Code.RESET_STATS) { /* .choice is whether to regen stats */ reset_stats(stats, points_spent, ref points_left); if (cmd.arg[0].value == 1) { generate_stats(stats, points_spent, ref points_left); } rolled_stats = false; } else if (cmd.command == Command_Code.ROLL_STATS) { throw new NotImplementedException(); //int i; //save_roller_data(&prev); ///* Get a new character */ //get_stats(stats); ///* Update stats with bonuses, etc. */ //get_bonuses(); ///* There's no real need to do this here, but it's tradition. */ //get_ahw(Player.Player.instance); //Player.Player.instance.history = get_history(Player.Player.instance.race.history, &Player.Player.instance.sc); //Player.Player.instance.sc_birth = Player.Player.instance.sc; //event_signal(EVENT_GOLD); //event_signal(EVENT_AC); //event_signal(EVENT_HP); //event_signal(EVENT_STATS); ///* Give the UI some dummy info about the points situation. */ //points_left = 0; //for (i = 0; i < A_MAX; i++) //{ // points_spent[i] = 0; //} //event_signal_birthpoints(points_spent, points_left); ///* Lock out buying and selling of stats based on rolled stats. */ //rolled_stats = true; } else if (cmd.command == Command_Code.PREV_STATS) { throw new NotImplementedException(); ///* Only switch to the stored "previous" // character if we've actually got one to load. */ //if (prev.age) //{ // load_roller_data(&prev, &prev); // get_bonuses(); //} //event_signal(EVENT_GOLD); //event_signal(EVENT_AC); //event_signal(EVENT_HP); //event_signal(EVENT_STATS); } else if (cmd.command == Command_Code.NAME_CHOICE) { /* Set player name */ Player_Other.instance.full_name = cmd.arg[0].text; //string_free((void *) cmd.arg[0].string); /* Don't change savefile name. If the UI wants it changed, they can do it. XXX (Good idea?) */ Files.process_player_name(false); } /* Various not-specific-to-birth commands. */ else if (cmd.command == Command_Code.HELP) { throw new NotImplementedException(); //char buf[80]; //strnfmt(buf, sizeof(buf), "birth.txt"); //screen_save(); //show_file(buf, null, 0, 0); //screen_load(); } else if (cmd.command == Command_Code.QUIT) { Utilities.quit(); } } roll_hp(); Squelch.birth_init(); /* Clear old messages, add new starting message */ History.clear(); History.add("Began the quest to destroy Morgoth.", History.PLAYER_BIRTH, null); /* Reset message prompt (i.e. no extraneous -more-s) */ Term.msg_flag = true; /* Note player birth in the message recall */ Message.add(" ", Message_Type.MSG_GENERIC); Message.add(" ", Message_Type.MSG_GENERIC); Message.add("====================", Message_Type.MSG_GENERIC); Message.add(" ", Message_Type.MSG_GENERIC); Message.add(" ", Message_Type.MSG_GENERIC); /* Give the player some money */ get_money(); /* Outfit the player, if they can sell the stuff */ if (!Option.birth_no_selling.value) { player_outfit(Player.Player.instance); } /* Initialise the stores */ Store.reset(); /* Now we're really done.. */ Game_Event.signal(Game_Event.Event_Type.LEAVE_BIRTH); }