summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/ghost.cc2
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/newgame.cc316
-rw-r--r--crawl-ref/source/newgame.h6
-rw-r--r--crawl-ref/source/ng-input.cc302
-rw-r--r--crawl-ref/source/ng-input.h11
6 files changed, 337 insertions, 301 deletions
diff --git a/crawl-ref/source/ghost.cc b/crawl-ref/source/ghost.cc
index 1b682b3603..a7bdf67767 100644
--- a/crawl-ref/source/ghost.cc
+++ b/crawl-ref/source/ghost.cc
@@ -14,7 +14,7 @@
#include "externs.h"
#include "itemname.h"
#include "itemprop.h"
-#include "newgame.h"
+#include "ng-input.h"
#include "skills2.h"
#include "stuff.h"
#include "mtransit.h"
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index c017f736ed..30ff3862b2 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -86,6 +86,7 @@ mt19937ar.o \
mtransit.o \
mutation.o \
newgame.o \
+ng-input.o \
ng-restr.o \
jobs.o \
species.o \
diff --git a/crawl-ref/source/newgame.cc b/crawl-ref/source/newgame.cc
index e73e4bad0b..50f46dcd31 100644
--- a/crawl-ref/source/newgame.cc
+++ b/crawl-ref/source/newgame.cc
@@ -7,6 +7,7 @@
#include "AppHdr.h"
#include "newgame.h"
+#include "ng-input.h"
#include "ng-restr.h"
#include "jobs.h"
@@ -58,17 +59,13 @@
#include "stuff.h"
#include "tutorial.h"
-extern std::string init_file_error;
-
#define MIN_START_STAT 3
-static void _enter_player_name(bool blankOK);
static void _give_basic_knowledge(job_type which_job);
static void _give_basic_spells(job_type which_job);
static void _give_last_paycheck(job_type which_job);
static void _init_player(void);
static void _jobs_stat_init(job_type which_job);
-static void _opening_screen(void);
static void _species_stat_init(species_type which_species);
static void _create_wanderer(void);
@@ -81,13 +78,22 @@ static void _fix_up_god_name(void);
static newgame_def ng;
-// XXX: temporary to get data to ng-restr.cc.
+// XXX: temporary to get data in and out of
+// purely rewritten functions.
void newgame_def::init(const player &p)
{
+ name = p.your_name;
species = p.species;
job = p.char_class;
}
+void newgame_def::save(player &p)
+{
+ p.your_name = name;
+ p.species = species;
+ p.char_class = job;
+}
+
static char ng_race, ng_cls;
static bool ng_random;
static int ng_ck, ng_dk;
@@ -861,8 +867,10 @@ bool new_game(void)
if (!SysEnv.crawl_name.empty())
you.your_name = SysEnv.crawl_name;
- _opening_screen();
- _enter_player_name(true);
+ opening_screen();
+ ng.init(you);
+ enter_player_name(ng, true);
+ ng.save(you);
if (!you.your_name.empty())
{
@@ -935,7 +943,9 @@ game_start:
(is_vowel( specs[0] )) ? "n" : "", specs.c_str(),
you.class_name );
- _enter_player_name(false);
+ ng.init(you);
+ enter_player_name(ng, false);
+ ng.save(you);
if (_check_saved_game())
{
@@ -1832,296 +1842,6 @@ static void _give_basic_spells(job_type which_job)
return;
}
-// Eventually, this should be something more grand. {dlb}
-static void _opening_screen(void)
-{
-#ifdef USE_TILE
- // More grand... Like this? ;)
- if (Options.tile_title_screen)
- tiles.draw_title();
-#endif
-
- std::string msg =
- "<yellow>Hello, welcome to " CRAWL " " + Version::Long() + "!</yellow>" EOL
- "<brown>(c) Copyright 1997-2002 Linley Henzell, "
- "2002-2009 Crawl DevTeam" EOL
- "Please consult crawl_manual.txt for instructions and legal details."
- "</brown>" EOL;
-
- const bool init_found = init_file_error.empty();
-
- if (!init_found)
- msg += "<lightred>No init file ";
- else
- msg += "<lightgrey>(Read options from ";
-
- if (init_found)
- {
-#ifdef DGAMELAUNCH
- // For dgl installs, show only the last segment of the .crawlrc
- // file name so that we don't leak details of the directory
- // structure to (untrusted) users.
- msg += get_base_filename(Options.filename);
-#else
- msg += Options.filename;
-#endif
- msg += ".)";
- }
- else
- {
- msg += init_file_error;
- msg += ", using defaults.";
- }
-
- msg += EOL;
-
- formatted_string::parse_string(msg).display();
- textcolor( LIGHTGREY );
-}
-
-static void _show_name_prompt(int where, bool blankOK,
- const std::vector<player_save_info> &existing_chars,
- slider_menu &menu)
-{
- cgotoxy(1, where);
- textcolor( CYAN );
- if (blankOK)
- {
- if (Options.prev_name.length() && Options.remember_name)
- {
- cprintf(EOL
- "Press <Enter> for \"%s\", or . to be prompted later."
- EOL,
- Options.prev_name.c_str());
- }
- else
- {
- cprintf(EOL
- "Press <Enter> to answer this after species and "
- "job are chosen." EOL);
- }
- }
-
- 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();
- cgotoxy(name_x, name_y);
- }
-
- textcolor( LIGHTGREY );
-}
-
-static void _preprocess_character_name(std::string &name, bool blankOK)
-{
- if (name.empty() && blankOK && Options.prev_name.length()
- && Options.remember_name)
- {
- name = Options.prev_name;
- }
-
- // '.', '?' and '*' are blanked.
- if (name.length() == 1
- && (name[0] == '.' || name[0] == '*' || name[0] == '?'))
- {
- name = "";
- }
-}
-
-static bool _is_good_name(std::string &name, bool blankOK, bool verbose)
-{
- _preprocess_character_name(name, blankOK);
-
- // verification begins here {dlb}:
- if (name.empty())
- {
- if (blankOK)
- return (true);
-
- if (verbose)
- 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(name.c_str(), "bones") == 0)
- {
- if (verbose)
- cprintf(EOL "That's a silly name!" EOL);
- return (false);
- }
-#endif
- return (validate_player_name(name, verbose));
-}
-
-static int newname_keyfilter(int &ch)
-{
- if (ch == CK_DOWN || ch == CK_PGDN || ch == '\t')
- return -1;
-
- return 1;
-}
-
-static bool _read_player_name(std::string &name,
- const std::vector<player_save_info> &existing,
- slider_menu &menu)
-{
- const int name_x = wherex(), name_y = wherey();
- int (*keyfilter)(int &) = newname_keyfilter;
- if (existing.empty())
- keyfilter = NULL;
- char buf[kNameLen];
- // XXX: Prompt displays garbage otherwise, but don't really know why.
- // Other places don't do this. --rob
- buf[0] = '\0';
- line_reader reader(buf, sizeof(buf));
-
- reader.set_keyproc(keyfilter);
-
- while (true)
- {
- cgotoxy(name_x, name_y);
- if (name_x <= 80)
- cprintf("%-*s", 80 - name_x + 1, "");
-
- cgotoxy(name_x, name_y);
- int ret = reader.read_line(false);
- if (!ret)
- {
- name = buf;
- return (true);
- }
-
- if (ret == CK_ESCAPE)
- return (false);
-
- if (ret != CK_ESCAPE && existing.size())
- {
- menu.set_search(name);
- menu.show();
- const MenuEntry *sel = menu.selected_entry();
- if (sel)
- {
- const player_save_info &p =
- *static_cast<player_save_info*>( sel->data );
- name = p.name;
- return (true);
- }
- }
-
- // Go back and prompt the user.
- }
-}
-
-static void _enter_player_name(bool blankOK)
-{
- int prompt_start = wherey();
- bool ask_name = true;
- std::vector<player_save_info> existing_chars;
- slider_menu char_menu(MF_SINGLESELECT | MF_NOWRAP, false);
-
- if (!you.your_name.empty())
- ask_name = false;
-
- if (blankOK && (ask_name || !_is_good_name(you.your_name, false, false)))
- {
- existing_chars = find_saved_characters();
- if (existing_chars.empty())
- {
- cgotoxy(1,12);
- formatted_string::parse_string(
- " If you've never been here before, you might want to try out" EOL
- " the Dungeon Crawl tutorial. To do this, press "
- "<white>Ctrl-T</white> on the next" EOL
- " screen.").display();
- }
- else
- {
- MenuEntry *title = new MenuEntry("Or choose an existing character:");
- title->colour = LIGHTCYAN;
- char_menu.set_title( title );
- for (unsigned int i = 0; i < existing_chars.size(); ++i)
- {
- std::string desc = " " + existing_chars[i].short_desc();
- if (static_cast<int>(desc.length()) >= get_number_of_cols())
- desc = desc.substr(0, get_number_of_cols() - 1);
-
-#ifdef USE_TILE
- MenuEntry *me = new PlayerMenuEntry(desc);
-#else
- MenuEntry *me = new MenuEntry(desc);
-#endif
- me->data = &existing_chars[i];
- char_menu.add_entry(me);
- }
- }
- }
-
- do
- {
- // Prompt for a new name if current one unsatisfactory {dlb}:
- if (ask_name)
- {
- _show_name_prompt(prompt_start, blankOK, existing_chars, char_menu);
-
- // If the player wants out, we bail out.
- if (!_read_player_name(you.your_name, existing_chars, char_menu))
- end(0);
- trim_string(you.your_name);
- }
- }
- while (ask_name = !_is_good_name(you.your_name, blankOK, true));
-}
-
-bool validate_player_name(const std::string &name, bool verbose)
-{
-#if defined(TARGET_OS_DOS) || defined(TARGET_OS_WINDOWS)
- // Quick check for CON -- blows up real good under DOS/Windows.
- if (stricmp(name.c_str(), "con") == 0
- || stricmp(name.c_str(), "nul") == 0
- || stricmp(name.c_str(), "prn") == 0
- || strnicmp(name.c_str(), "LPT", 3) == 0)
- {
- if (verbose)
- cprintf(EOL "Sorry, that name gives your OS a headache." EOL);
- return (false);
- }
-#endif
-
- for (unsigned int i = 0; i < name.length(); i++)
- {
- char c = name[i];
- // 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 character that
- // might be a problem for some random shell or OS... so we
- // play it very conservative here. -- bwr
- if (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != ' ')
- {
- if (verbose)
- {
- cprintf( EOL
- "Alpha-numerics, spaces, dashes, periods "
- "and underscores only, please."
- EOL );
- }
- return (false);
- }
- }
-
- return (true);
-}
-
static void _make_rod(item_def &item, stave_type rod_type, int ncharges)
{
item.base_type = OBJ_STAVES;
diff --git a/crawl-ref/source/newgame.h b/crawl-ref/source/newgame.h
index d48fd291b8..ea3279e999 100644
--- a/crawl-ref/source/newgame.h
+++ b/crawl-ref/source/newgame.h
@@ -44,11 +44,15 @@ enum startup_wand_type
class player;
struct newgame_def
{
+ std::string name;
+
species_type species;
job_type job;
+
// TODO: fill in
void init(const player &p);
+ void save(player &p);
};
undead_state_type get_undead_state(const species_type sp);
@@ -68,6 +72,4 @@ bool choose_class(void);
* *********************************************************************** */
void give_basic_mutations(species_type speci);
-bool validate_player_name(const std::string &name, bool verbose);
-
#endif
diff --git a/crawl-ref/source/ng-input.cc b/crawl-ref/source/ng-input.cc
new file mode 100644
index 0000000000..c0cff468b6
--- /dev/null
+++ b/crawl-ref/source/ng-input.cc
@@ -0,0 +1,302 @@
+#include "AppHdr.h"
+
+#include "ng-input.h"
+#include "newgame.h"
+
+#include "cio.h"
+#include "files.h"
+#include "menu.h"
+#include "stuff.h"
+
+extern std::string init_file_error; // defined in acr.cc
+
+// Eventually, this should be something more grand. {dlb}
+void opening_screen(void)
+{
+#ifdef USE_TILE
+ // More grand... Like this? ;)
+ if (Options.tile_title_screen)
+ tiles.draw_title();
+#endif
+
+ std::string msg =
+ "<yellow>Hello, welcome to " CRAWL " " + Version::Long() + "!</yellow>" EOL
+ "<brown>(c) Copyright 1997-2002 Linley Henzell, "
+ "2002-2009 Crawl DevTeam" EOL
+ "Please consult crawl_manual.txt for instructions and legal details."
+ "</brown>" EOL;
+
+ const bool init_found = init_file_error.empty();
+
+ if (!init_found)
+ msg += "<lightred>No init file ";
+ else
+ msg += "<lightgrey>(Read options from ";
+
+ if (init_found)
+ {
+#ifdef DGAMELAUNCH
+ // For dgl installs, show only the last segment of the .crawlrc
+ // file name so that we don't leak details of the directory
+ // structure to (untrusted) users.
+ msg += get_base_filename(Options.filename);
+#else
+ msg += Options.filename;
+#endif
+ msg += ".)";
+ }
+ else
+ {
+ msg += init_file_error;
+ msg += ", using defaults.";
+ }
+
+ msg += EOL;
+
+ formatted_string::parse_string(msg).display();
+ textcolor( LIGHTGREY );
+}
+
+static void _show_name_prompt(int where, bool blankOK,
+ const std::vector<player_save_info> &existing_chars,
+ slider_menu &menu)
+{
+ cgotoxy(1, where);
+ textcolor( CYAN );
+ if (blankOK)
+ {
+ if (Options.prev_name.length() && Options.remember_name)
+ {
+ cprintf(EOL
+ "Press <Enter> for \"%s\", or . to be prompted later."
+ EOL,
+ Options.prev_name.c_str());
+ }
+ else
+ {
+ cprintf(EOL
+ "Press <Enter> to answer this after species and "
+ "job are chosen." EOL);
+ }
+ }
+
+ 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();
+ cgotoxy(name_x, name_y);
+ }
+
+ textcolor( LIGHTGREY );
+}
+
+static void _preprocess_character_name(std::string &name, bool blankOK)
+{
+ if (name.empty() && blankOK && Options.prev_name.length()
+ && Options.remember_name)
+ {
+ name = Options.prev_name;
+ }
+
+ // '.', '?' and '*' are blanked.
+ if (name.length() == 1
+ && (name[0] == '.' || name[0] == '*' || name[0] == '?'))
+ {
+ name = "";
+ }
+}
+
+static bool _is_good_name(std::string &name, bool blankOK, bool verbose)
+{
+ _preprocess_character_name(name, blankOK);
+
+ // verification begins here {dlb}:
+ if (name.empty())
+ {
+ if (blankOK)
+ return (true);
+
+ if (verbose)
+ 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(name.c_str(), "bones") == 0)
+ {
+ if (verbose)
+ cprintf(EOL "That's a silly name!" EOL);
+ return (false);
+ }
+#endif
+ return (validate_player_name(name, verbose));
+}
+
+static int newname_keyfilter(int &ch)
+{
+ if (ch == CK_DOWN || ch == CK_PGDN || ch == '\t')
+ return -1;
+
+ return 1;
+}
+
+static bool _read_player_name(std::string &name,
+ const std::vector<player_save_info> &existing,
+ slider_menu &menu)
+{
+ const int name_x = wherex(), name_y = wherey();
+ int (*keyfilter)(int &) = newname_keyfilter;
+ if (existing.empty())
+ keyfilter = NULL;
+ char buf[kNameLen];
+ // XXX: Prompt displays garbage otherwise, but don't really know why.
+ // Other places don't do this. --rob
+ buf[0] = '\0';
+ line_reader reader(buf, sizeof(buf));
+
+ reader.set_keyproc(keyfilter);
+
+ while (true)
+ {
+ cgotoxy(name_x, name_y);
+ if (name_x <= 80)
+ cprintf("%-*s", 80 - name_x + 1, "");
+
+ cgotoxy(name_x, name_y);
+ int ret = reader.read_line(false);
+ if (!ret)
+ {
+ name = buf;
+ return (true);
+ }
+
+ if (ret == CK_ESCAPE)
+ return (false);
+
+ if (ret != CK_ESCAPE && existing.size())
+ {
+ menu.set_search(name);
+ menu.show();
+ const MenuEntry *sel = menu.selected_entry();
+ if (sel)
+ {
+ const player_save_info &p =
+ *static_cast<player_save_info*>( sel->data );
+ name = p.name;
+ return (true);
+ }
+ }
+
+ // Go back and prompt the user.
+ }
+}
+
+// Reads a valid name from the player, writing it to ng.name.
+void enter_player_name(newgame_def &ng, bool blankOK)
+{
+ int prompt_start = wherey();
+ bool ask_name = true;
+ std::vector<player_save_info> existing_chars;
+ slider_menu char_menu(MF_SINGLESELECT | MF_NOWRAP, false);
+
+ if (!ng.name.empty())
+ ask_name = false;
+
+ if (blankOK && (ask_name || !_is_good_name(ng.name, false, false)))
+ {
+ existing_chars = find_saved_characters();
+ if (existing_chars.empty())
+ {
+ cgotoxy(1,12);
+ formatted_string::parse_string(
+ " If you've never been here before, you might want to try out" EOL
+ " the Dungeon Crawl tutorial. To do this, press "
+ "<white>Ctrl-T</white> on the next" EOL
+ " screen.").display();
+ }
+ else
+ {
+ MenuEntry *title = new MenuEntry("Or choose an existing character:");
+ title->colour = LIGHTCYAN;
+ char_menu.set_title( title );
+ for (unsigned int i = 0; i < existing_chars.size(); ++i)
+ {
+ std::string desc = " " + existing_chars[i].short_desc();
+ if (static_cast<int>(desc.length()) >= get_number_of_cols())
+ desc = desc.substr(0, get_number_of_cols() - 1);
+
+#ifdef USE_TILE
+ MenuEntry *me = new PlayerMenuEntry(desc);
+#else
+ MenuEntry *me = new MenuEntry(desc);
+#endif
+ me->data = &existing_chars[i];
+ char_menu.add_entry(me);
+ }
+ }
+ }
+
+ do
+ {
+ // Prompt for a new name if current one unsatisfactory {dlb}:
+ if (ask_name)
+ {
+ _show_name_prompt(prompt_start, blankOK, existing_chars, char_menu);
+
+ // If the player wants out, we bail out.
+ if (!_read_player_name(ng.name, existing_chars, char_menu))
+ end(0);
+ trim_string(ng.name);
+ }
+ }
+ while (ask_name = !_is_good_name(ng.name, blankOK, true));
+}
+
+bool validate_player_name(const std::string &name, bool verbose)
+{
+#if defined(TARGET_OS_DOS) || defined(TARGET_OS_WINDOWS)
+ // Quick check for CON -- blows up real good under DOS/Windows.
+ if (stricmp(name.c_str(), "con") == 0
+ || stricmp(name.c_str(), "nul") == 0
+ || stricmp(name.c_str(), "prn") == 0
+ || strnicmp(name.c_str(), "LPT", 3) == 0)
+ {
+ if (verbose)
+ cprintf(EOL "Sorry, that name gives your OS a headache." EOL);
+ return (false);
+ }
+#endif
+
+ for (unsigned int i = 0; i < name.length(); i++)
+ {
+ char c = name[i];
+ // 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 character that
+ // might be a problem for some random shell or OS... so we
+ // play it very conservative here. -- bwr
+ if (!isalnum(c) && c != '-' && c != '.' && c != '_' && c != ' ')
+ {
+ if (verbose)
+ {
+ cprintf( EOL
+ "Alpha-numerics, spaces, dashes, periods "
+ "and underscores only, please."
+ EOL );
+ }
+ return (false);
+ }
+ }
+
+ return (true);
+}
diff --git a/crawl-ref/source/ng-input.h b/crawl-ref/source/ng-input.h
new file mode 100644
index 0000000000..8c45247f90
--- /dev/null
+++ b/crawl-ref/source/ng-input.h
@@ -0,0 +1,11 @@
+#ifndef NG_INPUT_H
+#define NG_INPUT_H
+
+struct newgame_def;
+
+void opening_screen();
+bool validate_player_name(const std::string &name, bool verbose);
+void enter_player_name(newgame_def &ng, bool blankOK);
+
+#endif
+