diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2006-11-22 08:41:20 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2006-11-22 08:41:20 +0000 |
commit | 1d0f57cbceb778139ca215cc4fcfd1584951f6dd (patch) | |
tree | cafd60c944c51fcce778aa5d6912bc548c518339 /crawl-ref/source/newgame.cc | |
parent | 6f5e187a9e5cd348296dba2fd89d2e206e775a01 (diff) | |
download | crawl-ref-1d0f57cbceb778139ca215cc4fcfd1584951f6dd.tar.gz crawl-ref-1d0f57cbceb778139ca215cc4fcfd1584951f6dd.zip |
Merged stone_soup r15:451 into trunk.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@452 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/newgame.cc')
-rw-r--r-- | crawl-ref/source/newgame.cc | 746 |
1 files changed, 370 insertions, 376 deletions
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc index eca23d3815..c4ffc8cbd1 100644 --- a/crawl-ref/source/newgame.cc +++ b/crawl-ref/source/newgame.cc @@ -58,6 +58,7 @@ #ifdef DOS #include <conio.h> +#include <dos.h> #endif #ifdef UNIX @@ -66,18 +67,6 @@ #include <unistd.h> #endif -#ifdef USE_EMX -#include <sys/types.h> -#include <fcntl.h> -#include <unistd.h> -#endif - -#ifdef OS9 -#include <stat.h> -#else -#include <sys/stat.h> -#endif - #include "externs.h" #include "abl-show.h" @@ -86,8 +75,10 @@ #include "fight.h" #include "initfile.h" #include "itemname.h" +#include "itemprop.h" #include "items.h" #include "macro.h" +#include "menu.h" #include "player.h" #include "randart.h" #include "skills.h" @@ -95,8 +86,9 @@ #include "spl-util.h" #include "stuff.h" #include "version.h" -#include "wpn-misc.h" +#include "view.h" +extern std::string init_file_location; #define MIN_START_STAT 1 @@ -136,6 +128,7 @@ static char ng_race, ng_cls; static bool ng_random; static int ng_ck, ng_dk, ng_pr; static int ng_weapon; +static int ng_book; static void reset_newgame_options(void) { @@ -145,6 +138,7 @@ static void reset_newgame_options(void) ng_dk = DK_NO_SELECTION; ng_pr = GOD_NO_GOD; ng_weapon = WPN_UNKNOWN; + ng_book = SBT_NO_SELECTION; } static void save_newgame_options(void) @@ -158,6 +152,7 @@ static void save_newgame_options(void) Options.prev_dk = ng_dk; Options.prev_pr = ng_pr; Options.prev_weapon = ng_weapon; + Options.prev_book = ng_book; write_newgame_options_file(); } @@ -170,6 +165,7 @@ static void set_startup_options(void) Options.death_knight = Options.prev_dk; Options.chaos_knight = Options.prev_ck; Options.priest = Options.prev_pr; + Options.book = Options.prev_book; } static bool prev_startup_options_set(void) @@ -251,7 +247,7 @@ static void pick_random_species_and_class( void ) { // we only want draconians counted once in this loop... // we'll add the variety lower down -- bwr - if (sp >= SP_WHITE_DRACONIAN && sp <= SP_UNK2_DRACONIAN) + if (sp >= SP_WHITE_DRACONIAN && sp <= SP_BASE_DRACONIAN) continue; for (int cl = JOB_FIGHTER; cl < NUM_JOBS; cl++) @@ -283,64 +279,35 @@ static void pick_random_species_and_class( void ) static bool check_saved_game(void) { FILE *handle; - char char_fil[kFileNameSize]; - -#ifdef LOAD_UNPACKAGE_CMD - // Create the file name base - char name_buff[kFileNameLen]; - - snprintf( name_buff, sizeof(name_buff), - SAVE_DIR_PATH "%s%d", you.your_name, (int) getuid() ); - - char zip_buff[kFileNameLen]; - strcpy(zip_buff, name_buff); - strcat(zip_buff, PACKAGE_SUFFIX); + std::string basename = get_savedir_filename( you.your_name, "", ""); + std::string savename = basename + ".sav"; - // Create save dir name - strcpy(char_fil, name_buff); - strcat(char_fil, ".sav"); - - handle = fopen(zip_buff, "rb+"); +#ifdef LOAD_UNPACKAGE_CMD + std::string zipname = basename + PACKAGE_SUFFIX; + handle = fopen(zipname.c_str(), "rb+"); if (handle != NULL) { + fclose(handle); cprintf(EOL "Loading game..." EOL); // Create command char cmd_buff[1024]; - snprintf( cmd_buff, sizeof(cmd_buff), LOAD_UNPACKAGE_CMD, name_buff ); + snprintf( cmd_buff, sizeof(cmd_buff), LOAD_UNPACKAGE_CMD, + basename.c_str() ); if (system( cmd_buff ) != 0) { cprintf( EOL "Warning: Zip command (LOAD_UNPACKAGE_CMD) returned non-zero value!" EOL ); } - fclose(handle); - // Remove save game package - unlink(zip_buff); + unlink(zipname.c_str()); } - else - { -#ifdef DO_ANTICHEAT_CHECKS - // Simple security patch -- must have zip file otherwise invalidate - // the character. Right now this just renames the .sav file to - // .bak, allowing anyone with the appropriate permissions to - // fix a character in the case of a bug. This could be changed - // to unlinking the file(s) which would remove the character. - strcat(name_buff, ".bak"); - rename(char_fil, name_buff); -#endif - } - -#else - strcpy(char_fil, ""); - strncat(char_fil, you.your_name, kFileNameLen); - strcat(char_fil, ".sav"); #endif - handle = fopen(char_fil, "rb+"); + handle = fopen(savename.c_str(), "rb+"); if (handle != NULL) { @@ -350,19 +317,45 @@ static bool check_saved_game(void) return false; } +static unsigned char random_potion_description() +{ + int desc, nature, colour; + + do { + desc = random2( PDQ_NQUALS * PDC_NCOLOURS ); + + if (coinflip()) + desc %= PDC_NCOLOURS; + + nature = PQUAL(desc); + colour = PCOLOUR(desc); + + // nature and colour correspond to primary and secondary + // in itemname.cc; this check ensures clear potions don't + // get odd qualifiers. + } while ((colour == PDC_CLEAR && nature > PDQ_VISCOUS) + || desc == PDESCS(PDC_CLEAR) + || desc == PDESCQ(PDQ_GLUGGY, PDC_WHITE)); + + return (unsigned char) desc; +} + bool new_game(void) { int i, j; // loop variables {dlb} //jmf: NEW ASSERTS: we ought to do a *lot* of these ASSERT(NUM_SPELLS < SPELL_NO_SPELL); - ASSERT(NUM_DURATIONS > DUR_LAST_DUR); ASSERT(NUM_JOBS < JOB_UNKNOWN); - ASSERT(NUM_ATTRIBUTES < 30); + ASSERT(NUM_ATTRIBUTES >= 30); init_player(); - you.exp_available = 25; // now why is this all the way up here? {dlb} + if (!Options.player_name.empty()) + { + strncpy(you.your_name, Options.player_name.c_str(), kNameLen); + you.your_name[kNameLen - 1] = 0; + } textcolor(LIGHTGREY); @@ -372,21 +365,20 @@ bool new_game(void) if (SysEnv.crawl_name) { strncpy( you.your_name, SysEnv.crawl_name, kNameLen ); - you.your_name[ kNameLen - 1 ] = '\0'; + you.your_name[ kNameLen - 1 ] = 0; } openingScreen(); enterPlayerName(true); - if (you.your_name[0] != '\0') + if (you.your_name[0] != 0) { if (check_saved_game()) { textcolor( BROWN ); cprintf( EOL "Welcome back, " ); textcolor( YELLOW ); - cprintf( you.your_name ); - cprintf( "!" ); + cprintf( "%s!", you.your_name ); textcolor( LIGHTGREY ); save_player_name(); @@ -408,7 +400,7 @@ bool new_game(void) strcpy( you.class_name, get_class_name( you.char_class ) ); // new: pick name _after_ race and class choices - if (you.your_name[0] == '\0') + if (you.your_name[0] == 0) { clrscr(); @@ -432,8 +424,7 @@ bool new_game(void) textcolor( BROWN ); cprintf(EOL EOL "Welcome back, "); textcolor( YELLOW ); - cprintf(you.your_name); - cprintf("!"); + cprintf("%s!", you.your_name); textcolor( LIGHTGREY ); return (false); @@ -449,8 +440,8 @@ bool new_game(void) you.is_undead = ((you.species == SP_MUMMY) ? US_UNDEAD : (you.species == SP_GHOUL) ? US_HUNGRY_DEAD : US_ALIVE); - // before we get into the inventory init, set light radius based - // on species vision. currently, all species see out to 8 squares. + // before we get into the inventory init, set light radius based + // on species vision. currently, all species see out to 8 squares. you.normal_vision = 8; you.current_vision = 8; @@ -627,7 +618,7 @@ bool new_game(void) // don't change object type modifier unless it starts plain if (you.inv[i].base_type <= OBJ_ARMOUR - && cmp_equip_race( you.inv[i], 0 )) // == DARM_PLAIN + && get_equip_race(you.inv[i]) == 0 ) // == DARM_PLAIN { // now add appropriate species type mod: switch (you.species) @@ -664,8 +655,11 @@ bool new_game(void) } } - you.item_description[IDESC_POTIONS][POT_PORRIDGE] = 153; // "gluggy white" - you.item_description[IDESC_POTIONS][POT_WATER] = 0; // "clear" + you.item_description[IDESC_POTIONS][POT_PORRIDGE] = + PDESCQ(PDQ_GLUGGY, PDC_WHITE); + + you.item_description[IDESC_POTIONS][POT_WATER] = + PDESCS(PDC_CLEAR); int passout; @@ -689,9 +683,7 @@ bool new_game(void) break; case IDESC_POTIONS: // potions - you.item_description[i][j] = random2( 15 * 14 ); - if (coinflip()) - you.item_description[i][j] %= 14; + you.item_description[i][j] = random_potion_description(); break; case IDESC_SCROLLS: // scrolls @@ -1422,6 +1414,7 @@ bool class_allowed( unsigned char speci, int char_class ) case SP_HUMAN: case SP_DEMIGOD: case SP_DEMONSPAWN: + case SP_GHOUL: return true; } return false; @@ -1432,6 +1425,88 @@ bool class_allowed( unsigned char speci, int char_class ) } } // end class_allowed() + +static void choose_book( item_def& book, int firstbook, int numbooks ) +{ + int keyin = 0; + clrscr(); + book.base_type = OBJ_BOOKS; + book.quantity = 1; + book.plus = 0; + book.special = 1; + book.colour = CYAN; + + // using the fact that CONJ_I and MINOR_MAGIC_I are both + // fire books, CONJ_II and MINOR_MAGIC_II are both ice books + if ( Options.book && Options.book <= numbooks ) + { + book.sub_type = firstbook + Options.book - 1; + ng_book = Options.book; + return; + } + + if ( Options.prev_book > numbooks && Options.prev_book != SBT_RANDOM ) + Options.prev_book = SBT_NO_SELECTION; + + if ( !Options.random_pick ) + { + textcolor( CYAN ); + cprintf(EOL " You have a choice of books:" EOL); + textcolor( LIGHTGREY ); + + for (int i=0; i < numbooks; ++i) + { + char buf[ITEMNAME_SIZE]; + book.sub_type = firstbook + i; + item_name( book, DESC_PLAIN, buf ); + cprintf("%c - %s" EOL, 'a' + i, buf); + } + + textcolor(BROWN); + cprintf(EOL "? - Random" ); + if ( Options.prev_book != SBT_NO_SELECTION ) { + cprintf("; Enter - %s", + Options.prev_book == SBT_FIRE ? "Fire" : + Options.prev_book == SBT_COLD ? "Cold" : + Options.prev_book == SBT_SUMM ? "Summoning" : + Options.prev_book == SBT_RANDOM ? "Random" : + "Buggy Book"); + } + cprintf(EOL); + + do + { + textcolor( CYAN ); + cprintf(EOL "Which book? "); + textcolor( LIGHTGREY ); + + keyin = get_ch(); + } while (keyin != '?' && + ((keyin != '\r' && keyin != '\n') || + Options.prev_book == SBT_NO_SELECTION ) && + (keyin < 'a' || keyin > ('a' + numbooks))); + + if ( keyin == '\r' || keyin == '\n' ) + { + if ( Options.prev_book == SBT_RANDOM ) + keyin = '?'; + else + keyin = ('a' + Options.prev_book - 1); + } + } + + if (Options.random_pick || Options.book == SBT_RANDOM || keyin == '?') + ng_book = SBT_RANDOM; + else + ng_book = keyin - 'a' + 1; + + if ( Options.random_pick || keyin == '?' ) + keyin = random2(numbooks) + 'a'; + + book.sub_type = firstbook + keyin - 'a'; +} + + static char startwep[5] = { WPN_SHORT_SWORD, WPN_MACE, WPN_HAND_AXE, WPN_SPEAR, WPN_TRIDENT }; @@ -1477,10 +1552,8 @@ void choose_weapon( void ) int x = effective_stat_bonus(startwep[i]); standard_name_weap(startwep[i], wepName); - snprintf( info, INFO_SIZE, "%c - %s%s" EOL, 'a' + i, wepName, - (x <= -4) ? " (not ideal)" : "" ); - - cprintf(info); + cprintf("%c - %s%s" EOL, 'a' + i, wepName, + (x <= -4) ? " (not ideal)" : "" ); if (Options.prev_weapon == startwep[i]) prevmatch = true; @@ -1527,7 +1600,10 @@ void choose_weapon( void ) } if (keyin != '?' && effective_stat_bonus(startwep[keyin-'a']) > -4) + { cprintf(EOL "A fine choice. " EOL); + delay(1000); + } } if (Options.random_pick || Options.weapon == WPN_RANDOM || keyin == '?') @@ -1553,167 +1629,7 @@ void choose_weapon( void ) void init_player(void) { - unsigned char i = 0; // loop variable - - you.birth_time = time( NULL ); - you.real_time = 0; - you.num_turns = 0; - -#ifdef WIZARD - you.wizard = (Options.wiz_mode == WIZ_YES) ? true : false; -#else - you.wizard = false; -#endif - - you.activity = ACT_NONE; - you.berserk_penalty = 0; - you.berserker = 0; - you.conf = 0; - you.confusing_touch = 0; - you.deaths_door = 0; - you.disease = 0; - you.elapsed_time = 0; - you.exhausted = 0; - you.haste = 0; - you.invis = 0; - you.levitation = 0; - you.might = 0; - you.paralysis = 0; - you.poison = 0; - you.rotting = 0; - you.fire_shield = 0; - you.slow = 0; - you.special_wield = SPWLD_NONE; - you.sure_blade = 0; - you.synch_time = 0; - - you.base_hp = 5000; - you.base_hp2 = 5000; - you.base_magic_points = 5000; - you.base_magic_points2 = 5000; - - you.magic_points_regeneration = 0; - you.strength = 0; - you.max_strength = 0; - you.intel = 0; - you.max_intel = 0; - you.dex = 0; - you.max_dex = 0; - you.experience = 0; - you.experience_level = 1; - you.max_level = 1; - you.char_class = JOB_UNKNOWN; - - you.hunger = 6000; - you.hunger_state = HS_SATIATED; - - you.gold = 0; - // you.speed = 10; // 0.75; // unused - - you.burden = 0; - you.burden_state = BS_UNENCUMBERED; - - you.spell_no = 0; - - you.your_level = 0; - you.level_type = LEVEL_DUNGEON; - you.where_are_you = BRANCH_MAIN_DUNGEON; - you.char_direction = DIR_DESCENDING; - - you.prev_targ = MHITNOT; - you.pet_target = MHITNOT; - - you.x_pos = 0; - you.y_pos = 0; - - you.running = 0; - you.run_x = 0; - you.run_y = 0; - you.travel_x = 0; - you.travel_y = 0; - - for (i = 0; i < 3; i++) - { - you.run_check[i].grid = 0; - you.run_check[i].dx = 0; - you.run_check[i].dy = 0; - } - - you.religion = GOD_NO_GOD; - you.piety = 0; - - you.gift_timeout = 0; - - for (i = 0; i < MAX_NUM_GODS; i++) - { - you.penance[i] = 0; - you.worshipped[i] = 0; - } - - ghost.name[0] = '\0'; - - for (i = 0; i < NUM_GHOST_VALUES; i++) - ghost.values[i] = 0; - - for (i = EQ_WEAPON; i < NUM_EQUIP; i++) - you.equip[i] = -1; - - for (i = 0; i < 25; i++) - you.spells[i] = SPELL_NO_SPELL; - - for (i = 0; i < 52; i++) - { - you.spell_letter_table[i] = -1; - you.ability_letter_table[i] = ABIL_NON_ABILITY; - } - - for (i = 0; i < 100; i++) - you.mutation[i] = 0; - - for (i = 0; i < 100; i++) - you.demon_pow[i] = 0; - - for (i = 0; i < 50; i++) - you.had_book[i] = 0; - - for (i = 0; i < 50; i++) - you.unique_items[i] = UNIQ_NOT_EXISTS; - - for (i = 0; i < NO_UNRANDARTS; i++) - set_unrandart_exist(i, 0); - - for (i = 0; i < 50; i++) - { - you.skills[i] = 0; - you.skill_points[i] = 0; - you.skill_order[i] = MAX_SKILL_ORDER; - you.practise_skill[i] = 1; - } - - you.skill_cost_level = 1; - you.total_skill_points = 0; - - for (i = 0; i < 30; i++) - you.attribute[i] = 0; - - for (i = 0; i < ENDOFPACK; i++) - { - you.inv[i].quantity = 0; - you.inv[i].base_type = OBJ_WEAPONS; - you.inv[i].sub_type = WPN_CLUB; - you.inv[i].plus = 0; - you.inv[i].plus2 = 0; - you.inv[i].special = 0; - you.inv[i].colour = 0; - set_ident_flags( you.inv[i], ISFLAG_IDENT_MASK ); - - you.inv[i].x = -1; - you.inv[i].y = -1; - you.inv[i].link = i; - } - - for (i = 0; i < NUM_DURATIONS; i++) - you.duration[i] = 0; + you.init(); } void give_last_paycheck(int which_job) @@ -1803,7 +1719,7 @@ void species_stat_init(unsigned char which_species) case SP_PALE_DRACONIAN: case SP_UNK0_DRACONIAN: case SP_UNK1_DRACONIAN: - case SP_UNK2_DRACONIAN: sb = 9; ib = 6; db = 2; break; // 17 + case SP_BASE_DRACONIAN: sb = 9; ib = 6; db = 2; break; // 17 } modify_all_stats( sb, ib, db ); @@ -1993,116 +1909,202 @@ void give_basic_spells(int which_job) // eventually, this should be something more grand {dlb} void openingScreen(void) { -/* ********************************************** -// this does not work just yet ... {dlb}: - cprintf(EOL "Hello, "); - - if ( you.your_name[0] != '\0' ) - { - cprintf(you.your_name); // better be less than 31 characters :P {dlb} - // of course, invalid names will appear {dlb} - cprintf(", "); - } -********************************************** */ - textcolor( YELLOW ); - cprintf("Hello, welcome to Dungeon Crawl " VERSION "!"); + cprintf("Hello, welcome to " CRAWL " " VERSION "!"); textcolor( BROWN ); cprintf(EOL "(c) Copyright 1997-2002 Linley Henzell"); - cprintf(EOL "Please consult crawl.txt for instructions and legal details." - EOL); + cprintf(EOL + "Please consult crawl_manual.txt for instructions and legal details." + EOL); + + bool init_found = init_file_location.find("not found") == std::string::npos; + if (!init_found) + textcolor( LIGHTRED ); + else + textcolor( LIGHTGREY ); + + cprintf("Init file %s%s" EOL, + init_found? "read: " : "", + init_file_location.c_str()); textcolor( LIGHTGREY ); return; } // end openingScreen() +static void show_name_prompt(int where, bool blankOK, + const std::vector<player> &existing_chars, + slider_menu &menu) +{ + gotoxy(1, where); + textcolor( CYAN ); + if (blankOK) + { + if (Options.prev_name.length() && Options.remember_name) + cprintf(EOL "Press <Enter> for \"%s\"." EOL, + Options.prev_name.c_str()); + else + cprintf(EOL + "Press <Enter> to answer this after race and " + "class are chosen." EOL); + } -void enterPlayerName(bool blankOK) + cprintf(EOL "What is your name today? "); + + if (!existing_chars.empty()) + { + const int name_x = wherex(), name_y = wherey(); + menu.set_limits(name_y + 3, get_number_of_lines()); + menu.display(); + gotoxy(name_x, name_y); + } + + textcolor( LIGHTGREY ); +} + +static void preprocess_character_name(char *name, bool blankOK) { - // temporary 'til copyover to you.your_name {dlb} - // made this rediculously long so that the game doesn't - // crash if a really really long name is entered (argh). {gdl} - char name_entered[200]; + if (!*name && blankOK && Options.prev_name.length() && + Options.remember_name) + { + strncpy(name, Options.prev_name.c_str(), kNameLen); + name[kNameLen - 1] = 0; + } - // anything to avoid goto statements {dlb} - bool acceptable_name = false; - bool first_time = true; + // '.', '?' and '*' are blanked. + if (!name[1] && (*name == '.' || + *name == '*' || + *name == '?')) + *name = 0; +} - // first time -- names set through init.txt/environment assumed ok {dlb} - if (you.your_name[0] != '\0') - acceptable_name = true; +static bool is_good_name(char *name, bool blankOK) +{ + preprocess_character_name(name, blankOK); - do + // verification begins here {dlb}: + if (you.your_name[0] == 0) { - // prompt for a new name if current one unsatisfactory {dlb}: - if (!acceptable_name) + if (blankOK) + return (true); + + cprintf(EOL "That's a silly name!" EOL); + return (false); + } + + // if MULTIUSER is defined, userid will be tacked onto the end + // of each character's files, making bones a valid player name. +#ifndef MULTIUSER + // this would cause big probs with ghosts + // what would? {dlb} + // ... having the name "bones" of course! The problem comes from + // the fact that bones files would have the exact same filename + // as level files for a character named "bones". -- bwr + if (stricmp(you.your_name, "bones") == 0) + { + cprintf(EOL "That's a silly name!" EOL); + return (false); + } +#endif + return (verifyPlayerName()); +} + +static int newname_keyfilter(int &ch) +{ + if (ch == CK_DOWN || ch == CK_PGDN || ch == '\t') + return -1; + return 1; +} + +static bool read_player_name( + char *name, + int len, + const std::vector<player> &existing, + slider_menu &menu) +{ + const int name_x = wherex(), name_y = wherey(); + int (*keyfilter)(int &) = newname_keyfilter; + if (existing.empty()) + keyfilter = NULL; + + line_reader reader(name, len); + reader.set_keyproc(keyfilter); + + for (;;) + { + gotoxy(name_x, name_y); + if (name_x <= 80) + cprintf("%-*s", 80 - name_x + 1, ""); + + gotoxy(name_x, name_y); + int ret = reader.read_line(false); + if (!ret) + return (true); + + if (ret == CK_ESCAPE) + return (false); + + if (ret != CK_ESCAPE && existing.size()) { - textcolor( CYAN ); - if (blankOK && first_time) + menu.set_search(name); + menu.show(); + const MenuEntry *sel = menu.selected_entry(); + if (sel) { - if (Options.prev_name.length() && Options.remember_name) - cprintf(EOL "Press <Enter> for \"%s\"." EOL, - Options.prev_name.c_str()); - else - cprintf(EOL - "Press <Enter> to answer this after race and " - "class are chosen." EOL); + const player &p = *static_cast<player*>( sel->data ); + strncpy(name, p.your_name, kNameLen); + name[kNameLen - 1] = 0; + return (true); } + } - first_time = false; + // Go back and prompt the user. + } +} - cprintf(EOL "What is your name today? "); - textcolor( LIGHTGREY ); - get_input_line( name_entered, sizeof( name_entered ) ); - - strncpy( you.your_name, name_entered, kNameLen ); - you.your_name[ kNameLen - 1 ] = '\0'; - } +void enterPlayerName(bool blankOK) +{ + int prompt_start = wherey(); + bool ask_name = true; + char *name = you.your_name; + std::vector<player> existing_chars; + slider_menu char_menu; - if (!*you.your_name && blankOK && Options.prev_name.length() && - Options.remember_name) - { - strncpy(you.your_name, Options.prev_name.c_str(), kNameLen); - you.your_name[kNameLen - 1] = 0; - } + if (you.your_name[0] != 0) + ask_name = false; - // '.', '?' and '*' are blanked. - if (!you.your_name[1] && (*you.your_name == '.' || - *you.your_name == '*' || - *you.your_name == '?')) - { - *you.your_name = 0; - } - - // verification begins here {dlb}: - if (you.your_name[0] == '\0') + if (blankOK) + { + existing_chars = find_saved_characters(); + + MenuEntry *title = new MenuEntry("Or choose an existing character:"); + title->colour = LIGHTCYAN; + char_menu.set_title( title ); + for (int i = 0, size = existing_chars.size(); i < size; ++i) { - if (blankOK) - return; + std::string desc = " " + existing_chars[i].short_desc(); + if ((int) desc.length() >= get_number_of_cols()) + desc = desc.substr(0, get_number_of_cols() - 1); - cprintf(EOL "That's a silly name!" EOL); - acceptable_name = false; + MenuEntry *me = new MenuEntry(desc); + me->data = &existing_chars[i]; + char_menu.add_entry(me); } + char_menu.set_flags(MF_EASY_EXIT | MF_SINGLESELECT); + } - // if SAVE_DIR_PATH is defined, userid will be tacked onto the end - // of each character's files, making bones a valid player name. -#ifndef SAVE_DIR_PATH - // this would cause big probs with ghosts - // what would? {dlb} - // ... having the name "bones" of course! The problem comes from - // the fact that bones files would have the exact same filename - // as level files for a character named "bones". -- bwr - else if (stricmp(you.your_name, "bones") == 0) + do + { + // prompt for a new name if current one unsatisfactory {dlb}: + if (ask_name) { - cprintf(EOL "That's a silly name!" EOL); - acceptable_name = false; - } -#endif - else - acceptable_name = verifyPlayerName(); + show_name_prompt(prompt_start, blankOK, existing_chars, char_menu); + // If the player wants out, we bail out. + if (!read_player_name(name, kNameLen, existing_chars, char_menu)) + end(0); + } } - while (!acceptable_name); + while (ask_name = !is_good_name(you.your_name, blankOK)); } // end enterPlayerName() bool verifyPlayerName(void) @@ -2117,7 +2119,7 @@ bool verifyPlayerName(void) return (false); } - // quick check for LPTx -- thank you, Mr. Tanksley! ;-) + // quick check for LPTx -- thank you, Mr. Tanksley! ;-) if (strnicmp(you.your_name, "LPT", 3) == 0) { switch (william_tanksley_asked_for_this) @@ -2133,7 +2135,7 @@ bool verifyPlayerName(void) return (true); } // end switch - william_tanksley_asked_for_this --; + william_tanksley_asked_for_this--; return (false); } #endif @@ -2141,14 +2143,6 @@ bool verifyPlayerName(void) const size_t len = strlen( you.your_name ); for (unsigned int i = 0; i < len; i++) { -#if MAC - // the only bad character on Macs is the path seperator - if (you.your_name[i] == ':') - { - cprintf(EOL "No colons, please." EOL); - return (false); - } -#else // Note that this includes systems which may be using the // packaging system. The packaging system is very simple // and doesn't take the time to escape every characters that @@ -2159,10 +2153,9 @@ bool verifyPlayerName(void) cprintf( EOL "Alpha-numerics and underscores only, please." EOL ); return (false); } -#endif } -#ifdef SAVE_DIR_PATH +#ifdef MULTIUSER // Until we have a better way to handle the fact that this could lead // to some confusion with where the name ends and the uid begins. -- bwr if (isdigit( you.your_name[ len - 1 ] )) @@ -2379,19 +2372,19 @@ static bool give_wanderer_weapon( int slot, int wpn_skill ) static void create_wanderer( void ) { const int util_skills[] = - { SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH, + { SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH, SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT, SK_INVOCATIONS, SK_EVOCATIONS }; const int num_util_skills = sizeof(util_skills) / sizeof(int); - // Long swords is missing to increae it's rarity because we + // Long swords is missing to increase its rarity because we // can't give out a long sword to a starting character (they're // all too good)... Staves is also removed because it's not // one of the fighter options.-- bwr const int fight_util_skills[] = { SK_FIGHTING, SK_SHORT_BLADES, SK_AXES, SK_MACES_FLAILS, SK_POLEARMS, - SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH, + SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH, SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT, SK_INVOCATIONS, SK_EVOCATIONS }; const int num_fight_util_skills = sizeof(fight_util_skills) / sizeof(int); @@ -2402,7 +2395,7 @@ static void create_wanderer( void ) SK_FIRE_MAGIC, SK_ICE_MAGIC, SK_AIR_MAGIC, SK_EARTH_MAGIC, SK_FIGHTING, SK_SHORT_BLADES, SK_LONG_SWORDS, SK_AXES, SK_MACES_FLAILS, SK_POLEARMS, SK_STAVES, - SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH, + SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH, SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT, SK_INVOCATIONS, SK_EVOCATIONS }; const int num_not_rare_skills = sizeof(not_rare_skills) / sizeof(int); @@ -2415,7 +2408,7 @@ static void create_wanderer( void ) SK_FIRE_MAGIC, SK_ICE_MAGIC, SK_AIR_MAGIC, SK_EARTH_MAGIC, SK_FIGHTING, SK_SHORT_BLADES, SK_LONG_SWORDS, SK_AXES, SK_MACES_FLAILS, SK_POLEARMS, SK_STAVES, - SK_DARTS, SK_THROWING, SK_ARMOUR, SK_DODGING, SK_STEALTH, + SK_DARTS, SK_RANGED_COMBAT, SK_ARMOUR, SK_DODGING, SK_STEALTH, SK_STABBING, SK_SHIELDS, SK_TRAPS_DOORS, SK_UNARMED_COMBAT, SK_INVOCATIONS, SK_EVOCATIONS }; const int num_all_skills = sizeof(all_skills) / sizeof(int); @@ -2486,9 +2479,9 @@ static void create_wanderer( void ) you.skills[ skill ] = 1; } - int wpn_skill = SK_FIGHTING; // prefered weapon type - int wpn_skill_size = 0; // level of skill in prefered weapon type - int num_wpn_skills = 0; // used to choose prefered weapon + int wpn_skill = SK_FIGHTING; // preferred weapon type + int wpn_skill_size = 0; // level of skill in preferred weapon type + int num_wpn_skills = 0; // used to choose preferred weapon int total_wpn_skills = 0; // used to choose template // This algorithm is the same as the one used to pick a random @@ -2638,14 +2631,14 @@ static void create_wanderer( void ) add_spell_to_memory( spell_list[ school ] ); } } - else if (you.skills[ SK_THROWING ] && one_chance_in(3)) // these are rare + else if (you.skills[ SK_RANGED_COMBAT ] && one_chance_in(3)) // these are rare { // Ranger style wanderer // Rare since starting with a throwing weapon is very good // Create a default launcher template, but the // quantity may be reset to 0 if we don't want one -- bwr - // thorwing weapons are lowered to -1 to make them + // throwing weapons are lowered to -1 to make them // not as good as the one's hunters get, ammo is // also much smaller -- bwr you.inv[1].quantity = 1; @@ -2844,10 +2837,10 @@ static char letter_to_species(int keyn) static char species_to_letter(int spec) { - if (spec > SP_RED_DRACONIAN && spec <= SP_UNK2_DRACONIAN) + if (spec > SP_RED_DRACONIAN && spec <= SP_BASE_DRACONIAN) spec = SP_RED_DRACONIAN; - else if (spec > SP_UNK2_DRACONIAN) - spec -= SP_UNK2_DRACONIAN - SP_RED_DRACONIAN; + else if (spec > SP_BASE_DRACONIAN) + spec -= SP_BASE_DRACONIAN - SP_RED_DRACONIAN; return 'a' + spec - 1; } @@ -2891,12 +2884,12 @@ spec_query: textcolor( YELLOW ); if (strlen(you.your_name) > 0) { - cprintf(you.your_name); + cprintf("%s", you.your_name); if (you.char_class != JOB_UNKNOWN) cprintf(" the "); } if (you.char_class != JOB_UNKNOWN) - cprintf(get_class_name(you.char_class)); + cprintf("%s", get_class_name(you.char_class)); if (!shortgreet) cprintf("."); @@ -2918,7 +2911,7 @@ spec_query: *linebuf = 0; for (int i = SP_HUMAN; i < NUM_SPECIES; ++i) { - if (i > SP_RED_DRACONIAN && i <= SP_UNK2_DRACONIAN) + if (i > SP_RED_DRACONIAN && i <= SP_BASE_DRACONIAN) continue; if (you.char_class != JOB_UNKNOWN && @@ -3051,7 +3044,7 @@ spec_query: return true; } -// returns true if a class was chosen, false if we should go back to +// returns true if a class was chosen, false if we should go back to // race selection. bool choose_class(void) @@ -3089,12 +3082,12 @@ job_query: textcolor( YELLOW ); if (strlen(you.your_name) > 0) { - cprintf(you.your_name); + cprintf("%s", you.your_name); if (you.species) cprintf(" the "); } if (you.species) - cprintf(species_name(you.species,you.experience_level)); + cprintf("%s", species_name(you.species,you.experience_level)); if (!shortgreet) cprintf("."); @@ -3126,7 +3119,7 @@ job_query: putch( letter ); cprintf( " - " ); - cprintf( get_class_name(i) ); + cprintf( "%s", get_class_name(i) ); if (j % 2) cprintf(EOL); @@ -3301,7 +3294,7 @@ void give_items_skills() { you.inv[0].quantity = 1; you.inv[0].base_type = OBJ_WEAPONS; - you.inv[0].sub_type = WPN_CLUB; + you.inv[0].sub_type = WPN_ANCUS; you.inv[0].plus = 0; you.inv[0].special = 0; you.inv[0].colour = BROWN; @@ -3399,7 +3392,7 @@ void give_items_skills() if (you.species == SP_KOBOLD) { - you.skills[SK_THROWING] = 1; + you.skills[SK_RANGED_COMBAT] = 1; you.skills[SK_DARTS] = 1; you.skills[SK_DODGING] = 1; you.skills[SK_STEALTH] = 1; @@ -3419,13 +3412,13 @@ void give_items_skills() else { // Players get dodging or armour skill depending on their - // starting armour now (note: the armour has to be quiped + // starting armour now (note: the armour has to be equipped // for this function to work) you.skills[(player_light_armour()? SK_DODGING : SK_ARMOUR)] = 2; you.skills[SK_SHIELDS] = 2; - you.skills[SK_THROWING] = 2; + you.skills[SK_RANGED_COMBAT] = 2; you.skills[(coinflip() ? SK_STABBING : SK_SHIELDS)]++; } break; @@ -3485,12 +3478,7 @@ void give_items_skills() you.equip[EQ_BODY_ARMOUR] = 1; // extra items being tested: - you.inv[2].base_type = OBJ_BOOKS; - you.inv[2].sub_type = BOOK_MINOR_MAGIC_I + random2(3); - you.inv[2].quantity = 1; - you.inv[2].plus = 0; // = 127 - you.inv[2].special = 1; - you.inv[2].colour = CYAN; + choose_book( you.inv[2], BOOK_MINOR_MAGIC_I, 3 ); you.skills[SK_DODGING] = 1; you.skills[SK_STEALTH] = 1; @@ -3652,7 +3640,7 @@ void give_items_skills() you.skills[SK_STEALTH] = 2; you.skills[SK_STABBING] = 1; you.skills[SK_DODGING + random2(3)]++; - you.skills[SK_THROWING] = 1; + you.skills[SK_RANGED_COMBAT] = 1; you.skills[SK_DARTS] = 1; you.skills[SK_TRAPS_DOORS] = 2; break; @@ -3856,12 +3844,12 @@ void give_items_skills() you.skills[SK_DODGING] = 1; you.skills[SK_STEALTH] = 3; you.skills[SK_STABBING] = 2; - you.skills[SK_THROWING] = 1; + you.skills[SK_RANGED_COMBAT] = 1; you.skills[SK_DARTS] = 1; if (you.species == SP_DEEP_ELF) you.skills[SK_CROSSBOWS] = 1; else - you.skills[SK_THROWING] += 1; + you.skills[SK_RANGED_COMBAT] += 1; break; @@ -3874,7 +3862,7 @@ void give_items_skills() { you.inv[0].quantity = 1; you.inv[0].base_type = OBJ_WEAPONS; - you.inv[0].sub_type = WPN_CLUB; + you.inv[0].sub_type = WPN_ANCUS; you.inv[0].plus = 0; you.inv[0].plus2 = 0; you.inv[0].special = 0; @@ -3954,7 +3942,7 @@ void give_items_skills() you.skills[SK_POLEARMS] = 1; you.skills[SK_ARMOUR] = 2; you.skills[SK_DODGING] = 2; - you.skills[SK_THROWING] = 2; + you.skills[SK_RANGED_COMBAT] = 2; } break; @@ -4017,7 +4005,7 @@ void give_items_skills() you.equip[EQ_BODY_ARMOUR] = 4; you.skills[SK_FIGHTING] = 2; - you.skills[SK_THROWING] = 3; + you.skills[SK_RANGED_COMBAT] = 3; // Removing spellcasting -- bwr // you.skills[SK_SPELLCASTING] = 1; @@ -4064,7 +4052,7 @@ void give_items_skills() you.skills[SK_POLEARMS] = 2; you.skills[SK_DODGING] = 2; - you.skills[SK_THROWING] += 1; + you.skills[SK_RANGED_COMBAT] += 1; break; default: @@ -4108,9 +4096,15 @@ void give_items_skills() you.equip[EQ_WEAPON] = 0; you.equip[EQ_BODY_ARMOUR] = 1; - you.inv[2].base_type = OBJ_BOOKS; - you.inv[2].sub_type = give_first_conjuration_book(); - you.inv[2].plus = 0; + + if ( you.char_class == JOB_CONJURER ) + choose_book( you.inv[2], BOOK_CONJURATIONS_I, 2 ); + else + { + you.inv[2].base_type = OBJ_BOOKS; + // subtype will always be overridden + you.inv[2].plus = 0; + } switch (you.char_class) { @@ -4283,7 +4277,7 @@ void give_items_skills() you.skills[SK_STEALTH] = 1; if (you.species == SP_GNOME && you.char_class == JOB_EARTH_ELEMENTALIST) - you.skills[SK_THROWING]++; + you.skills[SK_RANGED_COMBAT]++; else you.skills[ coinflip() ? SK_DODGING : SK_STEALTH ]++; break; @@ -4332,7 +4326,7 @@ void give_items_skills() you.skills[SK_FIGHTING] = 1; you.skills[SK_UNARMED_COMBAT] = 3; - you.skills[SK_THROWING] = 2; + you.skills[SK_RANGED_COMBAT] = 2; you.skills[SK_DODGING] = 2; you.skills[SK_SPELLCASTING] = 2; you.skills[SK_TRANSMIGRATION] = 2; @@ -4419,7 +4413,7 @@ void give_items_skills() you.equip[EQ_WEAPON] = 0; you.equip[EQ_BODY_ARMOUR] = 1; - you.skills[SK_THROWING] = 1; + you.skills[SK_RANGED_COMBAT] = 1; you.skills[SK_DARTS] = 2; you.skills[SK_DODGING] = 2; you.skills[SK_STEALTH] = 1; @@ -4722,7 +4716,7 @@ void give_items_skills() you.skills[SK_FIGHTING] = 2; you.skills[SK_DODGING] = 1; you.skills[SK_SHIELDS] = 1; - you.skills[SK_THROWING] = 2; + you.skills[SK_RANGED_COMBAT] = 2; you.skills[SK_STAVES] = 3; you.skills[SK_INVOCATIONS] = 2; break; @@ -4806,7 +4800,7 @@ void give_items_skills() you.skills[SK_STEALTH] = 2; you.skills[SK_STABBING] = 2; you.skills[SK_DODGING + random2(3)]++; - //you.skills[SK_THROWING] = 1; //jmf: removed these, added magic below + //you.skills[SK_RANGED_COMBAT] = 1; //jmf: removed these, added magic below //you.skills[SK_DARTS] = 1; you.skills[SK_SPELLCASTING] = 1; you.skills[SK_ENCHANTMENTS] = 1; |