PageRenderTime 65ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/branches/IsengardDev/IronHells/src/client/angband/birth.c

#
C | 1423 lines | 725 code | 317 blank | 381 comment | 204 complexity | 92ed625af6c370f2cdaa7bc238228ae6 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, Apache-2.0
  1. /* File: birth.c */
  2. /*
  3. * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
  4. *
  5. * This software may be copied and distributed for educational, research,
  6. * and not for profit purposes provided that this copyright and statement
  7. * are included in all such copies. Other copyrights may also apply.
  8. */
  9. #include "angband.h"
  10. #include "sdl/scene.h"
  11. #include "script.h"
  12. /*
  13. * Forward declare
  14. */
  15. typedef struct birther birther;
  16. /*
  17. * A structure to hold "rolled" information
  18. */
  19. struct birther
  20. {
  21. s16b age;
  22. s16b wt;
  23. s16b ht;
  24. s16b sc;
  25. s32b au;
  26. s16b stat[A_MAX];
  27. char history[250];
  28. };
  29. /*
  30. * The last character displayed
  31. */
  32. static birther prev;
  33. /*
  34. * Current stats (when rolling a character).
  35. */
  36. static s16b stat_use[A_MAX];
  37. /*
  38. * Save the currently rolled data for later.
  39. */
  40. static void save_prev_data(void)
  41. {
  42. int i;
  43. /*** Save the current data ***/
  44. /* Save the data */
  45. prev.age = p_ptr->age;
  46. prev.wt = p_ptr->wt;
  47. prev.ht = p_ptr->ht;
  48. prev.sc = p_ptr->sc;
  49. prev.au = p_ptr->au;
  50. /* Save the stats */
  51. for (i = 0; i < A_MAX; i++)
  52. {
  53. prev.stat[i] = p_ptr->stat_max[i];
  54. }
  55. /* Save the history */
  56. my_strcpy(prev.history, p_ptr->history, sizeof(prev.history));
  57. }
  58. /*
  59. * Load the previously rolled data.
  60. */
  61. static void load_prev_data(void)
  62. {
  63. int i;
  64. birther temp;
  65. /*** Save the current data ***/
  66. /* Save the data */
  67. temp.age = p_ptr->age;
  68. temp.wt = p_ptr->wt;
  69. temp.ht = p_ptr->ht;
  70. temp.sc = p_ptr->sc;
  71. temp.au = p_ptr->au;
  72. /* Save the stats */
  73. for (i = 0; i < A_MAX; i++)
  74. {
  75. temp.stat[i] = p_ptr->stat_max[i];
  76. }
  77. /* Save the history */
  78. my_strcpy(temp.history, p_ptr->history, sizeof(temp.history));
  79. /*** Load the previous data ***/
  80. /* Load the data */
  81. p_ptr->age = prev.age;
  82. p_ptr->wt = prev.wt;
  83. p_ptr->ht = prev.ht;
  84. p_ptr->sc = prev.sc;
  85. p_ptr->au = prev.au;
  86. /* Load the stats */
  87. for (i = 0; i < A_MAX; i++)
  88. {
  89. p_ptr->stat_max[i] = prev.stat[i];
  90. p_ptr->stat_cur[i] = prev.stat[i];
  91. }
  92. /* Load the history */
  93. my_strcpy(p_ptr->history, prev.history, sizeof(p_ptr->history));
  94. /*** Save the current data ***/
  95. /* Save the data */
  96. prev.age = temp.age;
  97. prev.wt = temp.wt;
  98. prev.ht = temp.ht;
  99. prev.sc = temp.sc;
  100. prev.au = temp.au;
  101. /* Save the stats */
  102. for (i = 0; i < A_MAX; i++)
  103. {
  104. prev.stat[i] = temp.stat[i];
  105. }
  106. /* Save the history */
  107. my_strcpy(prev.history, temp.history, sizeof(prev.history));
  108. }
  109. /*
  110. * Adjust a stat by an amount.
  111. *
  112. * This just uses "modify_stat_value()" unless "maximize" mode is false,
  113. * and a positive bonus is being applied, in which case, a special hack
  114. * is used, with the "auto_roll" flag affecting the result.
  115. *
  116. * The "auto_roll" flag selects "maximal" changes for use with the
  117. * auto-roller initialization code. Otherwise, if "maximize" mode
  118. * is being used, the changes are fixed. Otherwise, semi-random
  119. * changes will occur, with larger changes at lower values.
  120. */
  121. static int adjust_stat(int value, int amount, int auto_roll)
  122. {
  123. /* Negative amounts or maximize mode */
  124. if ((amount < 0) || adult_maximize)
  125. {
  126. return (modify_stat_value(value, amount));
  127. }
  128. /* Special hack */
  129. else
  130. {
  131. int i;
  132. /* Apply reward */
  133. for (i = 0; i < amount; i++)
  134. {
  135. if (value < 18)
  136. {
  137. value++;
  138. }
  139. else if (value < 18+70)
  140. {
  141. value += ((auto_roll ? 15 : randint(15)) + 5);
  142. }
  143. else if (value < 18+90)
  144. {
  145. value += ((auto_roll ? 6 : randint(6)) + 2);
  146. }
  147. else if (value < 18+100)
  148. {
  149. value++;
  150. }
  151. }
  152. }
  153. /* Return the result */
  154. return (value);
  155. }
  156. /*
  157. * Roll for a characters stats
  158. *
  159. * For efficiency, we include a chunk of "calc_bonuses()".
  160. */
  161. void get_stats(void)
  162. {
  163. int i, j;
  164. int bonus;
  165. int dice[18];
  166. /* Roll and verify some stats */
  167. while (TRUE)
  168. {
  169. /* Roll some dice */
  170. for (j = i = 0; i < 18; i++)
  171. {
  172. /* Roll the dice */
  173. dice[i] = randint(3 + i % 3);
  174. /* Collect the maximum */
  175. j += dice[i];
  176. }
  177. /* Verify totals */
  178. if ((j > 42) && (j < 54)) break;
  179. }
  180. /* Roll the stats */
  181. for (i = 0; i < A_MAX; i++)
  182. {
  183. /* Extract 5 + 1d3 + 1d4 + 1d5 */
  184. j = 5 + dice[3*i] + dice[3*i+1] + dice[3*i+2];
  185. /* Save that value */
  186. p_ptr->stat_max[i] = j;
  187. /* Obtain a "bonus" for "race" and "class" */
  188. bonus = rp_ptr->r_adj[i] + cp_ptr->c_adj[i];
  189. /* Variable stat maxes */
  190. if (adult_maximize)
  191. {
  192. /* Start fully healed */
  193. p_ptr->stat_cur[i] = p_ptr->stat_max[i];
  194. /* Efficiency -- Apply the racial/class bonuses */
  195. stat_use[i] = modify_stat_value(p_ptr->stat_max[i], bonus);
  196. }
  197. /* Fixed stat maxes */
  198. else
  199. {
  200. /* Apply the bonus to the stat (somewhat randomly) */
  201. stat_use[i] = adjust_stat(p_ptr->stat_max[i], bonus, FALSE);
  202. /* Save the resulting stat maximum */
  203. p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stat_use[i];
  204. }
  205. }
  206. }
  207. /*
  208. * Roll for some info that the auto-roller ignores
  209. */
  210. void get_extra(void)
  211. {
  212. int i, j, min_value, max_value;
  213. /* Level one */
  214. p_ptr->max_lev = p_ptr->lev = 1;
  215. /* Experience factor */
  216. p_ptr->expfact = rp_ptr->r_exp + cp_ptr->c_exp;
  217. /* Hitdice */
  218. p_ptr->hitdie = rp_ptr->r_mhp + cp_ptr->c_mhp;
  219. /* Initial hitpoints */
  220. p_ptr->mhp = p_ptr->hitdie;
  221. /* Minimum hitpoints at highest level */
  222. min_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 3) / 8;
  223. min_value += PY_MAX_LEVEL;
  224. /* Maximum hitpoints at highest level */
  225. max_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 5) / 8;
  226. max_value += PY_MAX_LEVEL;
  227. /* Pre-calculate level 1 hitdice */
  228. p_ptr->player_hp[0] = p_ptr->hitdie;
  229. /* Roll out the hitpoints */
  230. while (TRUE)
  231. {
  232. /* Roll the hitpoint values */
  233. for (i = 1; i < PY_MAX_LEVEL; i++)
  234. {
  235. j = randint(p_ptr->hitdie);
  236. p_ptr->player_hp[i] = p_ptr->player_hp[i-1] + j;
  237. }
  238. /* XXX Could also require acceptable "mid-level" hitpoints */
  239. /* Require "valid" hitpoints at highest level */
  240. if (p_ptr->player_hp[PY_MAX_LEVEL-1] < min_value) continue;
  241. if (p_ptr->player_hp[PY_MAX_LEVEL-1] > max_value) continue;
  242. /* Acceptable */
  243. break;
  244. }
  245. }
  246. /*
  247. * Get the racial history, and social class, using the "history charts".
  248. */
  249. void get_history(void)
  250. {
  251. int i, chart, roll, social_class;
  252. /* Clear the previous history strings */
  253. p_ptr->history[0] = '\0';
  254. /* Initial social class */
  255. social_class = randint(4);
  256. /* Starting place */
  257. chart = rp_ptr->hist;
  258. /* Process the history */
  259. while (chart)
  260. {
  261. /* Start over */
  262. i = 0;
  263. /* Roll for nobility */
  264. roll = randint(100);
  265. /* Get the proper entry in the table */
  266. while ((chart != h_info[i].chart) || (roll > h_info[i].roll)) i++;
  267. /* Get the textual history */
  268. my_strcat(p_ptr->history, (h_text + h_info[i].text), sizeof(p_ptr->history));
  269. /* Add in the social class */
  270. social_class += (int)(h_info[i].bonus) - 50;
  271. /* Enter the next chart */
  272. chart = h_info[i].next;
  273. }
  274. /* Verify social class */
  275. if (social_class > 100) social_class = 100;
  276. else if (social_class < 1) social_class = 1;
  277. /* Save the social class */
  278. p_ptr->sc = social_class;
  279. }
  280. /*
  281. * Computes character's age, height, and weight
  282. */
  283. void get_ahw(void)
  284. {
  285. /* Calculate the age */
  286. p_ptr->age = rp_ptr->b_age + randint(rp_ptr->m_age);
  287. /* Calculate the height/weight for males */
  288. if (p_ptr->psex == SEX_MALE)
  289. {
  290. p_ptr->ht = Rand_normal(rp_ptr->m_b_ht, rp_ptr->m_m_ht);
  291. p_ptr->wt = Rand_normal(rp_ptr->m_b_wt, rp_ptr->m_m_wt);
  292. }
  293. /* Calculate the height/weight for females */
  294. else if (p_ptr->psex == SEX_FEMALE)
  295. {
  296. p_ptr->ht = Rand_normal(rp_ptr->f_b_ht, rp_ptr->f_m_ht);
  297. p_ptr->wt = Rand_normal(rp_ptr->f_b_wt, rp_ptr->f_m_wt);
  298. }
  299. }
  300. /*
  301. * Get the player's starting money
  302. */
  303. void get_money(void)
  304. {
  305. int i;
  306. int gold;
  307. /* Social Class determines starting gold */
  308. gold = (p_ptr->sc * 6) + randint(100) + 300;
  309. /* Process the stats */
  310. for (i = 0; i < A_MAX; i++)
  311. {
  312. /* Mega-Hack -- reduce gold for high stats */
  313. if (stat_use[i] >= 18+50) gold -= 300;
  314. else if (stat_use[i] >= 18+20) gold -= 200;
  315. else if (stat_use[i] > 18) gold -= 150;
  316. else gold -= (stat_use[i] - 8) * 10;
  317. }
  318. /* Minimum 100 gold */
  319. if (gold < 100) gold = 100;
  320. /* Save the gold */
  321. p_ptr->au = gold;
  322. }
  323. /*
  324. * Clear all the global "character" data
  325. */
  326. void player_wipe(void)
  327. {
  328. int i;
  329. /* Wipe the player */
  330. (void)WIPE(p_ptr, player_type);
  331. /* Clear the inventory */
  332. for (i = 0; i < INVEN_TOTAL; i++)
  333. {
  334. object_wipe(&inventory[i]);
  335. }
  336. /* Start with no artifacts made yet */
  337. for (i = 0; i < z_info->a_max; i++)
  338. {
  339. artifact_type *a_ptr = &a_info[i];
  340. a_ptr->cur_num = 0;
  341. }
  342. /* Start with no quests */
  343. for (i = 0; i < MAX_Q_IDX; i++)
  344. {
  345. q_list[i].level = 0;
  346. }
  347. /* Add a special quest */
  348. q_list[0].level = 99;
  349. /* Add a second quest */
  350. q_list[1].level = 100;
  351. /* Reset the "objects" */
  352. for (i = 1; i < z_info->k_max; i++)
  353. {
  354. object_kind *k_ptr = &k_info[i];
  355. /* Reset "tried" */
  356. k_ptr->tried = FALSE;
  357. /* Reset "aware" */
  358. k_ptr->aware = FALSE;
  359. }
  360. /* Reset the "monsters" */
  361. for (i = 1; i < z_info->r_max; i++)
  362. {
  363. monster_race *r_ptr = &r_info[i];
  364. monster_lore *l_ptr = &l_list[i];
  365. /* Hack -- Reset the counter */
  366. r_ptr->cur_num = 0;
  367. /* Hack -- Reset the max counter */
  368. r_ptr->max_num = 100;
  369. /* Hack -- Reset the max counter */
  370. if (r_ptr->flags1 & (RF1_UNIQUE)) r_ptr->max_num = 1;
  371. /* Clear player kills */
  372. l_ptr->pkills = 0;
  373. }
  374. /* Hack -- no ghosts */
  375. r_info[z_info->r_max-1].max_num = 0;
  376. /* Hack -- Well fed player */
  377. p_ptr->food = PY_FOOD_FULL - 1;
  378. /* None of the spells have been learned yet */
  379. for (i = 0; i < PY_MAX_SPELLS; i++) p_ptr->spell_order[i] = 99;
  380. }
  381. /*
  382. * Init players with some belongings
  383. *
  384. * Having an item makes the player "aware" of its purpose.
  385. */
  386. void player_outfit(void)
  387. {
  388. int i;
  389. const start_item *e_ptr;
  390. object_type *i_ptr;
  391. object_type object_type_body;
  392. /* Hack -- Give the player his equipment */
  393. for (i = 0; i < MAX_START_ITEMS; i++)
  394. {
  395. /* Access the item */
  396. e_ptr = &(cp_ptr->start_items[i]);
  397. /* Get local object */
  398. i_ptr = &object_type_body;
  399. /* Hack -- Give the player an object */
  400. if (e_ptr->tval > 0)
  401. {
  402. /* Get the object_kind */
  403. int k_idx = lookup_kind(e_ptr->tval, e_ptr->sval);
  404. /* Valid item? */
  405. if (!k_idx) continue;
  406. /* Prepare the item */
  407. object_prep(i_ptr, k_idx);
  408. i_ptr->number = (byte)rand_range(e_ptr->min, e_ptr->max);
  409. object_aware(i_ptr);
  410. object_known(i_ptr);
  411. (void)inven_carry(i_ptr);
  412. }
  413. }
  414. }
  415. /*
  416. * Helper function for 'player_birth()'.
  417. *
  418. * This function allows the player to select a sex, race, and class, and
  419. * modify options (including the birth options).
  420. */
  421. static bool player_birth_aux_1(void)
  422. {
  423. int k, n, i;
  424. cptr str;
  425. char ch;
  426. #if 0
  427. char p1 = '(';
  428. #endif
  429. char p2 = ')';
  430. char buf[80];
  431. /*** Instructions ***/
  432. /* Clear screen */
  433. Term_clear();
  434. /* Display some helpful information */
  435. Term_putstr(5, 10, -1, TERM_WHITE,
  436. "Please answer the following questions. Most of the questions");
  437. Term_putstr(5, 11, -1, TERM_WHITE,
  438. "display a set of standard answers, and many will also accept");
  439. Term_putstr(5, 12, -1, TERM_WHITE,
  440. "some special responses, including 'Q' to quit, 'S' to restart,");
  441. Term_putstr(5, 13, -1, TERM_WHITE,
  442. "and '?' for help. Note that 'Q' and 'S' must be capitalized.");
  443. /*** Player sex ***/
  444. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_GENDER);
  445. /* Extra info */
  446. Term_putstr(5, 15, -1, TERM_WHITE,
  447. "Your 'sex' does not have any significant gameplay effects.");
  448. /* Prompt for "Sex" */
  449. for (n = 0; n < MAX_SEXES; n++)
  450. {
  451. /* Analyze */
  452. p_ptr->psex = n;
  453. sp_ptr = &sex_info[p_ptr->psex];
  454. str = sp_ptr->title;
  455. /* Display */
  456. strnfmt(buf, sizeof(buf), "%c%c %s", I2A(n), p2, str);
  457. put_str(buf, 21 + (n/5), 2 + 15 * (n%5));
  458. }
  459. /* Choose */
  460. sp_ptr = NULL;
  461. while (1)
  462. {
  463. sprintf(buf, "Choose a sex (%c-%c, or * for random): ",
  464. I2A(0), I2A(n-1));
  465. put_str(buf, 20, 2);
  466. ch = inkey();
  467. if (ch == 'Q') quit(NULL);
  468. if (ch == 'S') return (FALSE);
  469. k = (islower((unsigned char)ch) ? A2I(ch) : -1);
  470. if (ch == ESCAPE) ch = '*';
  471. if (ch == '*') k = rand_int(MAX_SEXES);
  472. if ((k >= 0) && (k < n)) break;
  473. if (ch == '?') do_cmd_help();
  474. else bell("Illegal sex!");
  475. }
  476. /* Set sex */
  477. p_ptr->psex = k;
  478. sp_ptr = &sex_info[p_ptr->psex];
  479. /* Sex */
  480. put_str("Sex", 3, 1);
  481. c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 8);
  482. /* Clean up */
  483. clear_from(15);
  484. /*** Player race ***/
  485. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_RACE);
  486. /* Extra info */
  487. Term_putstr(5, 15, -1, TERM_WHITE,
  488. "Your 'race' determines various intrinsic factors and bonuses.");
  489. /* Dump races */
  490. for (n = 0; n < z_info->p_max; n++)
  491. {
  492. /* Analyze */
  493. p_ptr->prace = n;
  494. rp_ptr = &p_info[p_ptr->prace];
  495. str = p_name + rp_ptr->name;
  496. /* Display */
  497. strnfmt(buf, sizeof(buf), "%c%c %s", I2A(n), p2, str);
  498. put_str(buf, 21 + (n/5), 2 + 15 * (n%5));
  499. }
  500. /* Choose */
  501. rp_ptr = NULL;
  502. while (1)
  503. {
  504. sprintf(buf, "Choose a race (%c-%c, or * for random): ",
  505. I2A(0), I2A(n-1));
  506. put_str(buf, 20, 2);
  507. ch = inkey();
  508. if (ch == 'Q') quit(NULL);
  509. if (ch == 'S') return (FALSE);
  510. k = (islower((unsigned char)ch) ? A2I(ch) : -1);
  511. if (ch == ESCAPE) ch = '*';
  512. if (ch == '*') k = rand_int(z_info->p_max);
  513. if ((k >= 0) && (k < n)) break;
  514. if (ch == '?') do_cmd_help();
  515. else bell("Illegal race!");
  516. }
  517. /* Set race */
  518. p_ptr->prace = k;
  519. rp_ptr = &p_info[p_ptr->prace];
  520. /* Race */
  521. put_str("Race", 4, 1);
  522. c_put_str(TERM_L_BLUE, p_name + rp_ptr->name, 4, 8);
  523. /* Clean up */
  524. clear_from(15);
  525. /*** Player class ***/
  526. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_CLASS);
  527. /* Extra info */
  528. Term_putstr(5, 15, -1, TERM_WHITE,
  529. "Your 'class' determines various intrinsic abilities and bonuses.");
  530. Term_putstr(5, 16, -1, TERM_WHITE,
  531. "Any entries with a (*) should only be used by advanced players.");
  532. /* Dump classes */
  533. for (n = 0; n < z_info->c_max; n++)
  534. {
  535. cptr mod = "";
  536. /* Analyze */
  537. p_ptr->pclass = n;
  538. cp_ptr = &c_info[p_ptr->pclass];
  539. mp_ptr = &cp_ptr->spells;
  540. str = c_name + cp_ptr->name;
  541. /* Verify legality */
  542. if (!(rp_ptr->choice & (1L << n))) mod = " (*)";
  543. /* Display */
  544. strnfmt(buf, sizeof(buf), "%c%c %s%s", I2A(n), p2, str, mod);
  545. put_str(buf, 21 + (n/3), 2 + 20 * (n%3));
  546. }
  547. /* Get a class */
  548. cp_ptr = NULL;
  549. while (1)
  550. {
  551. sprintf(buf, "Choose a class (%c-%c, or * for random): ",
  552. I2A(0), I2A(n-1));
  553. put_str(buf, 20, 2);
  554. ch = inkey();
  555. if (ch == 'Q') quit(NULL);
  556. if (ch == 'S') return (FALSE);
  557. k = (islower((unsigned char)ch) ? A2I(ch) : -1);
  558. if (ch == ESCAPE) ch = '*';
  559. if (ch == '*')
  560. {
  561. while (1)
  562. {
  563. k = rand_int(z_info->c_max);
  564. /* Try again if not a legal choice */
  565. if (!(rp_ptr->choice & (1L << k))) continue;
  566. break;
  567. }
  568. }
  569. if ((k >= 0) && (k < n)) break;
  570. if (ch == '?') do_cmd_help();
  571. else bell("Illegal class!");
  572. }
  573. /* Set class */
  574. p_ptr->pclass = k;
  575. cp_ptr = &c_info[p_ptr->pclass];
  576. mp_ptr = &cp_ptr->spells;
  577. /* Class */
  578. put_str("Class", 5, 1);
  579. c_put_str(TERM_L_BLUE, c_name + cp_ptr->name, 5, 8);
  580. /* Clean up */
  581. clear_from(15);
  582. #if 0
  583. /*** Birth options ***/
  584. /* Extra info */
  585. Term_putstr(5, 15, -1, TERM_WHITE,
  586. "You can change your options at any time, but the 'Birth' options");
  587. Term_putstr(5, 16, -1, TERM_WHITE,
  588. "must be changed now to affect the birth of this character.");
  589. /* Verify birth options */
  590. while (1)
  591. {
  592. sprintf(buf, "Modify options (y/n)? ");
  593. put_str(buf, 20, 2);
  594. ch = inkey();
  595. if (ch == 'Q') quit(NULL);
  596. if (ch == 'S') return (FALSE);
  597. if ((ch == '\r') || (ch == '\n')) break;
  598. if (ch == 'y' || ch == 'n') break;
  599. if (ch == '?') do_cmd_help();
  600. else bell("Illegal answer!");
  601. }
  602. /* Verify */
  603. if (ch == 'y')
  604. {
  605. /* Interact with options */
  606. do_cmd_options();
  607. }
  608. #endif
  609. /* Set adult options from birth options */
  610. for (i = OPT_BIRTH; i < OPT_CHEAT; i++)
  611. {
  612. op_ptr->opt[OPT_ADULT + (i - OPT_BIRTH)] = op_ptr->opt[i];
  613. }
  614. /* Reset score options from cheat options */
  615. for (i = OPT_CHEAT; i < OPT_ADULT; i++)
  616. {
  617. op_ptr->opt[OPT_SCORE + (i - OPT_CHEAT)] = op_ptr->opt[i];
  618. }
  619. /* Clean up */
  620. clear_from(10);
  621. /* Done */
  622. return (TRUE);
  623. }
  624. /*
  625. * Initial stat costs (initial stats always range from 10 to 18 inclusive).
  626. */
  627. static const int birth_stat_costs[(18-10)+1] = { 0, 1, 2, 4, 7, 11, 16, 22, 30 };
  628. /*
  629. * Helper function for 'player_birth()'.
  630. *
  631. * This function handles "point-based" character creation.
  632. *
  633. * The player selects, for each stat, a value from 10 to 18 (inclusive),
  634. * each costing a certain amount of points (as above), from a pool of 48
  635. * available points, to which race/class modifiers are then applied.
  636. *
  637. * Each unused point is converted into 100 gold pieces.
  638. */
  639. static bool player_birth_aux_2(void)
  640. {
  641. int i;
  642. int row = 3;
  643. int col = 42;
  644. int stat = 0;
  645. int stats[A_MAX];
  646. int cost;
  647. char ch;
  648. char buf[80];
  649. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_STATS_POINTBASED);
  650. /* Initialize stats */
  651. for (i = 0; i < A_MAX; i++)
  652. {
  653. /* Initial stats */
  654. stats[i] = 10;
  655. }
  656. /* Roll for base hitpoints */
  657. get_extra();
  658. /* Roll for age/height/weight */
  659. get_ahw();
  660. /* Roll for social class */
  661. get_history();
  662. /* Interact */
  663. while (1)
  664. {
  665. /* Reset cost */
  666. cost = 0;
  667. /* Process stats */
  668. for (i = 0; i < A_MAX; i++)
  669. {
  670. /* Variable stat maxes */
  671. if (adult_maximize)
  672. {
  673. /* Reset stats */
  674. p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stats[i];
  675. }
  676. /* Fixed stat maxes */
  677. else
  678. {
  679. /* Obtain a "bonus" for "race" and "class" */
  680. int bonus = rp_ptr->r_adj[i] + cp_ptr->c_adj[i];
  681. /* Apply the racial/class bonuses */
  682. p_ptr->stat_cur[i] = p_ptr->stat_max[i] =
  683. modify_stat_value(stats[i], bonus);
  684. }
  685. /* Total cost */
  686. cost += birth_stat_costs[stats[i] - 10];
  687. }
  688. /* Restrict cost */
  689. if (cost > 48)
  690. {
  691. /* Warning */
  692. bell("Excessive stats!");
  693. /* Reduce stat */
  694. stats[stat]--;
  695. /* Recompute costs */
  696. continue;
  697. }
  698. /* Gold is inversely proportional to cost */
  699. p_ptr->au = (100 * (48 - cost)) + 100;
  700. /* Calculate the bonuses and hitpoints */
  701. p_ptr->update |= (PU_BONUS | PU_HP);
  702. /* Update stuff */
  703. update_stuff();
  704. /* Fully healed */
  705. p_ptr->chp = p_ptr->mhp;
  706. /* Fully rested */
  707. p_ptr->csp = p_ptr->msp;
  708. /* Display the player */
  709. display_player(0);
  710. /* Display the costs header */
  711. put_str("Cost", row - 1, col + 32);
  712. /* Display the costs */
  713. for (i = 0; i < A_MAX; i++)
  714. {
  715. /* Display cost */
  716. sprintf(buf, "%4d", birth_stat_costs[stats[i] - 10]);
  717. put_str(buf, row + i, col + 32);
  718. }
  719. /* Prompt XXX XXX XXX */
  720. sprintf(buf, "Total Cost %2d/48. Use 2/8 to move, 4/6 to modify, 'Enter' to accept.", cost);
  721. prt(buf, 0, 0);
  722. /* Place cursor just after cost of current stat */
  723. Term_gotoxy(col + 36, row + stat);
  724. /* Get key */
  725. ch = inkey();
  726. /* Quit */
  727. if (ch == 'Q') quit(NULL);
  728. /* Start over */
  729. if (ch == 'S') return (FALSE);
  730. /* Done */
  731. if ((ch == '\r') || (ch == '\n')) break;
  732. /* Prev stat */
  733. if (ch == '8')
  734. {
  735. stat = (stat + A_MAX - 1) % A_MAX;
  736. }
  737. /* Next stat */
  738. if (ch == '2')
  739. {
  740. stat = (stat + 1) % A_MAX;
  741. }
  742. /* Decrease stat */
  743. if ((ch == '4') && (stats[stat] > 10))
  744. {
  745. stats[stat]--;
  746. }
  747. /* Increase stat */
  748. if ((ch == '6') && (stats[stat] < 18))
  749. {
  750. stats[stat]++;
  751. }
  752. }
  753. /* Done */
  754. return (TRUE);
  755. }
  756. /*
  757. * Helper function for 'player_birth()'.
  758. *
  759. * This function handles "auto-rolling" and "random-rolling".
  760. *
  761. * The delay may be reduced, but is recommended to keep players
  762. * from continuously rolling up characters, which can be VERY
  763. * expensive CPU wise. And it cuts down on player stupidity.
  764. */
  765. static bool player_birth_aux_3(void)
  766. {
  767. int i, j, m, v;
  768. bool flag;
  769. bool prev = FALSE;
  770. char ch;
  771. char b1 = '[';
  772. char b2 = ']';
  773. char buf[80];
  774. #ifdef ALLOW_AUTOROLLER
  775. s16b stat_limit[A_MAX];
  776. s32b stat_match[A_MAX];
  777. s32b auto_round = 0L;
  778. s32b last_round;
  779. /*** Autoroll ***/
  780. /* Initialize */
  781. if (adult_auto_roller)
  782. {
  783. int mval[A_MAX];
  784. char inp[80];
  785. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_STATS_AUTOROLLER);
  786. /* Extra info */
  787. Term_putstr(5, 10, -1, TERM_WHITE,
  788. "The auto-roller will automatically ignore characters which do");
  789. Term_putstr(5, 11, -1, TERM_WHITE,
  790. "not meet the minimum values for any stats specified below.");
  791. Term_putstr(5, 12, -1, TERM_WHITE,
  792. "Note that stats are not independent, so it is not possible to");
  793. Term_putstr(5, 13, -1, TERM_WHITE,
  794. "get perfect (or even high) values for all your stats.");
  795. /* Prompt for the minimum stats */
  796. put_str("Enter minimum value for: ", 15, 2);
  797. /* Output the maximum stats */
  798. for (i = 0; i < A_MAX; i++)
  799. {
  800. /* Reset the "success" counter */
  801. stat_match[i] = 0;
  802. /* Race/Class bonus */
  803. j = rp_ptr->r_adj[i] + cp_ptr->c_adj[i];
  804. /* Obtain the "maximal" stat */
  805. m = adjust_stat(17, j, TRUE);
  806. /* Save the maximum */
  807. mval[i] = m;
  808. /* Extract a textual format */
  809. /* cnv_stat(m, inp); */
  810. /* Above 18 */
  811. if (m > 18)
  812. {
  813. sprintf(inp, "(Max of 18/%02d):", (m - 18));
  814. }
  815. /* From 3 to 18 */
  816. else
  817. {
  818. sprintf(inp, "(Max of %2d):", m);
  819. }
  820. /* Prepare a prompt */
  821. strnfmt(buf, sizeof(buf), "%-5s%-20s", stat_names[i], inp);
  822. /* Dump the prompt */
  823. put_str(buf, 16 + i, 5);
  824. }
  825. /* Input the minimum stats */
  826. for (i = 0; i < A_MAX; i++)
  827. {
  828. /* Get a minimum stat */
  829. while (TRUE)
  830. {
  831. char *s;
  832. /* Move the cursor */
  833. put_str("", 16 + i, 30);
  834. /* Default */
  835. strcpy(inp, "");
  836. /* Get a response (or escape) */
  837. if (!askfor_aux(inp, 9)) inp[0] = '\0';
  838. /* Hack -- add a fake slash */
  839. strcat(inp, "/");
  840. /* Hack -- look for the "slash" */
  841. s = strchr(inp, '/');
  842. /* Hack -- Nuke the slash */
  843. *s++ = '\0';
  844. /* Hack -- Extract an input */
  845. v = atoi(inp) + atoi(s);
  846. /* Break on valid input */
  847. if (v <= mval[i]) break;
  848. }
  849. /* Save the minimum stat */
  850. stat_limit[i] = (v > 0) ? v : 0;
  851. }
  852. }
  853. #endif /* ALLOW_AUTOROLLER */
  854. /* Clean up */
  855. clear_from(10);
  856. /*** Generate ***/
  857. /* Roll */
  858. while (TRUE)
  859. {
  860. int col = 42;
  861. /* Feedback */
  862. if (adult_auto_roller)
  863. {
  864. fprintf(stderr, "Using adult auto-roller.\n");
  865. Term_clear();
  866. /* Label */
  867. put_str(" Limit", 2, col+5);
  868. /* Label */
  869. put_str(" Freq", 2, col+13);
  870. /* Label */
  871. put_str(" Roll", 2, col+24);
  872. /* Put the minimal stats */
  873. for (i = 0; i < A_MAX; i++)
  874. {
  875. /* Label stats */
  876. put_str(stat_names[i], 3+i, col);
  877. /* Put the stat */
  878. cnv_stat(stat_limit[i], buf);
  879. c_put_str(TERM_L_BLUE, buf, 3+i, col+5);
  880. }
  881. /* Note when we started */
  882. last_round = auto_round;
  883. /* Label count */
  884. put_str("Round:", 10, col+13);
  885. /* Indicate the state */
  886. put_str("(Hit ESC to stop)", 12, col+13);
  887. /* Auto-roll */
  888. while (1)
  889. {
  890. bool accept = TRUE;
  891. /* Get a new character */
  892. get_stats();
  893. /* Advance the round */
  894. auto_round++;
  895. /* Hack -- Prevent overflow */
  896. if (auto_round >= 1000000L) break;
  897. /* Check and count acceptable stats */
  898. for (i = 0; i < A_MAX; i++)
  899. {
  900. /* This stat is okay */
  901. if (stat_use[i] >= stat_limit[i])
  902. {
  903. stat_match[i]++;
  904. }
  905. /* This stat is not okay */
  906. else
  907. {
  908. accept = FALSE;
  909. }
  910. }
  911. /* Break if "happy" */
  912. if (accept) break;
  913. /* Take note every 25 rolls */
  914. flag = (!(auto_round % 25L));
  915. /* Update display occasionally */
  916. if (flag || (auto_round < last_round + 100))
  917. {
  918. /* Put the stats (and percents) */
  919. for (i = 0; i < A_MAX; i++)
  920. {
  921. /* Put the stat */
  922. cnv_stat(stat_use[i], buf);
  923. c_put_str(TERM_L_GREEN, buf, 3+i, col+24);
  924. /* Put the percent */
  925. if (stat_match[i])
  926. {
  927. int p = 1000L * stat_match[i] / auto_round;
  928. byte attr = (p < 100) ? TERM_YELLOW : TERM_L_GREEN;
  929. sprintf(buf, "%3d.%d%%", p/10, p%10);
  930. c_put_str(attr, buf, 3+i, col+13);
  931. }
  932. /* Never happened */
  933. else
  934. {
  935. c_put_str(TERM_RED, "(NONE)", 3+i, col+13);
  936. }
  937. }
  938. /* Dump round */
  939. put_str(format("%10ld", auto_round), 10, col+20);
  940. /* Make sure they see everything */
  941. Term_fresh();
  942. /* Delay 1/10 second */
  943. if (flag) Term_xtra(TERM_XTRA_DELAY, 100);
  944. /* Do not wait for a key */
  945. inkey_scan = TRUE;
  946. /* Check for a keypress */
  947. if (inkey()) break;
  948. }
  949. }
  950. }
  951. /* Otherwise just get a character */
  952. else
  953. {
  954. fprintf(stderr, "Not using adult auto-roller.\n");
  955. /* Get a new character */
  956. get_stats();
  957. }
  958. /* Flush input */
  959. flush();
  960. /*** Display ***/
  961. /* Roll for base hitpoints */
  962. get_extra();
  963. /* Roll for age/height/weight */
  964. get_ahw();
  965. /* Roll for social class */
  966. get_history();
  967. /* Roll for gold */
  968. get_money();
  969. /* Input loop */
  970. while (TRUE)
  971. {
  972. /* Calculate the bonuses and hitpoints */
  973. p_ptr->update |= (PU_BONUS | PU_HP);
  974. /* Update stuff */
  975. update_stuff();
  976. /* Fully healed */
  977. p_ptr->chp = p_ptr->mhp;
  978. /* Fully rested */
  979. p_ptr->csp = p_ptr->msp;
  980. /* Display the player */
  981. display_player(0);
  982. /* Prepare a prompt (must squeeze everything in) */
  983. Term_gotoxy(2, 23);
  984. Term_addch(TERM_WHITE, b1);
  985. Term_addstr(-1, TERM_WHITE, "'r' to reroll");
  986. if (prev) Term_addstr(-1, TERM_WHITE, ", 'p' for prev");
  987. Term_addstr(-1, TERM_WHITE, ", or 'Enter' to accept");
  988. Term_addch(TERM_WHITE, b2);
  989. /* Prompt and get a command */
  990. ch = inkey();
  991. /* Quit */
  992. if (ch == 'Q') quit(NULL);
  993. /* Start over */
  994. if (ch == 'S') return (FALSE);
  995. /* 'Enter' accepts the roll */
  996. if ((ch == '\r') || (ch == '\n')) break;
  997. /* Reroll this character */
  998. if ((ch == ' ') || (ch == 'r')) break;
  999. /* Previous character */
  1000. if (prev && (ch == 'p'))
  1001. {
  1002. load_prev_data();
  1003. continue;
  1004. }
  1005. /* Help */
  1006. if (ch == '?')
  1007. {
  1008. do_cmd_help();
  1009. continue;
  1010. }
  1011. /* Warning */
  1012. bell("Illegal auto-roller command!");
  1013. }
  1014. /* Are we done? */
  1015. if ((ch == '\r') || (ch == '\n')) break;
  1016. /* Save this for the "previous" character */
  1017. save_prev_data();
  1018. /* Note that a previous roll exists */
  1019. prev = TRUE;
  1020. }
  1021. /* Clear prompt */
  1022. clear_from(23);
  1023. /* Done */
  1024. return (TRUE);
  1025. }
  1026. /*
  1027. * Helper function for 'player_birth()'.
  1028. *
  1029. * See "display_player" for screen layout code.
  1030. */
  1031. static bool player_birth_aux(void)
  1032. {
  1033. char ch;
  1034. cptr prompt = "['Q' to suicide, 'S' to start over, or any other key to continue]";
  1035. /* Ask questions */
  1036. if (!player_birth_aux_1()) return (FALSE);
  1037. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_STATS);
  1038. /* Point-based */
  1039. if (adult_point_based)
  1040. {
  1041. fprintf(stderr, "Adult point-based rolling.\n");
  1042. /* Point based */
  1043. if (!player_birth_aux_2()) return (FALSE);
  1044. }
  1045. /* Random */
  1046. else
  1047. {
  1048. fprintf(stderr, "Auto-rolling.\n");
  1049. /* Auto-roll */
  1050. if (!player_birth_aux_3()) return (FALSE);
  1051. }
  1052. /* Get a name, prepare savefile */
  1053. get_name();
  1054. /* Display the player */
  1055. display_player(0);
  1056. /* Prompt for it */
  1057. prt(prompt, Term->hgt - 1, Term->wid / 2 - strlen(prompt) / 2);
  1058. /* Get a key */
  1059. ch = inkey();
  1060. /* Quit */
  1061. if (ch == 'Q') quit(NULL);
  1062. /* Start over */
  1063. if (ch == 'S') return (FALSE);
  1064. /* Accept */
  1065. return (TRUE);
  1066. }
  1067. /*
  1068. * Create a new character.
  1069. *
  1070. * Note that we may be called with "junk" leftover in the various
  1071. * fields, so we must be sure to clear them first.
  1072. */
  1073. void player_birth(void)
  1074. {
  1075. int i, n;
  1076. /* Create a new character */
  1077. while (1)
  1078. {
  1079. IH_SetScene(IH_SCENE_NEW_CHARACTER);
  1080. IH_SetStage(IH_SCENE_NEW_CHARACTER_STAGE_GENDER);
  1081. /* Wipe the player */
  1082. player_wipe();
  1083. /* Roll up a new character */
  1084. if (player_birth_aux()) break;
  1085. }
  1086. /* Note player birth in the message recall */
  1087. message_add(" ", MSG_GENERIC);
  1088. message_add(" ", MSG_GENERIC);
  1089. message_add("====================", MSG_GENERIC);
  1090. message_add(" ", MSG_GENERIC);
  1091. message_add(" ", MSG_GENERIC);
  1092. /* Hack -- outfit the player */
  1093. player_outfit();
  1094. /* Event -- player birth done */
  1095. player_birth_done_hook();
  1096. /* Shops */
  1097. for (n = 0; n < MAX_STORES; n++)
  1098. {
  1099. /* Initialize */
  1100. store_init(n);
  1101. /* Ignore home */
  1102. if (n == STORE_HOME) continue;
  1103. /* Maintain the shop (ten times) */
  1104. for (i = 0; i < 10; i++) store_maint(n);
  1105. }
  1106. }