selection screen
This involved the following:
I'm quite happy with the new species order, but the order of jobs could be improved. Luckily, changing that is totally easy now. :) See newgame.cc for old vs. new orders.
(And yes, there is an option to keep the old way.)
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3503 c06c8d41-db1a-0410-9941-cceddc491573
UKYGZDI6PYZPXDACCQGVPHANUP5ADCSNROOZIE7LYIZQWSNFHJZAC
A4BTFRR7MAUIABPGMTNPKPZVVSP5XPFGEOCX4YEI7U3EUAKNJAMAC
TW7QOMTSLYPGUUWHGHLY5G5LV6QQRQIKK4BSE64RY7RDGKVDHCEAC
DE2BXPJDLWN7F3LAYKUSWI5CFEYZMV2ZN4K2Y356NWIX4AIGD73QC
ESLX22QMGDOB3NWE5HHHLUNLKWBYGAEK6DCXPIRBGTDNDOCMW3RQC
HH5S4A3M4XPI23PCXKKG36H5ES2Z67NDLQFFMPA5PEWL3FJ4674QC
3GRGONHWIZ7PTTNMJ6CIZEMIKC7N2DTU62BLJ5QG4E7RGA5O2XMAC
CYAVI4PYWMMKTPYT5N2B3MI4OSHZFLPKOZFSLFJUXRYAACYXWW3AC
JZCODQCOUBBBPPR4TLOAPIB4BQLDY3ORTJXTWEQSUJVJ7DMK7FVAC
355HO2F6CLJGKAPTBSGTDZK4YTCDKBS57B2TBUWIXQJ5A4UYRPAQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
SJP5BHX6MFWF3OSQPEF4WUWZWPUGMOVURTT2CUVT6H3A66LETXUAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
M5ZDZJBTOJ7SWQPZZQPC24JYZKP26MWSRDHXBWQE2MPPL6WCXOIQC
NJ66DHOK2SWT6MWW5FIWHKZE3HHMFNCBBUYLDJGZGCH3B752OBYQC
YN7KNAJU72XINIQ3GP7RJLKW3STMN5VWJV2K66ICPZXR2VMYLZPAC
XHFG7QUF4UF7OYU7KWT2EB6XITI2BZDHH2D2FD7YP33C3M4GRBKQC
ZJLJGSB2XSBQU42OFQMXL3EG4CXAQGOYAU6YTV2SAWZEJIPFH2CAC
P2ZCF3BBG523ZEOD6XQA4X5YEHBTWH3IM33YVHXP2SQ5POXZIH4QC
GUXTGUEMZYBRGV5QUAQSJHG3AOIQDWWCDIMOX4LASFJAZVGL2WQAC
LABXKXWWQY2V4FUDLGVTDYHXINAP6KRHZDHBQ2FE22FFOEIZPL6QC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
BTO5WE4OEK64DZQVNYLOESM74KKQNE7KSNMQVF5UDB26OBKP7ORQC
QHABWX5UYQAREZC4B6JGSRXSUH6DQLRD7WB4YGV4HHUHMTXY3ERAC
OVM7ZULJJ6Q23AQ747AWBGISGDQYCGF2NT5YTXKW633I56WIYZPQC
RC6L3CIBLJEH4GWRFD7UQNGI6PZT74FRUVOYHSAN2XCC74NZUASQC
TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC
WWR4IDWLXP4XLBWDZBA5GFG7CRKUJQNRK7FFUFOISK6OJTMYQPFQC
6LT6USGJOTDMRJGXLAN2NSZXK2GKWEXDKKUV6SVV7ZC6WI6EKMDQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
WTBQLBYFLQCF3NRAMB4Z2YA4MHYVFYI5YS7FXXBPICY2KCBA63AQC
4O3VTUJT5T7NBNF3Q45XO2WHS6TCJXVLH6CKX4K36WUBDRT5F6KAC
JR2RAQ523LOWNDYJNK6AZVKI6WVMI622PIV72XWOVZYPXPUKSQWAC
DWQDVEHZSTDVFS2GU24ZLIGJDA3M4767TB734JAQEAUVOOCLZ75AC
Z6343ZVG2VOE7WOLBS7YLIWJ6XGCRCGJRJLP5WUVRTG7VOIXRRLAC
5HBRQ2QZTFBQE2Z2CFADUI2D52LO5Z5CNHXHA7BJP3LGO7FJPUCQC
B5OK4FEITJ6MUT7J76OJJH2TOPTZGG7J7UPIJ6Z6WA5FC526FLTAC
FYD4A5TIETIV2ZLFYWGHXANU6WQFKMVREHM7OZY2TAXSBMMCDLJAC
CJKEUBURR2NB7I43WBO3LGPSNMCM6SGR5HOPQKK5IKC3PN47JUDQC
TI2HASZUN3QBTNWRCXLXJHOZBOUHFEOQUCPK5EYLATL7BP32H6LQC
ZBPZZ5A7AB2VFZKQ2UJXVDGUK22OCZJCEN2RWTGDGK3VXFCCDKVAC
CC5NTNYE2VPD25CVJI6LL5TLZEGBGIL3PZEXKYXQDIVZGDLGBNOQC
LAMIVDKY7LO5ONX5Z273ZCCEA5UBENOJD5VWNE4AK2EXGFED6BFQC
NTHQ3RE6DK47HACSWRRVH7QPETSRCLTWMUN2AWKNVWYSV55GFNZAC
VIFRP3HZEONFR6PQRYZYM3YUEJOQ7T4F5CZY4MN4YJMB23FMU7XAC
33XVUXSKVD3XYQVD63WXGLLICWXFMZSU2YRP2VNOII5A3OU2C3UQC
JXOE7KJIEAJHPLMZAJ6O4YHDTRB6BGNP6XT3ZSEFYGSIUMHR77KQC
DMRXDEKHHBQNY37NPGZFAGUQPALWFANGGK4CUWIOQUPSLM2JBNFQC
J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC
EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC
W6IY6LF3MREPXC23AAKA2BJNUCJYCSOWY55DIWJWFLUEE2Y3LGNQC
U4PJNTYRHCH5UT4JJWFDCLSZSAJW7DSWWNIJ2R464VQUZCFN3T6QC
6BO27PEAAOYJEOL5F5RWDMSLU7WUYSKC4LCANVIDMRZRMZWCEYUAC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
UCJ7DCJX4EJMHNTJUITNDG7K7KFFLGHIFOLSKDY7LFBNWGT3AAKAC
KFWZ6CK4MZRLZN7YCZV32OAJBB5XVEJQR6SR474UQX2MJGXI4F7AC
RVST2QHYJ757ZHK4AUJ5NGPDZ44AD6RVFVXYPKQIBJXZBDNUCHXQC
UF4ODJOCV3ZL7DXRLLOFVWHUKKJX34FO4ZM6VJAWEJ3QVP3XZ2AAC
EHSY6DVGUMI6C67WKET3GDJVLWJWGYBYQONNDK5JVT7BCTHBEZVAC
},
{ // SP_UNK0_DRACONIAN (27)
90, // SK_FIGHTING
100, // SK_SHORT_BLADES
100, // SK_LONG_BLADES
100, // SK_UNUSED_1
100, // SK_AXES
100, // SK_MACES_FLAILS
100, // SK_POLEARMS
100, // SK_STAVES
120, // SK_SLINGS
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
120, // SK_THROWING
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
100, // SK_STABBING
100, // SK_SHIELDS
100, // SK_TRAPS_DOORS
100, // SK_UNARMED_COMBAT
100, // undefined
100, // undefined
100, // undefined
100, // undefined
100, // undefined
(100 * 130) / 100, // SK_SPELLCASTING
100, // SK_CONJURATIONS
120, // SK_ENCHANTMENTS
100, // SK_SUMMONINGS
100, // SK_NECROMANCY
100, // SK_TRANSLOCATIONS
100, // SK_TRANSMIGRATION
100, // SK_DIVINATIONS
100, // SK_FIRE_MAGIC
100, // SK_ICE_MAGIC
100, // SK_AIR_MAGIC
100, // SK_EARTH_MAGIC
100, // SK_POISON_MAGIC
(100 * 75) / 100, // SK_INVOCATIONS
(100 * 75) / 100, // SK_EVOCATIONS
{ // SP_UNK1_DRACONIAN (28)
90, // SK_FIGHTING
100, // SK_SHORT_BLADES
100, // SK_LONG_BLADES
100, // SK_UNUSED_1
100, // SK_AXES
100, // SK_MACES_FLAILS
100, // SK_POLEARMS
100, // SK_STAVES
120, // SK_SLINGS
120, // SK_BOWS
120, // SK_CROSSBOWS
120, // SK_DARTS
120, // SK_THROWING
200, // SK_ARMOUR
120, // SK_DODGING
120, // SK_STEALTH
100, // SK_STABBING
100, // SK_SHIELDS
100, // SK_TRAPS_DOORS
100, // SK_UNARMED_COMBAT
100, // undefined
100, // undefined
100, // undefined
100, // undefined
100, // undefined
(100 * 130) / 100, // SK_SPELLCASTING
100, // SK_CONJURATIONS
120, // SK_ENCHANTMENTS
100, // SK_SUMMONINGS
100, // SK_NECROMANCY
100, // SK_TRANSLOCATIONS
100, // SK_TRANSMIGRATION
100, // SK_DIVINATIONS
100, // SK_FIRE_MAGIC
100, // SK_ICE_MAGIC
100, // SK_AIR_MAGIC
100, // SK_EARTH_MAGIC
100, // SK_POISON_MAGIC
(100 * 75) / 100, // SK_INVOCATIONS
(100 * 75) / 100, // SK_EVOCATIONS
},
"HO", "Ko", "Mu", "Na", "Gn", "Og", "Tr", "OM", "Dr", "Dr",
"Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr",
"Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp", "HD", "El" };
"HO", "Ko", "Mu", "Na", "Gn", "Og", "Tr", "OM",
// the draconians
"Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr", "Dr",
"Ce", "DG", "Sp", "Mi", "DS", "Gh", "Ke", "Mf", "Vp",
// placeholders
"HD", "El" };
/* March 2008: change order of species and jobs on character selection screen
as suggested by Markus Maier. Summarizing comments below are copied directly
from Markus' SourceForge comments. */
// listed in two columns to match the selection screen output
// Take care to list all valid species here, or they cannot be directly chosen.
// The red draconian is later replaced by a random variant.
// The old and new lists are expected to have the same length.
static species_type old_species_order[] = {
SP_HUMAN, SP_HIGH_ELF,
SP_GREY_ELF, SP_DEEP_ELF,
SP_SLUDGE_ELF, SP_MOUNTAIN_DWARF,
SP_HALFLING, SP_HILL_ORC,
SP_KOBOLD, SP_MUMMY,
SP_NAGA, SP_GNOME,
SP_OGRE, SP_TROLL,
SP_OGRE_MAGE, SP_RED_DRACONIAN,
SP_CENTAUR, SP_DEMIGOD,
SP_SPRIGGAN, SP_MINOTAUR,
SP_DEMONSPAWN, SP_GHOUL,
SP_KENKU, SP_MERFOLK,
SP_VAMPIRE
};
// Fantasy staples and humanoid creatures come first, then dimunitive and
// stealthy creatures, then monstrous creatures, then planetouched and after
// all living creatures finally the undead. (MM)
static species_type new_species_order[] = {
// comparatively human-like looks
SP_HUMAN, SP_HIGH_ELF,
SP_GREY_ELF, SP_DEEP_ELF,
SP_SLUDGE_ELF, SP_MOUNTAIN_DWARF,
SP_HILL_ORC, SP_MERFOLK,
// small species
SP_HALFLING, SP_GNOME,
SP_KOBOLD, SP_SPRIGGAN,
// significantly different body type than human
SP_NAGA, SP_CENTAUR,
SP_OGRE, SP_OGRE_MAGE,
SP_TROLL, SP_MINOTAUR,
SP_KENKU, SP_RED_DRACONIAN,
// celestial species
SP_DEMIGOD, SP_DEMONSPAWN,
// undead species
SP_MUMMY, SP_GHOUL,
SP_VAMPIRE
};
return static_cast<species_type>(SP_RED_DRACONIAN + random2(9));
if (index < 0 || (unsigned int) index >= ARRAYSIZE(old_species_order))
{
return (SP_UNKNOWN);
}
return (Options.use_old_selection_order ? old_species_order[index]
: new_species_order[index]);
}
// listed in two columns to match the selection screen output
// Take care to list all valid classes here, or they cannot be directly chosen.
// The old and new lists are expected to have the same length.
static job_type old_jobs_order[] = {
JOB_FIGHTER, JOB_WIZARD,
JOB_PRIEST, JOB_THIEF,
JOB_GLADIATOR, JOB_NECROMANCER,
JOB_PALADIN, JOB_ASSASSIN,
JOB_BERSERKER, JOB_HUNTER,
JOB_CONJURER, JOB_ENCHANTER,
JOB_FIRE_ELEMENTALIST, JOB_ICE_ELEMENTALIST,
JOB_SUMMONER, JOB_AIR_ELEMENTALIST,
JOB_EARTH_ELEMENTALIST, JOB_CRUSADER,
JOB_DEATH_KNIGHT, JOB_VENOM_MAGE,
JOB_CHAOS_KNIGHT, JOB_TRANSMUTER,
JOB_HEALER, JOB_REAVER,
JOB_STALKER, JOB_MONK,
JOB_WARPER, JOB_WANDERER
};
// First plain fighters, then religious fighters, then spell-casting
// fighters, then primary spell-casters, then stabbers and shooters. (MM)
static job_type new_jobs_order[] = {
// fighters
JOB_FIGHTER, JOB_GLADIATOR,
JOB_MONK, JOB_BERSERKER,
// religious professions (incl. Berserker above)
JOB_PALADIN, JOB_PRIEST,
JOB_CHAOS_KNIGHT, JOB_DEATH_KNIGHT,
JOB_HEALER, JOB_CRUSADER,
// general and niche spellcasters (incl. Crusader above)
JOB_REAVER, JOB_WIZARD,
JOB_CONJURER, JOB_ENCHANTER,
JOB_SUMMONER, JOB_NECROMANCER,
JOB_WARPER, JOB_TRANSMUTER,
JOB_FIRE_ELEMENTALIST, JOB_ICE_ELEMENTALIST,
JOB_AIR_ELEMENTALIST, JOB_EARTH_ELEMENTALIST,
// poison specialists and stabbers
JOB_VENOM_MAGE, JOB_STALKER,
JOB_THIEF, JOB_ASSASSIN,
JOB_HUNTER, JOB_WANDERER
};
static job_type get_class(const int index)
{
if (index < 0 || (unsigned int) index >= ARRAYSIZE(old_jobs_order))
{
return JOB_UNKNOWN;
}
return (Options.use_old_selection_order? old_jobs_order[index]
: new_jobs_order[index]);
int pcls = letter_to_class(oclass);
return pcls != JOB_UNKNOWN? get_class_name(pcls) : "Random";
job_type pclass = get_class(letter_to_index(oclass));
return (pclass == JOB_UNKNOWN? "Random" : get_class_name(pclass));
return (species
&& species != NUM_SPECIES
&& species != SP_UNKNOWN
&& !((display?
(species > SP_RED_DRACONIAN
&& species <= SP_BASE_DRACONIAN)
: (species >= SP_UNK0_DRACONIAN
&& species <= SP_BASE_DRACONIAN))
|| species == SP_ELF
|| species == SP_HILL_DWARF));
}
if (!species) // species only start at 1
return (false);
if (species >= SP_ELF) // these are all invalid
return (false);
// no problem with these
if (species <= SP_RED_DRACONIAN || species > SP_BASE_DRACONIAN)
return (true);
static species_type random_species()
{
species_type sp = SP_UNKNOWN;
do
sp = static_cast<species_type>( random2(NUM_SPECIES) );
while (!is_species_valid_choice(sp));
return (sp);
// draconians other than red return false if display == true
return (!display);
branches[BRANCH_ORCISH_MINES].startdepth = random_range(6, 11);
branches[BRANCH_ELVEN_HALLS].startdepth = random_range(3, 4);
branches[BRANCH_LAIR].startdepth = random_range(8, 13);
branches[BRANCH_HIVE].startdepth = random_range(11, 16);
branches[BRANCH_SLIME_PITS].startdepth = random_range(8, 10);
branches[BRANCH_ORCISH_MINES].startdepth = random_range(6, 11);
branches[BRANCH_ELVEN_HALLS].startdepth = random_range(3, 4);
branches[BRANCH_LAIR].startdepth = random_range(8, 13);
branches[BRANCH_HIVE].startdepth = random_range(11, 16);
branches[BRANCH_SLIME_PITS].startdepth = random_range(8, 10);
branches[BRANCH_SNAKE_PIT].startdepth = random_range(3, 8);
branches[BRANCH_VAULTS].startdepth = random_range(14, 19);
branches[BRANCH_CRYPT].startdepth = random_range(2, 4);
branches[BRANCH_SNAKE_PIT].startdepth = random_range(3, 8);
branches[BRANCH_VAULTS].startdepth = random_range(14, 19);
branches[BRANCH_CRYPT].startdepth = random_range(2, 4);
ng_weapon = (Options.random_pick ||
Options.weapon == WPN_RANDOM ||
keyin == '*')
? WPN_RANDOM : you.inv[0].sub_type;
ng_weapon = (Options.random_pick || Options.weapon == WPN_RANDOM
|| keyin == '*') ? WPN_RANDOM
: you.inv[0].sub_type;
" If you've never been here before, you might want to try "
"out" EOL " the Dungeon Crawl tutorial. To do this, press "
"<white>T</white> on the next" EOL " screen.").display();
}
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)
" If you've never been here before, you might want to try out" EOL
" the Dungeon Crawl tutorial. To do this, press "
"<white>T</white> on the next" EOL
" screen.").display();
}
else
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);
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);
}
static job_type letter_to_class(int keyn)
{
switch ( keyn )
{
case 'a': return JOB_FIGHTER;
case 'b': return JOB_WIZARD;
case 'c': return JOB_PRIEST;
case 'd': return JOB_THIEF;
case 'e': return JOB_GLADIATOR;
case 'f': return JOB_NECROMANCER;
case 'g': return JOB_PALADIN;
case 'h': return JOB_ASSASSIN;
case 'i': return JOB_BERSERKER;
case 'j': return JOB_HUNTER;
case 'k': return JOB_CONJURER;
case 'l': return JOB_ENCHANTER;
case 'm': return JOB_FIRE_ELEMENTALIST;
case 'n': return JOB_ICE_ELEMENTALIST;
case 'o': return JOB_SUMMONER;
case 'p': return JOB_AIR_ELEMENTALIST;
case 'q': return JOB_EARTH_ELEMENTALIST;
case 'r': return JOB_CRUSADER;
case 's': return JOB_DEATH_KNIGHT;
case 't': return JOB_VENOM_MAGE;
case 'u': return JOB_CHAOS_KNIGHT;
case 'v': return JOB_TRANSMUTER;
case 'w': return JOB_HEALER;
case 'y': return JOB_REAVER;
case 'z': return JOB_STALKER;
case 'A': return JOB_MONK;
case 'B': return JOB_WARPER;
case 'C': return JOB_WANDERER;
}
return JOB_UNKNOWN;
static species_type letter_to_species(int keyn)
{
const int offset = letter_to_index(keyn);
if (offset < 0)
return (SP_UNKNOWN);
int rc;
if ( offset + SP_HUMAN < SP_RED_DRACONIAN )
rc = offset + SP_HUMAN;
else if ( offset + SP_HUMAN == SP_RED_DRACONIAN ) // random draco
rc = random_draconian_species();
else // skip over draconian species
rc = offset + (SP_BASE_DRACONIAN - SP_RED_DRACONIAN) + 1;
return (rc >= NUM_SPECIES? SP_UNKNOWN : static_cast<species_type>(rc));
}
static char species_to_letter(int spec)
{
if (spec > SP_RED_DRACONIAN && spec <= SP_BASE_DRACONIAN)
spec = SP_RED_DRACONIAN;
else if (spec > SP_BASE_DRACONIAN)
spec -= SP_BASE_DRACONIAN - SP_RED_DRACONIAN;
int letter = 'a' + spec - 1;
if (letter > 'z')
letter = 'A' + (letter - 'z') - 1;
return (letter);
}
// the list musn't be longer than the number of actual species
COMPILE_CHECK(ARRAYSIZE(old_species_order) <= NUM_SPECIES, c1);
// check whether the two lists have the same size
COMPILE_CHECK(ARRAYSIZE(old_species_order) == ARRAYSIZE(new_species_order), c2);
const int num_species = ARRAYSIZE(old_species_order);
case 'X':
cprintf(EOL "Goodbye!");
end(0);
break;
case CK_BKSP:
case ' ':
you.species = SP_UNKNOWN;
Options.race = 0;
return true;
case '!':
pick_random_species_and_class();
Options.random_pick = true; // used to give random weapon/god as well
ng_random = true;
return false;
case '\r':
case '\n':
if (Options.prev_race && prevraceok)
keyn = Options.prev_race;
break;
case '\t':
if (prev_startup_options_set())
{
if (Options.prev_randpick ||
(Options.prev_race == '*' && Options.prev_cls == '*'))
{
Options.random_pick = true;
ng_random = true;
pick_random_species_and_class();
return false;
}
set_startup_options();
you.species = SP_UNKNOWN;
you.char_class = JOB_UNKNOWN;
return true;
}
break;
// access to the help files
case '?':
if ((keyn == '\r' || keyn == '\n') && Options.prev_race && prevraceok)
keyn = Options.prev_race;
if (keyn == '\t' && prev_startup_options_set())
// These are handled specially as they _could_ be set
// using Options.race or prev_race
if (keyn == 'T') // easy to set in init.txt
if (Options.prev_randpick ||
(Options.prev_race == '*' && Options.prev_cls == '*'))
{
Options.random_pick = true;
ng_random = true;
pick_random_species_and_class();
return false;
}
set_startup_options();
you.species = SP_UNKNOWN;
you.char_class = JOB_UNKNOWN;
return true;
}
if (keyn == CK_BKSP || keyn == ' ')
{
you.species = SP_UNKNOWN;
Options.race = 0;
return true;
return !pick_tutorial();
!class_allowed(letter_to_species(keyn), you.char_class)));
}
else if (keyn == '!')
{
pick_random_species_and_class();
Options.random_pick = true; // used to give random weapon/god as well
ng_random = true;
return false;
!class_allowed(get_species(index), you.char_class)));
keyn = index_to_letter(index);
// the list musn't be longer than the number of actual classes
COMPILE_CHECK(ARRAYSIZE(old_jobs_order) <= NUM_JOBS, c1);
// check whether the two lists have the same size
COMPILE_CHECK(ARRAYSIZE(old_jobs_order) == ARRAYSIZE(new_jobs_order), c2);
const int num_classes = ARRAYSIZE(old_jobs_order);
case 'X':
cprintf(EOL "Goodbye!");
end(0);
break;
case ESCAPE:
case CK_BKSP:
case ' ':
if (keyn != ' ' || you.species == SP_UNKNOWN)
{
you.char_class = JOB_UNKNOWN;
return false;
}
case 'T':
return pick_tutorial();
case '!':
pick_random_species_and_class();
// used to give random weapon/god as well
Options.random_pick = true;
ng_random = true;
return true;
case '\r':
case '\n':
if (Options.prev_cls && prevclassok)
keyn = Options.prev_cls;
break;
case '\t':
if (prev_startup_options_set())
{
if (Options.prev_randpick ||
(Options.prev_race == '*' && Options.prev_cls == '*'))
{
Options.random_pick = true;
ng_random = true;
pick_random_species_and_class();
return true;
}
set_startup_options();
// Toss out old species selection, if any.
you.species = SP_UNKNOWN;
you.char_class = JOB_UNKNOWN;
return false;
}
break;
// help files
case '?':
if ((keyn == '\r' || keyn == '\n') && Options.prev_cls && prevclassok)
keyn = Options.prev_cls;
job_type chosen_job = JOB_UNKNOWN;
if (keyn == '*')
{
// pick a job at random... see god retribution for proof this
// is uniform. -- bwr
int job_count = 0;
Options.random_pick = true;
ng_random = true;
pick_random_species_and_class();
return true;
}
set_startup_options();
// Toss out old species selection, if any.
you.species = SP_UNKNOWN;
you.char_class = JOB_UNKNOWN;
if (you.species == SP_UNKNOWN ||
class_allowed(you.species, static_cast<job_type>(i)))
{
job_count++;
if (one_chance_in( job_count ))
chosen_job = static_cast<job_type>(i);
}
}
ASSERT( chosen_job != JOB_UNKNOWN );
if (keyn == '*')
{
// pick a job at random... see god retribution for proof this
// is uniform. -- bwr
int job_count = 0;
job_type job = JOB_UNKNOWN;
for (int i = 0; i < NUM_JOBS; i++)
{
if ( i == JOB_QUITTER )
continue;
if (you.species == SP_UNKNOWN ||
class_allowed(you.species, static_cast<job_type>(i)))
{
job_count++;
if (one_chance_in( job_count ))
job = static_cast<job_type>(i);
}
}
ASSERT( job != JOB_UNKNOWN );
chosen_job = job;
chosen_job = get_class(letter_to_index(keyn));
}
pick_random_species_and_class();
// used to give random weapon/god as well
Options.random_pick = true;
ng_random = true;
return true;
}
else if (keyn == 'T')
{
return pick_tutorial();
}
else if ((keyn == ' ' && you.species == SP_UNKNOWN) ||
keyn == 'x' || keyn == ESCAPE || keyn == CK_BKSP)
{
you.char_class = JOB_UNKNOWN;
return false;
Options.cls = 0;
printed = false;
you.skills[SK_THROWING] = 2;
you.skills[((coinflip() || you.species == SP_VAMPIRE)?
SK_STABBING : SK_SHIELDS)]++;
if (you.species == SP_VAMPIRE || coinflip())
you.skills[SK_STABBING]++;
else
you.skills[SK_SHIELDS]++;