/trunk/IronHellsOgre/src/ironhells/angband/birth.c
C | 1531 lines | 854 code | 292 blank | 385 comment | 186 complexity | 4d4ac96f562a46f5d67ae33864a73cd0 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, Apache-2.0
- /* $Id: birth.c 217 2004-11-12 14:22:13Z cipher $ */
- /*
- * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
- *
- * This software may be copied and distributed for educational, research,
- * and not for profit purposes provided that this copyright and statement
- * are included in all such copies. Other copyrights may also apply.
- */
- #include "angband.h"
- #include "script.h"
- /*
- * Forward declare
- */
- typedef struct birther birther;
- /*
- * A structure to hold "rolled" information
- */
- struct birther
- {
- s16b age;
- s16b wt;
- s16b ht;
- s16b sc;
- s32b au;
- s16b stat[A_MAX];
- char history[250];
- };
- /*
- * The last character displayed
- */
- static birther prev;
- /*
- * Current stats (when rolling a character).
- */
- static s16b stat_use[A_MAX];
- /*
- * Save the currently rolled data for later.
- */
- static void
- save_prev_data(void)
- {
- int i;
- /*** Save the current data ***/
- /* Save the data */
- prev.age = p_ptr->age;
- prev.wt = p_ptr->wt;
- prev.ht = p_ptr->ht;
- prev.sc = p_ptr->sc;
- prev.au = p_ptr->au;
- /* Save the stats */
- for(i = 0; i < A_MAX; i++)
- {
- prev.stat[i] = p_ptr->stat_max[i];
- }
- /* Save the history */
- my_strcpy(prev.history, p_ptr->history, sizeof(prev.history));
- }
- /*
- * Load the previously rolled data.
- */
- static void
- load_prev_data(void)
- {
- int i;
- birther temp;
- /*** Save the current data ***/
- /* Save the data */
- temp.age = p_ptr->age;
- temp.wt = p_ptr->wt;
- temp.ht = p_ptr->ht;
- temp.sc = p_ptr->sc;
- temp.au = p_ptr->au;
- /* Save the stats */
- for(i = 0; i < A_MAX; i++)
- {
- temp.stat[i] = p_ptr->stat_max[i];
- }
- /* Save the history */
- my_strcpy(temp.history, p_ptr->history, sizeof(temp.history));
- /*** Load the previous data ***/
- /* Load the data */
- p_ptr->age = prev.age;
- p_ptr->wt = prev.wt;
- p_ptr->ht = prev.ht;
- p_ptr->sc = prev.sc;
- p_ptr->au = prev.au;
- /* Load the stats */
- for(i = 0; i < A_MAX; i++)
- {
- p_ptr->stat_max[i] = prev.stat[i];
- p_ptr->stat_cur[i] = prev.stat[i];
- }
- /* Load the history */
- my_strcpy(p_ptr->history, prev.history, sizeof(p_ptr->history));
- /*** Save the current data ***/
- /* Save the data */
- prev.age = temp.age;
- prev.wt = temp.wt;
- prev.ht = temp.ht;
- prev.sc = temp.sc;
- prev.au = temp.au;
- /* Save the stats */
- for(i = 0; i < A_MAX; i++)
- {
- prev.stat[i] = temp.stat[i];
- }
- /* Save the history */
- my_strcpy(prev.history, temp.history, sizeof(prev.history));
- }
- /*
- * Adjust a stat by an amount.
- *
- * This just uses "modify_stat_value()" unless "maximize" mode is false,
- * and a positive bonus is being applied, in which case, a special hack
- * is used, with the "auto_roll" flag affecting the result.
- *
- * The "auto_roll" flag selects "maximal" changes for use with the
- * auto-roller initialization code. Otherwise, if "maximize" mode
- * is being used, the changes are fixed. Otherwise, semi-random
- * changes will occur, with larger changes at lower values.
- */
- static int
- adjust_stat(int value,
- int amount,
- int auto_roll)
- {
- /* Negative amounts or maximize mode */
- if((amount < 0) || adult_maximize)
- {
- return (modify_stat_value(value, amount));
- }
- /* Special hack */
- else
- {
- int i;
- /* Apply reward */
- for(i = 0; i < amount; i++)
- {
- if(value < 18)
- {
- value++;
- }
- else if(value < 18 + 70)
- {
- value += ((auto_roll ? 15 : randint(15)) + 5);
- }
- else if(value < 18 + 90)
- {
- value += ((auto_roll ? 6 : randint(6)) + 2);
- }
- else if(value < 18 + 100)
- {
- value++;
- }
- }
- }
- /* Return the result */
- return (value);
- }
- /*
- * Roll for a characters stats
- *
- * For efficiency, we include a chunk of "calc_bonuses()".
- */
- static void
- get_stats(void)
- {
- int i, j;
- int bonus;
- int dice[18];
- /* Roll and verify some stats */
- while(TRUE)
- {
- /* Roll some dice */
- for(j = i = 0; i < 18; i++)
- {
- /* Roll the dice */
- dice[i] = randint(3 + i % 3);
- /* Collect the maximum */
- j += dice[i];
- }
- /* Verify totals */
- if((j > 42) && (j < 54))
- break;
- }
- /* Roll the stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* Extract 5 + 1d3 + 1d4 + 1d5 */
- j = 5 + dice[3 * i] + dice[3 * i + 1] + dice[3 * i + 2];
- /* Save that value */
- p_ptr->stat_max[i] = j;
- /* Obtain a "bonus" for "race" and "class" */
- bonus = rp_ptr->r_adj[i] + cp_ptr->c_adj[i];
- /* Variable stat maxes */
- if(adult_maximize)
- {
- /* Start fully healed */
- p_ptr->stat_cur[i] = p_ptr->stat_max[i];
- /* Efficiency -- Apply the racial/class bonuses */
- stat_use[i] = modify_stat_value(p_ptr->stat_max[i], bonus);
- }
- /* Fixed stat maxes */
- else
- {
- /* Apply the bonus to the stat (somewhat randomly) */
- stat_use[i] = adjust_stat(p_ptr->stat_max[i], bonus, FALSE);
- /* Save the resulting stat maximum */
- p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stat_use[i];
- }
- }
- }
- /*
- * Roll for some info that the auto-roller ignores
- */
- static void
- get_extra(void)
- {
- int i, j, min_value, max_value;
- /* Level one */
- p_ptr->max_lev = p_ptr->lev = 1;
- /* Experience factor */
- p_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp;
- /* Hitdice */
- p_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp;
- /* Initial hitpoints */
- p_ptr->mhp = p_ptr->hitdie;
- /* Minimum hitpoints at highest level */
- min_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 3) / 8;
- min_value += PY_MAX_LEVEL;
- /* Maximum hitpoints at highest level */
- max_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 5) / 8;
- max_value += PY_MAX_LEVEL;
- /* Pre-calculate level 1 hitdice */
- p_ptr->player_hp[0] = p_ptr->hitdie;
- /* Roll out the hitpoints */
- while(TRUE)
- {
- /* Roll the hitpoint values */
- for(i = 1; i < PY_MAX_LEVEL; i++)
- {
- j = randint(p_ptr->hitdie);
- p_ptr->player_hp[i] = p_ptr->player_hp[i - 1] + j;
- }
- /* XXX Could also require acceptable "mid-level" hitpoints */
- /* Require "valid" hitpoints at highest level */
- if(p_ptr->player_hp[PY_MAX_LEVEL - 1] < min_value)
- continue;
- if(p_ptr->player_hp[PY_MAX_LEVEL - 1] > max_value)
- continue;
- /* Acceptable */
- break;
- }
- }
- /*
- * Get the racial history, and social class, using the "history charts".
- */
- static void
- get_history(void)
- {
- int i, chart, roll, social_class;
- /* Clear the previous history strings */
- p_ptr->history[0] = '\0';
- /* Initial social class */
- social_class = randint(4);
- /* Starting place */
- chart = rp_ptr->hist;
- /* Process the history */
- while(chart)
- {
- /* Start over */
- i = 0;
- /* Roll for nobility */
- roll = randint(100);
- /* Get the proper entry in the table */
- while((chart != h_info[i].chart) || (roll > h_info[i].roll))
- i++;
- /* Get the textual history */
- my_strcat(p_ptr->history, (h_text + h_info[i].text),
- sizeof(p_ptr->history));
- /* Add in the social class */
- social_class += (int) (h_info[i].bonus) - 50;
- /* Enter the next chart */
- chart = h_info[i].next;
- }
- /* Verify social class */
- if(social_class > 100)
- social_class = 100;
- else if(social_class < 1)
- social_class = 1;
- /* Save the social class */
- p_ptr->sc = social_class;
- }
- /*
- * Computes character's age, height, and weight
- */
- static void
- get_ahw(void)
- {
- /* Calculate the age */
- p_ptr->age = rp_ptr->b_age + randint(rp_ptr->m_age);
- /* Calculate the height/weight for males */
- if(p_ptr->psex == SEX_MALE)
- {
- p_ptr->ht = Rand_normal(rp_ptr->m_b_ht, rp_ptr->m_m_ht);
- p_ptr->wt = Rand_normal(rp_ptr->m_b_wt, rp_ptr->m_m_wt);
- }
- /* Calculate the height/weight for females */
- else if(p_ptr->psex == SEX_FEMALE)
- {
- p_ptr->ht = Rand_normal(rp_ptr->f_b_ht, rp_ptr->f_m_ht);
- p_ptr->wt = Rand_normal(rp_ptr->f_b_wt, rp_ptr->f_m_wt);
- }
- }
- /*
- * Get the player's starting money
- */
- static void
- get_money(void)
- {
- int i;
- int gold;
- /* Social Class determines starting gold */
- gold = (p_ptr->sc * 6) + randint(100) + 300;
- /* Process the stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* Mega-Hack -- reduce gold for high stats */
- if(stat_use[i] >= 18 + 50)
- gold -= 300;
- else if(stat_use[i] >= 18 + 20)
- gold -= 200;
- else if(stat_use[i] > 18)
- gold -= 150;
- else
- gold -= (stat_use[i] - 8) * 10;
- }
- /* Minimum 100 gold */
- if(gold < 100)
- gold = 100;
- /* Save the gold */
- p_ptr->au = gold;
- }
- /*
- * Clear all the global "character" data
- */
- static void
- player_wipe(void)
- {
- int i;
- /* Wipe the player */
- (void) WIPE(p_ptr, player_type);
- /* Clear the inventory */
- for(i = 0; i < INVEN_TOTAL; i++)
- {
- object_wipe(&inventory[i]);
- }
- /* Start with no artifacts made yet */
- for(i = 0; i < z_info->a_max; i++)
- {
- artifact_type *a_ptr = &a_info[i];
- a_ptr->cur_num = 0;
- }
- /* Start with no quests */
- for(i = 0; i < MAX_Q_IDX; i++)
- {
- q_list[i].level = 0;
- }
- /* Add a special quest */
- q_list[0].level = 99;
- /* Add a second quest */
- q_list[1].level = 100;
- /* Reset the "objects" */
- for(i = 1; i < z_info->k_max; i++)
- {
- object_kind *k_ptr = &k_info[i];
- /* Reset "tried" */
- k_ptr->tried = FALSE;
- /* Reset "aware" */
- k_ptr->aware = FALSE;
- }
- /* Reset the "monsters" */
- for(i = 1; i < z_info->r_max; i++)
- {
- monster_race *r_ptr = &r_info[i];
- monster_lore *l_ptr = &l_list[i];
- /* Hack -- Reset the counter */
- r_ptr->cur_num = 0;
- /* Hack -- Reset the max counter */
- r_ptr->max_num = 100;
- /* Hack -- Reset the max counter */
- if(r_ptr->flags1 & (RF1_UNIQUE))
- r_ptr->max_num = 1;
- /* Clear player kills */
- l_ptr->pkills = 0;
- }
- /* Hack -- no ghosts */
- r_info[z_info->r_max - 1].max_num = 0;
- /* Hack -- Well fed player */
- p_ptr->food = PY_FOOD_FULL - 1;
- /* None of the spells have been learned yet */
- for(i = 0; i < PY_MAX_SPELLS; i++)
- p_ptr->spell_order[i] = 99;
- }
- /*
- * Init players with some belongings
- *
- * Having an item makes the player "aware" of its purpose.
- */
- static void
- player_outfit(void)
- {
- int i;
- const start_item *e_ptr;
- object_type *i_ptr;
- object_type object_type_body;
- /* Hack -- Give the player his equipment */
- for(i = 0; i < MAX_START_ITEMS; i++)
- {
- /* Access the item */
- e_ptr = &(cp_ptr->start_items[i]);
- /* Get local object */
- i_ptr = &object_type_body;
- /* Hack -- Give the player an object */
- if(e_ptr->tval > 0)
- {
- /* Get the object_kind */
- int k_idx =
- lookup_kind(e_ptr->tval, e_ptr->sval);
- /* Valid item? */
- if(!k_idx)
- continue;
- /* Prepare the item */
- object_prep(i_ptr, k_idx);
- i_ptr->number = (byte) rand_range(e_ptr->min, e_ptr->max);
- object_aware(i_ptr);
- object_known(i_ptr);
- (void) inven_carry(i_ptr);
- }
- }
- }
- /*
- * Helper function for 'player_birth()'.
- *
- * This function allows the player to select a sex, race, and class, and
- * modify options (including the birth options).
- */
- static bool
- player_birth_aux_1(void)
- {
- int k, n, i;
- cptr str;
- char ch;
- #if 0
- char p1 = '(';
- #endif
- char p2 = ')';
- char buf[80];
- /*** Instructions ***/
- /* Clear screen */
- Disp_clear();
- /* Display some helpful information */
- Disp_putstr(5, 10, -1, COLOR_WHITE,
- "Please answer the following questions. Most of the questions");
- Disp_putstr(5, 11, -1, COLOR_WHITE,
- "display a set of standard answers, and many will also accept");
- Disp_putstr(5, 12, -1, COLOR_WHITE,
- "some special responses, including 'Q' to quit, 'S' to restart,");
- Disp_putstr(5, 13, -1, COLOR_WHITE,
- "and '?' for help. Note that 'Q' and 'S' must be capitalized.");
- /*** Player sex ***/
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_GENDER);
- /* Extra info */
- Disp_putstr(5, 15, -1, COLOR_WHITE,
- "Your 'sex' does not have any significant gameplay effects.");
- /* Prompt for "Sex" */
- for(n = 0; n < MAX_SEXES; n++)
- {
- /* Analyze */
- p_ptr->psex = n;
- sp_ptr = &sex_info[p_ptr->psex];
- str = sp_ptr->title;
- /* Display */
- strnfmt(buf, sizeof(buf), "%c%c %s", I2A(n), p2, str);
- put_str(buf, 21 + (n / 5), 2 + 15 * (n % 5));
- }
- /* Choose */
- sp_ptr = NULL;
- while(1)
- {
- sprintf(buf, "Choose a sex (%c-%c, or * for random): ",
- I2A(0), I2A(n - 1));
- put_str(buf, 20, 2);
- ch = inkey();
- if(ch == 'Q')
- quit(NULL);
- if(ch == 'S')
- return (FALSE);
- k = (islower((unsigned char) ch) ? A2I(ch) : -1);
- if(ch == ESCAPE)
- ch = '*';
- if(ch == '*')
- k = rand_int(MAX_SEXES);
- if((k >= 0) && (k < n))
- break;
- if(ch == '?')
- do_cmd_help();
- else
- bell("Illegal sex!");
- }
- /* Set sex */
- p_ptr->psex = k;
- sp_ptr = &sex_info[p_ptr->psex];
- /* Sex */
- put_str("Sex", 3, 1);
- c_put_str(COLOR_L_BLUE, sp_ptr->title, 3, 8);
- /* Clean up */
- clear_from(15);
- /*** Player race ***/
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_RACE);
- /* Extra info */
- Disp_putstr(5, 15, -1, COLOR_WHITE,
- "Your 'race' determines various intrinsic factors and bonuses.");
- /* Dump races */
- for(n = 0; n < z_info->p_max; n++)
- {
- /* Analyze */
- p_ptr->prace = n;
- rp_ptr = &p_info[n];
- str = p_name + rp_ptr->name;
- /* Display */
- strnfmt(buf, sizeof(buf), "%c%c %s", I2A(n), p2, str);
- put_str(buf, 21 + (n / 5), 2 + 15 * (n % 5));
- }
- /* Choose */
- rp_ptr = NULL;
- while(1)
- {
- sprintf(buf, "Choose a race (%c-%c, or * for random): ",
- I2A(0), I2A(n - 1));
- put_str(buf, 20, 2);
- ch = inkey();
- if(ch == 'Q')
- quit(NULL);
- if(ch == 'S')
- return (FALSE);
- k = (islower((unsigned char) ch) ? A2I(ch) : -1);
- if(ch == ESCAPE)
- ch = '*';
- if(ch == '*')
- k = rand_int(z_info->p_max);
- if((k >= 0) && (k < n))
- break;
- if(ch == '?')
- do_cmd_help();
- else
- bell("Illegal race!");
- }
- /* Set race */
- p_ptr->prace = k;
- rp_ptr = &p_info[p_ptr->prace];
- /* Race */
- put_str("Race", 4, 1);
- c_put_str(COLOR_L_BLUE, p_name + rp_ptr->name, 4, 8);
- /* Clean up */
- clear_from(15);
- /*** Player class ***/
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_CLASS);
- /* Extra info */
- Disp_putstr(5, 15, -1, COLOR_WHITE,
- "Your 'class' determines various intrinsic abilities and bonuses.");
- Disp_putstr(5, 16, -1, COLOR_WHITE,
- "Any entries with a (*) should only be used by advanced players.");
- /* Dump classes */
- for(n = 0; n < z_info->c_max; n++)
- {
- cptr mod = "";
- /* Analyze */
- p_ptr->pclass = n;
- cp_ptr = &c_info[p_ptr->pclass];
- mp_ptr = &cp_ptr->spells;
- str = c_name + cp_ptr->name;
- /* Verify legality */
- if(!(rp_ptr->choice & (1L << n)))
- mod = " (*)";
- /* Display */
- strnfmt(buf, sizeof(buf), "%c%c %s%s", I2A(n), p2, str, mod);
- put_str(buf, 21 + (n / 3), 2 + 20 * (n % 3));
- }
- /* Get a class */
- cp_ptr = NULL;
- while(1)
- {
- sprintf(buf, "Choose a class (%c-%c, or * for random): ",
- I2A(0), I2A(n - 1));
- put_str(buf, 20, 2);
- ch = inkey();
- if(ch == 'Q')
- quit(NULL);
- if(ch == 'S')
- return (FALSE);
- k = (islower((unsigned char) ch) ? A2I(ch) : -1);
- if(ch == ESCAPE)
- ch = '*';
- if(ch == '*')
- {
- while(1)
- {
- k = rand_int(z_info->c_max);
- /* Try again if not a legal choice */
- if(!(rp_ptr->choice & (1L << k)))
- continue;
- break;
- }
- }
- if((k >= 0) && (k < n))
- break;
- if(ch == '?')
- do_cmd_help();
- else
- bell("Illegal class!");
- }
- /* Set class */
- p_ptr->pclass = k;
- cp_ptr = &c_info[p_ptr->pclass];
- mp_ptr = &cp_ptr->spells;
- /* Class */
- put_str("Class", 5, 1);
- c_put_str(COLOR_L_BLUE, c_name + cp_ptr->name, 5, 8);
- /* Clean up */
- clear_from(15);
- /*** Birth options ***/
- fprintf(stderr, "player_birth_aux_1(): options?\n");
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_OPTIONS_QUERY);
- /* Extra info */
- Disp_putstr(5, 15, -1, COLOR_WHITE,
- "You can change your options at any time, but the 'Birth' options");
- Disp_putstr(5, 16, -1, COLOR_WHITE,
- "must be changed now to affect the birth of this character.");
- /* Verify birth options */
- fprintf(stderr, "player_birth_aux_1(): options input loop\n");
- while(1)
- {
- sprintf(buf, "Modify options (y/n)? ");
- put_str(buf, 20, 2);
- ch = inkey();
- fprintf(stderr, "player_birth_aux_1(): ch = %c\n", ch);
- if(ch == 'Q')
- quit(NULL);
- if(ch == 'S')
- return (FALSE);
- if((ch == '\r') || (ch == '\n'))
- break;
- if(ch == 'y' || ch == 'n')
- break;
- if(ch == '?')
- do_cmd_help();
- else
- bell("Illegal answer!");
- }
- /* Verify */
- fprintf(stderr, "player_birth_aux_1(): verify\n");
- if(ch == 'y')
- {
- Disp_xtra(DISP_XTRA_PREP, DISPLAY_OPTIONS);
- Disp_xtra(DISP_XTRA_SHOW, DISPLAY_OPTIONS);
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_OPTIONS);
-
- /* Interact with options */
- do_cmd_options();
- }
- /* Set adult options from birth options */
- fprintf(stderr, "player_birth_aux_1(): set adult options\n");
- for(i = OPT_BIRTH; i < OPT_CHEAT; i++)
- {
- op_ptr->opt[OPT_ADULT + (i - OPT_BIRTH)] = op_ptr->opt[i];
- }
- /* Reset score options from cheat options */
- for(i = OPT_CHEAT; i < OPT_ADULT; i++)
- {
- op_ptr->opt[OPT_SCORE + (i - OPT_CHEAT)] = op_ptr->opt[i];
- }
- /* Clean up */
- clear_from(10);
- /* Done */
- fprintf(stderr, "player_birth_aux_1(): return TRUE\n");
- return (TRUE);
- }
- /*
- * Initial stat costs (initial stats always range from 10 to 18 inclusive).
- */
- static const int birth_stat_costs[(18 - 10) + 1] =
- { 0, 1, 2, 4, 7, 11, 16, 22, 30 };
- /*
- * Helper function for 'player_birth()'.
- *
- * This function handles "point-based" character creation.
- *
- * The player selects, for each stat, a value from 10 to 18 (inclusive),
- * each costing a certain amount of points (as above), from a pool of 48
- * available points, to which race/class modifiers are then applied.
- *
- * Each unused point is converted into 100 gold pieces.
- */
- static bool
- player_birth_aux_2(void)
- {
- int i;
- int row = 3;
- int col = 42;
- int stat = 0;
- int stats[A_MAX];
- int cost;
- char ch;
- char buf[80];
- /* Set the display */
- Disp_xtra(DISP_XTRA_STAGE,
- SCENE_NEW_CHARACTER_STAGE_STATS_POINTBASED);
- /* Initialize stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* Initial stats */
- stats[i] = 10;
- }
- /* Roll for base hitpoints */
- get_extra();
- /* Roll for age/height/weight */
- get_ahw();
- /* Roll for social class */
- get_history();
- /* Interact */
- while(1)
- {
- /* Reset cost */
- cost = 0;
- /* Process stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* Variable stat maxes */
- if(adult_maximize)
- {
- /* Reset stats */
- p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stats[i];
- }
- /* Fixed stat maxes */
- else
- {
- /* Obtain a "bonus" for "race" and "class" */
- int bonus =
- rp_ptr->r_adj[i] + cp_ptr->c_adj[i];
- /* Apply the racial/class bonuses */
- p_ptr->stat_cur[i] = p_ptr->stat_max[i] =
- modify_stat_value(stats[i], bonus);
- }
- /* Total cost */
- cost += birth_stat_costs[stats[i] - 10];
- }
- /* Restrict cost */
- if(cost > 48)
- {
- /* Warning */
- bell("Excessive stats!");
- /* Reduce stat */
- stats[stat]--;
- /* Recompute costs */
- continue;
- }
- /* Gold is inversely proportional to cost */
- p_ptr->au = (100 * (48 - cost)) + 100;
- /* Calculate the bonuses and hitpoints */
- p_ptr->update |= (PU_BONUS | PU_HP);
- /* Update stuff */
- update_stuff();
- /* Fully healed */
- p_ptr->chp = p_ptr->mhp;
- /* Fully rested */
- p_ptr->csp = p_ptr->msp;
- /* Display the player */
- display_player(0);
- /* Display the costs header */
- put_str("Cost", row - 1, col + 32);
- /* Display the costs */
- for(i = 0; i < A_MAX; i++)
- {
- /* Display cost */
- sprintf(buf, "%4d", birth_stat_costs[stats[i] - 10]);
- put_str(buf, row + i, col + 32);
- }
- /* Prompt XXX XXX XXX */
- sprintf(buf,
- "Total Cost %2d/48. Use 2/8 to move, 4/6 to modify, 'Enter' to accept.",
- cost);
- prt(buf, 0, 0);
- /* Place cursor just after cost of current stat */
- Disp_gotoxy(col + 36, row + stat);
-
- Disp_param(DISPLAY_CHARACTER, DISP_PARAM_VAR1, (void *)(stat + 1));
- /* Get key */
- ch = inkey();
- /* Quit */
- if(ch == 'Q')
- quit(NULL);
- /* Start over */
- if(ch == 'S')
- return (FALSE);
- /* Done */
- if((ch == '\r') || (ch == '\n'))
- break;
- /* Prev stat */
- if(ch == '8')
- {
- stat = (stat + A_MAX - 1) % A_MAX;
- }
- /* Next stat */
- if(ch == '2')
- {
- stat = (stat + 1) % A_MAX;
- }
- /* Decrease stat */
- if((ch == '4') && (stats[stat] > 10))
- {
- stats[stat]--;
- }
- /* Increase stat */
- if((ch == '6') && (stats[stat] < 18))
- {
- stats[stat]++;
- }
- }
- /* Done */
- return (TRUE);
- }
- /*
- * Helper function for 'player_birth()'.
- *
- * This function handles "auto-rolling" and "random-rolling".
- *
- * The delay may be reduced, but is recommended to keep players
- * from continuously rolling up characters, which can be VERY
- * expensive CPU wise. And it cuts down on player stupidity.
- */
- static bool
- player_birth_aux_3(void)
- {
- int i, j, m, v;
- bool flag;
- bool prev = FALSE;
- char ch;
- char b1 = '[';
- char b2 = ']';
- char buf[80];
- #ifdef ALLOW_AUTOROLLER
- s16b stat_limit[A_MAX];
- s32b stat_match[A_MAX];
- s32b auto_round = 0L;
- s32b last_round;
- /*** Autoroll ***/
- /* Initialize */
- if(adult_auto_roller)
- {
- int mval[A_MAX];
- char inp[80];
- Disp_xtra(DISP_XTRA_STAGE,
- SCENE_NEW_CHARACTER_STAGE_STATS_AUTOROLLER);
- /* Extra info */
- Disp_putstr(5, 10, -1, COLOR_WHITE,
- "The auto-roller will automatically ignore characters which do");
- Disp_putstr(5, 11, -1, COLOR_WHITE,
- "not meet the minimum values for any stats specified below.");
- Disp_putstr(5, 12, -1, COLOR_WHITE,
- "Note that stats are not independent, so it is not possible to");
- Disp_putstr(5, 13, -1, COLOR_WHITE,
- "get perfect (or even high) values for all your stats.");
- /* Prompt for the minimum stats */
- put_str("Enter minimum value for: ", 15, 2);
- /* Output the maximum stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* Reset the "success" counter */
- stat_match[i] = 0;
- /* Race/Class bonus */
- j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i];
- /* Obtain the "maximal" stat */
- m = adjust_stat(17, j, TRUE);
- /* Save the maximum */
- mval[i] = m;
- /* Extract a textual format */
- /* cnv_stat(m, inp); */
- /* Above 18 */
- if(m > 18)
- {
- sprintf(inp, "(Max of 18/%02d):", (m - 18));
- }
- /* From 3 to 18 */
- else
- {
- sprintf(inp, "(Max of %2d):", m);
- }
- /* Prepare a prompt */
- strnfmt(buf, sizeof(buf), "%-5s%-20s", stat_names[i], inp);
- /* Dump the prompt */
- put_str(buf, 16 + i, 5);
-
- Disp_xtra(DISP_XTRA_PREP, DISPLAY_DIALOG);
- Disp_param(DISPLAY_DIALOG, DISP_PARAM_BUFFER1, (void *)buf);
-
- Disp_param(DISPLAY_DIALOG, DISP_PARAM_BUFFER2, (void *)inp);
- #if 0
- }
- /* Input the minimum stats */
- for(i = 0; i < A_MAX; i++)
- {
- #endif
- /* Get a minimum stat */
- while(TRUE)
- {
- char *s;
- /* Move the cursor */
- put_str("", 16 + i, 30);
- /* Default */
- strcpy(inp, "");
- /* Get a response (or escape) */
- Disp_xtra(DISP_XTRA_SHOW, DISPLAY_DIALOG);
-
- if(!askfor_aux(inp, 9))
- inp[0] = '\0';
- /* Hack -- add a fake slash */
- strcat(inp, "/");
- /* Hack -- look for the "slash" */
- s = strchr(inp, '/');
- /* Hack -- Nuke the slash */
- *s++ = '\0';
- /* Hack -- Extract an input */
- v = atoi(inp) + atoi(s);
- /* Break on valid input */
- if(v <= mval[i])
- break;
- }
- Disp_xtra(DISP_XTRA_HIDE, DISPLAY_DIALOG);
- /* Save the minimum stat */
- stat_limit[i] = (v > 0) ? v : 0;
- }
- }
- #endif /* ALLOW_AUTOROLLER */
- /* Clean up */
- clear_from(10);
- /*** Generate ***/
- Disp_xtra(DISP_XTRA_PREP, DISPLAY_CHARACTER);
- Disp_xtra(DISP_XTRA_SHOW, DISPLAY_CHARACTER);
- /* Roll */
- while(TRUE)
- {
- int col = 42;
- /* Feedback */
- if(adult_auto_roller)
- {
- Disp_clear();
- /* Labels */
- put_str(" Limit", 2, col + 5);
- put_str(" Freq", 2, col + 13);
- put_str(" Roll", 2, col + 24);
- /* Put the minimal stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* Label stats */
- put_str(stat_names[i], 3 + i, col);
- /* Put the stat */
- cnv_stat(stat_limit[i], buf);
- c_put_str(COLOR_L_BLUE, buf, 3 + i, col + 5);
- }
- /* Note when we started */
- last_round = auto_round;
- /* Label count */
- put_str("Round:", 10, col + 13);
- /* Indicate the state */
- put_str("(Hit ESC to stop)", 12, col + 13);
- /* Auto-roll */
- while(1)
- {
- bool accept = TRUE;
- /* Get a new character */
- get_stats();
- /* Advance the round */
- auto_round++;
- /* Hack -- Prevent overflow */
- if(auto_round >= 1000000L)
- break;
- /* Check and count acceptable stats */
- for(i = 0; i < A_MAX; i++)
- {
- /* This stat is okay */
- if(stat_use[i] >= stat_limit[i])
- {
- stat_match[i]++;
- }
- /* This stat is not okay */
- else
- {
- accept = FALSE;
- }
- }
- /* Break if "happy" */
- if(accept)
- break;
- /* Take note every 25 rolls */
- flag = (!(auto_round % 25L));
- /* Update display occasionally */
- if(flag || (auto_round < last_round + 100))
- {
- /* Put the stats (and percents) */
- for(i = 0; i < A_MAX; i++)
- {
- /* Put the stat */
- cnv_stat(stat_use[i], buf);
- c_put_str(COLOR_L_GREEN, buf,
- 3 + i, col + 24);
- /* Put the percent */
- if(stat_match[i])
- {
- int p = 1000L *
- stat_match[i] / auto_round;
- byte attr =
- (p <
- 100) ? COLOR_YELLOW : COLOR_L_GREEN;
- sprintf(buf,
- "%3d.%d%%", p / 10, p % 10);
- c_put_str(attr, buf, 3 + i, col + 13);
- }
- /* Never happened */
- else
- {
- c_put_str(COLOR_RED,
- "(NONE)", 3 + i, col + 13);
- }
- }
- /* Dump round */
- put_str(format("%10ld", auto_round),
- 10, col + 20);
- /* Make sure they see everything */
- Disp_fresh();
- /* Delay 1/10 second */
- if(flag)
- Disp_xtra(DISP_XTRA_DELAY, 100);
- /* Do not wait for a key */
- inkey_scan = TRUE;
- /* Check for a keypress */
- if(inkey())
- break;
- }
- }
- }
- /* Otherwise just get a character */
- else
- {
- /* Get a new character */
- get_stats();
- }
- /* Flush input */
- flush();
- /*** Display ***/
- /* Force the overlay to redisplay its stats */
- Disp_param(DISPLAY_CHARACTER, DISP_PARAM_RECALC, NULL);
- /* Set the display */
- Disp_xtra(DISP_XTRA_STAGE,
- SCENE_NEW_CHARACTER_STAGE_STATS_APPROVE);
- /* Roll for base hitpoints */
- get_extra();
- /* Roll for age/height/weight */
- get_ahw();
- /* Roll for social class */
- get_history();
- /* Roll for gold */
- get_money();
- /* Input loop */
- while(TRUE)
- {
- fprintf(stderr, "player_birth_aux_3(): top of input loop\n");
- /* Calculate the bonuses and hitpoints */
- p_ptr->update |= (PU_BONUS | PU_HP);
- /* Update stuff */
- update_stuff();
- /* Fully healed */
- p_ptr->chp = p_ptr->mhp;
- /* Fully rested */
- p_ptr->csp = p_ptr->msp;
- /* Display the player */
- display_player(0);
- /* Prepare a prompt (must squeeze everything in) */
- Disp_gotoxy(2, 23);
- Disp_addch(COLOR_WHITE, b1);
- Disp_addstr(-1, COLOR_WHITE, "'r' to reroll");
- if(prev)
- Disp_addstr(-1, COLOR_WHITE, ", 'p' for prev");
- Disp_addstr(-1, COLOR_WHITE, ", or 'Enter' to accept");
- Disp_addch(COLOR_WHITE, b2);
- /* Prompt and get a command */
- fprintf(stderr, "player_birth_aux_3(): get character\n");
- ch = inkey();
- fprintf(stderr, "player_birth_aux_3(): ch = '%c'\n", ch);
- /* Quit */
- if(ch == 'Q')
- quit(NULL);
- /* Start over */
- if(ch == 'S')
- return (FALSE);
- /* 'Enter' accepts the roll */
- if((ch == '\r') || (ch == '\n'))
- break;
- /* Reroll this character */
- if((ch == ' ') || (ch == 'r'))
- break;
- /* Previous character */
- if(prev && (ch == 'p'))
- {
- load_prev_data();
- continue;
- }
- /* Help */
- if(ch == '?')
- {
- do_cmd_help();
- continue;
- }
- /* Warning */
- bell("Illegal auto-roller command!");
- }
- /* Are we done? */
- fprintf(stderr, "player_birth_aux_3(): are we done?\n");
- if((ch == '\r') || (ch == '\n'))
- break;
- /* Save this for the "previous" character */
- save_prev_data();
- /* Note that a previous roll exists */
- prev = TRUE;
- }
- /* Clear prompt */
- clear_from(23);
- /* Done */
- fprintf(stderr, "player_birth_aux_3(): return(true);\n");
- return (TRUE);
- }
- /*
- * Helper function for 'player_birth()'.
- *
- * See "display_player" for screen layout code.
- */
- static int
- player_birth_aux(void)
- {
- char ch;
- cptr prompt =
- "['Q' to suicide, 'S' to start over, or any other key to continue]";
- /* Ask questions */
- if(!player_birth_aux_1())
- return (FALSE);
- /* Point-based */
- if(adult_point_based)
- {
- /* Point based */
- fprintf(stderr, "player_birth_aux(): point-based\n");
- if(!player_birth_aux_2())
- return (FALSE);
- }
- /* Random */
- else
- {
- /* Auto-roll */
- fprintf(stderr, "player_birth_aux(): auto-roll\n");
- if(!player_birth_aux_3())
- return (FALSE);
- }
- /* Set the display */
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_NAME);
- /* Get a name, prepare savefile */
- get_name();
- /* Display the player */
- display_player(0);
- /* Set the display */
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_FINALIZE);
- /* Prompt for it */
- prt(prompt, Disp->hgt - 1, Disp->wid / 2 - strlen(prompt) / 2);
- /* Get a key */
- ch = inkey();
- /* Quit */
- if(ch == 'Q')
- return(-1);
- // quit(NULL);
- /* Start over */
- if(ch == 'S')
- return (FALSE);
- /* Accept */
- return (TRUE);
- }
- /*
- * 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.
- */
- int
- player_birth(void)
- {
- int i, n;
- /* Create a new character */
- while(1)
- {
- int rc;
-
- Disp_xtra(DISP_XTRA_SCENE, SCENE_NEW_CHARACTER);
- Disp_xtra(DISP_XTRA_STAGE, SCENE_NEW_CHARACTER_STAGE_GENDER);
- /* Wipe the player */
- player_wipe();
- /* Roll up a new character */
- rc = player_birth_aux();
-
- if(rc == -1)
- return -1;
-
- if(rc)
- break;
- }
- /* Note player birth in the message recall */
- message_add(" ", MSG_GENERIC);
- message_add(" ", MSG_GENERIC);
- message_add("====================", MSG_GENERIC);
- message_add(" ", MSG_GENERIC);
- message_add(" ", MSG_GENERIC);
- /* Hack -- outfit the player */
- player_outfit();
- /* Event -- player birth done */
- player_birth_done_hook();
- /* Shops */
- for(n = 0; n < MAX_STORES; n++)
- {
- /* Initialize */
- store_init(n);
- /* Ignore home */
- if(n == STORE_HOME)
- continue;
- /* Maintain the shop (ten times) */
- for(i = 0; i < 10; i++)
- {
- store_maint(n);
- }
- }
-
- return 0;
- }